feat(compiler): 优化对象属性访问性能

- 引入 PropertyDef 实体类来管理属性定义
- 添加 OBJECT_PROP 常量用于标识对象属性
- 修复 findNativeProperty 方法中的参数传递问题
- 实现 native 属性类型的引用优化,提升 this_ 对象的属性访问性能
- 为整型和浮点型属性创建直接引用访问机制
- 改进属性查找逻辑,支持 nativePropertyDef 和 nativeClassDef 属性
- 在编译代码中添加对象属性引用声明,优化运行时性能
- 添加测试用例验证默认数组属性功能
pull/1/head
韩天峰 4 months ago
parent 12ff420d87
commit c86059217d
  1. 45
      src/Php/CompilerBase.php
  2. 2
      src/Php/Context/FunctionContext.php
  3. 25
      tests/aot/object_property/001.phpt

@ -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;
}

@ -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;

@ -0,0 +1,25 @@
--TEST--
default array property
--FILE--
<?php
use native_types;
class Test {
protected int $x = 100;
function bar() {
$n = 12345;
while($n--) {
$this->x += $n;
}
var_dump($this->x);
}
}
function main() {
$obj = new Test;
$obj->bar();
}
?>
--EXPECT--
int(76193440)
Loading…
Cancel
Save