refactor(php): 重构编译器基础类中的类和函数指针获取方法

- 将 getClassEntryPtr 方法重命名为 getClassId 并修改返回值为整数ID
- 将 getFuncPtr 方法重命名为 getFuncId 并修改返回值为整数ID
- 添加新的 getMethodPtr 方法用于获取方法指针
- 重新实现 getClassEntryPtr 和 getFuncPtr 方法,基于新的ID获取方法
- 更新方法调用逻辑以使用新的方法指针机制
- 在C++模板中添加 php_get_method 函数实现
- 更新PHP AOT辅助头文件中的函数声明
- 优化Reflection类中的反射异常处理和参数类型引用
pull/1/head
韩天峰 7 months ago
parent 257616d571
commit 9c51551567
  1. 41
      src/Php/CompilerBase.php
  2. 20
      src/Php/Reflection.php
  3. 13
      src/cpp/php_aot_helper.h
  4. 8
      src/template/extension.cc.php
  5. 10
      tests/aot/method-call.phpt

@ -649,7 +649,7 @@ class CompilerBase extends \PhpAot\Core\Translator
return implode(self::NAMESPACE_SEPARATOR, array_reverse($names));
}
protected function getClassEntryPtr(string $className): string
protected function getClassId(string $className): int
{
if (isset($this->classMap[$className])) {
$id = $this->classMap[$className];
@ -657,11 +657,10 @@ class CompilerBase extends \PhpAot\Core\Translator
$id = $this->classIndex++;
$this->classMap[$className] = $id;
}
return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')';
return $id;
}
protected function getFuncPtr(string $funcName, bool $macro = true): string
protected function getFuncId($funcName): int
{
if (isset($this->funcMap[$funcName])) {
$id = $this->funcMap[$funcName];
@ -669,12 +668,31 @@ class CompilerBase extends \PhpAot\Core\Translator
$id = $this->funcIndex++;
$this->funcMap[$funcName] = $id;
}
return $id;
}
protected function getClassEntryPtr(string $className): string
{
$id = $this->getClassId($className);
return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')';
}
protected function getFuncPtr(string $funcName, bool $macro = true): string
{
$id = $this->getFuncId($funcName);
if ($macro) {
return $id . ', ' . $this->getLiteralString($funcName);
}
return 'php_get_func(' . $id . ', ' . $this->getLiteralString($funcName) . ')';
}
protected function getMethodPtr(string $class, string $method): string
{
$funcId = $this->getFuncId($class . '::' . $method);
$classId = $this->getClassId($class);
return 'php_get_method(' . $funcId . ', ' . $this->getLiteralString($method) . ', ' . $classId . ', ' . $this->getLiteralString($class) . ')';
}
protected function parseFunctionDeclaration(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef
{
// .stub 存根定义 C++ Native 函数,必须设置返回值类型
@ -3122,20 +3140,27 @@ class CompilerBase extends \PhpAot\Core\Translator
} else {
$class = '';
}
$method = $this->identifierToStr($expr->name);
$nativeFunc = $this->findNativeMethod($expr, $object, $method);
if ($nativeFunc) {
return $this->parseNativeMethodCall($object, $nativeFunc, $expr->args);
}
if (empty($expr->args)) {
return $object . '.exec(' . $method . ')';
}
if ($this->isNamedMethod($expr->name)) {
$funcName = $this->parseIdentifier($expr->name);
} else {
$funcName = '';
}
return $object . '.exec(' . $method . ', ' . $this->parseCallArgs($expr->args, $funcName, $class) . ')';
if ($class and $funcName) {
$method = $this->getMethodPtr($class, $funcName);
}
if (empty($expr->args)) {
return $object . '.exec(' . $method . ')';
}
return $object . '.exec(' . $method . ', {' . $this->parseCallArgs($expr->args, $funcName, $class) . '})';
}
protected function identifierToStr(NodeAbstract $node, bool $require = true): string

@ -9,7 +9,10 @@
namespace PhpAot\Php;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionParameter;
use ReflectionUnionType;
class Reflection
{
@ -21,7 +24,7 @@ class Reflection
if (!isset(self::$functions[$fn])) {
try {
$ref = new ReflectionFunction($fn);
} catch (\ReflectionException $e) {
} catch (ReflectionException $e) {
return null;
}
self::$functions[$fn] = $ref;
@ -35,7 +38,7 @@ class Reflection
if (!isset(self::$classes[$className])) {
try {
$ref = new ReflectionClass($className);
} catch (\ReflectionException $e) {
} catch (ReflectionException $e) {
return null;
}
self::$classes[$className] = $ref;
@ -54,14 +57,14 @@ class Reflection
if (!$returnType) {
return null;
}
if ($returnType instanceof \ReflectionUnionType) {
if ($returnType instanceof ReflectionUnionType) {
return null;
}
return $returnType->getName();
}
public static function getFunctionParameter(string $fn, int $index): ?\ReflectionParameter
public static function getFunctionParameter(string $fn, int $index): ?ReflectionParameter
{
$func = self::getFunction($fn);
if (!$func) {
@ -75,16 +78,19 @@ class Reflection
return $args[$index];
}
public static function getClassMethodParameter(string $className, string $fn, int $index): ?\ReflectionParameter
public static function getClassMethodParameter(string $className, string $fn, int $index): ?ReflectionParameter
{
$classRef = self::getClass($className);
if (!$classRef) {
return null;
}
$method = $classRef->getMethod($fn);
if (!$method) {
try {
$method = $classRef->getMethod($fn);
} catch (ReflectionException $e) {
return null;
}
$args = $method->getParameters();
if ($index >= count($args)) {
return null;

@ -1,20 +1,21 @@
#include <phpx.h>
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);
extern zend_class_entry *php_get_class(int class_id, const php::Str &class_name);
extern zend_function *php_get_func(int func_id, const php::Str &func_name);
extern zend_function *php_get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name);
static inline php::Variant CALL(int func_id, const php::String &func_name, const php::ArgList &args) {
static inline php::Variant CALL(int func_id, const php::Str &func_name, const php::ArgList &args) {
return php::call(php_get_func(func_id, func_name), args);
}
static inline php::Variant CALL(int func_id, const php::String &func_name) {
static inline php::Variant CALL(int func_id, const php::Str &func_name) {
return php::call(php_get_func(func_id, func_name));
}
static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name, const php::ArgList &args) {
static inline php::Variant CALL_SILENT(int func_id, const php::Str &func_name, const php::ArgList &args) {
return php::silentCall(php_get_func(func_id, func_name), args);
}
static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name) {
static inline php::Variant CALL_SILENT(int func_id, const php::Str &func_name) {
return php::silentCall(php_get_func(func_id, func_name));
}

@ -41,6 +41,14 @@ zend_function *php_get_func(int func_id, const php::String &func_name) {
return <?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id];
}
zend_function *php_get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name) {
if (UNEXPECTED(<?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id] == nullptr)) {
auto ce = php_get_class(class_id, class_name);
<?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id] = php::getMethod(ce, method_name);
}
return <?= Translator::PREFIX . Translator::FUNC_MAP ?>[func_id];
}
// literal strings
php::Str <?=Translator::LITERAL_STRINGS?>[] = {
<?php

@ -0,0 +1,10 @@
--TEST--
method call
--FILE--
<?php
$date = new DateTime('2000-01-01');
$rs = $date->format('Y-m-d H:i:s');
var_dump($rs);
?>
--EXPECT--
string(19) "2000-01-01 00:00:00"
Loading…
Cancel
Save