-
-
Notifications
You must be signed in to change notification settings - Fork 164
shapes: true field representations and one birth shape (step 5 P2b–P2d, T1) #11674
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Charter step 5 (T1): a class whose constructor prologue writes every `number` field from a parameter before anything can read it (the #7510 "declared at allocation" proof) is now born with a shape whose representation is `F64` for exactly those fields. Codegen makes the decision once (`typed_shape::class_birth_rep_in`) and passes the word to the module-init mint (`js_object_shape_id_for_class_keys{,_live}` and `js_gc_typed_shape_id_for_keys` take a trailing `rep: u64`); the inline allocation and the runtime stamped allocator birth-fill those lanes with `+0.0` instead of `undefined`; the class-field store precheck finite-tests every value bound for an `F64` birth lane, so a non-Number or non-finite value takes the checked, generalizing path. The rep is part of a birth shape's static-id content (`static_shape_ids::BirthShape::rep`; `js_object_shape_id_for_class_keys_static` takes it too), so an importing module's all-`Any` stub never adopts an `F64` birth id. `PERRY_FIELD_REPR_VERIFY` gains the reverse typed-layout cross-check: a compiled birth id that declares an `F64` lane may not leave any raw-f64 slot of its intact layout `Any`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| Class instances can now keep a Number-only field in its unboxed form too. The | ||
| restriction that kept every class instance on the boxed representation is | ||
| gone: every class-field fast path already matches the instance by its exact | ||
| shape, and a shape that marks a field Number-only sends other values through | ||
| the checked path. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Deleting a property from an object whose Number-only fields are stored | ||
| unboxed no longer runs an extra release step first; the delete already moves | ||
| the object to a general shape before it shifts any value. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,8 @@ | ||||||||||||||||
| Every compiled fast path that stores into an object's field now respects the | ||||||||||||||||
| field's recorded representation: when a shape says a slot holds a Number, the | ||||||||||||||||
| inline store and the inline property-add accept only a plain double there and | ||||||||||||||||
| send anything else (an object, a string, an integer box, NaN, Infinity) to the | ||||||||||||||||
| runtime, which re-describes the field before storing. Deleting a property | ||||||||||||||||
|
Comment on lines
+3
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Correct the description of what the runtime does with NaN, Infinity, and integer boxes. The fragment lists "an integer box, NaN, Infinity" together with objects and strings as values the runtime "re-describes the field" for. These three are JS Numbers. The checked store keeps the 📝 Proposed wording-inline store and the inline property-add accept only a plain double there and
-send anything else (an object, a string, an integer box, NaN, Infinity) to the
-runtime, which re-describes the field before storing. Deleting a property
+inline store and the inline property-add accept only a plain finite double
+there and send anything else to the runtime. The runtime stores an integer
+box, NaN, or Infinity as its canonical double and keeps the representation; it
+re-describes the field only for a non-Number value. Deleting a property📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| drops the representation before it moves values between slots. A new | ||||||||||||||||
| `field-rep-assert` runtime feature (always on in debug builds) checks at every | ||||||||||||||||
| collection that each such slot holds a double. | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| When a property is sometimes added with a non-number value, objects built the | ||
| same way now settle on one shape for it instead of splitting between a | ||
| number-only shape and a general one, so code that reads or writes that | ||
| property keeps one fast path. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| A property add now publishes its field representation in the same shape | ||
| publish that installs the key (or the grown slot bound), instead of minting an | ||
| all-`Any` shape first and the representation-carrying one after it. Shape | ||
| mints on tsc return to their pre-P2b count (14,345 vs 14,335; P2b had 19,438). | ||
|
Comment on lines
+3
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Rewrite the PR Several fragments describe intermediate slices of this PR (P2b, P2c, P2d, a removed release step, a fixture change). These are not final user-visible behavior. When the release notes are assembled, the entries reference states that never shipped and partly contradict each other.
Based on learnings: "describe the final shipped behavior as one coherent release-note entry. Do not include separate development-slice narratives that may contradict one another when the release notes are assembled." 📍 Affects 4 files
🤖 Prompt for AI AgentsSource: Learnings |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| Adding a property now records its field representation in the shape: a key-add | ||
| of a Number into an inline slot gives the new shape an `F64` lane, any other | ||
| value (or an overflow slot) an `Any` lane, and the predecessor's lanes carry. | ||
| The transition cache needs no new key bit: a cached edge serves a value only | ||
| when its target's lane admits it (an `F64` lane refuses a non-Number, a target | ||
| with a deprecated lane never serves, so new objects converge on the normalized | ||
| shape). The by-name cache-hit writers and `js_object_set_field` now store | ||
| through the checked funnel, so an `F64` slot always holds a canonical double. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Charter step 5: a loop region's bare store runs no field-representation check, so the region now tells the runtime which keys it may store a value not proven a canonical double into (`js_region_loop_prime` / `js_region_loop_pack` take a trailing `boxed_mask`), and the pack refuses a word whose shape has a non-`Any` lane at such a key (census route `rt_rloop_refuse_f64_stored`); the static supplier (`static_region_slots`) refuses the same keys against the birth rep. A proven double still stores bare into any lane. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| The field-representation store-check test now reaches the compiled store and | ||
| property-add fast paths with a non-Number after they were primed on a Number | ||
| field, and forces a collection after each case, so a fast path that skipped | ||
| the check fails the test instead of passing unnoticed. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Charter step 5 (P2d): `PERRY_FIELD_REPR_VERIFY=1` checks the field-representation invariant at every object trace in a runtime built with `gc-instruments` (always on in debug and with `field-rep-assert`), plus a cross-check that an intact typed layout never calls an F64 lane a pointer slot; a binary without the feature aborts at startup when the knob is set. Every property-IC miss entry (generic get fast miss, put-value set and dynamic set misses, class-field get/set fast misses) now migrates a receiver whose shape has a deprecated lane before it learns anything from it. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - A method call on a receiver whose class codegen proved (the `$typed_f64_recv` clone route in `try_lower_instance_method_call`) now runs the clone only while the receiver's (class id, ShapeId) pair is the class's own (`emit_class_field_read_precheck`, raw): an alias the object escaped to may store a non-Number into a field, which moves the object off its birth shape, and the clone reads its fields as raw doubles. Otherwise the call takes the generic target. |
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.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Rewrite this as one shipped-behavior entry.
This line labels the change “Charter step 5 (T1)” and lists internal codegen and runtime details.
changelog.d/11674-shape-field-rep-class-instances.mdalready describes the user-visible behavior. Merge the overlapping content into one final-behavior entry, retaining any distinct shipped behavior.Based on learnings, Perry changelog fragments in
changelog.d/should describe final behavior in one coherent release-note entry, not separate development-slice narratives.🧰 Tools
🪛 LanguageTool
[grammar] ~1-~1: Use a hyphen to join words.
Context: ...); the inline allocation and the runtime stamped allocator birth-fill those lanes...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents
Source: Learnings