`JSONTransitionCache` for `JSON.parse` Structure transitions
Component: JSC runtime | 1e80c1e
JSC는 객체의 shape를 Structure로 표현하며, property가 하나 추가될 때마다 Structure transition이 발생합니다. JSON.parse는 property를 하나씩 추가하며 객체를 생성합니다. 그래서 객체 하나를 만드는 동안 여러 Structure를 차례로 거치게 됩니다. 기존에도 "single transition" 최적화가 있었습니다. 다만 공유되는 빈 객체 Structure에서 parsing을 시작하는 경우에는 효과가 없었습니다. 이 Structure에서는 transition 대상이 여러 갈래로 나뉘기 때문입니다. 이 commit에서는 JSONTransitionCache가 추가되었습니다. from→to Structure 쌍을 저장하는 hash 기반 테이블로, 256개 entry의 primary와 64개 entry의 secondary로 구성됩니다. 이를 통해 JSON.parse는 transition table 조회를 건너뛸 수 있습니다.
Significance
같은 key 구성을 공유하는 객체가 많을 때, 관찰되는 semantics를 바꾸지 않고 JSON.parse 속도를 높였습니다. 다만 매우 hot한 parsing 경로에 Structure identity를 key로 하는 persistent cache가 추가되었고, 이 cache는 GC가 추적하는 대상입니다. 각 entry에는 from/to Structure만 저장되며, property 이름은 저장되지 않습니다. 대신 from-StructureID, key 길이, 첫 문자와 마지막 문자를 조합한 hash만 사용합니다. 이 값은 destination Structure에 기록된 transition 이름과 다시 대조해 검증됩니다. 한편 entry에는 write barrier가 없고, 평상시에는 mark되지 않습니다. parse가 진행 중일 때는 visitAggregate()가 모든 entry를 mark합니다. 반대로 실행 중인 parse가 없으면, GC가 끝날 때마다 reconcileAtGCEnd()가 cache 전체를 비웁니다. 두 판단 모두 mutator가 정지된 상태에서 이루어집니다. 따라서 cache가 일관되지 않은 parse 상태를 관찰하는 일은 발생하지 않습니다.
Audit directions
좁은 범위: write barrier 없이 parse 중에만 mark하는 방식은 하나의 전제에 의존합니다. parse가 진행될 수 있는 모든 시점에 visitAggregate()가 살아 있는 entry를 빠짐없이 mark해야 한다는 것입니다. 따라서 parse-in-progress flag가 모든 JSON.parse 재진입 지점을 커버하는지 점검할 필요가 있습니다. 넓은 범위: write barrier 없이 raw Structure pointer를 보관하는 GC-visible cache는 stop-the-world 시점의 일괄 삭제에 안전성을 의존합니다. 유사한 transition cache나 IC cache에서도 같은 marking-vs-wipe 계약이 지켜지는지 검토해야 합니다. 판별 단서: WriteBarrier<> wrapper 없이 cell pointer를 저장하는 cache.