diff --git a/js/src/jit/WarpBuilder.cpp b/js/src/jit/WarpBuilder.cpp index b23c9f04f1bc..f6ca7ed5ac7d 100644 --- a/js/src/jit/WarpBuilder.cpp +++ b/js/src/jit/WarpBuilder.cpp @@ -1796,6 +1796,18 @@ bool WarpBuilder::transpileCall(BytecodeLocation loc, return TranspileCacheIRToMIR(this, loc, cacheIRSnapshot, {argc}, callInfo); } +void WarpBuilder::buildCreateThis(CallInfo& callInfo) { + MOZ_ASSERT(callInfo.constructing()); + + // Inline the this-object allocation on the caller-side. + MDefinition* callee = callInfo.callee(); + MDefinition* newTarget = callInfo.getNewTarget(); + auto* createThis = MCreateThis::New(alloc(), callee, newTarget); + current->add(createThis); + callInfo.thisArg()->setImplicitlyUsedUnchecked(); + callInfo.setThis(createThis); +} + bool WarpBuilder::buildCallOp(BytecodeLocation loc) { uint32_t argc = loc.getCallArgc(); JSOp op = loc.getOp(); @@ -1831,13 +1843,7 @@ bool WarpBuilder::buildCallOp(BytecodeLocation loc) { bool needsThisCheck = false; if (callInfo.constructing()) { - // Inline the this-object allocation on the caller-side. - MDefinition* callee = callInfo.callee(); - MDefinition* newTarget = callInfo.getNewTarget(); - MCreateThis* createThis = MCreateThis::New(alloc(), callee, newTarget); - current->add(createThis); - callInfo.thisArg()->setImplicitlyUsedUnchecked(); - callInfo.setThis(createThis); + buildCreateThis(callInfo); needsThisCheck = true; } @@ -2868,28 +2874,20 @@ bool WarpBuilder::build_SpreadCall(BytecodeLocation loc) { } bool WarpBuilder::build_SpreadNew(BytecodeLocation loc) { - MDefinition* newTarget = current->pop(); - MDefinition* argArr = current->pop(); - MDefinition* thisValue = current->pop(); - MDefinition* callee = current->pop(); + bool constructing = true; + CallInfo callInfo(alloc(), constructing, loc.resultIsPopped()); + callInfo.initForSpreadCall(current); - // Inline the constructor on the caller-side. - MCreateThis* createThis = MCreateThis::New(alloc(), callee, newTarget); - current->add(createThis); - thisValue->setImplicitlyUsedUnchecked(); + buildCreateThis(callInfo); - // Load dense elements of the argument array. Note that the bytecode ensures - // this is an array. - MElements* elements = MElements::New(alloc(), argArr); - current->add(elements); - - WrappedFunction* wrappedTarget = nullptr; - auto* apply = MConstructArray::New(alloc(), wrappedTarget, callee, elements, - createThis, newTarget); - apply->setBailoutKind(BailoutKind::TooManyArguments); - current->add(apply); - current->push(apply); - return resumeAfter(apply, loc); + MInstruction* call = makeSpreadCall(callInfo); + if (!call) { + return false; + } + call->setBailoutKind(BailoutKind::TooManyArguments); + current->add(call); + current->push(call); + return resumeAfter(call, loc); } bool WarpBuilder::build_SpreadSuperCall(BytecodeLocation loc) { diff --git a/js/src/jit/WarpBuilder.h b/js/src/jit/WarpBuilder.h index c508284d75cc..82028066dd7c 100644 --- a/js/src/jit/WarpBuilder.h +++ b/js/src/jit/WarpBuilder.h @@ -306,6 +306,8 @@ class MOZ_STACK_CLASS WarpBuilder : public WarpBuilderShared { bool usesEnvironmentChain() const; MDefinition* walkEnvironmentChain(uint32_t numHops); + void buildCreateThis(CallInfo& callInfo); + [[nodiscard]] bool transpileCall(BytecodeLocation loc, const WarpCacheIR* cacheIRSnapshot, CallInfo* callInfo); diff --git a/js/src/jit/WarpBuilderShared.cpp b/js/src/jit/WarpBuilderShared.cpp index 35b29920ab93..7bf272224923 100644 --- a/js/src/jit/WarpBuilderShared.cpp +++ b/js/src/jit/WarpBuilderShared.cpp @@ -64,13 +64,20 @@ MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck, MInstruction* WarpBuilderShared::makeSpreadCall(CallInfo& callInfo, bool isSameRealm, WrappedFunction* target) { - // TODO: support SpreadNew and SpreadSuperCall - MOZ_ASSERT(!callInfo.constructing()); - // Load dense elements of the argument array. MElements* elements = MElements::New(alloc(), callInfo.arrayArg()); current->add(elements); + if (callInfo.constructing()) { + auto* construct = + MConstructArray::New(alloc(), target, callInfo.callee(), elements, + callInfo.thisArg(), callInfo.getNewTarget()); + if (isSameRealm) { + construct->setNotCrossRealm(); + } + return construct; + } + auto* apply = MApplyArray::New(alloc(), target, callInfo.callee(), elements, callInfo.thisArg());