feat(aot): 添加对全局变量和Stmt_Block语句块的支持

- 在CompilerBase中添加Stmt_Block解析支持
- 新增global-int测试用例验证全局变量整型操作
- 新增globals-null-arithmetic测试用例处理NULL全局变量算术运算
- 修复switch语句缩进格式问题
- 初始化micro_bench中last_time变量
- 注释掉部分性能测试以聚焦核心功能
pull/1/head
韩天峰 3 months ago
parent 48a8ddd8b5
commit 9eec3e7483
  1. 159
      examples/micro_bench.php
  2. 3
      src/Php/CompilerBase.php
  3. 51
      tests/aot/basic/global-int.phpt
  4. 71
      tests/aot/place-holder/globals-null-arithmetic.phpt
  5. 18
      tests/aot/switch/001.phpt

@ -258,22 +258,22 @@ function start_test()
function end_test($start, $name, $overhead = null) function end_test($start, $name, $overhead = null)
{ {
global $total; global $total;
global $last_time; global $last_time;
$end = gethrtime(); $end = gethrtime();
ob_end_clean(); ob_end_clean();
$last_time = $end-$start; $last_time = $end - $start;
$total += $last_time; $total += $last_time;
$num = number_format($last_time,3); $num = number_format($last_time, 3);
$pad = str_repeat(" ", 24-strlen($name)-strlen($num)); $pad = str_repeat(" ", 24 - strlen($name) - strlen($num));
if (is_null($overhead)) { if (is_null($overhead)) {
echo $name.$pad.$num."\n"; echo $name . $pad . $num . "\n";
} else { } else {
$num2 = number_format($last_time - $overhead,3); $num2 = number_format($last_time - $overhead, 3);
echo $name.$pad.$num." ".$num2."\n"; echo $name . $pad . $num . " " . $num2 . "\n";
} }
ob_start(); ob_start();
return gethrtime(); return gethrtime();
} }
function total() function total()
@ -294,6 +294,7 @@ function main()
{ {
global $total, $last_time, $g_var; global $total, $last_time, $g_var;
$g_var = 0; $g_var = 0;
$last_time = 0;
$t0 = $t = start_test(); $t0 = $t = start_test();
empty_loop(N); empty_loop(N);
$t = end_test($t, 'empty_loop'); $t = end_test($t, 'empty_loop');
@ -304,68 +305,68 @@ function main()
$t = end_test($t, 'undef_func()', $overhead); $t = end_test($t, 'undef_func()', $overhead);
simpleicall(N); simpleicall(N);
$t = end_test($t, 'int_func()', $overhead); $t = end_test($t, 'int_func()', $overhead);
Foo::read_static(N); // Foo::read_static(N);
$t = end_test($t, '$x = self::$x', $overhead); // $t = end_test($t, '$x = self::$x', $overhead);
Foo::write_static(N); // Foo::write_static(N);
$t = end_test($t, 'self::$x = 0', $overhead); // $t = end_test($t, 'self::$x = 0', $overhead);
Foo::isset_static(N); // Foo::isset_static(N);
$t = end_test($t, 'isset(self::$x)', $overhead); // $t = end_test($t, 'isset(self::$x)', $overhead);
Foo::empty_static(N); // Foo::empty_static(N);
$t = end_test($t, 'empty(self::$x)', $overhead); // $t = end_test($t, 'empty(self::$x)', $overhead);
read_static(N); // read_static(N);
$t = end_test($t, '$x = Foo::$x', $overhead); // $t = end_test($t, '$x = Foo::$x', $overhead);
write_static(N); // write_static(N);
$t = end_test($t, 'Foo::$x = 0', $overhead); // $t = end_test($t, 'Foo::$x = 0', $overhead);
isset_static(N); // isset_static(N);
$t = end_test($t, 'isset(Foo::$x)', $overhead); // $t = end_test($t, 'isset(Foo::$x)', $overhead);
empty_static(N); // empty_static(N);
$t = end_test($t, 'empty(Foo::$x)', $overhead); // $t = end_test($t, 'empty(Foo::$x)', $overhead);
Foo::call_static(N); // Foo::call_static(N);
$t = end_test($t, 'self::f()', $overhead); // $t = end_test($t, 'self::f()', $overhead);
call_static(N); // call_static(N);
$t = end_test($t, 'Foo::f()', $overhead); // $t = end_test($t, 'Foo::f()', $overhead);
$x = new Foo(); // $x = new Foo();
$x->read_prop(N); // $x->read_prop(N);
$t = end_test($t, '$x = $this->x', $overhead); // $t = end_test($t, '$x = $this->x', $overhead);
$x->write_prop(N); // $x->write_prop(N);
$t = end_test($t, '$this->x = 0', $overhead); // $t = end_test($t, '$this->x = 0', $overhead);
$x->assign_add_prop(N); // $x->assign_add_prop(N);
$t = end_test($t, '$this->x += 2', $overhead); // $t = end_test($t, '$this->x += 2', $overhead);
$x->pre_inc_prop(N); // $x->pre_inc_prop(N);
$t = end_test($t, '++$this->x', $overhead); // $t = end_test($t, '++$this->x', $overhead);
$x->pre_dec_prop(N); // $x->pre_dec_prop(N);
$t = end_test($t, '--$this->x', $overhead); // $t = end_test($t, '--$this->x', $overhead);
$x->post_inc_prop(N); // $x->post_inc_prop(N);
$t = end_test($t, '$this->x++', $overhead); // $t = end_test($t, '$this->x++', $overhead);
$x->post_dec_prop(N); // $x->post_dec_prop(N);
$t = end_test($t, '$this->x--', $overhead); // $t = end_test($t, '$this->x--', $overhead);
$x->isset_prop(N); // $x->isset_prop(N);
$t = end_test($t, 'isset($this->x)', $overhead); // $t = end_test($t, 'isset($this->x)', $overhead);
$x->empty_prop(N); // $x->empty_prop(N);
$t = end_test($t, 'empty($this->x)', $overhead); // $t = end_test($t, 'empty($this->x)', $overhead);
$x->call(N); // $x->call(N);
$t = end_test($t, '$this->f()', $overhead); // $t = end_test($t, '$this->f()', $overhead);
$x->read_const(N); // $x->read_const(N);
$t = end_test($t, '$x = Foo::TEST', $overhead); // $t = end_test($t, '$x = Foo::TEST', $overhead);
create_object(N); // create_object(N);
$t = end_test($t, 'new Foo()', $overhead); // $t = end_test($t, 'new Foo()', $overhead);
read_const(N); // read_const(N);
$t = end_test($t, '$x = TEST', $overhead); // $t = end_test($t, '$x = TEST', $overhead);
read_auto_global(N); // read_auto_global(N);
$t = end_test($t, '$x = $_GET', $overhead); // $t = end_test($t, '$x = $_GET', $overhead);
read_global_var(N); // read_global_var(N);
$t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead); // $t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead);
read_hash(N); // read_hash(N);
$t = end_test($t, '$x = $hash[\'v\']', $overhead); // $t = end_test($t, '$x = $hash[\'v\']', $overhead);
read_str_offset(N); // read_str_offset(N);
$t = end_test($t, '$x = $str[0]', $overhead); // $t = end_test($t, '$x = $str[0]', $overhead);
issetor(N); // issetor(N);
$t = end_test($t, '$x = $a ?: null', $overhead); // $t = end_test($t, '$x = $a ?: null', $overhead);
issetor2(N); // issetor2(N);
$t = end_test($t, '$x = $f ?: tmp', $overhead); // $t = end_test($t, '$x = $f ?: tmp', $overhead);
ternary(N); // ternary(N);
$t = end_test($t, '$x = $f ? $f : $a', $overhead); // $t = end_test($t, '$x = $f ? $f : $a', $overhead);
ternary2(N); // ternary2(N);
$t = end_test($t, '$x = $f ? $f : tmp', $overhead); // $t = end_test($t, '$x = $f ? $f : tmp', $overhead);
total(); total();
} }

@ -1505,6 +1505,9 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Stmt_TryCatch': case 'Stmt_TryCatch':
$result = $this->parseTryCatch($v); $result = $this->parseTryCatch($v);
break; break;
case 'Stmt_Block':
$result = $this->parseStmts($v->stmts);
break;
case 'Stmt_Class': case 'Stmt_Class':
$this->fatalError($v, 'Cannot declare class in function'); $this->fatalError($v, 'Cannot declare class in function');
break; break;

@ -0,0 +1,51 @@
--TEST--
global vars with native types
--FILE--
<?php
use native_types;
function increment_global_int(int $n): void {
global $global_int;
for ($i = 0; $i < $n; $i++) {
$global_int += 1;
}
}
function increment_global_float(float $v): void {
global $global_float;
$global_float += $v;
}
function read_global_int(): int {
global $global_int;
return $global_int;
}
function read_global_float(): float {
global $global_float;
return $global_float;
}
function main(): void {
global $global_int, $global_float;
$global_int = 0;
$global_float = 0.0;
increment_global_int(5);
var_dump(read_global_int());
increment_global_int(3);
var_dump(read_global_int());
increment_global_float(1.5);
var_dump(read_global_float());
increment_global_float(2.25);
var_dump(read_global_float());
}
?>
--EXPECT--
int(5)
int(8)
float(1.5)
float(3.75)

@ -0,0 +1,71 @@
--TEST--
NULL globals in arithmetic should treat NULL as 0
--FILE--
<?php
declare(strict_types=1);
// Test 1: NULL global += float
function test_global_add() {
global $a;
$a += 0.575;
var_dump($a);
}
// Test 2: NULL global = float
function test_global_assign() {
global $b;
$b = 0.575;
var_dump($b);
}
// Test 3: Read NULL global, use in subtraction
function test_null_subtraction() {
global $c;
var_dump($c - 0.5); // NULL - float, NULL should be treated as 0
}
// Test 4: NULL global += int
function test_add_int() {
global $d;
$d += 5;
var_dump($d);
}
// Test 5: Full micro_bench simulation
function test_bench_sim() {
global $total, $last_time;
// First "end_test" call
$last_time = 0.575;
$total += $last_time;
var_dump($total);
var_dump($last_time);
// Read overhead
$overhead = $last_time;
// Second "end_test" call
$last_time = 0.014;
$total += $last_time;
$adjusted = $last_time - $overhead;
var_dump($total);
var_dump($adjusted);
}
function main(): void {
test_global_add();
test_global_assign();
test_null_subtraction();
test_add_int();
test_bench_sim();
}
?>
--EXPECT--
float(0.575)
float(0.575)
float(-0.5)
int(5)
float(0.575)
float(0.575)
float(0.589)
float(-0.5609999999999999)

@ -4,17 +4,17 @@ switch
<?php <?php
function test($value) { function test($value) {
switch ($value) { switch ($value) {
case 100: case 100:
echo "gt 100\n"; echo "gt 100\n";
break; break;
case 88: { case 88: {
echo "gt 88\n"; echo "gt 88\n";
break; break;
} }
default: default:
echo "default\n"; echo "default\n";
break; break;
} }
} }
function main() function main()
{ {

Loading…
Cancel
Save