Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: d11c8c7ba675067079fe261af351c44e5fd3278b
https://github.com/WebKit/WebKit/commit/d11c8c7ba675067079fe261af351c44e5fd3278b
Author: Sosuke Suzuki <[email protected]>
Date: 2026-07-09 (Thu, 09 Jul 2026)
Changed paths:
A JSTests/microbenchmarks/await-async-function-call-chain.js
A JSTests/microbenchmarks/promise-then-chain-distinct-functions.js
A JSTests/stress/microtask-call-cache.js
M Source/JavaScriptCore/interpreter/MicrotaskCall.h
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/JSMicrotask.cpp
M Source/JavaScriptCore/runtime/JSMicrotask.h
M Source/JavaScriptCore/runtime/JSPromise.cpp
M Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
M Source/JavaScriptCore/runtime/MicrotaskQueue.cpp
M Source/JavaScriptCore/runtime/MicrotaskQueueInlines.h
Log Message:
-----------
[JSC] Use a polymorphic cache for microtask calls
https://bugs.webkit.org/show_bug.cgi?id=318847
Reviewed by Yusuke Suzuki.
The microtask drain loop has a call cache with a single entry. It
remembers the last callee (executable, CodeBlock, and entry address), and
a hit skips getCallData / prepareForExecution / incoming-call relinking.
But one entry misses whenever an async function awaits another async
function: the callee's completion wakes the caller, so their resumes are
always adjacent in the microtask stream, and the cache never sees the
same callee twice in a row. This is the common shape of async code, and
the miss path took ~14% of drain time in an await-chain profile.
This change widens the cache to 8 entries with round-robin replacement,
so all callees of a typical await/then chain stay cached.
It also inlines JSGlobalObject::queueMicrotask and microtaskQueue(),
which were out-of-line and copied a QueuedTask on every enqueue. This
part alone is worth about 5-8% on promise-heavy microbenchmarks.
Baseline
Patched
promise-then-chain-distinct-functions 16.9122+-0.1662 ^
10.7162+-0.1512 ^ definitely 1.5782x faster
await-async-function-call-chain 16.0482+-0.1623 ^
12.5936+-0.2134 ^ definitely 1.2743x faster
Tests: JSTests/microbenchmarks/await-async-function-call-chain.js
JSTests/microbenchmarks/promise-then-chain-distinct-functions.js
* JSTests/microbenchmarks/await-async-function-call-chain.js: Added.
(async d5):
(async d4):
(async d3):
(async d2):
(async d1):
(async run):
* JSTests/microbenchmarks/promise-then-chain-distinct-functions.js: Added.
(async run):
* JSTests/stress/microtask-call-cache.js: Added.
(shouldBe):
(async a1):
(async a2):
(async a3):
(async a4):
(async a5):
(async a6):
(async a7):
(async a8):
(async a9):
(async a10):
(async a11):
(async a12):
(makeAdder.return.async adder):
(makeAdder):
(async test):
(async run):
* Source/JavaScriptCore/interpreter/MicrotaskCall.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::microtaskQueue const): Deleted.
(JSC::JSGlobalObject::queueMicrotask): Deleted.
* Source/JavaScriptCore/runtime/JSMicrotask.cpp:
(JSC::callMicrotask):
(JSC::runInternalMicrotask):
* Source/JavaScriptCore/runtime/JSMicrotask.h:
* Source/JavaScriptCore/runtime/JSPromise.cpp:
* Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp:
* Source/JavaScriptCore/runtime/MicrotaskQueue.cpp:
(JSC::runMicrotask):
(JSC::MicrotaskQueue::drainImpl):
* Source/JavaScriptCore/runtime/MicrotaskQueueInlines.h:
(JSC::JSGlobalObject::microtaskQueue const):
(JSC::JSGlobalObject::queueMicrotask):
Canonical link: https://commits.webkit.org/316864@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications