Skip to content

[JSC] Optimize returned promise from async function when it does not have await#63356

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
Constellation:eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await
Apr 23, 2026
Merged

[JSC] Optimize returned promise from async function when it does not have await#63356
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
Constellation:eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await

Conversation

@Constellation
Copy link
Copy Markdown
Member

@Constellation Constellation commented Apr 22, 2026

19dc01a

[JSC] Optimize returned promise from async function when it does not have await
https://bugs.webkit.org/show_bug.cgi?id=313029
rdar://175369313

Reviewed by Yijia Huang.

Let's optimize returned promise from async function when we do not have
`await`. Currently, we are calling operationFulfillPromiseFirstResolving
for the created promise when resolving. But since we know that we do not
have `await`, we do not need to create a promise a-priori, and we can
just create and resolve a promise when returning. This is more efficient
since we can fold it into a fulfilled promise allocation when input is
proven as non-object.

Test: JSTests/stress/async-function-empty-resolved-promise.js

* JSTests/stress/async-function-empty-resolved-promise.js: Added.
(shouldBe):
(async empty):
(async emptyArrow):
(C.prototype.async emptyMethod):
(C):
(const.obj.async emptyShort):
(async onlyUsing):
(async onlyAwaitUsing):
(async returnsThenable):
(async throwsLiteral):
(async throwsError):
(thrower):
(async defaultThrower):
(async defaultThrowerBody):
(async run.async returnsPromise):
(async run):
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOperations.h:
* 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):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* Source/JavaScriptCore/parser/Nodes.h:
(JSC::ScopeNode::isEmptyBody const):
* Source/JavaScriptCore/runtime/Intrinsic.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSGlobalObject::init):

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

697b279

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
❌ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe 🛠 win ⏳ 🛠 ios-apple
🛠 ios-sim ✅ 🛠 mac-AS-debug 🧪 wpe-wk2 🧪 win-tests ⏳ 🛠 mac-apple
✅ 🧪 webkitperl 🧪 ios-wk2 🧪 api-mac 🧪 api-wpe ⏳ 🛠 vision-apple
🧪 ios-wk2-wpt 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
✅ 🛠 🧪 jsc 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 🧪 jsc-debug-arm64 🛠 ios-safer-cpp 🧪 mac-wk2 🧪 gtk-wk2
🛠 vision 🧪 mac-AS-debug-wk2 🧪 api-gtk
🛠 vision-sim ✅ 🧪 mac-wk2-stress 🛠 playstation
✅ 🛠 🧪 unsafe-merge 🧪 vision-wk2 🧪 mac-intel-wk2 ✅ 🛠 jsc-armv7
✅ 🛠 tv 🛠 mac-safer-cpp ✅ 🧪 jsc-armv7-tests
🛠 tv-sim
🛠 watch
🛠 watch-sim

@Constellation Constellation requested a review from a team as a code owner April 22, 2026 21:13
@Constellation Constellation self-assigned this Apr 22, 2026
@Constellation Constellation added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label Apr 22, 2026
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Apr 22, 2026
@Constellation Constellation removed the merging-blocked Applied to prevent a change from being merged label Apr 22, 2026
@Constellation Constellation force-pushed the eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await branch from 141712d to 7b190ec Compare April 22, 2026 22:11
@Constellation Constellation force-pushed the eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await branch from 7b190ec to 0ea821e Compare April 22, 2026 22:13

JumpList slowCases;

FrozenValue* structure = m_graph.freezeStrong(globalObject->promiseStructure());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use

RegisteredStructure structure = m_graph.registerStructure(globalObject->promiseStructure());

which is same as the one used by compileCreatePromise?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, changed.

@Constellation Constellation force-pushed the eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await branch from 0ea821e to 697b279 Compare April 23, 2026 18:45
@Constellation Constellation added the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Apr 23, 2026
…have await

https://bugs.webkit.org/show_bug.cgi?id=313029
rdar://175369313

Reviewed by Yijia Huang.

Let's optimize returned promise from async function when we do not have
`await`. Currently, we are calling operationFulfillPromiseFirstResolving
for the created promise when resolving. But since we know that we do not
have `await`, we do not need to create a promise a-priori, and we can
just create and resolve a promise when returning. This is more efficient
since we can fold it into a fulfilled promise allocation when input is
proven as non-object.

Test: JSTests/stress/async-function-empty-resolved-promise.js

* JSTests/stress/async-function-empty-resolved-promise.js: Added.
(shouldBe):
(async empty):
(async emptyArrow):
(C.prototype.async emptyMethod):
(C):
(const.obj.async emptyShort):
(async onlyUsing):
(async onlyAwaitUsing):
(async returnsThenable):
(async throwsLiteral):
(async throwsError):
(thrower):
(async defaultThrower):
(async defaultThrowerBody):
(async run.async returnsPromise):
(async run):
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOperations.h:
* 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):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* Source/JavaScriptCore/parser/Nodes.h:
(JSC::ScopeNode::isEmptyBody const):
* Source/JavaScriptCore/runtime/Intrinsic.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSGlobalObject::init):

Canonical link: https://commits.webkit.org/311883@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await branch from 697b279 to 19dc01a Compare April 23, 2026 19:58
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 311883@main (19dc01a): https://commits.webkit.org/311883@main

Reviewed commits have been landed. Closing PR #63356 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 19dc01a into WebKit:main Apr 23, 2026
@webkit-commit-queue webkit-commit-queue removed the unsafe-merge-queue Applied to send a pull request to merge-queue, but skip building and testing label Apr 23, 2026
@Constellation Constellation deleted the eng/JSC-Optimize-returned-promise-from-async-function-when-it-does-not-have-await branch April 23, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants