Parent: #473
JSON.stringify builds its canonical output in the precise heap temporary allocator, then Value.strAlloc copies that completed byte sequence into another canonical allocation before managed string storage can consume or transcode it. The ownership-aware string path already accepts allocator-owned bytes and handles canonical/flat conversion plus cleanup.
Executed exact-parent evidence on real zig-gc, stripped ReleaseFast, frozen representative_json rows (2,200 jobs x 90 round trips):
- checksum:
324952086on parent and candidate, base and variant - backing allocations:
1,793,004 -> 1,595,004on both rows (-198,000, exactly one per stringify) - backing requested bytes:
597,332,140 -> 582,348,852base (-14,983,288) - backing requested bytes:
597,282,868 -> 582,324,324variant (-14,958,544) - GC cells, shape transitions, and property-lock counts unchanged
- one diagnostic CPU pass: base
588.876 ms -> 580.944 ms; variant573.591 ms -> 574.729 ms(timing publication remains blocked until a clean host)
The proposed fix transfers the completed ArrayList slice through Value.strOwned using the allocator that owns it. This is not a JSON fast-path or external implementation; it removes a redundant whole-result copy while preserving the existing managed-string ownership and physical-storage conversion path.
Definition of done:
- allocation-failure and string-storage unit coverage passes
- pinned Test262 JSON subtree and VM agreement remain clean
- no-GIL TSan stringify witness remains clean
- exact-parent frozen checksums and counters are recorded
- clean-host seven-sample publication under #473 before closing