JSC RegExp#lastIndex Inline Cache
d2c63be
Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp
+ case AccessCase::RegExpLastIndexLoad: {
+ ASSERT(!accessCase.viaGlobalProxy());
+ fallThrough.append(jit.branchIfNotType(baseGPR, RegExpObjectType));
+ jit.loadValue(CCallHelpers::Address(baseGPR, RegExpObject::offsetOfLastIndex()), valueRegs);
+ succeed();
+ return;
+ }
+
+ case AccessCase::RegExpLastIndexStore: {
+ ASSERT(!accessCase.viaGlobalProxy());
+ fallThrough.append(jit.branchIfNotType(baseGPR, RegExpObjectType));
+ fallThrough.append(
+ jit.branchTestPtr(
+ CCallHelpers::NonZero,
+ CCallHelpers::Address(baseGPR, RegExpObject::offsetOfRegExpAndFlags()),
+ CCallHelpers::TrustedImm32(RegExpObject::lastIndexIsNotWritableFlag)));
+ jit.storeValue(valueRegs, CCallHelpers::Address(baseGPR, RegExpObject::offsetOfLastIndex()));
+ succeed();
+ return;
+ }
JSC의 inline cache 시스템은 property 연산을 type별로 특화된 machine-code stub으로 캐싱합니다. JIT가 property access를 만나면 해당 객체의 Structure를 키로 삼아 stub을 생성하는데, 이후 동일한 접근에서는 generic slow path 없이 stub을 직접 실행하게 됩니다. 이 commit은 IC가 reg.lastIndex 읽기/쓰기를 직접 처리할 수 있도록 확장한 변경입니다. RegExp#lastIndex는 global/sticky regex 루프의 매 반복마다 접근되는 고빈도 property입니다.
Load IC는 직접 field access 방식입니다. RegExpObjectType을 기준으로 분기한 뒤, 미리 알고 있는 offset에서 값을 읽습니다. Store IC에는 writable-flag 검사가 추가되었습니다. RegExp#lastIndex는 own이자 non-configurable이지만, Object.freeze() 등을 통해 writable 속성이 제거될 수 있습니다. 그러므로 frozen RegExp의 경우 IC는 slow path로 fall through해야 합니다. 벤치마크 결과, 기존 regexp-last-index 벤치마크에서 약 2배, 전용 microbenchmark에서 약 1.3배의 성능 향상이 확인되었습니다.
Significance
regex 처리가 빈번한 코드에서 의미 있는 throughput 향상을 제공하는 변경입니다. 다만 JSC inline cache compiler에 새로운 IC case가 추가될수록 JIT의 attack surface도 그만큼 넓어집니다. Polymorphic IC path는 RegExp 인스턴스뿐 아니라, 우연히 lastIndex property를 가진 일반 객체도 처리해야 합니다. 이 경우 branchIfNotType(baseGPR, RegExpObjectType) guard가 non-RegExp 객체를 generic slow path로 분기시킵니다.
Audit directions
Aaaaaaaaaaaaa Aa Aaaa Aaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaa Aa Aaaaaaaaa Aaa Aa Aaaaaaaaaaaa Aaaa Aa Aaa Aaaaa Aaa Aaa Aaaaa a Aaaaa Aaaa Aaa Aaaaaaaaaaaa Aaaa Aaa Aaa Aaaa Aaa a Aaaaa Aaaaa Aaa Aaaaa Aaaaaaa Aaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaaaaa Aaaa Aaaaa Aaa Aaaa Aaaaaaaaa Aaaaaaaa Aaaaaaaaa a Aaa Aa Aaa Aa Aaa Aaaaa Aaaaaaaa Aaaa Aaaaa Aaaa Aaaa Aaaaa Aaaaaaaaa Aaa Aa Aaa Aaaaaaaaaaaa Aaaa Aaa Aaa Aaa Aaaa Aaaaaaaaaa Aa Aaaaa Aaa Aaa Aaaaa Aaa Aaaaaaaaa Aaaaaaaaaa Aaaa Aaaa Aa Aaa Aa Aaaaaaaaaaa Aaa Aaaaa Aaa Aaaaa Aaaaaa