Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 7b485a76e9cc4b0e8dd03e5e904967b7a621c2b2
https://github.com/WebKit/WebKit/commit/7b485a76e9cc4b0e8dd03e5e904967b7a621c2b2
Author: Sosuke Suzuki <[email protected]>
Date: 2026-09-23 (Wed, 23 Sep 2026)
Changed paths:
A JSTests/microbenchmarks/reflect-construct-arguments-new-target.js
A JSTests/microbenchmarks/reflect-construct-array-literal.js
A JSTests/microbenchmarks/reflect-construct-generic.js
A JSTests/microbenchmarks/reflect-construct-rest.js
A JSTests/stress/reflect-construct-builtin-targets.js
A JSTests/stress/reflect-construct-call-site-guard.js
A JSTests/stress/reflect-construct-constant-array-literal.js
A JSTests/stress/reflect-construct-fast-path.js
A JSTests/stress/reflect-construct-new-target.js
A JSTests/stress/reflect-construct-step-order.js
M Source/JavaScriptCore/builtins/BuiltinNames.h
M Source/JavaScriptCore/bytecode/LinkTimeConstant.h
M Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
M Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
M Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
M Source/JavaScriptCore/parser/ASTBuilder.h
M Source/JavaScriptCore/parser/NodeConstructors.h
M Source/JavaScriptCore/parser/Nodes.h
M Source/JavaScriptCore/runtime/CommonIdentifiers.h
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/ReflectObject.cpp
M Source/JavaScriptCore/runtime/ReflectObject.h
Log Message:
-----------
[JSC] Emit `op_construct_varargs` directly for `Reflect.construct` call sites
https://bugs.webkit.org/show_bug.cgi?id=324411
Reviewed by Yusuke Suzuki.
Reflect.construct is implemented as a C++ host function, and a call site
reaches it through op_call.
Transpilers such as Babel compile classes and inheritance into functions
and Reflect.construct, so Reflect.construct still runs often, in library
code in particular. The bundles in JetStream 3 contain about 60 call
sites of it.
This patch makes the parser give a `Reflect.construct(...)` call its own
AST node, and makes the bytecode compiler emit op_construct_varargs for
it instead of op_call. The call site first checks that the callee is the
original Reflect.construct and that the arguments pass the validation
Reflect.construct does, and makes the ordinary call otherwise.
Baseline
Patched
reflect-construct-array-literal 70.7964+-0.8957 ^
40.5625+-0.4576 ^ definitely 1.7454x faster
reflect-construct-rest 71.8457+-1.1228 ^
23.8364+-0.2105 ^ definitely 3.0141x faster
reflect-construct-arguments-new-target 108.5354+-0.8155 ^
31.6552+-0.9397 ^ definitely 3.4287x faster
reflect-construct-generic 66.4016+-0.6294 ^
46.7929+-0.4365 ^ definitely 1.4191x faster
Tests: JSTests/microbenchmarks/reflect-construct-arguments-new-target.js
JSTests/microbenchmarks/reflect-construct-array-literal.js
JSTests/microbenchmarks/reflect-construct-generic.js
JSTests/microbenchmarks/reflect-construct-rest.js
JSTests/stress/reflect-construct-builtin-targets.js
JSTests/stress/reflect-construct-call-site-guard.js
JSTests/stress/reflect-construct-constant-array-literal.js
JSTests/stress/reflect-construct-fast-path.js
JSTests/stress/reflect-construct-new-target.js
JSTests/stress/reflect-construct-step-order.js
* JSTests/microbenchmarks/reflect-construct-arguments-new-target.js: Added.
(Base):
(Derived):
(test):
* JSTests/microbenchmarks/reflect-construct-array-literal.js: Added.
(Point):
(test):
* JSTests/microbenchmarks/reflect-construct-generic.js: Added.
(Point):
(construct):
* JSTests/microbenchmarks/reflect-construct-rest.js: Added.
(Point):
(create):
* JSTests/stress/reflect-construct-builtin-targets.js: Added.
(shouldBe):
(Other):
(array.MyArray):
(array.withLength):
(array.withLengthAndSameNewTarget):
(array.withLengthAndNewTarget):
(array.withElements):
(array.withElementsAndNewTarget):
(array.empty):
(array.subclass):
(array):
(object.withoutNewTarget):
(object.sameNewTarget):
(object.otherNewTarget):
(object.empty):
(wrappers.string):
(wrappers.stringWithNewTarget):
(wrappers.emptyString):
(wrappers.number):
(wrappers.numberWithNewTarget):
(wrappers.boolean):
(wrappers.symbol):
(wrappers.bigInt):
(wrappers):
(collections.MyMap):
(collections.map):
(collections.mapWithNewTarget):
(collections.mapWithEntries):
(collections.setWithNewTarget):
(collections.weakMap):
(collections.weakMapWithNewTarget):
(collections.weakSet):
(collections.weakSetWithNewTarget):
(collections.set noInline):
(buffersAndTypedArrays.arrayBuffer):
(buffersAndTypedArrays.arrayBufferWithNewTarget):
(buffersAndTypedArrays.typedArray):
(buffersAndTypedArrays.typedArrayWithNewTarget):
(buffersAndTypedArrays.typedArrayFromArray):
(buffersAndTypedArrays.dataView):
(buffersAndTypedArrays):
(otherBuiltins.MyError):
(otherBuiltins.MyPromise):
(otherBuiltins.regExp):
(otherBuiltins.regExpWithNewTarget):
(otherBuiltins.regExpFromRegExp):
(otherBuiltins.date):
(otherBuiltins.dateWithNewTarget):
(otherBuiltins.error):
(otherBuiltins.typeError):
(otherBuiltins.promise):
(otherBuiltins.functionConstructor):
(otherBuiltins.proxy):
* JSTests/stress/reflect-construct-call-site-guard.js: Added.
(shouldBe):
(Point):
(Other):
(calleeIsNotTheOriginalReflectConstruct.literal):
(calleeIsNotTheOriginalReflectConstruct.generic):
(calleeIsNotTheOriginalReflectConstruct.let.withGetter.get construct):
(calleeIsNotTheOriginalReflectConstruct):
(replacedOnTheGlobalReflect.literal):
(replacedOnTheGlobalReflect.generic):
(replacedOnTheGlobalReflect.Reflect.construct):
(optionalChaining.optionalBase):
(optionalChaining.optionalCall):
(optionalChaining):
(argumentEvaluation.record):
(argumentEvaluation.literal):
(argumentEvaluation.generic):
(argumentEvaluation.invalid):
(argumentEvaluation.assignsTarget):
(argumentEvaluation.assignsList):
(argumentEvaluation):
(ordinaryCalls.spreadAll):
(ordinaryCalls.spreadTail):
(ordinaryCalls.oneArgument):
(ordinaryCalls.bracket):
(ordinaryCalls.throughGlobalThis):
(ordinaryCalls.holeyLiteral):
(ordinaryCalls.spreadLiteral):
(ordinaryCalls):
(nesting.Box):
(nesting.nested):
(nesting.nestedWithApply):
(positions.Counter):
(positions.tail):
(positions.ignoredResult):
(positions.inCondition):
(positions.Derived):
(positions):
(withStatement.test):
(withStatement):
* JSTests/stress/reflect-construct-constant-array-literal.js: Added.
(shouldBe):
(Other):
(int32Literal):
(doubleLiteral):
(mixedLiteral):
(withNewTarget):
(storedBeforeCall):
(pushedBeforeCall):
(usedAfterward):
* JSTests/stress/reflect-construct-fast-path.js: Added.
(shouldBe):
(Point3D):
(Other):
(arrayLiteral.test):
(arrayLiteral.testWithNewTarget):
(arrayLiteral.testEmpty):
(arrayLiteral.testDerived):
(arrayLiteral.testExtraArguments):
(arrayLiteral):
(listModifiedByLaterArgument.test):
(listModifiedByLaterArgument):
(argumentsObjects.Base):
(argumentsObjects.Sloppy):
(argumentsObjects.Strict):
(argumentsObjects.Mapped):
(argumentsObjects.OverriddenLength):
(argumentsObjects.rest):
(argumentsObjects.spread):
(argumentsObjects.test):
(argumentsObjects):
(tooManyArguments.construct):
(tooManyArguments.let.tooLong.get 0):
(tooManyArguments.strictArgumentsWithLongLength):
(tooManyArguments):
(errors.construct):
(errors.constructWithoutNewTarget):
(errors.constructLiteral):
(errors.checkAll):
(errors):
(constructorThatThrowsFromConstruct.test):
(constructorThatThrowsFromConstruct):
(exceptions.Thrower):
(exceptions.OverflowThenThrow):
(exceptions.literal):
(exceptions.literalOverflow):
(exceptions.generic):
(exceptions.let.throwingArrayLike.get 1):
(constructorArgumentTypeChange.Adder):
(constructorArgumentTypeChange.test):
(constructorArgumentTypeChange.Recorder):
(constructorArgumentTypeChange.testIgnoringResult):
(constructorArgumentTypeChange):
(polymorphicTargets.A):
(polymorphicTargets.B):
(polymorphicTargets.C):
(polymorphicTargets.literal):
(polymorphicTargets):
(callerAndStack.Sloppy):
(callerAndStack.literal):
(callerAndStack.generic):
(callerAndStack):
(genericArguments.construct):
(genericArguments.let.arrayLike.get length):
(genericArguments.let.arrayLike.get 0):
(genericArguments.let.arrayLike.get 1):
(genericArguments.get let):
(genericArguments.get Eighth):
(genericArguments):
* JSTests/stress/reflect-construct-new-target.js: Added.
(shouldBe):
(ClassBase):
(Derived):
(Other):
(prototypeIsReadFromNewTarget.literal):
(prototypeIsReadFromNewTarget.generic):
(prototypeIsReadFromNewTarget.literalDerived):
(prototypeIsReadFromNewTarget.get let):
(prototypeIsReadFromNewTarget.let.boundNewTarget):
(prototypeIsReadFromNewTarget.get let.list.get length):
(prototypeIsReadFromNewTarget.get let.list.get 0):
(prototypeIsReadFromNewTarget):
(nonObjectPrototypeUsesTheRealmOfNewTarget.literal):
(nonObjectPrototypeUsesTheRealmOfNewTarget.generic):
(nonObjectPrototypeUsesTheRealmOfNewTarget.literalArray):
(nonObjectPrototypeUsesTheRealmOfNewTarget.withPrototype):
(nonObjectPrototypeUsesTheRealmOfNewTarget):
(prototypeGetterThrows.literal):
(prototypeGetterThrows.literalDerived):
(prototypeGetterThrows.let.thrower):
(prototypeGetterThrows.get for):
(prototypeGetterThrows):
(returnValues.BaseReturning):
(returnValues.DerivedReturning):
(returnValues.literalBase):
(returnValues.literalDerivedReturning):
(returnValues.genericDerivedReturning):
(returnValues):
(whatIsAConstructor.generic):
(whatIsAConstructor.genericNewTarget):
(whatIsAConstructor.Base):
(whatIsAConstructor):
(whatIsAConstructor.async method):
(whatIsAConstructor.method):
(whatIsAConstructor.prototype.new.Proxy):
(boundTargets.literal):
(boundTargets.literalWithoutNewTarget):
(proxyTargets.literal):
(proxyTargets.generic):
(proxyTargets.get generic):
* JSTests/stress/reflect-construct-step-order.js: Added.
(shouldBe):
(Other):
(loggingList.return.get length):
(loggingList.return.get 0):
(loggingList.return.get 1):
(loggingList):
(validationOrder.construct):
(validationOrder.constructWithoutNewTarget):
(validationOrder.check):
(validationOrder):
(presentButUndefinedNewTarget.explicitUndefined):
(presentButUndefinedNewTarget.explicitNull):
(presentButUndefinedNewTarget.missing):
(presentButUndefinedNewTarget.missingList):
(presentButUndefinedNewTarget.noArguments):
(presentButUndefinedNewTarget):
(revokedProxies.construct):
(revokedProxies):
(listMustBeAnObject.construct):
(listMustBeAnObject):
(lengthConversion.construct):
(lengthConversion.listWithLength):
(lengthConversion.get shouldBe):
(lengthConversion):
(elementReads.construct):
(elementReads.get let):
(elementReads.get shouldBe):
(listMutatedWhileItIsRead.construct):
(listMutatedWhileItIsRead.show):
(listMutatedWhileItIsRead.get shouldBe):
(listMutatedWhileItIsRead.let.mapped):
(listMutatedWhileItIsRead.let.lengthSideEffect.get length):
(listMutatedWhileItIsRead):
(constructorMutatesTheList.Mutator):
(constructorMutatesTheList.construct):
(constructorMutatesTheList.literal):
(constructorMutatesTheList):
(callForms.viaCall):
(callForms.viaApply):
(callForms.viaReflectApply):
(callForms.viaBind):
(callForms.extraArguments):
(callForms.nested):
(callForms.nestedFunctionConstructor):
(callForms.asConstructor):
(callForms.selfTarget):
(callForms):
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitJumpIfNotReflectConstruct):
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::ReflectConstructFunctionCallDotNode::emitBytecode):
* Source/JavaScriptCore/parser/ASTBuilder.h:
(JSC::ASTBuilder::makeFunctionCallNode):
* Source/JavaScriptCore/parser/NodeConstructors.h:
(JSC::HasOwnPropertyFunctionCallDotNode::HasOwnPropertyFunctionCallDotNode):
(JSC::ReflectConstructFunctionCallDotNode::ReflectConstructFunctionCallDotNode):
* Source/JavaScriptCore/parser/Nodes.h:
* Source/JavaScriptCore/runtime/CommonIdentifiers.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/ReflectObject.cpp:
(JSC::initializeReflectConstructFunction):
* Source/JavaScriptCore/runtime/ReflectObject.h:
Canonical link: https://commits.webkit.org/321764@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications