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

Reply via email to