diff --git a/README.md b/README.md
index 168b3f04340..745a066ab18 100755
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ Presenter script and troubleshooting: [`docs/GETTING-STARTED.md`](docs/GETTING-S
| **003-MiniWebApp** VM + AOT link | β
|
| **003** AOT execute (home, hello, PATH_INFO, contact) | β
native execute ([#764](https://github.com/PurHur/php-compiler/issues/764) closed; close tracker [#1044](https://github.com/PurHur/php-compiler/issues/1044)) |
| Self-host **M0βM1** | β
|
-| Self-host **M2** spine | π§ **606** / 611 units ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#2066](https://github.com/PurHur/php-compiler/issues/2066)) |
+| Self-host **M2** spine | π§ **609** / 611 units ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#2126](https://github.com/PurHur/php-compiler/issues/2126)) |
| Full Zend PHP compatibility | β β subset only (matrices in `docs/`, not on status site) |
MiniWebApp gates: [docs/miniwebapp-gates.md](docs/miniwebapp-gates.md) ([#472](https://github.com/PurHur/php-compiler/issues/472)). Presenter verify: `make north-star1-verify` ([#1845](https://github.com/PurHur/php-compiler/issues/1845)). Docker image: `php-compiler:22.04-dev`.
@@ -147,7 +147,7 @@ Matrix details: [docs/local-ci-matrix.md](docs/local-ci-matrix.md).
|-----------|----------------|--------|
| **M0 β Bundled subset runs** | ~**109** literal `require_once` units in `test/selfhost/compiler_minimal/main.php` compile+link under AOT; native binary prints `compiler_minimal bundle OK` | β
([#557](https://github.com/PurHur/php-compiler/issues/557), [#913](https://github.com/PurHur/php-compiler/issues/913)) |
| **M1 β Compiler-shaped bundle** | Same bundle **lints** as one translation unit; **compile-smoke** links a tiny fixture and runs AOT echo (`compiler smoke`); driver smoke bundles `bin/compile.php`-adjacent units | β
([#1025](https://github.com/PurHur/php-compiler/issues/1025)) |
-| **M2 β Full top-level `lib/` + spine** | All **14** top-level `lib/*.php` lint β
; **`compiler_lib_spine_smoke`** (**606** / **611** inventory units; 5 deferred) native link β
; grow toward full `bin/vm.php` path | π§ 100% inventory coverage (cli shim substitutes) |
+| **M2 β Full top-level `lib/` + spine** | All **14** top-level `lib/*.php` lint β
; **`compiler_lib_spine_smoke`** (**609** / **611** inventory units; 2 deferred) native link β
; grow toward full `bin/vm.php` path | π§ 100% inventory coverage (cli shim substitutes) |
| **M3 β Native compiles PHP** | Self-host bundle links; HelloWorld AOT **runs** natively; **compile emit still Zend fallback** | π§ partial |
| **M4 β Bootstrap loop** | Native toolchain rebuilds the **next** compiler sources | β¬ |
| **M5 β Full self-host** | Real `bin/vm.php` / `bin/compile.php` on full inventory; **no Zend bootstrap** | β¬ **north star** ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
diff --git a/docs/bootstrap-m5-fast-path.md b/docs/bootstrap-m5-fast-path.md
index d53006eee36..cda30909c97 100644
--- a/docs/bootstrap-m5-fast-path.md
+++ b/docs/bootstrap-m5-fast-path.md
@@ -36,7 +36,7 @@ Supporting fixes from #1402:
| `Runtime::loadJitContext` | Deny-listed (LLVM 9 link crash; same fragment as JIT deny list) |
| `Runtime::__construct` | Slim ctor via `compileRuntimeConstructM3Native` β `compileBlockPhpLowering` (#1494) |
| `Runtime::initParsePipeline` / `Runtime::initCompiler` / `Runtime::loadCoreModules` | On deny list; `compileRuntime*M3Native` β PHP CFG lowering (#1494) |
-| `Runtime::initVmContext` | **Native** via `RuntimeInitVmContext::emit` (allocate `VM\Context`, set `runtime` + `vmContext`); wired in `compileBlock()`; off deny list (#1494). PHP CFG `new VMContext` still LLVM 9 link crash when combined with ctor spine. |
+| `Runtime::initVmContext` | **Native** via `RuntimeInitVmContext::emit` (allocate `VM\Context` + `ErrorReporter` + `ScriptStack`, wire `runtime` + `vmContext`); wired in `compileBlock()`; off deny list (#1494, #2126). PHP CFG `new VMContext` still LLVM 9 link crash when combined with ctor spine. |
| `Runtime::loadJit` | `compileRuntimeLoadJitM3Native` + nested `createJit` helpers (#1495) |
| `Runtime::standalone` | Compile-driver link OK (#1402, #1056) |
| `helloworld_compile_smoke` | Deny-listed for link (LLVM 9); compile_driver bundle keeps stub; runtime emit via `helloworld_m3_emit_native_entry.php` / `compile_smoke_m3_emit_native_entry.php` + `PHP_COMPILER_EMIT_HELPER_LINK=1` (#1768, #1983) |
diff --git a/docs/bootstrap-selfhost.md b/docs/bootstrap-selfhost.md
index c53b8cda9b9..e9c1b119dd9 100644
--- a/docs/bootstrap-selfhost.md
+++ b/docs/bootstrap-selfhost.md
@@ -1,6 +1,6 @@
# Self-host bootstrap roadmap
-**Project north star:** The **compiler fully compiles itself** β native AOT from `lib/` (no `vendor/` at cold boot), then compiles PHP and rebuilds the next compiler revision without Zend. **M2 spine:** **606** / **611** (`php script/bootstrap-spine-count.php`; 5 deferred native-link [#2066](https://github.com/PurHur/php-compiler/issues/2066)). **Living tracker:** [#1492](https://github.com/PurHur/php-compiler/issues/1492) (was [#1056](https://github.com/PurHur/php-compiler/issues/1056)) Β· **re-root doc:** [self-host-target.md](self-host-target.md) Β· public status: [development-status Β§ North star](https://purhur.github.io/php-compiler/development-status.html#north-star-self-host). Parent tracking: [#78](https://github.com/PurHur/php-compiler/issues/78) (roadmap), [#212](https://github.com/PurHur/php-compiler/issues/212) (closed umbrella).
+**Project north star:** The **compiler fully compiles itself** β native AOT from `lib/` (no `vendor/` at cold boot), then compiles PHP and rebuilds the next compiler revision without Zend. **M2 spine:** **609** / **611** (`php script/bootstrap-spine-count.php`; 2 deferred native-link [#2126](https://github.com/PurHur/php-compiler/issues/2126)). **Living tracker:** [#1492](https://github.com/PurHur/php-compiler/issues/1492) (was [#1056](https://github.com/PurHur/php-compiler/issues/1056)) Β· **re-root doc:** [self-host-target.md](self-host-target.md) Β· public status: [development-status Β§ North star](https://purhur.github.io/php-compiler/development-status.html#north-star-self-host). Parent tracking: [#78](https://github.com/PurHur/php-compiler/issues/78) (roadmap), [#212](https://github.com/PurHur/php-compiler/issues/212) (closed umbrella).
## Current gates
@@ -20,8 +20,8 @@
| Self-host probe in full CI | `./script/ci-local.sh` (LLVM tail) | β
default-on when LLVM 9 present; `BOOTSTRAP_SELFHOST_PROBE_GATE=0` to skip ([#829](https://github.com/PurHur/php-compiler/issues/829)) |
| Wave gate in full CI | `./script/ci-local.sh` (LLVM tail) | β
default-on when LLVM 9 present; `BOOTSTRAP_WAVE_CHECK=0` to skip; `./script/bootstrap-wave-check.sh --fail-fast` |
| 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` | β
**606/611** units ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#2001](https://github.com/PurHur/php-compiler/issues/2001), [#2066](https://github.com/PurHur/php-compiler/issues/2066))
-| M2 spine coverage drift | `php script/check-selfhost-spine-coverage-sync.php` | β
606/611 in spine; **5** deferred (native-link [#1960](https://github.com/PurHur/php-compiler/issues/1960), [#2066](https://github.com/PurHur/php-compiler/issues/2066)); `SELFHOST_SPINE_COVERAGE_SYNC_GATE=1` ([#1945](https://github.com/PurHur/php-compiler/issues/1945))
+| M2 lib spine smoke lint | `php bin/compile.php -l test/selfhost/compiler_lib_spine_smoke/main.php` | β
**609/611** units ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#2001](https://github.com/PurHur/php-compiler/issues/2001), [#2126](https://github.com/PurHur/php-compiler/issues/2126))
+| M2 spine coverage drift | `php script/check-selfhost-spine-coverage-sync.php` | β
609/611 in spine; **2** deferred (native-link [#1960](https://github.com/PurHur/php-compiler/issues/1960), [#2126](https://github.com/PurHur/php-compiler/issues/2126)); `SELFHOST_SPINE_COVERAGE_SYNC_GATE=1` ([#1945](https://github.com/PurHur/php-compiler/issues/1945))
| 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-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) |
diff --git a/docs/pages/development-status.md b/docs/pages/development-status.md
index 25cb7e0cbba..bb17219d4a1 100644
--- a/docs/pages/development-status.md
+++ b/docs/pages/development-status.md
@@ -14,7 +14,7 @@ permalink: /development-status.html
| **Try it** | `git clone` β `composer install` β `./phpc test --fast` β [`docs/GETTING-STARTED.md`](https://github.com/PurHur/php-compiler/blob/master/docs/GETTING-STARTED.md) |
| **Overall progress** | ~**50%** toward a self-hosting compiler (indicative) |
| **Wave 3 (May 2026)** | Language **12/12** Β· Stdlib **13/13** ([#1380](https://github.com/PurHur/php-compiler/issues/1380)) |
-| **North star (self-host)** | M0βM1 β
Β· M2 spine **606/611** native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960)) Β· M3 HelloWorld strict β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)) Β· M5 β¬ ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
+| **North star (self-host)** | M0βM1 β
Β· M2 spine **609/611** native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960)) Β· M3 HelloWorld strict β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)) Β· M5 β¬ ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
| **Example tests** | `examples/000β006` β VM + AOT regression fixtures (not a project north star) |
| **Not Zend parity** | Subset compiler (not full Zend PHP) |
@@ -51,7 +51,7 @@ Indicative composite toward a **web-capable, self-hosting** compiler (not line-c
| **Stdlib** | ~58% | Wave-3 batch ([#1367](https://github.com/PurHur/php-compiler/issues/1367)β[#1379](https://github.com/PurHur/php-compiler/issues/1379)): **13/13** closed on master |
| **Web AOT** (build, deploy) | ~70% | Project link β
; CLI execute β
; examples **003β006** as integration tests |
| **Example harness** (003-MiniWebApp, 005-SessionsWeb, β¦) | ~90% | VM + AOT execute + default-on CI gates β **regression fixtures only** |
-| **Self-host** (north star, M0βM5) | ~99% | M0βM1 β
; M2 spine **606/611** native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960)); M3 HelloWorld strict β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)), compile-smoke π§ ([#1937](https://github.com/PurHur/php-compiler/issues/1937)); M4βM5 β¬ β [self-host-target.md](https://github.com/PurHur/php-compiler/blob/master/docs/self-host-target.md)
+| **Self-host** (north star, M0βM5) | ~99% | M0βM1 β
; M2 spine **609/611** native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960)); M3 HelloWorld strict β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)), compile-smoke π§ ([#1937](https://github.com/PurHur/php-compiler/issues/1937)); M4βM5 β¬ β [self-host-target.md](https://github.com/PurHur/php-compiler/blob/master/docs/self-host-target.md)
**Overall (indicative): ~52%** toward the [project north star](#north-star-self-host) below.
@@ -115,7 +115,7 @@ The `examples/` tree (**000β006**) is kept for **VM + AOT regression testing**
|-----------|---------|--------|
| **M0 β Bundled subset runs** | ~109 literal `require_once` units in `test/selfhost/compiler_minimal/main.php` β `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) |
| **M1 β Compiler-shaped bundle** | Bundled `Compiler.php` AOT lint; compile-smoke native link + AOT echo (`compiler smoke`); driver smoke toward `bin/compile.php` | β
[#1025](https://github.com/PurHur/php-compiler/issues/1025), [#1095](https://github.com/PurHur/php-compiler/issues/1095) |
-| **M2 β Lib spine growth** | `compiler_lib_spine_smoke` bundle toward full `bin/vm.php` inventory (**611** files) | β
native link **606** / 611 units (100%; 5 deferred [#2066](https://github.com/PurHur/php-compiler/issues/2066); [#1960](https://github.com/PurHur/php-compiler/issues/1960), [#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
+| **M2 β Lib spine growth** | `compiler_lib_spine_smoke` bundle toward full `bin/vm.php` inventory (**611** files) | β
native link **609** / 611 units (100%; 2 deferred [#2126](https://github.com/PurHur/php-compiler/issues/2066); [#1960](https://github.com/PurHur/php-compiler/issues/1960), [#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
| **M3 β Native compiles PHP** | HelloWorld strict native emit β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)); compile-smoke fixture π§ ([#1937](https://github.com/PurHur/php-compiler/issues/1937)) | π§ partial ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
| **M4 β Bootstrap loop** | Native toolchain rebuilds the **next** compiler sources (same tree, new revision) | β¬ |
| **M5 β Full self-host** | Real `bin/vm.php` / `bin/compile.php` path on full inventory; **no Zend bootstrap** | β¬ **north star** ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) |
@@ -125,7 +125,7 @@ The `examples/` tree (**000β006**) is kept for **VM + AOT regression testing**
| Set | ~Files | Notes |
|-----|--------|-------|
| `compiler_minimal` bundle (M0) | **109** | Literal `require_once` closure |
-| `compiler_lib_spine_smoke` (M2) | **606** | vm.php-path lib/ + ext/standard growth bundl
+| `compiler_lib_spine_smoke` (M2) | **609** | vm.php-path lib/ + ext/standard growth bundl
| Top-level `lib/*.php` | **14** | Per-file AOT lint β
|
| Full vm.php inventory | **611** | Phase A inventory (`php script/bootstrap-inventory.php`) |
@@ -160,7 +160,7 @@ Details: [self-host-target.md](https://github.com/PurHur/php-compiler/blob/maste
| Native link + run | `./script/bootstrap-selfhost-link.sh` | β
M0 |
| Compile smoke link | `make bootstrap-selfhost-compile-smoke` | β
M1 |
| Compile smoke AOT echo | `make bootstrap-selfhost-compile-smoke-run` | β
M1 |
-| M2 spine native link | `BOOTSTRAP_LIB_SPINE_SMOKE=1 make bootstrap-selfhost-lib-spine-smoke` | β
`compiler_lib_spine_smoke bundle OK` (**606** / **611** units; [#2001](https://github.com/PurHur/php-compiler/issues/2001), [#2066](https://github.com/PurHur/php-compiler/issues/2066)) |
+| M2 spine native link | `BOOTSTRAP_LIB_SPINE_SMOKE=1 make bootstrap-selfhost-lib-spine-smoke` | β
`compiler_lib_spine_smoke bundle OK` (**609** / **611** units; [#2001](https://github.com/PurHur/php-compiler/issues/2001), [#2066](https://github.com/PurHur/php-compiler/issues/2066)) |
| M3 HelloWorld strict | `BOOTSTRAP_M3_HELLOWORLD_STRICT_GATE=1` β `bootstrap-selfhost-helloworld-probe.sh` | β
([#1493](https://github.com/PurHur/php-compiler/issues/1493)); opt-in gate default `0` until default-on ([#1866](https://github.com/PurHur/php-compiler/issues/1866)) |
| M3 compile-smoke probe | `BOOTSTRAP_M3_COMPILE_SMOKE_PROBE_GATE=1` (default) | β
partial β native **run** β
; strict native emit π§ ([#1937](https://github.com/PurHur/php-compiler/issues/1937)) |
| Wave gate | `./script/bootstrap-wave-check.sh` | β
locally / Docker; GHA workflow disabled |
diff --git a/docs/pages/index.html b/docs/pages/index.html
index 20cbe68d261..f948f21c486 100644
--- a/docs/pages/index.html
+++ b/docs/pages/index.html
@@ -142,7 +142,7 @@
π― Project north star β Self-host
Compiler fully compiles itself: native binary from lib/ (no vendor/),
compiles PHP, then rebuilds the next compiler revision without Zend.
- Status: M0 β
Β· M1 β
Β· M2 β
link (606/611) Β· M3 HelloWorld strict β
Β· compile-smoke π§ Β· M5 β¬.
+ Status: M0 β
Β· M1 β
Β· M2 β
link (609/611) Β· M3 HelloWorld strict β
Β· compile-smoke π§ Β· M5 β¬.
Full north-star doc β Β· Target doc Β· #1492
@@ -198,7 +198,7 @@ Overall progress
Strong on VM and AOT linking; wave-3 language **12/12** and stdlib **13/13** on master; local/Docker CI while remote GHA/Circle are disabled.
- North star M0βM1 done, M2 spine link (606/611, #1960), M3 HelloWorld strict (#1493); M5 full self-compile is the stretch goal ([#1492](https://github.com/PurHur/php-compiler/issues/1492)).
+ North star M0βM1 done, M2 spine link (609/611, #1960), M3 HelloWorld strict (#1493); M5 full self-compile is the stretch goal ([#1492](https://github.com/PurHur/php-compiler/issues/1492)).
Example web gates (make north-star1-verify, 005-SessionsWeb opt-in #1891/#1893) stay in CI as regression only.
@@ -244,7 +244,7 @@ Example polish
Self-host
Compile-itself
- M0βM1 β
; M2 spine 606/611 link β
; M3 HelloWorld strict β
; compile-smoke π§; M5 = full self-host.
+ M0βM1 β
; M2 spine 609/611 link β
; M3 HelloWorld strict β
; compile-smoke π§; M5 = full self-host.
@@ -254,7 +254,7 @@ Compile-itself
Self-host bootstrap
Stretch goal: the compiler fully compiles itself (M5). Zend still runs
- bin/compile.php today; native output is a growing lib/ bundle (~109 minimal β 606 spine units toward 611 vm.php-path files).
+ bin/compile.php today; native output is a growing lib/ bundle (~109 minimal β 609 spine units toward 611 vm.php-path files).
Full ladder: development-status.md
Β· self-host-target.md
Β· tracker #1492.
@@ -273,7 +273,7 @@
M1 β Compiler-shaped bundle
β
M2 β Full top-level lib/
- 14/14 lint β
; 606/611 spine units native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960), [#1419](https://github.com/PurHur/php-compiler/issues/1419)).
+ 14/14 lint β
; 609/611 spine units native link β
([#1960](https://github.com/PurHur/php-compiler/issues/1960), [#1419](https://github.com/PurHur/php-compiler/issues/1419)).
3
diff --git a/docs/roadmap-wave3.md b/docs/roadmap-wave3.md
index 22bf949368c..15ea405cbe8 100644
--- a/docs/roadmap-wave3.md
+++ b/docs/roadmap-wave3.md
@@ -19,7 +19,7 @@ Regenerate capability truth: `php script/capability-matrix.php`, `php script/cap
Related merges outside this wave: `goto` ([#1228](https://github.com/PurHur/php-compiler/issues/1228) / [#1333](https://github.com/PurHur/php-compiler/pull/1333)), anonymous classes ([#1233](https://github.com/PurHur/php-compiler/issues/1233) / [#1386](https://github.com/PurHur/php-compiler/pull/1386)).
-**M2 spine:** **606** / **611** inventory (`compiler_lib_spine_smoke` native link β
; 5 deferred native-link [#1960](https://github.com/PurHur/php-compiler/issues/1960), [#2066](https://github.com/PurHur/php-compiler/issues/2066); [#1492](https://github.com/PurHur/php-compiler/issues/1492), M2 batches [#1419](https://github.com/PurHur/php-compiler/issues/1419), [#1497](https://github.com/PurHur/php-compiler/issues/1497)). Target doc: [self-host-target.md](self-host-target.md)
+**M2 spine:** **609** / **611** inventory (`compiler_lib_spine_smoke` native link β
; 2 deferred native-link [#2126](https://github.com/PurHur/php-compiler/issues/2126); [#1492](https://github.com/PurHur/php-compiler/issues/1492), M2 batches [#1419](https://github.com/PurHur/php-compiler/issues/1419), [#1497](https://github.com/PurHur/php-compiler/issues/1497)). Target doc: [self-host-target.md](self-host-target.md)
## Language (#1354β#1366)
diff --git a/docs/self-host-target.md b/docs/self-host-target.md
index 95a0e8086cc..06233474243 100644
--- a/docs/self-host-target.md
+++ b/docs/self-host-target.md
@@ -34,8 +34,8 @@ That is **M5**. Everything below is the honest path from todayβs bootstrap to
| Layer | Today | Target |
|-------|-------|--------|
| **Bootstrap driver** | Zend runs `php bin/compile.php` | Compiled `bin/compile.php` |
-| **Bundle size** | **606** curated `require_once` in spine smoke (108 minimal overlap + **495** M2-only) | **611** inventory files |
-| **Inventory coverage** | **100%** of vm.php path in spine smoke (**606/611**; 5 deferred) | **100%*
+| **Bundle size** | **609** curated `require_once` in spine smoke (108 minimal overlap + **498** M2-only) | **611** inventory files |
+| **Inventory coverage** | **100%** of vm.php path in spine smoke (**609/611**; 2 deferred) | **100%*
| **HelloWorld** | Native **run** β
; **emit** still Zend fallback | Native compile + emit |
| **Bootstrap loop (M4)** | Gen-1 link + gen-2 Zend partial | Native gen-2 emit + full tree rebuild |
| **Vendor** | `composer install` + patches on host | Prelinked artifacts only |
@@ -62,7 +62,7 @@ That is **M5**. Everything below is the honest path from todayβs bootstrap to
|-----------|----------------|--------|-----|
| **M0** | AOT can link a **small** honest `lib/` subset | β
| 100% |
| **M1** | Bundle is **compiler-shaped** (lint + compile-smoke) | β
| 100% |
-| **M2** | Spine grows toward full `bin/vm.php` inventory | π§ **606/611** units | **100%*
+| **M2** | Spine grows toward full `bin/vm.php` inventory | π§ **609/611** units | **100%*
| **M3** | Self-host binary **compiles external PHP** (HelloWorld) without Zend emit | π§ partial | **~45%** |
| **M4** | Self-host binary **rebuilds** the next compiler tree | β¬ | 0% |
| **M5** | Full self-host; Zend retired from loop | β¬ north star | 0% |
@@ -73,7 +73,7 @@ That is **M5**. Everything below is the honest path from todayβs bootstrap to
| Indicator | Formula | May 2026 |
|-----------|---------|----------|
-| **M2 spine progress** | `require_once` units in `compiler_lib_spine_smoke` Γ· Phase A inventory file count | **606 / 611** (5 deferred [#2066](https://github.com/PurHur/php-compiler/issues/2066))
+| **M2 spine progress** | `require_once` units in `compiler_lib_spine_smoke` Γ· Phase A inventory file count | **609 / 611** (2 deferred [#2126](https://github.com/PurHur/php-compiler/issues/2126))
| **Public βSelf-hostβ row** | Same M2 ratio until M3βM5 gates add weight ([`development-status.md`](pages/development-status.md)) | **~61%** |
| **Composite (internal)** | Milestone weights in table above (M0βM1 = 100%, M2 = spine %, M3βM5 = gate %) | **~54%** |
@@ -125,7 +125,7 @@ Parallel batches ([#1419](https://github.com/PurHur/php-compiler/issues/1419), [
| Entry | Units | Role |
|-------|------:|------|
| `test/selfhost/compiler_minimal/main.php` | **109** | M0 core |
-| `test/selfhost/compiler_lib_spine_smoke/main.php` | **606** | M2 growth (ext/standard + Vm* spine batch
+| `test/selfhost/compiler_lib_spine_smoke/main.php` | **609** | M2 growth (ext/standard + Vm* spine batch
| `test/selfhost/compiler_helloworld_smoke/` | β | M3 probe + compile driver |
| `test/selfhost/bootstrap_loop_smoke/` | β | M4 scaffold (gen-1βgen-2 loop probe; [#1498](https://github.com/PurHur/php-compiler/issues/1498)) |
diff --git a/lib/JIT/RuntimeInitVmContext.php b/lib/JIT/RuntimeInitVmContext.php
index 9ea818d53ca..ec6d975de10 100644
--- a/lib/JIT/RuntimeInitVmContext.php
+++ b/lib/JIT/RuntimeInitVmContext.php
@@ -7,6 +7,19 @@ final class RuntimeInitVmContext {
public static function emit(Context $context, ObjectType $object, Value $runtimeThis): void {
$ctxId = $object->lookup('PHPCompiler\\VM\\Context');
$ctx = $object->allocate($ctxId);
+
+ $errorsId = $object->lookup('PHPCompiler\\VM\\ErrorReporter');
+ $errors = $object->allocate($errorsId);
+ $errorsVar = new Variable($context, Variable::TYPE_OBJECT, Variable::KIND_VALUE, $errors);
+ $errorsSlot = $object->propertyFetch($ctx, 'PHPCompiler\\VM\\Context', 'errors');
+ $object->propertyStore($errorsSlot->objectPropertySlot, $errorsVar, Variable::TYPE_OBJECT);
+
+ $stackId = $object->lookup('PHPCompiler\\VM\\ScriptStack');
+ $scriptStack = $object->allocate($stackId);
+ $stackVar = new Variable($context, Variable::TYPE_OBJECT, Variable::KIND_VALUE, $scriptStack);
+ $stackSlot = $object->propertyFetch($ctx, 'PHPCompiler\\VM\\Context', 'scriptStack');
+ $object->propertyStore($stackSlot->objectPropertySlot, $stackVar, Variable::TYPE_OBJECT);
+
$runtimeVar = new Variable($context, Variable::TYPE_OBJECT, Variable::KIND_VALUE, $runtimeThis);
$runtimeSlot = $object->propertyFetch($ctx, 'PHPCompiler\\VM\\Context', 'runtime');
$object->propertyStore($runtimeSlot->objectPropertySlot, $runtimeVar, Variable::TYPE_OBJECT);
diff --git a/script/check-selfhost-spine-coverage-sync.php b/script/check-selfhost-spine-coverage-sync.php
index 1118bfeae79..4312ddf53c3 100644
--- a/script/check-selfhost-spine-coverage-sync.php
+++ b/script/check-selfhost-spine-coverage-sync.php
@@ -36,6 +36,8 @@
'bin/vm.php' => 'test/bootstrap-aot/vm_run_smoke.php',
'src/cli.php' => 'test/bootstrap-aot/cli_spine_shim.php',
'src/cli_driver.php' => 'test/bootstrap-aot/cli_spine_shim.php',
+ 'src/llvm-env.php' => 'test/bootstrap-aot/llvm_env_spine_shim.php',
+ 'src/macro_functions.php' => 'test/bootstrap-aot/macro_functions_spine_shim.php',
];
/**
@@ -45,9 +47,6 @@
$spineNativeLinkDeferred = [
'bin/vm.php',
'lib/AOT/Linker.php',
- 'src/llvm-env.php',
- 'src/macro_functions.php',
- 'src/yay-php8-compat.php',
];
/** Inventory paths not yet in spine (regenerated inventory ahead of bundle β #1922). */
diff --git a/test/bootstrap-aot/llvm_env_spine_shim.php b/test/bootstrap-aot/llvm_env_spine_shim.php
new file mode 100644
index 00000000000..91e4d3a4503
--- /dev/null
+++ b/test/bootstrap-aot/llvm_env_spine_shim.php
@@ -0,0 +1,19 @@
+ $names
+ */
+ function php_compiler_preload_llvm_deps(string $dir, array $names): void
+ {
+ }
+}
diff --git a/test/bootstrap-aot/macro_functions_spine_shim.php b/test/bootstrap-aot/macro_functions_spine_shim.php
new file mode 100644
index 00000000000..de585beccb9
--- /dev/null
+++ b/test/bootstrap-aot/macro_functions_spine_shim.php
@@ -0,0 +1,19 @@
+assertFileExists($entry);
$contents = (string) file_get_contents($entry);
$count = substr_count($contents, 'require_once __DIR__');
- $this->assertSame(606, $count, 'M2 spine 606/611 inventory (5 deferred native-link #2066)');
+ $this->assertSame(609, $count, 'M2 spine 609/611 inventory (2 deferred native-link #2126)');
foreach (self::LIB_SPINE_SMOKE_NEW_UNITS as $unit) {
$this->assertStringContainsString(
"require_once __DIR__.'/../../../{$unit}';",
diff --git a/test/unit/BootstrapSelfhostHelloWorldTest.php b/test/unit/BootstrapSelfhostHelloWorldTest.php
index 2499f4bbfde..f8a3d68f001 100644
--- a/test/unit/BootstrapSelfhostHelloWorldTest.php
+++ b/test/unit/BootstrapSelfhostHelloWorldTest.php
@@ -354,7 +354,7 @@ public function testExternalJitClassRegistersIdToName(): void
$this->assertStringContainsString(
'$this->classIdToName[$id] = $lcname;',
$source,
- 'registerExternalClass must populate classIdToName for RuntimeInitVmContext propertyFetch (#1514)'
+ 'registerExternalClass must populate classIdToName for RuntimeInitVmContext propertyFetch (#1514, #2126)'
);
}
diff --git a/test/unit/RuntimeInitVmContextTest.php b/test/unit/RuntimeInitVmContextTest.php
new file mode 100644
index 00000000000..a70f467a482
--- /dev/null
+++ b/test/unit/RuntimeInitVmContextTest.php
@@ -0,0 +1,26 @@
+assertStringContainsString('ErrorReporter', $source);
+ $this->assertStringContainsString('ScriptStack', $source);
+ $this->assertStringContainsString("'errors'", $source);
+ $this->assertStringContainsString("'scriptStack'", $source);
+ }
+
+ public function testSpineShimsExist(): void
+ {
+ $root = dirname(__DIR__, 2);
+ $this->assertFileExists($root.'/test/bootstrap-aot/llvm_env_spine_shim.php');
+ $this->assertFileExists($root.'/test/bootstrap-aot/macro_functions_spine_shim.php');
+ }
+}
diff --git a/test/unit/SelfhostSpineSubstitutesTest.php b/test/unit/SelfhostSpineSubstitutesTest.php
new file mode 100644
index 00000000000..1d520bbbee0
--- /dev/null
+++ b/test/unit/SelfhostSpineSubstitutesTest.php
@@ -0,0 +1,27 @@
+assertStringContainsString("'src/llvm-env.php' => 'test/bootstrap-aot/llvm_env_spine_shim.php'", $script);
+ $this->assertStringContainsString("'src/macro_functions.php' => 'test/bootstrap-aot/macro_functions_spine_shim.php'", $script);
+ $this->assertStringNotContainsString("'src/yay-php8-compat.php'", $script);
+ }
+
+ public function testSpineMainRequiresYayCompatAndShims(): void
+ {
+ $root = dirname(__DIR__, 2);
+ $main = (string) file_get_contents($root.'/test/selfhost/compiler_lib_spine_smoke/main.php');
+ $this->assertStringContainsString('src/yay-php8-compat.php', $main);
+ $this->assertStringContainsString('llvm_env_spine_shim.php', $main);
+ $this->assertStringContainsString('macro_functions_spine_shim.php', $main);
+ }
+}