Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 8e15aeeee3bc2d5257fec145a08f5532ae7447d7
      
https://github.com/WebKit/WebKit/commit/8e15aeeee3bc2d5257fec145a08f5532ae7447d7
  Author: Sosuke Suzuki <[email protected]>
  Date:   2026-07-04 (Sat, 04 Jul 2026)

  Changed paths:
    A JSTests/microbenchmarks/throw-new-error-from-deep-frames.js
    A JSTests/microbenchmarks/throw-preallocated-error-from-deep-frames.js
    A JSTests/microbenchmarks/throw-sentinel-from-deep-frames.js
    M Source/JavaScriptCore/interpreter/Interpreter.h
    M Source/JavaScriptCore/interpreter/InterpreterInlines.h
    M Source/JavaScriptCore/interpreter/StackVisitor.cpp
    M Source/JavaScriptCore/interpreter/StackVisitor.h
    M Source/JavaScriptCore/interpreter/VMEntryRecord.h
    M Source/JavaScriptCore/jit/RegisterSet.cpp
    M Source/JavaScriptCore/jit/RegisterSet.h

  Log Message:
  -----------
  [JSC] Improve exception unwinding performance
https://bugs.webkit.org/show_bug.cgi?id=318292

Reviewed by Yusuke Suzuki.

I noticed that JSC is significantly slower than V8 at unwinding when an
exception is thrown from a deep call stack. Profiling shows that most of
the time is spent in per-frame callee-save bookkeeping during
Interpreter::unwind.

This patch applies three independent optimizations:

1. Make StackVisitor::Frame::calleeSaveRegistersForUnwinding() return
   const RegisterAtOffsetList* instead of std::optional<RegisterAtOffsetList>.
   Every list it returns is a long-lived object, so there is no need to
   heap-allocate and free a copy for every unwound frame.

2. Add an m_vmEntryRecord field to UnwindFunctorBase, computed once in the
   constructor, instead of calling vmEntryRecord() on every call to
   copyCalleeSavesToEntryFrameCalleeSavesBuffer.

3. Use a prebuilt table (RegisterSet::vmCalleeSaveBufferSlotsByRegIndex())
   that maps Reg::index() to the register's slot in the entry frame
   callee-save buffer, instead of doing a binary search per register.
   This turns each lookup from O(log n) into O(1).

                                                   Baseline                  
Patched

throw-new-error-from-deep-frames              176.5424+-0.9251     ^    
129.7769+-1.6492        ^ definitely 1.3604x faster
throw-preallocated-error-from-deep-frames
                                              265.7363+-2.6056     ^    
175.6531+-2.0253        ^ definitely 1.5128x faster
throw-sentinel-from-deep-frames               266.3385+-1.5604     ^    
176.2640+-1.5277        ^ definitely 1.5110x faster

Tests: JSTests/microbenchmarks/throw-new-error-from-deep-frames.js
       JSTests/microbenchmarks/throw-preallocated-error-from-deep-frames.js
       JSTests/microbenchmarks/throw-sentinel-from-deep-frames.js

* JSTests/microbenchmarks/throw-new-error-from-deep-frames.js: Added.
(thrower):
(i.catch):
* JSTests/microbenchmarks/throw-preallocated-error-from-deep-frames.js: Added.
(thrower):
(i.catch):
* JSTests/microbenchmarks/throw-sentinel-from-deep-frames.js: Added.
(thrower):
(i.catch):
* Source/JavaScriptCore/interpreter/Interpreter.h:
(JSC::UnwindFunctorBase::UnwindFunctorBase): Deleted.
* Source/JavaScriptCore/interpreter/InterpreterInlines.h:
(JSC::UnwindFunctorBase::UnwindFunctorBase):
(JSC::UnwindFunctorBase::copyCalleeSavesToEntryFrameCalleeSavesBuffer const):
* Source/JavaScriptCore/interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::calleeSaveRegistersForUnwinding):
* Source/JavaScriptCore/interpreter/StackVisitor.h:
* Source/JavaScriptCore/jit/RegisterSet.cpp:
(JSC::RegisterSet::vmCalleeSaveBufferSlotsByRegIndex):
* Source/JavaScriptCore/jit/RegisterSet.h:

Canonical link: https://commits.webkit.org/316511@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to