phase11: ledger — the ceiling breaks three times, the content-free frame lever, sf3_merge fail-fast fixes
494 bodies / 503 regions. Three bodies above the old 244 B ceiling from two workers (248/248/264 B). Cookbook 59 extended with the unreferenced-array-local mechanism (cc1 gives unreferenced scalars no home but does allocate for unreferenced arrays), the amended three-direction rule, the per-band cost table, the sf3_merge fail-fast fixes, and the rank-instability broadcast.
This commit is contained in:
@@ -156,3 +156,72 @@ on it, exactly as the maspsx `#nop` fix did.
|
||||
merely *READS* a callee-saved register neither written nor saved earlier finds 11 more rows (8 above the
|
||||
ceiling), but the control fires on **2 of 493 registered regions**, so it is **not** disjoint and was
|
||||
**not** implemented. Recorded as a candidate requiring refinement, not applied.
|
||||
|
||||
## Cycle 1 — the ceiling breaks three times, and a content-free frame lever
|
||||
|
||||
**494 distinct bodies / 503 regions** (from the 484 / 493 baseline). **Three bodies now sit above the old
|
||||
244 B ceiling**, from two independent workers: `0x8009F6A0` (248 B, worker D), `0x80036134` (248 B,
|
||||
worker C), `0x800308C4` (264 B, worker D — the new corpus maximum). The dispatch-artefact verdict is
|
||||
settled **by result rather than by inference**.
|
||||
|
||||
### The lever that broke it, and its extension
|
||||
|
||||
**Finding 59, instance 1** (`0x8009F6A0`): the local buffer had to be `int t[3][4]`, only columns 0..2
|
||||
used — **not** `int t[9]`. The **4-word row stride is byte-load-bearing**: it moves the 2nd and 3rd
|
||||
triples to `0x10`/`0x20`, makes the frame **48 B instead of 40 B**, and leaves the unused `0x0C`/`0x1C`
|
||||
slots the original shows. Four spellings: nine `short` locals (100 B, cc1 drops the sign extension), nine
|
||||
`int` locals (100 B, right signedness, still no frame), `int t[9]` (248 B, **19 differing bytes, the
|
||||
first at the frame adjustment itself**), then `int t[3][4]` → MATCH.
|
||||
|
||||
**Finding 59, instance 2** (`0x800308C4`, 264 B): **8 words from a match and all eight were the frame** —
|
||||
the `addiu sp,sp,-96` prologue and its mirror epilogue, with **56 of 64 words already byte-identical**
|
||||
including every call site, delay slot and register. The missing 8 bytes are an **unreferenced array
|
||||
local**, and the mechanism is measured across five spellings:
|
||||
|
||||
| trailing declaration | vars | frame | result |
|
||||
|---|---|---|---|
|
||||
| (none) | 56 | 88 | DIFF, 8 words |
|
||||
| `int pad0, pad1;` (2 unreferenced **scalars**) | 56 | 88 | DIFF — **cc1 gives unreferenced scalars no home** |
|
||||
| `short t[12]` (one 24-byte array) | 56 | 88 | DIFF |
|
||||
| `int pad[2]` (unreferenced 8-byte **array**) | 64 | **96** | **MATCH** |
|
||||
| `short pad[4]` (unreferenced 8-byte **array**) | 64 | **96** | **MATCH** |
|
||||
|
||||
**cc1 allocates stack space for an unreferenced ARRAY local but not for an unreferenced SCALAR local.**
|
||||
The 8 bytes are **size-load-bearing and content-free** — any 8-byte array reproduces them. Recorded as a
|
||||
**limit of the reconstruction, not a recovered fact**, and marked as such in the file header.
|
||||
|
||||
**AMENDED RULE (cookbook 59): when the residual IS the frame, vary the local aggregate's declaration in
|
||||
THREE directions — element type, row stride, AND total size.** Two instances, two different directions,
|
||||
one diagnostic: *correct length + right instruction multiset and order + residual concentrated on the
|
||||
frame adjustment and every sp-relative offset ⇒ suspect a local aggregate's shape, not the control flow.*
|
||||
|
||||
### Cost above the ceiling, measured by two workers
|
||||
|
||||
| band | worker C | worker D |
|
||||
|---|---|---|
|
||||
| >244 B | 1 row attempted, 1 matched, **11 compile attempts** | 2 rows attempted, 2 matched, **4 and 6 spellings** |
|
||||
| ≤244 B | 2 attempts, 2 attempts, ~6 attempts (3 rows) | paired control pending |
|
||||
|
||||
Neither of D's matches was scheduler-bound, allocation-bound or harness-bound — both failed in exactly one
|
||||
place and both were closed by a **declaration change**. That is the "how tractable" answer at n=3: **the
|
||||
band is tractable, and the cost is real but not a grind.**
|
||||
|
||||
### Fail-fast fixes to `sf3_merge`, both triggered by real worker files
|
||||
|
||||
- A claim row with an unknown override key (`md5=...`) used to **merge silently** and only fail later at
|
||||
the gate with `unknown override key 'md5'`. `sf3_merge` now **validates override keys at merge time**
|
||||
and rejects the row with a message naming the valid keys and pointing at `report.tsv`. Generalised as
|
||||
cookbook 62: **validate at the earliest stage that can see the error**, because a late failure is
|
||||
diagnosed as a gate problem rather than a claim problem.
|
||||
- A bare header row is now rejected with *"looks like a column HEADER"* rather than a confusing
|
||||
`not a hex address: 'start'`.
|
||||
- A lone `-` in the override column is accepted as "no overrides", matching the absent-value convention
|
||||
the other tracked tables use.
|
||||
|
||||
Suite 237 → 246 tests. The candidate gate caught the bad row; the tracked registry was never touched.
|
||||
|
||||
### Operational note broadcast to all workers
|
||||
|
||||
**Ranks are not stable — key dispatch by address.** Worker D's row moved from rank 592 to 578 mid-session
|
||||
because the worklist regenerates and the partitions refilter after every merge. **Addresses are stable;
|
||||
ranks are not**, and rank-keyed scratch tooling drifts silently onto a different row.
|
||||
|
||||
Reference in New Issue
Block a user