[JSC] Map/Set iterator next must not touch JSMapIterator/JSSetIterator directly
7937fd7
ObjectAllocationSinking은 객체가 외부로 노출되지 않을 때 heap에 할당된 객체를 virtual SSA 필드로 대체하는 DFG optimization입니다. 이 최적화가 정상적으로 동작하려면 모든 쓰기 연산이 명시적인 PutInternalField 노드로 드러나야 합니다. OSR exit는 JIT 실행 도중 interpreter로 제어를 넘기는 시점이며, 이미 변경된 객체 상태는 그 순간 영구적으로 반영됩니다. 기존 MapIteratorNext는 iterator의 internal storage pointer와 bucket index를 노드 내부에서 암묵적인 side effect로 업데이트하고 있었습니다.
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
- Node* storage = addToGraph(MapIteratorNext, Edge(iterator, MapIteratorObjectUse));
- setResult(storage);
+ Node* tuple = addToGraph(MapIteratorNext, Edge(storageField), Edge(iteratedObjectField, MapObjectUse), Edge(entryField));
+ Node* newStorage = addToGraph(ExtractFromTuple, OpInfo(0), tuple);
+ newStorage->setResult(NodeResultJS);
+ Node* newEntry = addToGraph(ExtractFromTuple, OpInfo(1), tuple);
+ newEntry->setResult(NodeResultInt32);
+ addToGraph(PutInternalField, OpInfo(storageFieldIndex), mapIterator, newStorage);
+ addToGraph(PutInternalField, OpInfo(entryFieldIndex), mapIterator, newEntry);
+ FrozenValue* sentinelConst = m_graph.freezeStrong(m_graph.m_vm.orderedHashTableSentinel());
+ Node* done = addToGraph(CompareEqPtr, OpInfo(sentinelConst), newStorage);
+ setResult(done);
이 리팩터링으로 MapIteratorNext는 (storage, entry) 튜플을 반환하는 stateless read로 전환되었습니다. ByteCodeParser는 관련된 key/value 로드가 전부 완료된 후에야 새로운 storage와 entry index를 확정하는 명시적인 PutInternalField 노드를 생성합니다. 이를 통해 전체 write set이 두 최적화 경로 모두에 노출됩니다.
Significance
Map/Set에 대한 hot for-of 루프에서 heap allocation을 제거하는 iterator sinking이 가능해졌습니다. 또한 deferred commit을 통해, 기존에 OSR exit 발생 시 iterator가 미확정 중간 상태로 남아 있던 correctness 문제가 해결되었습니다.
Audit directions
Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaa Aaaaa a Aaaaaaa Aaaaa Aaaaaaaa Aaaaaaa Aaa Aaaaa Aaaa Aaa Aaaaa Aaaa Aa Aaaaa Aaa Aaa Aaaaaaaaaaa Aaaaa Aaaa Aaa Aaaaaaaaaaaaaaa Aaaa Aa Aaa Aaaaa Aaaaaa Aaaaa Aaaaaaa Aaaaaaaa Aa Aaa Aaaaaaaaa Aaaaaaaa Aaa Aaaaaa Aaaa Aaaa Aaaa Aa Aaaa Aaaaaaaaa Aa Aaa Aaaaaaaaaa Aaa Aaaa Aaaaa
Aa Aaaaaaaa Aaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaa Aa Aa Aaa Aaaaa Aaaa Aaaaaaaa a Aa Aaa Aa Aaaa Aaaa Aaaaaa Aaa Aa a Aa Aaa Aaa Aaaa Aaa Aaaaaaaaaaa Aaaaaa Aaa Aaa Aaaaa Aa Aaaa Aaa Aaa Aaaa Aaaaa
Aaaaaaaa Aaaaa Aaaa Aaaaaaaaaaaa Aaaaaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaaaaaaaaaa Aa Aaaaaaaa Aaaa Aa Aaa Aaaaaaaaaaaaa Aaaa Aaaaa a Aaaaaaa Aaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaa Aaaaaaaaaa Aa Aaaaaaaaaaaaaaa Aaa Aaaaa Aaaa Aaa Aaa Aaa Aaaaa a Aaa Aaa Aaaaaaaaaaa Aaaa Aaa Aa Aaaaaaaa Aa Aa Aaaa Aaaa
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaa Aaaaa Aaaaaaa Aaaaaa Aaa Aa Aaaaaaaaa Aaa Aa Aaa Aaaa Aaaa Aa Aaaaa Aaaaaaaaa Aa Aaa Aaaaaaaaaaa Aaaa Aaaaaaaaa Aa Aaaaaa Aaaaaa a Aaaaaa Aaaaaaaa Aaaa Aaa Aaaaa Aaa Aaa Aaaaa
🔒Several edge cases in the new deferred-commit and iterator-sinking paths are worth security investigation.
더 확인하려면 구독해 주세요