Problem
After #1003, SerializeJSONArray no longer allocates decimal index spellings, but each present packed element still enters the full string-keyed Interpreter.getProperty path. The frozen 2,200 x 90 representative rows perform 594,000 such reads. The index is already available as usize, yet generic lookup reparses it, probes indexed descriptor state, and enters prototype/generic property scaffolding before returning a present dense own value.
Change boundary
Add a narrow SerializeJSONProperty fast path for a direct ordinary Array whose current index has no own accessor and has a present dense element. Read the live value for every index immediately before toJSON/replacer processing. Any proxy, arguments mapping, accessor, hole, sparse named property, inherited property, exotic hook, or representation change must fall back to ordinary Get. Preserve shared-realm lock discipline and never hold an object lock across user code.
This issue does not authorize snapshotting element values: earlier toJSON/replacer callbacks can mutate later indices and those mutations must remain visible.
Completion
Add mutation, accessor, sparse/inherited, proxy, and arguments witnesses. Retain JSON Test262 and required VM/tree agreement; rerun OOM/deep/cycle/GC plus TSan/no-GIL gates. Compare seven exact-parent alternating pairs on both frozen JSON rows, the array-heavy shallow-4096 row, and the object-only depth-4096 control with exact checksums. Land only on a measured non-regression.