← All issues

Error.isError DFG/FTL intrinsic optimization

6c34b6a

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

+ case ErrorIsErrorIntrinsic: {
+ if (argumentCountIncludingThis < 2)
+ return CallOptimizationResult::DidNothing;
+
+ insertChecks();
+ setResult(addToGraph(IsCellWithType, OpInfo(ErrorInstanceType), get(virtualRegisterForArgumentIncludingThis(1, registerOffset))));
+ return CallOptimizationResult::Inlined;
+ }

Source/JavaScriptCore/runtime/ErrorConstructor.cpp

- JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("isError"_s, errorConstructorIsError, ...);
+ JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("isError"_s, errorConstructorIsError, ..., ErrorIsErrorIntrinsic);

JSC의 DFG와 FTL compiler는 bytecode parsing 단계에서 "intrinsic" 호출 지점을 인식하고, generic call을 생성하는 대신 전용 IR node로 대체합니다. IsCellWithType은 그러한 node 중 하나입니다. heap 객체마다 고정된 offset에 저장된 1바이트 크기의 태그인 JSCell 구조의 JSType 필드를 확인하는 역할을 합니다. 이번 commit은 Error.isError를 단순한 native C++ 함수에서 JIT가 인식하는 intrinsic으로 승격시켰습니다. 결과적으로 함수 호출이 ErrorInstanceType에 대한 단일 type-tag 비교로 대체되었습니다. 벤치마크 결과, error, non-error, mixed 입력 유형 전반에 걸쳐 1.7–2.3배의 성능 향상이 확인되었습니다.

Interpreter path (before):          DFG/FTL path (after):
Error.isError(v)                    Error.isError(v)
  └─► native call                   └─► IsCellWithType(v, ErrorInstanceType)
        └─► errorConstructorIsError        └─► load JSCell.m_type
              └─► return bool                    └─► cmp + setcc → bool

이 fast path의 정확성은 매우 중요합니다. built-in이든 user-defined이든 Error subclass instance가 ErrorInstanceType 이외의 JSType 태그를 보유하는 경우, interpreter가 true를 반환하는 상황에서 JIT가 조용히 false를 반환하게 됩니다. 이는 JIT-confusion bug로 이어집니다.

Proxy 동작 방식도 주목할 필요가 있습니다. Error를 감싼 Proxy가 intrinsic에 도달하면, JIT는 target이 아닌 Proxy wrapper 자체의 태그를 확인하여 false를 반환합니다. 이는 실제로 spec을 준수하는 동작입니다. Error.isError는 의도적으로 Proxy를 trapping하지 않도록 설계되어 있기 때문입니다. 다만 모든 시나리오에서 JIT와 interpreter의 경계가 일치하는지는 별도로 확인이 필요합니다.

🔒

The new JIT fast path for a type-predicate with Proxy and cross-realm edge cases has several audit-worthy corners.

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