refactor(aot): 优化 unsafe_cast 类型转换实现

- 将 std::unsafe_cast 的类型检查逻辑重构为统一的模板函数
- 修改异常类型从 RuntimeException 为 TypeError
- 更新编译器代码生成以使用新的类型转换函数
- 添加对 std::map 和 std::unordered_map 的类型转换支持
- 创建新的测试用例验证各种容器类型的 unsafe_cast 行为
- 修正现有测试用例中的异常类型断言
pull/1/head
韩天峰 4 months ago
parent 7f4dee40c0
commit 5d1e8d893c
  1. 24
      src/Php/CompilerBase.php
  2. 4
      src/Php/Parser/StdContainerParser.php
  3. 22
      tests/aot/std-array/008.phpt
  4. 22
      tests/aot/std-map/006.phpt
  5. 22
      tests/aot/std-unordered-map/006.phpt
  6. 2
      tests/aot/std-vector/007.phpt
  7. 2
      tests/aot/std-vector/008.phpt

@ -5482,13 +5482,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($type === self::TYPE_STD_ARRAY) {
$info = $this->context->stdArrays[$name];
if (isset($info['unsafePtr'])) {
$unsafePtrBox = $this->genTmpVarName();
$code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox<php::UnsafePtr>();' . PHP_EOL;
$code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL;
$code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL;
$code .= $this->getIndent() . '}' . PHP_EOL;
$code .= $this->getIndent();
$code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);';
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} elseif ($info['bytes'] > self::MAX_BYTES_IN_STACK) {
$code .= "auto {$name}_unique_ptr = std::make_unique<{$info['decl']}>();\n";
$code .= $this->getIndent() . ' auto &' . $name . ' = *' . $name . '_unique_ptr;';
@ -5498,13 +5492,7 @@ class CompilerBase extends \PhpAot\Core\Translator
} elseif ($type === self::TYPE_STD_VECTOR) {
$info = $this->context->stdContainers[$name];
if (isset($info['unsafePtr'])) {
$unsafePtrBox = $this->genTmpVarName();
$code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox<php::UnsafePtr>();' . PHP_EOL;
$code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL;
$code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL;
$code .= $this->getIndent() . '}' . PHP_EOL;
$code .= $this->getIndent();
$code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);';
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} else {
$code .= $info['decl'] . ' ' . $name;
if ($info['size'] !== null) {
@ -5517,13 +5505,7 @@ class CompilerBase extends \PhpAot\Core\Translator
} elseif ($type === self::TYPE_STD_MAP || $type === self::TYPE_STD_UNORDERED_MAP) {
$info = $this->context->stdContainers[$name];
if (isset($info['unsafePtr'])) {
$unsafePtrBox = $this->genTmpVarName();
$code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox<php::UnsafePtr>();' . PHP_EOL;
$code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL;
$code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL;
$code .= $this->getIndent() . '}' . PHP_EOL;
$code .= $this->getIndent();
$code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);';
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} else {
$code .= $info['decl'] . ' ' . $name . '{};';
}

@ -422,7 +422,7 @@ trait StdContainerParser
$this->addLocalVar($var, self::TYPE_STD_ARRAY);
$this->parseStdArray($var, $typeExpr);
$this->context->stdArrays[$var]['unsafePtr'] = $unsafePtr;
return '// reinterpret_cast<' . $this->context->stdArrays[$var]['decl'] . '*>(' . $unsafePtr . ')';
return '// php_unsafe_cast<' . $this->context->stdArrays[$var]['decl'] . '>(' . $unsafePtr . ')';
}
if ($containerType === 'vector') {
@ -436,7 +436,7 @@ trait StdContainerParser
$this->parseStdUnorderedMap($var, $typeExpr);
}
$this->context->stdContainers[$var]['unsafePtr'] = $unsafePtr;
return '// reinterpret_cast<' . $this->context->stdContainers[$var]['decl'] . '*>(' . $unsafePtr . ')';
return '// php_unsafe_cast<' . $this->context->stdContainers[$var]['decl'] . '>(' . $unsafePtr . ')';
}
protected function parseStdMapKeyType(NodeAbstract $expr, string $owner): string

@ -0,0 +1,22 @@
--TEST--
std array: unsafe_cast type mismatch
--FILE--
<?php
function std_array_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
{
$array = std::unsafe_cast(std::array(native_types::type_float, 3), $unsafePtr);
}
function main() {
$array = std::array(native_types::type_int, 3);
$ptr = std::unsafe_ptr($array);
try {
std_array_unsafe_ptr_type_mismatch($ptr);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch

@ -0,0 +1,22 @@
--TEST--
std map: unsafe_cast type mismatch
--FILE--
<?php
function std_map_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
{
$map = std::unsafe_cast(std::map(complex_types::type_str, native_types::type_float), $unsafePtr);
}
function main() {
$map = std::map(complex_types::type_str, native_types::type_int);
$ptr = std::unsafe_ptr($map);
try {
std_map_unsafe_ptr_type_mismatch($ptr);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch

@ -0,0 +1,22 @@
--TEST--
std unordered map: unsafe_cast type mismatch
--FILE--
<?php
function std_unordered_map_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
{
$map = std::unsafe_cast(std::unordered_map(native_types::type_int, native_types::type_float), $unsafePtr);
}
function main() {
$map = std::unordered_map(native_types::type_int, native_types::type_int);
$ptr = std::unsafe_ptr($map);
try {
std_unordered_map_unsafe_ptr_type_mismatch($ptr);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch

@ -13,7 +13,7 @@ function main() {
try {
std_vector_unsafe_ptr_type_mismatch($ptr);
} catch (RuntimeException $e) {
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}

@ -21,7 +21,7 @@ function main() {
try {
std_vector_unsafe_ptr_class_type_mismatch($ptr);
} catch (RuntimeException $e) {
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}

Loading…
Cancel
Save