From 87115456372738088443c522dc8adfedea30e120 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 1 Jul 2026 10:17:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor(php):=20=E9=87=8D=E6=9E=84=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E8=AE=BF=E9=97=AE=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=BB=A5=E6=8F=90=E9=AB=98=E4=BB=A3=E7=A0=81=E5=8F=AF=E8=AF=BB?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 提取实例属性获取逻辑到独立方法 resolveInstancePropertyFetchTarget - 提取静态属性获取逻辑到独立方法 resolveStaticPropertyFetchTarget - 添加 InstancePropertyFetchTarget 和 StaticPropertyFetchTarget 数据结构 - 优化原生实例属性获取的条件判断流程 - 简化原生静态属性获取的处理逻辑 - 提取静态属性引用注册逻辑到独立方法 registerStaticPropertyRef - 改进代码结构以提高可维护性和可测试性 --- src/Php/CompilerBase.php | 253 ++++++++++++++++++++++++--------------- 1 file changed, 158 insertions(+), 95 deletions(-) diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 8fe5987d..b45ea76b 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -43,12 +43,14 @@ use PhpAot\Php\Platform\Macos; use PhpAot\Php\Platform\PlatformBase; use PhpAot\Php\Platform\PlatformFactory; use PhpAot\Php\Platform\Windows; +use PhpAot\Php\Resolver\InstancePropertyFetchTarget; use PhpAot\Php\Resolver\PropertyAccessContext; use PhpAot\Php\Resolver\NativePropertyAccess; use PhpAot\Php\Resolver\PropertyAccessResult; use PhpAot\Php\Resolver\PropertyAccessResolver; use PhpAot\Php\Resolver\PropertyAssignTypeInfo; use PhpAot\Php\Resolver\StaticPropertyFetchResolution; +use PhpAot\Php\Resolver\StaticPropertyFetchTarget; use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\ArrayItem; @@ -4861,29 +4863,40 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont protected function getPropertyIdentifier(Expr\PropertyFetch $expr, NodeAbstract $object, NodeAbstract $property): ?string { - if ($this->isVarExpr($object) and $this->isIdExpr($property)) { - $objectName = $this->parseIdentifier($object); - $propertyName = $this->parseIdentifier($property); - $nativeProperty = null; - if ($objectName === 'this_') { - if ($this->classDef->trait) { - goto _dynamic_attr; - } - $result = $this->resolveNativeInstanceProperty($expr, $propertyName, $this->getFullClassName()); - $nativeProperty = $result ? $this->applyNativePropertyAccessResult($expr, $result) : null; - } elseif ($this->isTypedObject($objectName)) { - $className = $this->getObjectType($objectName); - $result = $this->resolveNativeInstanceProperty($expr, $propertyName, $className); - $nativeProperty = $result ? $this->applyNativePropertyAccessResult($expr, $result) : null; - } - if ($nativeProperty) { - return $nativeProperty; + $target = $this->resolveInstancePropertyFetchTarget($object, $property); + if ($target !== null) { + $result = $this->resolveNativeInstanceProperty($expr, $target->property, $target->class); + if ($result !== null) { + return $this->applyNativePropertyAccessResult($expr, $result); } } - _dynamic_attr: + return $this->identifierToStr($property, literal: true); } + private function resolveInstancePropertyFetchTarget( + NodeAbstract $object, + NodeAbstract $property, + ): ?InstancePropertyFetchTarget { + if (!$this->isVarExpr($object) or !$this->isIdExpr($property)) { + return null; + } + + $objectName = $this->parseIdentifier($object); + $propertyName = $this->parseIdentifier($property); + if ($objectName === 'this_') { + if ($this->classDef->trait) { + return null; + } + return new InstancePropertyFetchTarget($propertyName, $this->getFullClassName()); + } + if ($this->isTypedObject($objectName)) { + return new InstancePropertyFetchTarget($propertyName, $this->getObjectType($objectName)); + } + + return null; + } + protected function parsePropertyFetch(Expr\PropertyFetch $expr, bool $update = false): string { $object = $expr->var; @@ -4898,27 +4911,16 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont $def = $this->getNativePropertyDef($expr); if ($def and $this->nativeTypes) { $propName = $this->parseIdentifier($property); - $propVar = $this->getObjectPropVarName($objectVar, $propName); - if ($objectVar === 'this_') { - if ($this->canHoistObjectProp($objectVar, $propName)) { - if (!$this->hasObjectPropVar($propVar)) { - $info = $this->getHoistedObjectPropInfo($def->type); - $this->context->objectProps[$propVar] = [ - 'type' => $info['type'], - 'getter' => $getProperty, - 'kind' => $info['kind'], - ]; - } - $this->setNativePropertyVar($expr, $propVar); - $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); - return $propVar; - } - } elseif ($this->canHoistStableObjectProp($objectVar, $propName)) { - // SSA-stable object: lazily create reference at first access point - $result = $this->hoistStableObjectProp($objectVar, $propName, $id, $def->type); - $this->setNativePropertyVar($expr, $result); - $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); - return $result; + $typedFetch = $this->emitNativeInstancePropertyTypedFetch( + $expr, + $objectVar, + $propName, + $id, + $def, + $getProperty, + ); + if ($typedFetch !== null) { + return $typedFetch; } } if ($def) { @@ -4927,6 +4929,43 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return $getProperty; } + private function emitNativeInstancePropertyTypedFetch( + Expr\PropertyFetch $expr, + string $objectVar, + string $propName, + string $propertyId, + PropertyDef $def, + string $getter, + ): ?string { + $propVar = $this->getObjectPropVarName($objectVar, $propName); + if ($objectVar === 'this_') { + if (!$this->canHoistObjectProp($objectVar, $propName)) { + return null; + } + if (!$this->hasObjectPropVar($propVar)) { + $info = $this->getHoistedObjectPropInfo($def->type); + $this->context->objectProps[$propVar] = [ + 'type' => $info['type'], + 'getter' => $getter, + 'kind' => $info['kind'], + ]; + } + $this->setNativePropertyVar($expr, $propVar); + $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); + return $propVar; + } + + if (!$this->canHoistStableObjectProp($objectVar, $propName)) { + return null; + } + + // SSA-stable object: lazily create reference at first access point. + $result = $this->hoistStableObjectProp($objectVar, $propName, $propertyId, $def->type); + $this->setNativePropertyVar($expr, $result); + $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); + return $result; + } + protected function parseMagicConst(MagicConst $expr): string { $class = ($this->namespace ? $this->namespace . '\\' : '') . $this->class; @@ -5785,33 +5824,51 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont protected function resolveNativeStaticPropertyFetch(Expr\StaticPropertyFetch $expr): ?StaticPropertyFetchResolution { - if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) { - $class = $this->parseIdentifier($expr->class); - $propertyName = $this->parseIdentifier($expr->name); - if ($class === 'static') { - return null; - } - if ($class === 'self') { - if ($this->classDef->trait) { - $expression = Symbol::getStaticProperty() . '(' . Symbol::getCalledCe() . ', ' . $this->getLiteralString($propertyName) . ')'; - return new StaticPropertyFetchResolution(null, $expression, false); - } - $class = $this->getFullClassName(); - } elseif ($class === 'parent') { - if (!$this->classDef->extends) { - $this->fatalError($expr, 'Cannot access parent:: when current class does not extend any class'); - } - $class = $this->classDef->extends; - } else { - $class = $this->getNamespacedClassName($class); + $target = $this->resolveStaticPropertyFetchTarget($expr); + if ($target === null) { + return null; + } + if ($target->isDynamic()) { + return new StaticPropertyFetchResolution(null, $target->dynamicExpression, false); + } + $class = $target->class; + if ($class === null) { + return null; + } + $result = $this->resolveNativeStaticProperty($expr, $target->property, $class); + if ($result !== null) { + $expression = $this->applyNativePropertyAccessResult($expr, $result); + return new StaticPropertyFetchResolution($class, $expression, true); + } + return null; + } + + private function resolveStaticPropertyFetchTarget(Expr\StaticPropertyFetch $expr): ?StaticPropertyFetchTarget + { + if (!$this->isNameExpr($expr->class) or !$this->isIdExpr($expr->name)) { + return null; + } + + $class = $this->parseIdentifier($expr->class); + $propertyName = $this->parseIdentifier($expr->name); + if ($class === 'static') { + return null; + } + if ($class === 'self') { + if ($this->classDef->trait) { + $expression = Symbol::getStaticProperty() . '(' . Symbol::getCalledCe() . ', ' . $this->getLiteralString($propertyName) . ')'; + return new StaticPropertyFetchTarget($propertyName, null, $expression); } - $result = $this->resolveNativeStaticProperty($expr, $propertyName, $class); - if ($result !== null) { - $expression = $this->applyNativePropertyAccessResult($expr, $result); - return new StaticPropertyFetchResolution($class, $expression, true); + return new StaticPropertyFetchTarget($propertyName, $this->getFullClassName(), null); + } + if ($class === 'parent') { + if (!$this->classDef->extends) { + $this->fatalError($expr, 'Cannot access parent:: when current class does not extend any class'); } + return new StaticPropertyFetchTarget($propertyName, $this->classDef->extends, null); } - return null; + + return new StaticPropertyFetchTarget($propertyName, $this->getNamespacedClassName($class), null); } private function createPropertyAccessResolver(): PropertyAccessResolver @@ -5902,41 +5959,14 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont if ($resolution !== null) { $nativeProp = $resolution->expression; $def = $this->getNativePropertyDef($expr); - if ($this->nativeTypes && $def && $resolution->class !== null) { - $info = $this->getHoistedObjectPropInfo($def->type); - $propName = $this->parseIdentifier($expr->name); - $refVar = '_static_' . str_replace('\\', '_', $resolution->class) . '_' . $propName; - - if ($info['kind'] === 'zval') { - if (!isset($this->context->staticPropRefs[$refVar])) { - $classPtr = $this->getClassEntryPtr($resolution->class); - $this->context->staticPropRefs[$refVar] = [ - 'type' => $info['type'], - 'classPtr' => $classPtr, - 'offsetExpr' => $nativeProp, - 'kind' => $info['kind'], - ]; - } - $helper = $def->type === self::TYPE_FLOAT ? 'php_aot_static_float_ref' : 'php_aot_static_int_ref'; - $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); - return $helper . '(' . $refVar . ')'; - } - - if (!isset($this->context->staticPropRefs[$refVar])) { - $classPtr = $this->getClassEntryPtr($resolution->class); - $this->context->staticPropRefs[$refVar] = [ - 'type' => $info['type'], - 'classPtr' => $classPtr, - 'offsetExpr' => $nativeProp, - 'kind' => $info['kind'], - ]; - } + $class = $resolution->class; + if ($this->nativeTypes && $def && $class !== null) { $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_VAR); - return $refVar; + return $this->emitNativeStaticPropertyTypedFetch($expr, $class, $def, $nativeProp); } - if ($resolution->nativeProperty && $resolution->class !== null) { - $classPtr = $this->getClassEntryPtr($resolution->class); + if ($resolution->nativeProperty && $class !== null) { + $classPtr = $this->getClassEntryPtr($class); $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_DYNAMIC); return Symbol::getStaticProperty() . '(' . $classPtr . ', ' . $nativeProp . ')'; } else { @@ -5947,6 +5977,39 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont return null; } + private function emitNativeStaticPropertyTypedFetch( + Expr\StaticPropertyFetch $expr, + string $class, + PropertyDef $def, + string $nativeProp, + ): string { + $info = $this->getHoistedObjectPropInfo($def->type); + $propName = $this->parseIdentifier($expr->name); + $refVar = '_static_' . str_replace('\\', '_', $class) . '_' . $propName; + $this->registerStaticPropertyRef($refVar, $class, $nativeProp, $info); + + if ($info['kind'] === 'zval') { + $helper = $def->type === self::TYPE_FLOAT ? 'php_aot_static_float_ref' : 'php_aot_static_int_ref'; + return $helper . '(' . $refVar . ')'; + } + + return $refVar; + } + + private function registerStaticPropertyRef(string $refVar, string $class, string $offsetExpr, array $info): void + { + if (isset($this->context->staticPropRefs[$refVar])) { + return; + } + + $this->context->staticPropRefs[$refVar] = [ + 'type' => $info['type'], + 'classPtr' => $this->getClassEntryPtr($class), + 'offsetExpr' => $offsetExpr, + 'kind' => $info['kind'], + ]; + } + protected function parseStaticPropertyFetch(Expr\StaticPropertyFetch $expr): string { $native = $this->parseNativeStaticPropertyFetch($expr);