← 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's DFG and FTL compilers recognize "intrinsic" call sites during bytecode parsing and substitute dedicated IR nodes instead of emitting a generic call. IsCellWithType is one such node: it checks the JSType field in a JSCell's structure — a byte-sized tag stored at a fixed offset in every heap object. This commit promotes Error.isError from a plain native C++ function to a JIT-recognized intrinsic, replacing the function call with a single type-tag comparison against ErrorInstanceType. Benchmarks show 1.7–2.3x speedup across error, non-error, and mixed input shapes.

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

The correctness of this fast path is critical: if any Error subclass instance (built-in or user-defined) carries a JSType tag other than ErrorInstanceType, the JIT silently returns false where the interpreter returns true, creating a JIT-confusion bug. The Proxy semantics are also worth noting: if a Proxy wrapping an Error reaches the intrinsic, the JIT checks the tag on the Proxy wrapper itself (not the target), returning false — this is actually spec-compliant (Error.isError is deliberately non-Proxy-trapping), but the JIT/interpreter boundary should agree in all scenarios.

🔒

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

Subscribe to read more