From c86059217d4898ebf7b9284170f57e82bca4b94c Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 23 Apr 2026 12:47:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E4=BC=98=E5=8C=96=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=B1=9E=E6=80=A7=E8=AE=BF=E9=97=AE=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 PropertyDef 实体类来管理属性定义 - 添加 OBJECT_PROP 常量用于标识对象属性 - 修复 findNativeProperty 方法中的参数传递问题 - 实现 native 属性类型的引用优化,提升 this_ 对象的属性访问性能 - 为整型和浮点型属性创建直接引用访问机制 - 改进属性查找逻辑,支持 nativePropertyDef 和 nativeClassDef 属性 - 在编译代码中添加对象属性引用声明,优化运行时性能 - 添加测试用例验证默认数组属性功能 --- src/Php/CompilerBase.php | 45 ++++++++++++++++++++++++----- src/Php/Context/FunctionContext.php | 2 ++ tests/aot/object_property/001.phpt | 25 ++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 tests/aot/object_property/001.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 6f5483d6..7152cd33 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -15,6 +15,7 @@ use PhpAot\Php\Entity\ConstantDef; use PhpAot\Php\Entity\FunctionDef; use PhpAot\Php\Entity\InterfaceDef; use PhpAot\Php\Entity\MethodDef; +use PhpAot\Php\Entity\PropertyDef; use PhpAot\Php\Exception\DynamicCall; use PhpAot\Php\Exception\PlaceHolder; use PhpAot\Php\Exception\Redo; @@ -75,6 +76,7 @@ class CompilerBase extends \PhpAot\Core\Translator public const string ANON_CLASS = '_anon_class_'; public const string STATIC_VAR = '_static_var_'; public const string GLOBAL_VAR = '_global_var_'; + public const string OBJECT_PROP = '_object_prop_'; public const string CLASS_MAP = 'class_map'; public const string FUNC_MAP = 'func_map'; public const string PROP_MAP = 'property_map'; @@ -3427,10 +3429,10 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->classDef->trait) { goto _dynamic_attr; } - $nativeProperty = $this->findNativeProperty($object, $propertyName, $this->class, $this->namespace); + $nativeProperty = $this->findNativeProperty($expr, $propertyName, $this->class, $this->namespace); } elseif ($this->isTypedObject($objectName)) { $className = $this->getObjectType($objectName); - $nativeProperty = $this->findNativeProperty($object, $propertyName, $className); + $nativeProperty = $this->findNativeProperty($expr, $propertyName, $className); } if ($nativeProperty) { $expr->setAttribute('nativeProperty', $nativeProperty); @@ -3446,7 +3448,27 @@ class CompilerBase extends \PhpAot\Core\Translator $object = $expr->var; $property = $expr->name; $id = $this->getPropertyIdentifier($expr, $object, $property); - return $this->parseIdentifier($object) . '.attr(' . $id . ', ' . $this->escapeBool($update) . ')'; + $objectVar = $this->parseIdentifier($object); + $getProperty = $objectVar . '.attr(' . $id . ', ' . $this->escapeBool($update) . ')'; + // 将属性设置为 native 类型的引用,以提高性能,仅适用于 this_ ,其他类型对象可能会在中间发生改变 + // TODO 分析对象是否为 SSA , 如果是 SSA 则可以将属性设置为引用 + if ($expr->hasAttribute('nativePropertyDef') and $this->nativeTypes and $objectVar === 'this_') { + /** + * @var $def PropertyDef + */ + $def = $expr->getAttribute('nativePropertyDef'); + if ($def->type === self::TYPE_INT or $def->type === self::TYPE_FLOAT) { + $propVar = self::OBJECT_PROP . $objectVar . self::NAMESPACE_SEPARATOR . $this->parseIdentifier($property); + if (!isset($this->context->objectProps[$propVar])) { + $this->context->objectProps[$propVar] = [ + 'type' => $def->type, + 'getter' => $getProperty, + ]; + } + return $propVar; + } + } + return $getProperty; } protected function parseAssignOpShiftRight(Expr\AssignOp\ShiftRight $node): string @@ -4240,7 +4262,8 @@ class CompilerBase extends \PhpAot\Core\Translator $findClass = $namespace . '\\' . $class; } $scope = $this->class ? ltrim($namespace . '\\' . $class, '\\') : ''; - + $propertyDef = null; + $classDef = null; while (true) { if ($this->hasClass($findClass)) { $classDef = $this->getClass($findClass); @@ -4251,16 +4274,16 @@ class CompilerBase extends \PhpAot\Core\Translator return null; } if ($propertyDef->isPublic()) { - return $this->getPropertyOffset($classDef->getNamespacedName(false), $property); + break; } if ($propertyDef->isProtected()) { if ($scope) { - return $this->getPropertyOffset($classDef->getNamespacedName(false), $property); + break; } $this->fatalError($expr, "Cannot access protected property `{$property}` of class `{$class}`"); } else { if ($scope === $findClass) { - return $this->getPropertyOffset($classDef->getNamespacedName(false), $property); + break; } $this->fatalError($expr, "Cannot access private property `{$property}` of class `{$class}`"); } @@ -4271,6 +4294,11 @@ class CompilerBase extends \PhpAot\Core\Translator } break; } + if ($propertyDef and $classDef) { + $expr->setAttribute('nativePropertyDef', $propertyDef); + $expr->setAttribute('nativeClassDef', $classDef); + return $this->getPropertyOffset($classDef->getNamespacedName(false), $property); + } return null; } @@ -4784,6 +4812,9 @@ class CompilerBase extends \PhpAot\Core\Translator foreach ($this->context->globalVars as $name => $type) { $code .= $this->getIndent() . self::TYPE_VAR . ' &' . $name . ' = ' . $this->escapeGlobalVar($name) . ';' . PHP_EOL; } + foreach ($this->context->objectProps as $name => $info) { + $code .= $this->getIndent() . $info['type'] . ' &' . $name . ' = Z_LVAL_P(' . $info['getter'] . '.unwrap_ptr());' . PHP_EOL; + } return $code; } diff --git a/src/Php/Context/FunctionContext.php b/src/Php/Context/FunctionContext.php index 5776f641..b1ec68d6 100644 --- a/src/Php/Context/FunctionContext.php +++ b/src/Php/Context/FunctionContext.php @@ -33,6 +33,7 @@ class FunctionContext public bool $inAssignExpr = false; public array $beforeStmtLines = []; public array $afterStmtLines = []; + public array $objectProps; public function __construct() { @@ -40,6 +41,7 @@ class FunctionContext $this->staticVars = []; $this->arguments = []; $this->objects = []; + $this->objectProps = []; $this->ceWrappers = []; $this->tmpVarIndex = 0; $this->inLoop = false; diff --git a/tests/aot/object_property/001.phpt b/tests/aot/object_property/001.phpt new file mode 100644 index 00000000..877f41fc --- /dev/null +++ b/tests/aot/object_property/001.phpt @@ -0,0 +1,25 @@ +--TEST-- +default array property +--FILE-- +x += $n; + } + var_dump($this->x); + } +} + +function main() { + $obj = new Test; + $obj->bar(); +} +?> +--EXPECT-- +int(76193440) \ No newline at end of file