-
-
Notifications
You must be signed in to change notification settings - Fork 159
fix(codegen): initialize typed-shape layout on the standalone-ctor exit (#6921) #6930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
proggeramlug
merged 3 commits into
main
from
fix/codegen-typed-shape-layout-ctor-exit-6921
Jul 28, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| **codegen: initialize the typed-shape layout on `lower_new_impl`'s standalone-constructor exit (#6921).** | ||
|
|
||
| `lower_new_impl` had one exit that returned a freshly allocated class instance without emitting `js_gc_init_typed_shape_layout`; every other `new` exit emits it. Such an instance is left at `GC_LAYOUT_POINTER_FREE` with no `TypedLayoutDescriptor` — the one layout state where the per-store `layout_note_slot` call is load-bearing for GC correctness rather than a precision hint, since it is the only writer of the pointer-mask bit the collector reads. That blocked the full pointer-masked layout-note elision (the larger half of Phase 4b.1 in #6919, which had to narrow to the value-only predicate because of it). | ||
|
|
||
| **The arm appears to be unreachable today, and no reproducer exists.** `call_local_constructor_symbol` returns `None` only when `ctx.methods` lacks `(class.name, "<Class>_constructor")`, but `lower_new_impl` resolves `class` exclusively from `ctx.classes` (`new.rs:237`), `ctx.classes` *is* the `class_table`, and `build_method_names` iterates `class_table.values()` inserting that key unconditionally for every entry — local and imported alike (`method_registry.rs:112-119`). An instrumented compiler reported zero hits across all 430 `test-files/test_gap_*.ts` (codegen-only) plus three hand-written self-referential construction shapes (self-construction in a method, a recursive own constructor, a field initializer constructing its own class) — all of which do enter the recursion-guarded branch and all of which take the `Some` arm that already emitted the init. | ||
|
|
||
| The emitter lands anyway so the invariant "a user-class instance reaching a class-field store carries a typed descriptor, or is explicitly `GC_LAYOUT_UNKNOWN`" holds by construction at this exit rather than by an accident of the registry that a future change could silently revoke. Cost is zero — dead path today, and `emit_typed_shape_layout_init` is itself a no-op for a class with no `class_keys_globals` entry. | ||
|
|
||
| Because the arm is unreachable, no behavioral test can fail before and pass after. What is testable is the premise the fix rests on — the instance reaching this exit has had no constructor run, so the layout init sees all-`undefined` fields. `gc::tests::layout_trace::typed_shape_layout_init_on_unconstructed_instance_is_conservative` pins that a fresh instance really is `GC_LAYOUT_POINTER_FREE` with no descriptor; that a raw-f64 mask over `undefined` fields is refused and downgraded to `GC_LAYOUT_UNKNOWN` (why emitting the init is safe); and that a pointer-only mask is installed and its slot traced with no `layout_note_slot` call (why emitting it is useful). Green across the GC stress matrix: `PERRY_GC_FORCE_EVACUATE=1`, `PERRY_GC_VERIFY_EVACUATION=1`, `PERRY_GEN_GC=0`, `PERRY_WRITE_BARRIERS=0` and combinations. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: PerryTS/perry
Length of output: 50370
🏁 Script executed:
Repository: PerryTS/perry
Length of output: 50370
🏁 Script executed:
Repository: PerryTS/perry
Length of output: 32037
Root both heap objects across the allocation and tracing boundaries.
js_string_from_bytes()can allocate, andtrace_marked_objects()relocates marked nursery objects. Keepptr_onlyandchildinRuntimeHandleScope, reload them before writing the child slot after allocation and before reading its flags after tracing, and derivechild_headerfrom the refreshed child handle.🤖 Prompt for AI Agents
Sources: Coding guidelines, Learnings