Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 3f9955f695b6fd08fe816d37aaea66e8e67429fe
https://github.com/WebKit/WebKit/commit/3f9955f695b6fd08fe816d37aaea66e8e67429fe
Author: Yusuke Suzuki <[email protected]>
Date: 2026-05-13 (Wed, 13 May 2026)
Changed paths:
A JSTests/stress/promise-inline-child-reaction.js
A JSTests/stress/promise-packed-layout-gc-stress.js
M Source/JavaScriptCore/b3/B3AbstractHeapRepository.cpp
M Source/JavaScriptCore/b3/B3AbstractHeapRepository.h
M Source/JavaScriptCore/builtins/BuiltinNames.h
M Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
M Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
M Source/JavaScriptCore/bytecode/LinkTimeConstant.h
M Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
M Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
M Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
M Source/JavaScriptCore/dfg/DFGClobberize.h
M Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
M Source/JavaScriptCore/dfg/DFGCloneHelper.h
M Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
M Source/JavaScriptCore/dfg/DFGDoesGC.cpp
M Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
M Source/JavaScriptCore/dfg/DFGLoopUnrollingPhase.cpp
M Source/JavaScriptCore/dfg/DFGMayExit.cpp
M Source/JavaScriptCore/dfg/DFGNode.h
M Source/JavaScriptCore/dfg/DFGNodeType.h
M Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
M Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
M Source/JavaScriptCore/dfg/DFGSafeToExecute.h
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
M Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
M Source/JavaScriptCore/dfg/DFGValidate.cpp
M Source/JavaScriptCore/ftl/FTLCapabilities.cpp
M Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
M Source/JavaScriptCore/ftl/FTLOperations.cpp
M Source/JavaScriptCore/interpreter/Interpreter.cpp
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/JSPromise.cpp
M Source/JavaScriptCore/runtime/JSPromise.h
M Source/WebCore/Modules/streams/StreamInternals.js
M Source/WebCore/Modules/streams/WritableStreamInternals.js
Log Message:
-----------
[JSC] Do not allocate promise reaction when it is initial `then` calls and
one handler attachment
https://bugs.webkit.org/show_bug.cgi?id=314733
rdar://176981580
Reviewed by Yijia Huang.
This patch changes JSPromise layout so that we can avoid promise
reaction cell allocation when it is initial `then` calls and one
handler attachment. This is by-far common case: most of promise
use is having one `then(function () { ... })` fulfill handler and
it is rare that one promise is having multiple reactions. We
optimize this pattern so one reaction case is efficiently packed
without allocating a new promise reaction cell. This is achievable
since we now moved all JSPromise modification code from builtin JS
code to C++, so any new careful handling does not require builtin
JS interaction including JIT code. So,
1. We change JSPromise from JSInternalFieldObjectImpl to normal JS
object. We also add NewPromise / PhantomNewPromise DFG nodes to
keep its efficiency. This model is aligned to JSFunction for
example. So then, we are fine to have much more complicated fields
beyond JSValue fields.
2. We add CompactPointerTuple field in JSPromise to have cell and flags
in one field. This allows us to fold optimized fulfill / reject handlers
placed inside JSPromise instead of allocating a reaction cell.
Tests: JSTests/stress/promise-inline-child-reaction.js
JSTests/stress/promise-packed-layout-gc-stress.js
* JSTests/stress/promise-inline-child-reaction.js: Added.
(shouldBe):
(defer):
(async main):
(main.then):
* JSTests/stress/promise-packed-layout-gc-stress.js: Added.
(shouldBe):
(defer):
(async stressOne):
(async main):
(main.then):
* Source/JavaScriptCore/b3/B3AbstractHeapRepository.cpp:
* Source/JavaScriptCore/b3/B3AbstractHeapRepository.h:
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h:
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::promiseInternalFieldIndex): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_getPromiseInternalField): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putPromiseInternalField): Deleted.
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp:
(JSC::DFG::clobbersExitState):
* Source/JavaScriptCore/dfg/DFGCloneHelper.h:
* Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGLoopUnrollingPhase.cpp:
(JSC::DFG::LoopUnrollingPhase::LoopData::isMaterialNode):
* Source/JavaScriptCore/dfg/DFGMayExit.cpp:
* Source/JavaScriptCore/dfg/DFGNode.h:
(JSC::DFG::Node::convertToNewPromise):
(JSC::DFG::Node::convertToPhantomNewPromise):
(JSC::DFG::Node::convertToNewResolvedPromise):
(JSC::DFG::Node::hasStructure):
(JSC::DFG::Node::isPhantomAllocation):
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileCreatePromise):
(JSC::DFG::SpeculativeJIT::compileNewPromise):
(JSC::DFG::SpeculativeJIT::compileNewResolvedPromise):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileCreatePromise):
(JSC::DFG::SpeculativeJIT::compileNewPromise):
(JSC::DFG::SpeculativeJIT::compileNewResolvedPromise):
* Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp:
* Source/JavaScriptCore/dfg/DFGValidate.cpp:
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileNewPromise):
(JSC::FTL::DFG::LowerDFGToB3::compileCreatePromise):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* Source/JavaScriptCore/ftl/FTLOperations.cpp:
(JSC::FTL::JSC_DEFINE_NOEXCEPT_JIT_OPERATION):
* Source/JavaScriptCore/interpreter/Interpreter.cpp:
(JSC::Interpreter::getAsyncStackTrace):
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/JSPromise.cpp:
(JSC::JSPromise::visitChildrenImpl):
(JSC::JSPromise::resolve):
(JSC::JSPromise::reject):
(JSC::JSPromise::fulfill):
(JSC::JSPromise::pipeFrom):
(JSC::JSPromise::rejectAsHandled):
(JSC::JSPromise::setInlineMicrotaskReaction):
(JSC::JSPromise::setInlineHandlerReaction):
(JSC::JSPromise::spillInlineReaction):
(JSC::JSPromise::reactionHead):
(JSC::JSPromise::asyncStackTraceContext const):
(JSC::JSPromise::performPromiseThen):
(JSC::JSPromise::performPromiseThenWithInternalMicrotask):
(JSC::JSPromise::settleInlineInternalMicrotask):
(JSC::JSPromise::settleInlineHandler):
(JSC::JSPromise::rejectPromise):
(JSC::JSPromise::fulfillPromise):
(JSC::JSPromise::finishCreation):
(JSC::JSPromise::settleInlineReaction): Deleted.
* Source/JavaScriptCore/runtime/JSPromise.h:
(JSC::JSPromise::allocationSize):
(JSC::JSPromise::offsetOfPacked):
(JSC::JSPromise::offsetOfSlot):
(JSC::JSPromise::flags const):
(JSC::JSPromise::status const):
(JSC::JSPromise::isHandled const):
(JSC::JSPromise::settlementValue const):
(JSC::JSPromise::result const):
(JSC::JSPromise::markAsHandled):
(JSC::JSPromise::isFirstResolvingFunctionCalled const):
(JSC::JSPromise::inlineReactionKind const):
(JSC::JSPromise::hasInlineReaction const):
(JSC::JSPromise::hasInlineHandlerReaction const):
(JSC::JSPromise::inlineReactionContext const):
(JSC::JSPromise::inlineHandlerHandler const):
(JSC::JSPromise::inlineHandlerResultPromise const):
(JSC::JSPromise::payloadCell const):
(JSC::JSPromise::setFlags):
(JSC::JSPromise::setPackedCell):
(JSC::JSPromise::setSlot):
(JSC::JSPromise::clearSlot):
(JSC::JSPromise::inlineReactionMicrotask const):
(JSC::JSPromise::initialValues): Deleted.
(JSC::JSPromise::internalField const): Deleted.
(JSC::JSPromise::internalField): Deleted.
(JSC::JSPromise::reactionsOrResult const): Deleted.
(JSC::JSPromise::setReactionsOrResult): Deleted.
(JSC::JSPromise::setInlineReaction): Deleted.
(JSC::JSPromise::clearInlineReaction): Deleted.
* Source/WebCore/Modules/streams/StreamInternals.js:
(markPromiseAsHandled):
* Source/WebCore/Modules/streams/WritableStreamInternals.js:
(writableStreamDefaultWriterEnsureClosedPromiseRejected):
(writableStreamDefaultWriterEnsureReadyPromiseRejected):
Canonical link: https://commits.webkit.org/313220@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications