← All issues

JSC Inline Cache for undefined/null/true/false Property Keys

3ba3be2

Source/JavaScriptCore/bytecode/Repatch.cpp

+static NonStringPrimitiveKeyType nonStringPrimitiveKeyForSubscript(JSValue subscript)
+{
+ if (subscript.isUndefined())
+ return NonStringPrimitiveKeyType::Undefined;
+ if (subscript.isNull())
+ return NonStringPrimitiveKeyType::Null;
+ if (subscript == jsBoolean(true))
+ return NonStringPrimitiveKeyType::True;
+ if (subscript == jsBoolean(false))
+ return NonStringPrimitiveKeyType::False;
+ return NonStringPrimitiveKeyType::None;
+}

Source/JavaScriptCore/bytecode/AccessCase.cpp

+AccessCaseType AccessCase::convertToNonStringPrimitiveKeyAccessType(
+ AccessCaseType type, NonStringPrimitiveKeyType keyType)
+{
+ // Converts Load => IndexedUndefinedKeyLoad, etc.
+ // Transition => IndexedUndefinedKeyTransition, etc.
+ ...
+}

JSC의 inline cache(IC)는 JIT 컴파일 환경에서 property access를 빠르게 처리하는 핵심 메커니즘입니다. GetByVal이나 PutByVal이 동일한 key type과 object 구조로 반복 실행될 때, IC는 type에 특화된 machine-code stub을 생성해 이후의 C++ dispatch를 우회합니다. 시스템은 typed "access case" 단위로 구성되는데, Load(own property hit), Miss(property 없음), Transition(새 property 추가 시 structure 변경), Replace(기존 property 덮어쓰기) 등이 있으며 각각 structure check로 보호됩니다. 기존에는 undefined 같은 non-integer primitive key가 문자열 "undefined"로 coerce되어, string 기반 IC stub이나 generic slow path로 처리되었습니다.

이 commit은 새로운 access case type 계열을 도입했습니다. IndexedUndefinedKeyLoad, IndexedNullKeyMiss, IndexedTrueKeyTransition 등이 여기에 해당합니다. 이들은 문자열로 coerce하는 대신, key register에 대해 identity check(isUndefined(), isNull() 등)를 직접 수행한 뒤 일반적인 structure 기반 property lookup으로 진행하도록 설계되었습니다. 새로운 stub은 normal 형태와 handler(사전 컴파일) 형태 모두 구현되었으며, repatch 로직에서는 nonStringPrimitiveKeyForSubscript()가 해당 primitive를 감지해 convertToNonStringPrimitiveKeyAccessType()으로 라우팅합니다.

GetByVal IC dispatch (after this patch):

  key register
       │
       ├─ isInt32?          ──► [existing Int32 IC stubs]
       │
       ├─ isUndefined?      ──► IndexedUndefinedKeyLoad / Miss
       ├─ isNull?           ──► IndexedNullKeyLoad / Miss
       ├─ isTrue?           ──► IndexedTrueKeyLoad / Miss
       ├─ isFalse?          ──► IndexedFalseKeyLoad / Miss
       │
       ├─ isString/Symbol?  ──► [existing string IC stubs]
       │
       └─ other             ──► slow path (C++ call)

obj[undefined]obj[null] 같이 실제 코드에서 흔히 쓰이는 패턴이 이제 slow-path C++ 대신 JIT-compiled fast path로 처리됩니다. JSC에서 보안상 가장 민감한 서브시스템 중 하나에, 상당한 규모의 JIT code generation과 IC dispatch 로직이 새롭게 추가된 셈입니다.

🔒

New JIT stubs for a subtle key-coercion bypass — several edge cases in the repatch path and guard emission logic are worth investigating.

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