1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# Chapter split cleanup audit
This record distinguishes checked behavior, existing gaps, and future designs
while retiring the old combined Chapters 24/25. The final mapping is in the
[split record](chapter-split.md). Historical Java test names are retained as
regression identities; they do not identify current chapter boundaries.
## Corrections in this cleanup
- Chained comparisons now begin in Chapter 23. The early SCCP implementations
incorrectly compared a boolean intermediate with the third operand:
`10 < 30 < 20` returned true. Later implementations preserved the middle
operand but reused the first operator, making `0 < 2 <= 2` false. All current
snapshots from 23 onward now compare adjacent values using each written
operator. Regression cases cover both directions, strict/non-strict mixtures,
single evaluation, side effects, short-circuiting, and mixed-direction errors.
- Chapter 23's inherited, explicitly described fuzzer scratch contains many
comparisons using the former left-associative grammar. It is retained as an
ignored `testJigFuzzer`, consistent with the scratch-test policy; its mixed
directions are no longer valid source. Later snapshots already omitted it.
- Native-library and tuning material is preserved in [appendices](../docs/appendices/README.md),
and unfinished work is collected in the [roadmap](../docs/roadmap.md).
- The recursive-return diagnostic already passed. It remains enabled in the
earlier snapshots and is enabled again in 28a/28b. The mutual-recursion test had an obsolete graph-string
expectation; it now checks its existing four execution results in 24b–28b.
In 24a, local SCCP cannot infer the recursive return type; the same example
checks that conservative diagnostic instead. This makes the boundary explicit.
- Allocation/runtime measurement runs passed after the comparison correction;
the changed spill goldens record the resulting smaller graphs. Historical
published tables retain their original compiler labels and dates.
## Prefix-update follow-up
Prefix `++` and `--` now use the same name lookup as ordinary reads and postfix
updates in Chapters 23 through 28b. A method's field goes through memory; a
constructor-local field stays in SSA. Previously, the prefix path updated the
field declaration's parser slot and silently lost the write. The two-call
reproducer now returns 21 instead of 11. Narrow update results stay alive while
Store folding drops a redundant conversion from its own input.
`PrefixUpdateTest` covers increment/decrement, integer/float/byte fields,
multiple worklist seeds, local shadowing, final-field errors, native byte
wraparound, and module fields where supported. Existing final-constructor
coverage includes prefix updates in loops.
The focused Linux checks pass in all eight affected chapters, including native
SystemV byte-wraparound execution and the existing final-constructor tests.
The early final-field rejection is retained so an illegal prefix update never
enters the optimizer as a Store; native data bindings still update their writable
contents despite having a fixed address.
The Windows full suites cover 4,169 tests plus eight fuzzer regression runs;
shared printer and ISA checks pass. Focused reruns cover the final diagnostic
and prefix-result lifetime adjustments. The full Chapter 27 suite was rerun
after restricting the temporary keep to prefix results; its existing spill
expectations remain unchanged. No allocator goldens were updated.
## Implemented, with narrower limits than earlier prose suggested
The constructor-loop assertion is fixed in Chapters 25–27. Load forwarding now
waits for a stored loop Phi to acquire a type at least as precise as the Load,
and records a dependency to retry. The reduced case needs only a conditional
assignment in a loop; break/continue and final fields are not required.
Regressions cover the reduced case and the original constructor loop across
worklist seeds and execution inputs. Chapters 28a/28b already had the guard;
the corresponding earlier-chapter probes pass in 23/24a/24b.
- Separate compilation imports types and optimized IR without source parsing;
it reruns analysis and type checking with the new callers.
- Loading is by object and recorded dependencies, not individual used members.
A call to `sys.io.p` loads all ten bundled sys units. Independent, unrelated
objects can remain unloaded. Loading does not imply class initialization.
- Timestamp checks do not yet provide a reliable incremental build system.
The [design note](incremental-builds.md) records the missing pieces.
- Underscores select exports in modules; source privacy checks are still a
proposal awaiting review. Do not treat hidden exports as inaccessible source.
- Constructor-local final fields use SSA values and exit Stores. Reads of an
unfinished object are allowed only for initialized fields. Passing unfinished
self to arbitrary helpers and accepting completion only after SCCP are not
promised by the current chapter boundary.
## Existing failures and deferred validation
- The ideal evaluator does not truncate narrow stores in Chapter 23. A byte
update can therefore disagree with generated code; the postfix-only
reproducer is retained in the [roadmap](../docs/roadmap.md#narrow-stores-in-the-ideal-evaluator).
- `testModule0` is an ignored historical incremental-build experiment. It
assumes per-source output objects and unchanged explicit-input builds, neither
of which matches the present compiler's contract.
- Serialization's expensive byte-for-byte round-trip assertion remains disabled.
Ordinary import tests do not establish that stronger property.
- Direct probes of the remaining ignored tests found a stale forward-method
graph expectation and a missing `progs/sieve.smp` fixture in 28b. These and
the interactive stdin test remain ignored. Ignored Jig and
random-fuzzer entry points are intentional scratch/long-running tools.
Audit these separately before advertising their behavior as tested.
Selective loading, full incremental builds, source privacy, compact pointers,
argument arrays, deterministic inlining, and broader constructor rules remain
future work. They are not prerequisites for completing the chapter numbering.
## Validation
The affected snapshots (23, 24a, 24b, 25, 26, 27, 28a, 28b) were checked with
their full Make suites on Windows and Linux, plus focused reruns after updating
test expectations. The final Windows coverage is 4,143 tests plus eight fuzzer
regression runs, with the shared printer and ISA tests also passing. The
native library/client cases and final Chapter 28b release build pass on both OSes.
A local linear-history dry run produced all 31 tags in teaching order. The
final source snapshot, chapter navigation, Maven module IDs, and reviewed local
documentation links were checked. Measurement capture in 24b and dynamic
measurements in 24b/28b pass; the historical published tables were not rewritten.
|