← All issues

[JSC] Add Map / Set fast iteration

4337048

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

+ // MapIteratorNext는 iterator를 변경하기 때문에, 이후에는 에러를 던지는 경우를
+ // 제외하고 OSR exit를 수행할 수 없습니다. 그 외의 OSR exit가 발생하면
+ // iterator가 다시 한 번 전진하게 됩니다. normal OSR exit가 절대 발생하지 않는
+ // DFG 노드만 신중하게 출력하므로, 이 부분은 안전합니다.
+ auto mapIteratorNextNode = addToGraph(MapIteratorNext, OpInfo(0), OpInfo(prediction), iteratorNode);
+ auto isDoneNode = addToGraph(MapIteratorNextDone, mapIteratorNextNode);
+ addToGraph(Branch, OpInfo(branchData), isDoneNode);

Source/JavaScriptCore/bytecode/IterationModeMetadata.h

enum class IterationMode : uint8_t {
Generic,
Fast,
+ FastMap,
+ FastSet,
};

JSC의 계층형 JIT는 iterator_open/iterator_next bytecode를 통해 for-of 루프를 bytecode parser 수준에서 인라인 처리합니다. 컬렉션 타입이 인식되면 generic iterator protocol을 우회하는 방식입니다. 기존에는 이 fast path가 array에만 적용되었습니다. 이번 commit은 LLInt, Baseline, DFG, FTL 전 계층에 걸쳐 JSMapJSSet으로 적용 범위를 확장했습니다. 새로운 IterationMode variant인 FastMapFastSet이 추가되었으며, 내부 hash-table cursor를 직접 전진시키는 MapIteratorNext/SetIteratorNext intrinsic도 함께 도입되었습니다.

이번 변경으로 중요한 새 불변 조건이 하나 추가되었습니다. MapIteratorNext가 실행되어 iterator 상태를 변경한 이후에는, DFG가 normal OSR exit를 유발하는 노드를 출력해서는 안 됩니다. normal exit는 interpreter 상태를 복원하고 bytecode를 재실행합니다. 이 과정에서 MapIteratorNext가 다시 호출되면, iterator가 두 번 전진하게 됩니다. 전진 이후에는 exception 경로의 exit만 허용됩니다. 한편 constructArrayPair는 인라인 중 DFG speculation 실패를 방지하기 위해 Contiguous storage를 강제하도록 변경되었습니다.

Map과 Set에 대한 for-of 루프가 hot code에서 1.3~2배 빨라졌으며, 엄격한 OSR exit 제약이 적용된 security-sensitive 컬렉션 iteration을 위한 새로운 JIT 컴파일 fast path가 상당 부분 추가되었습니다.

🔒

New JIT fast paths with explicit OSR exit restrictions and cross-tier iterator state assumptions — several audit directions exist.

더 확인하려면 구독해 주세요