diff --git a/lib/JIT/IssetHelper.php b/lib/JIT/IssetHelper.php index acedc81d170..63f29b3cd71 100644 --- a/lib/JIT/IssetHelper.php +++ b/lib/JIT/IssetHelper.php @@ -184,6 +184,19 @@ private static function hashtableFromObjectContainer( return $context->type->object->splBackingHashtable($container); } if (null !== $container->objectPropertySlot) { + if (Variable::TYPE_HASHTABLE === $container->objectPropertyType) { + $htPtr = $context->builder->pointerCast( + $context->builder->load($container->objectPropertySlot), + $context->getTypeFromString('__hashtable__*') + ); + + return new Variable( + $context, + Variable::TYPE_HASHTABLE, + Variable::KIND_VALUE, + $htPtr + ); + } $valueType = $context->getTypeFromString('__value__'); $storage = $context->builder->alloca($valueType, 1, 'isset_obj_prop'); $valueMap = $context->structFieldMap['__value__']; diff --git a/lib/JIT/Variable.php b/lib/JIT/Variable.php index da844136ac3..9200508139e 100755 --- a/lib/JIT/Variable.php +++ b/lib/JIT/Variable.php @@ -433,6 +433,7 @@ public function free(): void { ? $this->value : $this->context->helper->loadValue($this); $this->context->refcount->delref($ptr); + return; } throw new \LogicException('Unknown free type: ' . $this->type); @@ -453,6 +454,12 @@ public function initialize(): void { $this->value ); break; + case self::TYPE_HASHTABLE: + $this->context->builder->store( + $this->context->getTypeFromString('__hashtable__*')->constNull(), + $this->value + ); + break; case self::TYPE_VALUE: case self::TYPE_NULL: $map = $this->context->structFieldMap['__value__']; @@ -489,10 +496,11 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = case self::TYPE_HASHTABLE: // Property slots own the hashtable; transient delref would free it (#58). $propertyBacked = null !== $this->objectPropertySlot; + $container = HashTableHelper::asDetachedHashtable($this->context, $this); if ( !$forWrite - && null !== $this->superglobalName - && '_FILES' !== $this->superglobalName + && null !== $container->superglobalName + && '_FILES' !== $container->superglobalName && self::TYPE_STRING === $dim->type && (null === $expectedType || Type::TYPE_ARRAY !== $expectedType->type) ) { @@ -502,7 +510,7 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = ? null : SuperglobalInit::compileTimeReadString( $this->context, - $this->superglobalName, + $container->superglobalName, $key ); if (null !== $baked) { @@ -513,7 +521,7 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = $baked ); } - $ht = $this->context->helper->loadValue($this); + $ht = $this->context->helper->loadValue($container); $keyVal = $this->context->helper->loadValue($dim); return HashTableHelper::readSuperglobalStringKeyToValueBox( @@ -523,7 +531,7 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = ); } } - $ht = $this->context->helper->loadValue($this); + $ht = $this->context->helper->loadValue($container); if (self::TYPE_VALUE === $dim->type || self::TYPE_OBJECT === $dim->type) { $keyObj = self::TYPE_OBJECT === $dim->type ? $this->context->helper->loadValue($dim) @@ -548,7 +556,7 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = return HashTableHelper::writableStringKeyValueBox($this->context, $ht, $key); } - if ('_FILES' === $this->superglobalName && !$forWrite) { + if ('_FILES' === $container->superglobalName && !$forWrite) { $childHt = $this->context->builder->call( $this->context->lookupFunction('__hashtable__readStringKeyHashtable'), $ht, @@ -608,7 +616,7 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = $this->context->lookupFunction('__string__separate'), $str ); - if (!$propertyBacked && null === $this->superglobalName) { + if (!$propertyBacked && null === $container->superglobalName) { $this->context->refcount->delref($ht); } @@ -619,11 +627,11 @@ public function dimFetch(self $dim, ?Type $expectedType = null, bool $forWrite = $owned ); } - if (null === $this->superglobalName) { + if (!$propertyBacked && null === $container->superglobalName) { $this->context->refcount->addref($ht); } $boxed = HashTableHelper::readIndexedToValueBox($this->context, $ht, $index); - if (null === $this->superglobalName) { + if (!$propertyBacked && null === $container->superglobalName) { $this->context->refcount->delref($ht); }