Allocation-free FastArray iteration with `op_iterator_close_check`
Component: JSC bytecode | 35637c6
op_iterator_open/op_iterator_next는 일반적인 JS iteration protocol을 구현합니다. 기존 FastArray path는 arrayIteratorProtocolWatchpointSet 아래에서 일반 Array를 별도로 처리합니다. 이 watchpoint는 Array.prototype[Symbol.iterator]나 %ArrayIteratorPrototype%.next가 교체되거나, prototype chain에 return이 나타나면 무효화됩니다. 이번 commit부터 FastArray mode에서는 op_iterator_open마다 JSArrayIterator를 allocate하지 않습니다. 대신 iteration state(array + index)는 sentinel을 이용해 iterator/next/iterable bytecode operand에 직접 저장됩니다. 새로 추가된 op_iterator_close_check opcode는 close 시점에 watchpoint가 이미 무효화된 경우에만 실제 JSArrayIterator를 뒤늦게 생성(materialize)합니다.
Significance
JS에서 가장 자주 실행되는 경로에 속하는 for-of와 array destructuring에서, loop를 열 때마다 발생하던 iterator allocation이 사라졌습니다. 다만 그 대가로 LLInt/Baseline/DFG 전반과 OSR 과정에서 기존 operand의 의미가 재정의되었습니다.
Audit directions
실행이 interpreter에서 시작되든, loop 도중 OSR로 tier-up하든, fast path에서 벗어나든 state machine은 항상 동일하게 재구성되어야 합니다. 문제는 DFG가 이 operand들을 typed value로 다룬다는 점입니다. 특히 ObjectUse check는 hasSeenFastArray metadata bit에 따라 조건부로 생략됩니다. 그래서 tier마다 iterator/next/iterable을 읽고 쓰는 방식이 조금이라도 어긋나면 type confusion 위험이 생깁니다. 좁은 범위: OSR entry/exit 지점에서 각 tier가 sentinel 상태와 materialize된 상태를 어떻게 구분하는지 점검할 필요가 있습니다. 넓은 범위: operand slot을 tier 간 state machine으로 재활용하는 bytecode라면 모두 같은 위험을 공유합니다. 단서: 다른 tier가 설정한 metadata bit를 기준으로 ObjectUse check를 생략하는 코드입니다.