From cebc388c575d075c77098e57f7b1d58c32a248cd Mon Sep 17 00:00:00 2001 From: PurHur Date: Mon, 25 May 2026 02:58:32 +0000 Subject: [PATCH 1/2] CI: default BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=1 in ci-local (#1867) Run M2 spine VM -r smoke in the LLVM tail by default after #1846 landed; opt out with BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=0 for spine-only link PRs. Document in local-ci-matrix and bootstrap-selfhost; extend CiScriptsTest. Co-authored-by: Cursor --- docs/bootstrap-selfhost.md | 2 +- docs/local-ci-matrix.md | 1 + script/ci-common.sh | 4 +-- script/ci-defaults.env | 2 +- test/unit/BootstrapLibSpineVmSmokeTest.php | 9 +++++++ test/unit/CiScriptsTest.php | 31 ++++++++++++++++++++++ 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/docs/bootstrap-selfhost.md b/docs/bootstrap-selfhost.md index aed35283ec0..8688a21c561 100644 --- a/docs/bootstrap-selfhost.md +++ b/docs/bootstrap-selfhost.md @@ -22,7 +22,7 @@ | Self-host native link | `./script/bootstrap-selfhost-link.sh` | ✅ `build/selfhost` prints `compiler_minimal bundle OK` ([#557](https://github.com/PurHur/php-compiler/issues/557), [#913](https://github.com/PurHur/php-compiler/issues/913)) | | M2 lib spine smoke lint | `php bin/compile.php -l test/selfhost/compiler_lib_spine_smoke/main.php` | ✅ **589/593** units ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#1419](https://github.com/PurHur/php-compiler/issues/1419) | M2 lib spine smoke native run | `./script/bootstrap-selfhost-lib-spine-smoke-link.sh` or `BOOTSTRAP_LIB_SPINE_SMOKE=1 make bootstrap-selfhost-lib-spine-smoke` | ✅ `build/selfhost-lib-spine-smoke` prints `compiler_lib_spine_smoke bundle OK` | -| M2 lib spine VM `-r` smoke | `./script/bootstrap-selfhost-lib-spine-vm-smoke.sh` or `BOOTSTRAP_LIB_SPINE_VM_SMOKE=1 make bootstrap-selfhost-lib-spine-vm-smoke` | ✅ same binary + `PHP_COMPILER_VM_SPINE_SMOKE=1` prints `vm-spine-ok` ([#1846](https://github.com/PurHur/php-compiler/issues/1846); CI opt-in `BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=1`) | +| M2 lib spine VM `-r` smoke | `./script/bootstrap-selfhost-lib-spine-vm-smoke.sh` or `BOOTSTRAP_LIB_SPINE_VM_SMOKE=1 make bootstrap-selfhost-lib-spine-vm-smoke` | ✅ same binary + `PHP_COMPILER_VM_SPINE_SMOKE=1` prints `vm-spine-ok` ([#1846](https://github.com/PurHur/php-compiler/issues/1846); `ci-local.sh` default `BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=1` ([#1867](https://github.com/PurHur/php-compiler/issues/1867)); set `0` to skip) | | M3 HelloWorld self-host probe lint | `php bin/compile.php -l test/selfhost/compiler_helloworld_smoke/main.php` | ✅ `compiler_compile_smoke` spine + `helloworld_compile_smoke` driver (linkable) | | M3 HelloWorld compile driver lint | `php bin/compile.php -l test/selfhost/compiler_helloworld_smoke/compile_driver.php` | ✅ `Runtime::parseAndCompile` + mode-file dispatch (native link opt-in) | | M3 HelloWorld self-host probe | `./script/bootstrap-selfhost-helloworld-probe.sh` or `make bootstrap-selfhost-helloworld` | 🚧 **partial** — bundle link ✅; HelloWorld AOT **run** native ✅; **emit uses Zend fallback** until native runtime compile passes ([#1492](https://github.com/PurHur/php-compiler/issues/1492); probe sets `M3_NATIVE_COMPILE=1` / `emit_path=native` only on selfhost compile-driver success; `BOOTSTRAP_M3_HELLOWORLD_STRICT=1` fails without fallback — see [bootstrap-m5-fast-path.md](bootstrap-m5-fast-path.md)) | diff --git a/docs/local-ci-matrix.md b/docs/local-ci-matrix.md index dc290ef36be..bc43c75e475 100644 --- a/docs/local-ci-matrix.md +++ b/docs/local-ci-matrix.md @@ -95,6 +95,7 @@ Defaults are exported from [`script/ci-defaults.env`](../script/ci-defaults.env) | `BOOTSTRAP_LOOP_PROBE_GATE` | `0` | `ci-local.sh` (LLVM tail, after selfhost-probe) | `./script/bootstrap-loop-probe.sh --dry-run` M4 ladder ([#1777](https://github.com/PurHur/php-compiler/issues/1777), [#1498](https://github.com/PurHur/php-compiler/issues/1498)) | | `BOOTSTRAP_WAVE_CHECK` | unset → `1` in `ci-local.sh` llvm tail; set `0` to skip | `ci-local.sh`, `ci-fast.sh` (`CI_FAST_BOOTSTRAP=1`) | `./script/bootstrap-wave-check.sh --fail-fast` after `@group aot-lint` | | `BOOTSTRAP_M3_HELLOWORLD_STRICT_GATE` | `0` | `ci-local.sh` (LLVM tail, after wave-check) | `bootstrap-selfhost-helloworld-probe.sh` with strict native emit ([#1526](https://github.com/PurHur/php-compiler/issues/1526)); set `1` when `emit_path=native` stable | +| `BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE` | `1` | `ci-local.sh` (LLVM tail, after selfhost-probe) | `bootstrap-selfhost-lib-spine-vm-smoke.sh` — M2 spine binary via `bin/vm.php -r` path ([#1846](https://github.com/PurHur/php-compiler/issues/1846), [#1867](https://github.com/PurHur/php-compiler/issues/1867)); set `0` for spine-only link PRs | | `CI_FAST_BOOTSTRAP` | `0` | `ci-fast.sh` | Optional llvm tail: bootstrap aot-lint + probe + wave-check when LLVM 9 present | | `JIT_PREFLIGHT_GATE` | `0` | `ci-fast.sh` | Early MCJIT probe after `composer install` ([#728](https://github.com/PurHur/php-compiler/issues/728)) | | `M2_SPINE_ISSUE_HYGIENE_GATE` | `1` | `ci-fast.sh` (`ci_run_inventory_checks`) | `script/check-m2-spine-issue-hygiene.php` — stale `m2-spine-unit` tickets ([#1819](https://github.com/PurHur/php-compiler/issues/1819), [#1808](https://github.com/PurHur/php-compiler/issues/1808)); set `0` for bulk spine PRs | diff --git a/script/ci-common.sh b/script/ci-common.sh index 0be2585df49..90f7bcce24f 100644 --- a/script/ci-common.sh +++ b/script/ci-common.sh @@ -230,9 +230,9 @@ ci_run_bootstrap_selfhost_probe() { "$_CI_SCRIPT_DIR/bootstrap-selfhost-compile-probe.sh" "${probe_args[@]}" } -# M2 lib spine VM -r smoke (issue #1846); default off until green in llvm tail. +# M2 lib spine VM -r smoke (issue #1846); default on in ci-defaults (#1867). ci_run_bootstrap_lib_spine_vm_smoke() { - if [[ "${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-0}" != "1" ]]; then + if [[ "${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-1}" != "1" ]]; then return 0 fi if ! ci_llvm_ready; then diff --git a/script/ci-defaults.env b/script/ci-defaults.env index 5e6b32c8f69..4e2bebf277f 100755 --- a/script/ci-defaults.env +++ b/script/ci-defaults.env @@ -22,7 +22,7 @@ export DEPLOY_SMOKE_003_EXECUTE="${DEPLOY_SMOKE_003_EXECUTE:-1}" # default on ( export BOOTSTRAP_SELFHOST_PROBE_UPDATE="${BOOTSTRAP_SELFHOST_PROBE_UPDATE:-0}" export BOOTSTRAP_LOOP_PROBE_GATE="${BOOTSTRAP_LOOP_PROBE_GATE:-0}" export BOOTSTRAP_M3_HELLOWORLD_STRICT_GATE="${BOOTSTRAP_M3_HELLOWORLD_STRICT_GATE:-0}" # opt-in (#1526); flip to 1 when strict probe stable -export BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE="${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-0}" +export BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE="${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-1}" # default on (#1867); opt-out for spine-only link PRs export CAPABILITY_SYNTAX_CHECK="${CAPABILITY_SYNTAX_CHECK:-1}" export M2_SPINE_ISSUE_HYGIENE_GATE="${M2_SPINE_ISSUE_HYGIENE_GATE:-1}" # default on (#1819); opt-out for bulk spine PRs export WAVE3_ROADMAP_SYNC_GATE="${WAVE3_ROADMAP_SYNC_GATE:-1}" # default on (#1814); opt-out WAVE3_ROADMAP_SYNC_GATE=0 for doc-only iteration diff --git a/test/unit/BootstrapLibSpineVmSmokeTest.php b/test/unit/BootstrapLibSpineVmSmokeTest.php index 2548e828c60..cb5acb56fc4 100644 --- a/test/unit/BootstrapLibSpineVmSmokeTest.php +++ b/test/unit/BootstrapLibSpineVmSmokeTest.php @@ -58,4 +58,13 @@ public function testWaveCheckDocumentsVmSpineSmokeFlag(): void $this->assertStringContainsString('--with-lib-spine-vm-smoke', $script); $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_VM_SMOKE', $script); } + + public function testCiDefaultsEnvDefinesVmSpineSmokeGateOn(): void + { + $defaults = (string) file_get_contents(self::$root.'/script/ci-defaults.env'); + $this->assertStringContainsString( + 'BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE="${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-1}"', + $defaults + ); + } } diff --git a/test/unit/CiScriptsTest.php b/test/unit/CiScriptsTest.php index 4e7fd829e37..8dac4be7a56 100644 --- a/test/unit/CiScriptsTest.php +++ b/test/unit/CiScriptsTest.php @@ -405,6 +405,37 @@ public function testLocalCiMatrixDocumentsBootstrapM3StrictGate(): void $this->assertStringContainsString('BOOTSTRAP_M3_HELLOWORLD_STRICT_GATE=1', $docSelfhost); } + public function testCiDefaultsEnvDefinesBootstrapLibSpineVmSmokeGateOn(): void + { + $defaults = (string) file_get_contents(dirname(__DIR__, 2).'/script/ci-defaults.env'); + $this->assertStringContainsString( + 'BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE="${BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-1}"', + $defaults + ); + $this->assertStringContainsString('#1867', $defaults); + } + + public function testCiLocalHonorsBootstrapLibSpineVmSmokeGate(): void + { + $local = (string) file_get_contents(dirname(__DIR__, 2).'/script/ci-local.sh'); + $this->assertStringContainsString('ci_run_bootstrap_lib_spine_vm_smoke', $local); + + $common = (string) file_get_contents(dirname(__DIR__, 2).'/script/ci-common.sh'); + $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE', $common); + $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE:-1', $common); + $this->assertStringContainsString('bootstrap-selfhost-lib-spine-vm-smoke.sh', $common); + } + + public function testLocalCiMatrixDocumentsBootstrapLibSpineVmSmokeGate(): void + { + $doc = (string) file_get_contents(dirname(__DIR__, 2).'/docs/local-ci-matrix.md'); + $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE', $doc); + $this->assertStringContainsString('bootstrap-selfhost-lib-spine-vm-smoke.sh', $doc); + + $docSelfhost = (string) file_get_contents(dirname(__DIR__, 2).'/docs/bootstrap-selfhost.md'); + $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=1', $docSelfhost); + } + public function testCiDefaultsEnvDefinesBootstrapSelfhostProbeUpdateOff(): void { $defaults = (string) file_get_contents(dirname(__DIR__, 2).'/script/ci-defaults.env'); From e0f647ff5e8d82fb89dc7ce9c9251facf0ff417d Mon Sep 17 00:00:00 2001 From: PurHur Date: Mon, 25 May 2026 03:56:10 +0000 Subject: [PATCH 2/2] JIT: register vendor parent classes during self-host AOT compile When PHP_COMPILER_SELFHOST_AOT=1, auto-register external parents that exist at compile time (e.g. PhpParser\NodeVisitorAbstract for SwitchDetectorAstVisitor) so spine bundle JIT does not fail on unknown extends. Co-authored-by: Cursor --- lib/JIT/Builtin/Type/Object_.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/JIT/Builtin/Type/Object_.php b/lib/JIT/Builtin/Type/Object_.php index 2a65db7da2d..af0f56a58bf 100755 --- a/lib/JIT/Builtin/Type/Object_.php +++ b/lib/JIT/Builtin/Type/Object_.php @@ -406,7 +406,11 @@ public function setClassParentName(string $className, string $parentName): void $childLc = strtolower(ltrim($className, '\\')); $parentLc = strtolower(ltrim($parentName, '\\')); if (!isset($this->classes[$parentLc])) { - throw new \LogicException("Class {$className} extends unknown class {$parentName}"); + if ('1' === getenv('PHP_COMPILER_SELFHOST_AOT') && class_exists($parentName)) { + $this->registerExternalClass($parentLc); + } else { + throw new \LogicException("Class {$className} extends unknown class {$parentName}"); + } } $this->classParentLc[$childLc] = $parentLc; }