Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/JIT/Builtin/StringTriggerError.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
* Do not re-add empty always-on shells in {@see Type} — leftover decls mint
* trigger_error.1 / undefined_array_key_warning_*.1 (#31894 / #32122 / #33234 / #33249).
* Context ensureMinimal no longer eagerly links this (#34641); ensureFull likewise
* (#35073). Type::register always-on declare+ensureLinked removed (#35392) —
* {@see Type\HashTable::implement} declares/ensures at entry; call sites /
* AssertFail::ensureLinked ensure before lookup.
* (#35073). Type::register always-on declare+ensureLinked removed (#35392).
* HashTable::implement entry ensure removed (#35648) — only readStringKeyValue +
* HashTableReadLlvm / call sites ensure before lookup; AssertFail::ensureLinked
* still covers assert paths.
* {@see JitTriggerErrorKernel::declareTriggerErrorAbi} before SilenceRuntime NestedJIT (#33253).
*/
final class StringTriggerError
Expand Down
20 changes: 10 additions & 10 deletions lib/JIT/Builtin/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -600,16 +600,16 @@ public function register(): void {
// __compiler_undefined_array_key_warning_cstr / _long always-on shells removed
// (#33249): StringTriggerError / JitTriggerErrorKernel owns the ABIs
// (getNamedFunction first via declareUndefinedArrayKeyAbis / implementUndefKey*Bridge).
// Type::register always-on declare+ensureLinked removed (#35392): HashTable::implement
// declares/ensures at entry; HashTableReadLlvm / call sites ensure before lookup
// (peer initialize #34513 / Context #34641 / #35073). SessionStartOptions NestedJIT
// moved to call-site (#33945). HELPER_RUNTIME_O=0 stays green via HashTable::implement
// + call-site ensure (#33248). Leftover Type NestedJIT vs Runtime ABI drift mint
// undefined_array_key_warning_*.1 (#31894 / #32122).
// Type::register always-on declare+ensureLinked removed (#35392): HashTable
// readStringKeyValue + HashTableReadLlvm / call sites ensure before lookup
// (#35648 lazy entry drop; peer initialize #34513 / Context #34641 / #35073).
// SessionStartOptions NestedJIT moved to call-site (#33945). HELPER_RUNTIME_O=0
// stays green via call-site ensure (#33248). Leftover Type NestedJIT vs Runtime
// ABI drift mint undefined_array_key_warning_*.1 (#31894 / #32122).
// __compiler_trigger_error always-on shell removed (#33234): StringTriggerError
// / JitTriggerErrorKernel owns the ABI (getNamedFunction first via
// implementTriggerErrorBridge). Type::register always-on ensureLinked removed
// (#35392 / peer #34513 initialize): HashTable::implement + AssertFail /
// (#35392 / peer #34513 initialize): HashTable::readStringKeyValue + AssertFail /
// trigger_error_ / JitBuiltinWarning / JitIncDec ensureLinked before lookup.
// Leftover Type NestedJIT vs Runtime ABI drift mint trigger_error.1
// (#31894 / #32122). User-script trigger_error()/user_error() stay
Expand Down Expand Up @@ -963,11 +963,11 @@ public function initialize(): void {
// StringTime / EnvLocal / StringTriggerError(initialize) / PendingHeaders
// always-on ensureLinked removed (#34513): StringTime::invoke /
// TouchLibcRuntime / Context::ensureStandaloneBodies (EnvLocal) /
// HashTable::implement + trigger_error_ / JitBuiltinWarning / header_ /
// HashTable::readStringKeyValue + trigger_error_ / JitBuiltinWarning / header_ /
// PendingHeaders already ensureLinked before lookup (peer #34474).
// Type::register always-on StringTriggerError also dropped (#35392) —
// HELPER_RUNTIME_O=0 NestedJIT covered by HashTable::implement + call sites
// (#33248). Eager NestedJIT on every full load vs Runtime ABI drift mints
// HELPER_RUNTIME_O=0 NestedJIT covered by call sites + readStringKeyValue
// (#33248 / #35648). Eager NestedJIT on every full load vs Runtime ABI drift mints
// time.1 / env_local_lookup.1 / trigger_error.1 / pending_header_*.1
// (#31894 / #32122).
// StringCslashes::ensureStandaloneBodies always-on removed (#34534):
Expand Down
22 changes: 18 additions & 4 deletions lib/JIT/Builtin/Type/HashTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,11 @@ private function registerFn(string $name, string $returnType, array $paramTypes)

public function implement(): void
{
// Undef-key + trigger_error ABIs before any implement* lookup (#35392 / #33249).
// Type::register no longer eagerly NestedJIT StringTriggerError (#32122 .1 mint).
StringTriggerError::declareUndefinedArrayKeyAbis($this->context);
StringTriggerError::ensureLinked($this->context);
// StringTriggerError undef-key always-on ensureLinked removed (#35648 / peer #35392):
// only implementReadStringKeyValue emits __compiler_undefined_array_key_warning_*;
// HashTableReadLlvm / call sites already ensure before lookup. Thin hello-world
// must not NestedJIT trigger_error during HashTable init — leftover NestedJIT vs
// Runtime ABI drift mints undefined_array_key_warning_*.1 (#31894 / #32122).
// StringNaturalCompare / StringStrcoll always-on ensureLinked removed (#35626):
// locale/natural sort implement* call ensureStrcollAbis / ensureNaturalCompareAbis
// before lookupFunction (peer #35614 Type::String_::implement lazy batch). Thin
Expand Down Expand Up @@ -261,6 +262,18 @@ private function ensureNaturalCompareAbis(): void
StringNaturalCompare::ensureStandaloneBodies($this->context);
}

/**
* Undefined string-key read warning ABI — only for readStringKeyValue (#35648).
*
* peekStringKeyValue / isset paths must not NestedJIT trigger_error. Do not
* re-add at implement() entry — leftover decls mint undefined_array_key_warning_*.1.
*/
private function ensureUndefinedArrayKeyAbis(): void
{
StringTriggerError::declareUndefinedArrayKeyAbis($this->context);
StringTriggerError::ensureLinked($this->context);
}

private function implementAlloc(): void
{
$fn = $this->context->lookupFunction('__hashtable__alloc');
Expand Down Expand Up @@ -1615,6 +1628,7 @@ private function implementPeekStringKeyValue(): void

private function implementReadStringKeyValue(): void
{
$this->ensureUndefinedArrayKeyAbis();
$fn = $this->context->lookupFunction('__hashtable__readStringKeyValue');
$block = $fn->appendBasicBlock('main');
$this->context->builder->positionAtEnd($block);
Expand Down
85 changes: 85 additions & 0 deletions test/unit/HashTableLazyUndefinedArrayKeyRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\Test\Unit;

use PHPUnit\Framework\TestCase;

/**
* Drop HashTable::implement always-on NestedJIT for undefined-array-key ABIs
* (#35648 / peer #35392 Type::register lazy batch, #35626 strcoll pattern).
*
* Thin hello-world AOT must not NestedJIT trigger_error during HashTable init —
* leftover NestedJIT vs Runtime ABI drift mints undefined_array_key_warning_*.1
* (#31894 / #32122).
*/
final class HashTableLazyUndefinedArrayKeyRuntimeShrinkTest extends TestCase
{
public function testHashTableImplementDropsEagerUndefinedArrayKeyEnsureLinked(): void
{
$source = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString('#35648', $source);
$pos = strpos($source, 'public function implement(): void');
$this->assertNotFalse($pos);
$next = strpos($source, 'private function ensureLibcStrtol', $pos);
$this->assertNotFalse($next);
$body = substr($source, $pos, $next - $pos);

foreach ([
'StringTriggerError::declareUndefinedArrayKeyAbis',
'StringTriggerError::ensureLinked',
'ensureUndefinedArrayKeyAbis',
] as $forbidden) {
$this->assertStringNotContainsString(
$forbidden,
$body,
'HashTable::implement must not eagerly '.$forbidden.' (#35648)'
);
}
}

public function testReadStringKeyValueEnsuresUndefinedArrayKeyBeforeLookup(): void
{
$source = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$fnPos = strpos($source, 'private function implementReadStringKeyValue(');
$this->assertNotFalse($fnPos);
$nextFn = strpos($source, 'private function implementReadStringKeyHashtable(', $fnPos + 1);
$this->assertNotFalse($nextFn);
$chunk = substr($source, $fnPos, $nextFn - $fnPos);
$this->assertStringContainsString(
'ensureUndefinedArrayKeyAbis',
$chunk,
'implementReadStringKeyValue must ensureUndefinedArrayKeyAbis before lookup (#35648)'
);
$ensurePos = strpos($chunk, 'ensureUndefinedArrayKeyAbis');
$lookupPos = strpos($chunk, '__compiler_undefined_array_key_warning_cstr');
$this->assertNotFalse($ensurePos);
$this->assertNotFalse($lookupPos);
$this->assertLessThan($lookupPos, $ensurePos);
}

public function testHashTableReadLlvmStillEnsuresBeforeEmit(): void
{
$source = (string) file_get_contents(__DIR__.'/../../lib/JIT/HashTableReadLlvm.php');
$this->assertStringContainsString('StringTriggerErrorJit::implement', $source);
}

public function testNoNewRuntimeCForLazyUndefinedArrayKeyAbis(): void
{
$runtimeDir = dirname(__DIR__, 2).'/lib/AOT/runtime';
foreach ([
'undefined_array_key.c',
'compiler_undefined_array_key.c',
'trigger_error.c',
] as $name) {
$this->assertFileDoesNotExist(
$runtimeDir.'/'.$name,
'must not add '.$name.' for #35648 — PHP JIT bridges only'
);
}
$linker = (string) file_get_contents(__DIR__.'/../../lib/AOT/Linker.php');
$this->assertStringContainsString('RUNTIME_C_SOURCES = [', $linker);
$this->assertStringNotContainsString('undefined_array_key.c', $linker);
}
}
23 changes: 17 additions & 6 deletions test/unit/TypeDeadTriggerErrorAbiRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ public function testTypeBuiltinDropsLeftoverAlwaysOnTriggerErrorAbi(): void
'Builtin\\Type must not always-register __compiler_trigger_error (#33234)'
);
// No further Type always-on leftover after #33267 exit/abort drop;
// StringTriggerError register ensure moved to HashTable::implement (#35392).
// StringTriggerError register ensure moved to readStringKeyValue (#35648).
$this->assertStringContainsString('LibcExtern::ensureExitAbort', $type);
$ht = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString('StringTriggerError::ensureLinked', $ht);
$this->assertStringContainsString('ensureUndefinedArrayKeyAbis', $ht);
}

public function testRuntimeOwnerDeclaresTriggerErrorAbiModuleLocally(): void
Expand Down Expand Up @@ -111,14 +111,25 @@ public function testTypeRegisterNoLongerEagerLinksSessionStartOptionsNestedJit()
);
$ht = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString(
'StringTriggerError::declareUndefinedArrayKeyAbis($this->context)',
'ensureUndefinedArrayKeyAbis',
$ht,
'HashTable::implement declares undef-key ABIs (#35392 / #33249)'
'HashTable readStringKeyValue ensures undef-key ABIs (#35648 / #33249)'
);
$fnPos = strpos($ht, 'private function implementReadStringKeyValue(');
$this->assertNotFalse($fnPos);
$chunk = substr($ht, $fnPos, 400);
$this->assertStringContainsString(
'ensureUndefinedArrayKeyAbis',
$chunk,
'readStringKeyValue must ensure undef-key ABIs (#35648 / #33248)'
);
$ensureMethodPos = strpos($ht, 'private function ensureUndefinedArrayKeyAbis');
$this->assertNotFalse($ensureMethodPos);
$ensureChunk = substr($ht, $ensureMethodPos, 400);
$this->assertStringContainsString(
'StringTriggerError::ensureLinked($this->context)',
$ht,
'HashTable::implement ensureLinked StringTriggerError (#35392 / #33248)'
$ensureChunk,
'ensureUndefinedArrayKeyAbis must ensureLinked StringTriggerError (#35648 / #33248)'
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public function testTypeInitializeDropsEagerTimeEnvTriggerPendingEnsureLinked():
);
$ht = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString(
'StringTriggerError::ensureLinked($this->context)',
'ensureUndefinedArrayKeyAbis',
$ht,
'HashTable::implement ensureLinked StringTriggerError for HELPER_RUNTIME_O=0 (#35392 / #33248)'
'HashTable readStringKeyValue ensures StringTriggerError for HELPER_RUNTIME_O=0 (#35648 / #33248)'
);
// SessionStorageGlobals::ensureGlobals also lazy as of #34566 (peer).
}
Expand Down
4 changes: 2 additions & 2 deletions test/unit/TypeDeadUndefinedArrayKeyAbiRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ public function testTypeBuiltinDropsLeftoverAlwaysOnUndefinedArrayKeyAbi(): void
'Builtin\\Type must not always-register undef-key long ABI (#33249)'
);
// No further Type always-on leftover after #33267 exit/abort drop;
// StringTriggerError register ensure moved to HashTable::implement (#35392).
// StringTriggerError register ensure moved to readStringKeyValue (#35648).
$this->assertStringContainsString('LibcExtern::ensureExitAbort', $type);
$ht = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString('StringTriggerError::ensureLinked', $ht);
$this->assertStringContainsString('ensureUndefinedArrayKeyAbis', $ht);
$this->assertStringContainsString('StringTriggerError::declareUndefinedArrayKeyAbis', $ht);
}

Expand Down
35 changes: 16 additions & 19 deletions test/unit/TypeRegisterLazyStringTriggerErrorRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
/**
* Drop Type::register always-on StringTriggerError (#35392 / peer #34513 initialize).
*
* HashTable::implement declares undef-key ABIs + ensureLinked at entry; call sites
* already ensure before lookup. Thin AOT must not NestedJIT trigger_error during
* HashTable::readStringKeyValue ensures undef-key ABIs; call sites already ensure
* before lookup. Thin AOT must not NestedJIT trigger_error during Type::register
* Type::register (#31894 / #32122 .1 mint class).
*/
final class TypeRegisterLazyStringTriggerErrorRuntimeShrinkTest extends TestCase
Expand Down Expand Up @@ -43,31 +43,28 @@ public function testTypeRegisterDropsEagerStringTriggerError(): void
);
}

public function testHashTableImplementEnsuresStringTriggerErrorBeforeLookups(): void
public function testHashTableReadStringKeyValueEnsuresStringTriggerErrorBeforeLookup(): void
{
$ht = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type/HashTable.php');
$this->assertStringContainsString('#35392', $ht);
$this->assertStringContainsString('#35648', $ht);
$fnPos = strpos($ht, 'private function implementReadStringKeyValue(');
$this->assertNotFalse($fnPos);
$nextFn = strpos($ht, 'private function implementReadStringKeyHashtable(', $fnPos + 1);
$this->assertNotFalse($nextFn);
$chunk = substr($ht, $fnPos, $nextFn - $fnPos);
$this->assertStringContainsString(
'ensureUndefinedArrayKeyAbis',
$chunk,
'implementReadStringKeyValue must ensure undef-key ABIs before lookup (#35648)'
);
$implPos = strpos($ht, 'public function implement(): void');
$this->assertNotFalse($implPos);
$implBody = substr($ht, $implPos, 600);
$this->assertStringContainsString(
'StringTriggerError::declareUndefinedArrayKeyAbis($this->context)',
$implBody,
'HashTable::implement must declare undef-key ABIs before lookups (#35392)'
);
$this->assertStringContainsString(
$this->assertStringNotContainsString(
'StringTriggerError::ensureLinked($this->context)',
$implBody,
'HashTable::implement must ensureLinked before undef-key lookup (#35392)'
'HashTable::implement must not eagerly ensureLinked (#35648)'
);
$declPos = strpos($implBody, 'StringTriggerError::declareUndefinedArrayKeyAbis');
$ensurePos = strpos($implBody, 'StringTriggerError::ensureLinked');
$allocPos = strpos($implBody, 'implementAlloc');
$this->assertNotFalse($declPos);
$this->assertNotFalse($ensurePos);
$this->assertNotFalse($allocPos);
$this->assertLessThan($allocPos, $declPos);
$this->assertLessThan($allocPos, $ensurePos);
}

public function testJitScalarEnumCoerceEnsuresBeforeLookup(): void
Expand Down
Loading