fix: 修复异常处理与exit语义,重构动态属性操作

pull/13/head
韩天峰 2 months ago
parent 5f9f7b2f96
commit c740a24501
  1. 2
      project.yml
  2. 49
      src/Php/CompilerBase.php
  3. 13
      tests/aot/basic/exit-zero.phpt
  4. 16
      tests/aot/exception/catch-exit.phpt
  5. 34
      tests/aot/object_property/property-array-write.phpt
  6. 3
      tests/aot/optimizations/int-calculation.phpt
  7. 8
      tests/aot/var_convert/002.phpt

@ -1,4 +1,4 @@
name: swoole-compiler
name: tpc
build-mode: bin
version: 0.1.0
cxx-std: c++17

@ -4744,9 +4744,12 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
protected function parseExit(Expr\Exit_ $node): string
{
if (!$node->expr) {
return 'php::exit(0)';
return 'std::exit(0)';
}
return 'php::exit(' . $this->parseIdentifier($node->expr) . ')';
$status = $this->parseExprAsValue($node->expr);
return '([&]() -> php::Var { php::Var exit_status = ' . $status . '; '
. 'if (exit_status.isInt()) { std::exit(exit_status.toInt()); } '
. 'php::echo(php::toString(exit_status)); std::exit(0); return php::null; })()';
}
protected function getFixedObjectPropDefaultValue(PropertyDef $def): ?string
@ -5606,14 +5609,23 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
{
$this->assertDynamicPropertyTarget($target);
return $target->getDynamicObjectExpr() . '.appendArrayProperty(' . $target->getDynamicPropertyExpr() . ', ' . $value . ')';
return $this->emitDynamicPropertyAppendArray(
$target->getDynamicObjectExpr(),
$target->getDynamicPropertyExpr(),
$value
);
}
protected function emitDynamicPropertyTargetUpdateArray(PropertyWriteTarget $target, string $dim, string $value): string
{
$this->assertDynamicPropertyTarget($target);
return $target->getDynamicObjectExpr() . '.updateArrayProperty(' . $target->getDynamicPropertyExpr() . ', ' . $dim . ', ' . $value . ')';
return $this->emitDynamicPropertyUpdateArray(
$target->getDynamicObjectExpr(),
$target->getDynamicPropertyExpr(),
$dim,
$value
);
}
protected function canEmitDynamicPropertyTarget(?PropertyWriteTarget $target): bool
@ -5670,7 +5682,11 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
return $this->emitDynamicPropertyTargetAppendArray($target, $value);
}
return $this->parseIdentifier($expr->var) . '.appendArrayProperty(' . $this->identifierToStr($expr->name) . ', ' . $value . ')';
return $this->emitDynamicPropertyAppendArray(
$this->parseIdentifier($expr->var),
$this->identifierToStr($expr->name, literal: true),
$value
);
}
protected function emitDynamicPropertyFetchUpdateArray(Expr\PropertyFetch $expr, string $dim, string $value, ?PropertyWriteTarget $target = null): string
@ -5679,7 +5695,22 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
return $this->emitDynamicPropertyTargetUpdateArray($target, $dim, $value);
}
return $this->parseIdentifier($expr->var) . '.updateArrayProperty(' . $this->identifierToStr($expr->name) . ', ' . $dim . ', ' . $value . ')';
return $this->emitDynamicPropertyUpdateArray(
$this->parseIdentifier($expr->var),
$this->identifierToStr($expr->name, literal: true),
$dim,
$value
);
}
protected function emitDynamicPropertyAppendArray(string $object, string $property, string $value): string
{
return "{$object}.attr({$property}, true).newItem() = {$value}";
}
protected function emitDynamicPropertyUpdateArray(string $object, string $property, string $dim, string $value): string
{
return "{$object}.attr({$property}, true).item({$dim}, true) = {$value}";
}
protected function assertDynamicPropertyTarget(PropertyWriteTarget $target): void
@ -6417,7 +6448,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
$finally = $v->finally;
$exVar = $this->genTmpVarName();
$this->addLocalVar($exVar, self::TYPE_OBJECT);
$this->addLocalVar($exVar, self::TYPE_VAR);
$code .= 'catch(zend_object *_ex) {' . PHP_EOL;
$code .= $this->getIndent() . $exVar . ' = php::catchException();' . PHP_EOL;
@ -6434,7 +6465,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
$code .= $this->parseStmts($finally->stmts);
$code .= PHP_EOL;
}
$code .= 'if (' . $exVar . ') {' . PHP_EOL . $this->getIndent() . 'php::throwException(' . $exVar . ');' . PHP_EOL . $this->getIndent() . '}';
$code .= 'if (' . $exVar . ') {' . PHP_EOL . $this->getIndent() . 'php::throwException(php::Object(' . $exVar . '));' . PHP_EOL . $this->getIndent() . '}';
return $code;
}
@ -6465,8 +6496,8 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
$code .= implode(' || ', $conditions);
$code .= ') {' . PHP_EOL;
$this->indentLevel++;
$code .= $this->getIndent() . "{$exVar} = php::null;" . PHP_EOL;
$code .= $this->parseStmts($catch->stmts);
$code .= $this->getIndent() . "{$exVar}.unset();" . PHP_EOL;
$this->indentLevel--;
$code .= $this->getIndent() . '}';

@ -0,0 +1,13 @@
--TEST--
exit(0) should terminate without fatal error
--ENV--
USE_ZEND_ALLOC=0
--FILE--
<?php
function main() {
exit(0);
echo "unreachable\n";
}
?>
--EXPECT--

@ -0,0 +1,16 @@
--TEST--
exit inside catch should not rethrow graceful exit as Throwable
--ENV--
USE_ZEND_ALLOC=0
--FILE--
<?php
try {
throw new RuntimeException('stop');
} catch (Throwable $e) {
exit(0);
}
echo "unreachable\n";
?>
--EXPECT--

@ -0,0 +1,34 @@
--TEST--
object property array append and keyed write use generic property path
--FILE--
<?php
class PropertyArrayWriteBox
{
public array $items = [];
public function append(mixed $value): void
{
$this->items[] = $value;
}
public function put(string $key, mixed $value): void
{
$this->items[$key] = $value;
}
}
function main() {
$box = new PropertyArrayWriteBox();
$box->append('first');
$box->put('lang', 'php');
var_dump($box->items);
}
?>
--EXPECT--
array(2) {
[0]=>
string(5) "first"
["lang"]=>
string(3) "php"
}

@ -3,6 +3,7 @@ SSA: int
--FILE--
<?php
function main(): void {
ini_set('precision', 17);
$a = 100;
$a += 3;
$a *= 232;
@ -15,4 +16,4 @@ function main(): void {
?>
--EXPECTF--
12
-9223372036854775797
9.2233720368547758E+18

@ -1,5 +1,11 @@
--TEST--
var convert chained on array element
--SKIPIF--
<?php
if (PHP_OS_FAMILY != 'Linux') {
echo "skip: only run on linux\n";
exit(0);
}
--FILE--
<?php
function stream_write_test(stream $stream) {
@ -8,7 +14,7 @@ function stream_write_test(stream $stream) {
function main()
{
$pair = stream_socket_pair(STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_TCP);
$pair = stream_socket_pair(AF_UNIX, STREAM_SOCK_STREAM, 0);
$pair[0]->toStream()->write('hello');
var_dump($pair[1]->toStream()->read(5));

Loading…
Cancel
Save