← All issues

[JSC] Inline `NumericStrings` int cache lookup in DFG and FTL `ToString(Int32)`

186e2a9

NumericStrings는 VM 단위로 유지되는 캐시로, 정수를 미리 계산된 JSString 표현과 대응시킵니다. 두 계층으로 구성됩니다. 하나는 0..1023 범위의 small-int를 직접 인덱싱하는 배열이고, 다른 하나는 WTF::IntHash<int> (rapidHashMix64 mum mixer)를 키로 사용하는 hash 기반의 m_intCache입니다. DFG/FTL이 cache lookup을 인라인화할 때는, hash 연산·memory load·조건 분기를 native instruction으로 직접 내보냅니다. C++ call frame은 없으며, 명시적으로 내보낸 것 이외의 runtime guard도 존재하지 않습니다.

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

- slowCases.append(branch32(AboveOrEqual, valueGPR, TrustedImm32(NumericStrings::cacheSize)));
- move(valueGPR, resultGPR);
- lshiftPtr(TrustedImm32(WTF::fastLog2(static_cast<unsigned>(sizeof(NumericStrings::StringWithJSString)))), resultGPR);
- addPtr(TrustedImmPtr(vm().numericStrings.smallIntCache()), resultGPR);
- loadPtr(Address(resultGPR, NumericStrings::StringWithJSString::offsetOfJSString()), resultGPR);
- doneCases.append(branchTestPtr(NonZero, resultGPR));
- callOperation(operationInt32ToStringWithValidRadix, resultGPR, LinkableConstant::globalObject(*this, node), valueGPR, TrustedImm32(10));

Source/JavaScriptCore/b3/B3AbstractHeapRepository.h

+ macro(IntCache, 0, sizeof(NumericStrings::CacheEntryWithJSString<int>)) \

이 commit은 64-bit DFG와 FTL backend에서 NumericStrings int-cache hash lookup을 인라인화했습니다. 대상은 기존 0..1023 small-int 범위 밖의 값에 대한 radix-10 ToString(Int32) 처리입니다. rapidHashMix64를 JIT machine code로 직접 내보내 m_intCache를 인덱싱하고, key가 일치하면 캐시된 JSString을 반환합니다. miss인 경우에만 vmCall이 실행됩니다. 새롭게 추가된 IntCache B3 abstract heap은 optimizer의 load 재배치 방식을 제어합니다. 32-bit DFG backend는 기존 small-int 전용 경로를 유지합니다. rapidHashMix64에 필요한 128-bit 곱셈이 32-bit 환경에서는 실용적이지 않기 때문입니다.

이로써 hot JIT code에서 large integer를 string으로 변환하는 속도가 약 2.38배 향상됩니다. 단, 새롭게 내보내진 JIT code는 runtime hash table에서 GC가 관리하는 JSString 포인터를 직접 역참조합니다.

🔒

New JIT-emitted GC-pointer loads from a hash table — edge cases in the inline fast path and B3 alias analysis are worth security investigation.

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