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

@ -1505,6 +1505,9 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Stmt_TryCatch':
$result = $this->parseTryCatch($v);
break;
case 'Stmt_Block':
$result = $this->parseStmts($v->stmts);
break;
case 'Stmt_Class':
$this->fatalError($v, 'Cannot declare class in function');
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
function test($value) {
switch ($value) {
case 100:
echo "gt 100\n";
break;
case 88: {
echo "gt 88\n";
break;
}
default:
case 100:
echo "gt 100\n";
break;
case 88: {
echo "gt 88\n";
break;
}
default:
echo "default\n";
break;
}
}
}
function main()
{

Loading…
Cancel
Save