Problem
A symbolized execution of the frozen representative JSON workload attributes the largest JSON.stringify subtree to ordinary named-property lookup rather than output writing or parsing. The diagnostic sample recorded 1,198 samples below jsonStringify, including 672 in Shape.lookupState, 307 in Interpreter.getPropertyWithReceiverFound, 219 in byte equality, and 160 in Object.namedOwnPropertySnapshot. This profile is a causal locator only; it is not publication timing because the symbolized runner used the arena diagnostic configuration.
SerializeJSONObject already snapshots its property-key list before reading values, but every selected key then takes the complete generic [[Get]] pipeline. On the common direct ordinary-object/data-property case, the current descriptor can be read with Object.namedOwnPropertySnapshot and passed directly into serialization.
Required semantic boundary
- Preserve ECMA-262 SerializeJSONProperty live value reads.
- If the current own descriptor is a data property, use that current value.
- If it became an accessor or disappeared, fall back to full [[Get]] so getters and inherited replacements remain observable.
- Keep Proxy, module namespace, typed-array, host-class, dense-element, and other exotic paths on the generic implementation.
- Preserve replacer PropertyList behavior, toJSON/replacer ordering, abrupt completion, stack-depth/OOM behavior, and no-GIL synchronization.
- Add witnesses where an earlier getter changes a later data value, converts it to an accessor, or deletes it to expose an inherited value.
Evidence and completion
Measure exact-parent alternating samples on both frozen representative_json rows with exact checksums and anti-specialization controls. Qualify focused unit tests, test262 JSON, required VM/tree agreement, deep/cycle/OOM paths, and the shared no-GIL TSan witness. Land only if the change is semantics-preserving and measurably improves the frozen row; otherwise document and reject it.
Parent: #473.