diff options
6 files changed, 54 insertions, 42 deletions
diff --git a/chapter25/README.md b/chapter25/README.md index b7925a1f..7ba16659 100644 --- a/chapter25/README.md +++ b/chapter25/README.md @@ -177,23 +177,18 @@ Chapter 21's adjacent-copy forwarding carries forward here as well: a copy used only by the next instruction is removed when the operand accepts its source register and is not tied to the instruction's result. -The table below is the **earlier audit**, before adjacent-copy forwarding. -The replay has ten String-constructor parse failures, also reproduced -with the original allocator. On the identical 216 successful allocations, -adjacent-copy forwarding reduced 2,563 / 5,496 moves / weighted moves to -2,494 / 5,399. The subsequent memory corrections produce 2,488 / 5,379 on -those same 216 successful allocations. These are partial comparisons, not -replacement complete-suite totals. The -current cohort 25 has 14 allocations, including later C return ABI checks; -the historical table has ten. Native cohort-25 checks and fresh system-library -encoding pass in both runs. See the [backport record](../docs/chapter-backports.md) -for the pending fixture failures. +The table below is the complete 2026-10-02 replay, after repairing three saved +String sources with explicit constructors for their required `cs` field. +All 212 historical entries now pass. This establishes a new baseline after the +fixture adaptations and recent compiler corrections; it is not an allocator-only +comparison with the earlier audit. The [backport record](../docs/chapter-backports.md) +retains the older partial comparisons. Run `make spill-stats`. Each row uses **Chapter 25's compiler**. The first five rows preserve the earlier 212 program/target entries, adapted to this chapter's syntax and library organization; the [fixture notes](src/test/java/com/seaofnodes/simple/spill/README.md) list those adaptations and the measurement limits. They use optimizer seed 123. -The last row includes nine allocations from `Chapter25Test` at its existing +The last row includes thirteen recorded allocations from `Chapter25Test` at its existing seeds plus a fresh system-library compilation at the driver's seed 456. Reusing `sys.o` must not make that substantial workload disappear from the measurements. These results are from Windows x86-64; earlier cohorts also include RISC-V/ARM @@ -201,36 +196,39 @@ SystemV and x86 SystemV. The reporter prints per-target totals as well. | Program cohort | Compilations | Split/move count | Loop-weighted count | |---|---:|---:|---:| -| Chapter 20 | 39 | 381 | 612 | -| Chapter 21 | 52 | 464 | 1,185 | -| Chapter 22 | 24 | 103 | 131 | -| Chapter 23 | 30 | 122 | 346 | -| Chapter 24 | 67 | 744 | 1,479 | -| Chapter 25 | 10 | 783 | 1,826 | -| **Total** | **222** | **2,597** | **5,579** | +| Chapter 20 | 39 | 375 | 606 | +| Chapter 21 | 52 | 479 | 1,172 | +| Chapter 22 | 24 | 103 | 103 | +| Chapter 23 | 30 | 129 | 353 | +| Chapter 24 | 67 | 696 | 1,410 | +| Chapter 25 | 14 | 786 | 1,815 | +| **Total** | **226** | **2,568** | **5,459** | `_spills` counts retained SplitNodes, including register-to-register moves; `_spillScaled` applies the loop weight. Neither measures just memory traffic. The old cohorts are allocation replays with register-legality checks, not reruns -of their native harnesses. `Chapter25Test` still runs its native/result checks. +of their native harnesses. All 23 `Chapter25Test` tests pass, including their +native/result checks, with no spill-golden failures. Use `make -j 4 tests` for the full chapter, including inherited emulator tests. ### Comments on the measurements -There is no uniform improvement to claim. Substituting Chapter 24's ranking -while keeping the rest of this compiler unchanged saves five moves on the 221 -client compilations (2,206 / 4,719 versus 2,211 / 4,724), but fails to allocate +The earlier allocator audit found no uniform improvement. Substituting Chapter +24's ranking while keeping the rest of that compiler unchanged saved five moves on the 221 +client compilations (2,206 / 4,719 versus 2,211 / 4,724), but failed to allocate the system library within eight rounds. It is therefore an incomplete comparison, not a lower valid whole-suite total. The existing area/cost ranking is retained; the round limit and correctness checks are unchanged. The system library itself -contributes 386 moves / 855 weighted moves. +contributed 386 moves / 855 weighted moves in that audit; the current replay +measures 373 / 828. A trial that favored all multi-use cloneable constants saved one move against the earlier ranking on those clients, but also failed the fresh library build. It was rejected. This is why both aggregate statistics and complete compilation and execution checks matter; a favorable subtotal cannot justify a change. -The earlier-cohort total rises from Chapter 24's 1,332 / 2,956 to 1,814 / 3,753. +In that earlier audit, the historical-cohort total rose from Chapter 24's +1,332 / 2,956 to Chapter 25's 1,814 / 3,753. Chapter 25 adds class initializers, module ownership, different escape analysis, and syntax/library adaptations. These are different machine graphs; the increase cannot be attributed to allocator quality alone. Compare a heuristic within one diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp index dafa7456..86220b7a 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp @@ -2,6 +2,7 @@ struct String { u8[] cs; int _hashCode; + new String = { u8[] data -> cs=data; }; }; // Compare two Strings diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp index 6cc28315..3a696d66 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp @@ -1,6 +1,7 @@ struct String { u8[] cs; int _hashCode; + new String = { u8[] data -> cs=data; }; }; // Compare two Strings diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp index 3fa2174c..1a4d55c1 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp @@ -2,6 +2,7 @@ struct String { u8[] cs; int _hashCode; + new String = { u8[] data -> cs=data; }; }; // Compare two Strings diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md index 6c78d46f..57435402 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md @@ -17,6 +17,13 @@ Chapter 25 cannot parse all earlier sources unchanged. Adaptations are explicit: - String, Scan, and linked S constructors replace `new S { field=...; }` with declared constructors and arguments. The explicit-receiver scanner functions become instance methods, preserving their operations. +- The saved `Chapter21Test-testStringExport`, `Chapter21AllocTest-testString`, + and `Chapter23AllocTest-testString` sources declare + `new String = { u8[] data -> cs=data; };` to initialize the required non-null + `cs` field. This repairs ten replay entries (four, three, and three), without + changing their equality/hash bodies or manifest membership. These adapted + sources are a new comparison baseline; their totals cannot be compared as + identical inputs with the earlier constructor-free fixtures. - The two short-circuit RHS initializer loops become equivalent guarded blocks, preserving allocation, side effects, and the final result. - Simple I/O cases include the old `write` binding and print helper directly. diff --git a/docs/chapter-backports.md b/docs/chapter-backports.md index 4b549771..02c0574a 100644 --- a/docs/chapter-backports.md +++ b/docs/chapter-backports.md @@ -282,10 +282,11 @@ pass complete spill reports after refreshing reduced-move expectations: Cohort 22 includes the two zero-move C return ABI checks added since the older 24-entry audit. Chapter 25's frozen 212-entry manifest remains unchanged. -Its reporter currently fails on ten pre-existing String-constructor parse errors; +At that audit, its reporter failed on ten pre-existing String-constructor parse errors; the unmodified allocator reproduces all ten. The same 216 successful allocations (including 14 current cohort-25 allocations) improve from 2,563 / 5,496 to -2,494 / 5,399, but these are partial totals. Fresh system-library encoding and +2,494 / 5,399, but these are partial totals. The subsequent historical String +fixture repair below restores complete reporting. Fresh system-library encoding and native cohort-25 checks pass. Logs: `build/copy-forward21-spills-final.log` through `build/copy-forward24-spills-final.log`, `build/copy-forward25-spills.log`, `build/copy-forward25-baseline.log`, and `build/copy-forward*-tests*.log`. @@ -349,18 +350,6 @@ lines beyond the original extraction. ### Other pending corrections -- **Chapter 25 historical String fixtures.** Ten replay entries fail before RA - because `Test.String.cs` is not fully initialized. They come from - `Chapter21Test-testStringExport.smp` (four entries), - `Chapter21AllocTest-testString.smp` (three), and - `Chapter23AllocTest-testString.smp` (three), under - `chapter25/src/test/java/com/seaofnodes/simple/spill/`. Both original and - adjacent-copy-forwarding allocators reproduce them. Adapt these constructor - fixtures separately and document the comparability change; do not omit the - failed entries from a claimed complete spill total. The ordinary Chapter 25 - suite passes, including its current String programs. - - - **Existing Chapter 18 floating-array assertion.** The unchanged `TypeStruct.makeAry` assertion accepts integers and nullable references but excludes TypeFloat; `return new flt[1];` fails under `-ea`. The Chapter 18 @@ -492,7 +481,7 @@ reports actual retained moves, per target and cohort, with assertions enabled. | 22 | Stronger copy-chain/backedge bias and cheap-spill ordering | 39, 52, 26 | | 23 | Group popular single-def uses by compatible register classes | 39, 52, 26, 30 | | 24 | One cold-only attempt for loop-Phi self-conflicts, then mandatory fallback | 39, 52, 26, 30, 67 | -| 25 | Existing area/cost ranking and later conflict strategies | 39, 52, 24, 30, 67, 14 (ten historical entries currently fail) | +| 25 | Existing area/cost ranking and later conflict strategies | 39, 52, 24, 30, 67, 14 | Shared corrections include RegMask/LRG bookkeeping, null use masks, kills without an output LRG, self-conflict splitting, compatible rematerialization, clobber-aware @@ -521,7 +510,9 @@ Chapter 25 freezes the 212 earlier compilation entries in Constructor/library adaptations change IR, so this is a program-cohort comparison, not identical machine graphs. Those rows replay allocation and legality checks; current Chapter25Test native checks and a fresh system-library encoding contribute -ten more allocations. Earlier audit total, before adjacent-copy forwarding: **2,597 moves / 5,579 loop-weighted moves** over 222 +14 more recorded allocations. The complete 2026-10-02 replay totals **2,568 moves / +5,459 loop-weighted moves** over 226 compilations after the fixture repair below. +Earlier audit total, before adjacent-copy forwarding: **2,597 moves / 5,579 loop-weighted moves** over 222 compilations. Chapter 25's area/cost implementation is retained. Substituting the earlier ranking saves five moves on the clients but fails a fresh `sys` allocation at the eight-round limit; a failed library cannot be omitted from the comparison. @@ -556,6 +547,18 @@ The top-level runner accepts explicit chapter lists, e.g. ## Validation record +- **Chapter 25 historical String fixtures (2026-10-02).** Added an explicit + constructor initializing the required non-null `cs` field in + `Chapter21Test-testStringExport.smp`, `Chapter21AllocTest-testString.smp`, and + `Chapter23AllocTest-testString.smp`. Equality/hash bodies and the frozen + 212-entry manifest are unchanged; all ten formerly failing entries now pass. + These source adaptations establish a new comparison baseline, rather than + demonstrating an allocator-only improvement. `make -C chapter25 spill-stats` + passes all 212 historical entries, fresh system-library encoding, and all 23 + Chapter25Test tests, with zero spill-golden failures. The complete 226 recorded + allocations total **2,568 retained moves / 5,459 weighted moves**; the README + contains the cohort breakdown. Log: `build/string-fixtures-spill.log`. + - **Function loop-tree boundaries, Chapters 18-25.** Stop the post-order loop walk at Return, seed each function's outer tree before visiting its body, and use that tree for synthetic exit projections, return Regions and the parent @@ -617,10 +620,11 @@ The top-level runner accepts explicit chapter lists, e.g. invariant length, a possibly aliasing arm, a changing loop pointer, differing stored values at a multiway merge, and reads before writes. Seeds 0 and 9 are retained in the regression for unresolved Store aliases and nested Phi queueing. - The historical spill replay retains exactly its **ten known String-constructor + At that audit, the historical spill replay retained exactly its **ten known String-constructor parse failures**, with no spill-golden or native-check failures. The same 216 successful allocations total **2,488 moves / 5,379 weighted moves**, compared with 2,494 / 5,399 before this port; this is not a complete-suite total. + The subsequent historical String fixture repair above restores a complete replay. Logs: `build/mem25-negative.log`, `build/mem25-seeds.log`, `build/mem25-final2.log` (spill replay), and `build/mem25-final4.log` (full tests and release). |
