refactor(Php): 优化字符串字面量处理和函数调用优化

- 提取字符串字面量处理逻辑到独立方法 getLiteralString
- 将 C++ 接口参数类型从 const char* 改为 const php::String&
- 修改字面量字符串数组类型从 php::Var 为 php::Str
- 添加 function_exists 函数调用的优化处理
- 更新头文件中的函数声明和内联函数参数类型
- 调整示例代码中的性能测试部分注释状态
pull/1/head
韩天峰 7 months ago
parent 5b44e4d390
commit 6dd8d2d6bc
  1. 136
      examples/micro_bench.php
  2. 25
      src/Php/CompilerBase.php
  3. 3
      src/Php/FuncCallOptimizer.php
  4. 2
      src/Php/Translator.php
  5. 12
      src/cpp/php_aot_helper.h
  6. 6
      src/template/extension.cc.php

@ -18,7 +18,7 @@ function hallo2() {
function simpleicall($n) {
for ($i = 0; $i < $n; $i++)
function_exists('hallo');
$ret = function_exists('hallo');
}
class Foo {
@ -287,74 +287,74 @@ function main()
empty_loop(N);
$t = end_test($t, 'empty_loop');
$overhead = $last_time;
simpleucall(N);
$t = end_test($t, 'func()', $overhead);
simpleudcall(N);
$t = end_test($t, 'undef_func()', $overhead);
// simpleucall(N);
// $t = end_test($t, 'func()', $overhead);
// simpleudcall(N);
// $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();
}

@ -607,11 +607,11 @@ class CompilerBase extends \PhpAot\Core\Translator
if (isset($this->classMap[$className])) {
$id = $this->classMap[$className];
} else {
$id = $this->classIndex++;
$id = $this->classIndex++;
$this->classMap[$className] = $id;
}
return 'php_get_class(' . $id . ', "' . $this->escapeString($className) . '")';
return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')';
}
protected function getFuncPtr(string $funcName): string
@ -622,7 +622,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$id = $this->funcIndex++;
$this->funcMap[$funcName] = $id;
}
return $id . ', "' . $this->escapeString($funcName) . '"';
return $id . ', ' . $this->getLiteralString($funcName);
}
protected function parseFunctionDeclaration(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef
@ -712,7 +712,16 @@ class CompilerBase extends \PhpAot\Core\Translator
}
}
protected function parseScalar(Node $expr)
protected function getLiteralString(string $string): string
{
if ($this->noLiteralStrings) {
return '"' . $this->escapeString($string) . '"';
}
$index = $this->literalStrings[$string] ?? $this->addLiteralString($string);
return self::LITERAL_STRINGS . '[' . $index . ']';
}
protected function parseScalar(Node\Scalar $expr)
{
$type = $expr->getType();
switch ($type) {
@ -721,13 +730,7 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Scalar_Float':
return $this->parseScalarFloat($expr);
case 'Scalar_String':
if ($this->noLiteralStrings) {
return '"' . $this->escapeString($expr->value) . '"';
}
$index = $this->literalStrings[$expr->value] ?? $this->addLiteralString($expr->value);
return self::LITERAL_STRINGS . '[' . $index . ']';
return $this->getLiteralString($expr->value);
default:
abort($expr);
}

@ -44,6 +44,9 @@ trait FuncCallOptimizer
if ($name === 'abs') {
return 'php::math::abs(' . $this->parseIdentifier($expr->args[0]->value) . ')';
}
if ($name === 'function_exists') {
return 'php::fn::function_exists(' . $this->parseIdentifier($expr->args[0]->value) . ')';
}
return false;
}

@ -197,7 +197,7 @@ class Translator extends Preprocessor
}
$literalStringsCount = count($this->literalStrings);
$lines[] = 'extern php::Var ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL;
$lines[] = 'extern ' . self::TYPE_STR . ' ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL;
$classCount = count($this->classMap);
$lines[] = 'extern zend_class_entry *' . self::PREFIX . self::CLASS_MAP . '[' . $classCount . '];' . PHP_EOL;

@ -1,20 +1,20 @@
#include <phpx.h>
extern zend_class_entry *php_get_class(int class_id, const char *class_name);
extern zend_function *php_get_func(int func_id, const char *func_name);
extern zend_class_entry *php_get_class(int class_id, const php::String &class_name);
extern zend_function *php_get_func(int func_id, const php::String &func_name);
static inline php::Variant CALL(int func_id, const char *func_name, const std::initializer_list<php::Variant> &args) {
static inline php::Variant CALL(int func_id, const php::String &func_name, const std::initializer_list<php::Variant> &args) {
return php::call(php_get_func(func_id, func_name), args);
}
static inline php::Variant CALL(int func_id, const char *func_name) {
static inline php::Variant CALL(int func_id, const php::String &func_name) {
return php::call(php_get_func(func_id, func_name));
}
static inline php::Variant CALL_SILENT(int func_id, const char *func_name, const std::initializer_list<php::Variant> &args) {
static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name, const std::initializer_list<php::Variant> &args) {
return php::silentCall(php_get_func(func_id, func_name), args);
}
static inline php::Variant CALL_SILENT(int func_id, const char *func_name) {
static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name) {
return php::silentCall(php_get_func(func_id, func_name));
}

@ -27,14 +27,14 @@ zend_class_entry *<?= Translator::PREFIX . Translator::CLASS_MAP . '[' . count($
// func
zend_function *<?= Translator::PREFIX . Translator::FUNC_MAP . '[' . count($this->funcMap) . ']' ?>;
zend_class_entry *php_get_class(int class_id, const char *class_name) {
zend_class_entry *php_get_class(int class_id, const php::String &class_name) {
if (UNEXPECTED(<?= Translator::PREFIX . Translator::CLASS_MAP ?>[class_id] == nullptr)) {
<?= Translator::PREFIX . Translator::CLASS_MAP ?>[class_id] = php::getClassEntrySafe(class_name);
}
return <?= Translator::PREFIX . Translator::CLASS_MAP ?>[class_id];
}
zend_function *php_get_func(int func_id, const char *func_name) {
zend_function *php_get_func(int func_id, const php::String &func_name) {
if (UNEXPECTED(<?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id] == nullptr)) {
<?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id] = php::getFunction(func_name);
}
@ -42,7 +42,7 @@ zend_function *php_get_func(int func_id, const char *func_name) {
}
// literal strings
php::Var <?=Translator::LITERAL_STRINGS?>[] = {
php::Str <?=Translator::LITERAL_STRINGS?>[] = {
<?php
foreach ($this->literalStrings as $str => $index):
?>

Loading…
Cancel
Save