author | André Bargull <andre.bargull@gmail.com> |
Thu, 05 Mar 2020 16:01:44 +0000 | |
changeset 517074 | 2f8f4267d3e7024be6324270ec4959478b540880 |
parent 517073 | 74c24cb3ac9a99e776ed265767342c8c504b1e1d |
child 517075 | 2872f192769e2eb1e57d03ac1dd6cbf56bc9f738 |
push id | 37186 |
push user | malexandru@mozilla.com |
push date | Fri, 06 Mar 2020 09:47:39 +0000 |
treeherder | mozilla-central@a1b3010b6b87 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1619343 |
milestone | 75.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jit/CodeGenerator.cpp | file | annotate | diff | comparison | revisions | |
js/src/jit/MIR.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5270,20 +5270,20 @@ void CodeGenerator::emitCallInvokeFuncti // Push the space used by the arguments. masm.moveStackPtrTo(objreg); masm.Push(extraStackSize); pushArg(objreg); // argv. pushArg(ToRegister(apply->getArgc())); // argc. pushArg(Imm32(apply->mir()->ignoresReturnValue())); // ignoresReturnValue. - pushArg(Imm32(false)); // isConstrucing. + pushArg(Imm32(apply->mir()->isConstructing())); // isConstructing. pushArg(ToRegister(apply->getFunction())); // JSFunction*. - // This specialization og callVM restore the extraStackSize after the call. + // This specialization of callVM restores the extraStackSize after the call. using Fn = bool (*)(JSContext*, HandleObject, bool, bool, uint32_t, Value*, MutableHandleValue); callVM<Fn, jit::InvokeFunction>(apply, &extraStackSize); masm.Pop(extraStackSize); } // Do not bailout after the execution of this function since the stack no longer @@ -5520,33 +5520,59 @@ void CodeGenerator::emitApplyGeneric(T* // // objreg is dead across this call. // // extraStackSpace is garbage on entry and defined on exit. emitPushArguments(apply, extraStackSpace); masm.checkStackAlignment(); + bool constructing = apply->mir()->isConstructing(); + // If the function is native, only emit the call to InvokeFunction. if (apply->hasSingleTarget() && apply->getSingleTarget()->isNativeWithCppEntry()) { emitCallInvokeFunction(apply, extraStackSpace); + +#ifdef DEBUG + // Native constructors are guaranteed to return an Object value, so we never + // have to replace a primitive result with the previously allocated Object + // from CreateThis. + if (constructing) { + Label notPrimitive; + masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, + ¬Primitive); + masm.assumeUnreachable("native constructors don't return primitives"); + masm.bind(¬Primitive); + } +#endif + emitPopArguments(extraStackSpace); return; } Label end, invoke; // Guard that calleereg is an interpreted function with a JSScript. - masm.branchIfFunctionHasNoJitEntry(calleereg, /* constructing */ false, - &invoke); - - // Guard that calleereg is not a class constrcuctor - masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor, - calleereg, objreg, &invoke); + masm.branchIfFunctionHasNoJitEntry(calleereg, constructing, &invoke); + + // Guard that callee allows the [[Call]] or [[Construct]] operation required. + if (constructing) { + masm.branchTestFunctionFlags(calleereg, FunctionFlags::CONSTRUCTOR, + Assembler::Zero, &invoke); + } else { + masm.branchFunctionKind(Assembler::Equal, FunctionFlags::ClassConstructor, + calleereg, objreg, &invoke); + } + + // Use the slow path if CreateThis was unable to create the |this| object. + if (constructing) { + Address thisAddr(masm.getStackPointer(), 0); + masm.branchTestNull(Assembler::Equal, thisAddr, &invoke); + } // Call with an Ion frame or a rectifier frame. { if (apply->mir()->maybeCrossRealm()) { masm.switchToObjectRealm(calleereg, objreg); } // Knowing that calleereg is a non-native function, load jitcode. @@ -5555,17 +5581,17 @@ void CodeGenerator::emitApplyGeneric(T* // Create the frame descriptor. unsigned pushed = masm.framePushed(); Register stackSpace = extraStackSpace; masm.addPtr(Imm32(pushed), stackSpace); masm.makeFrameDescriptor(stackSpace, FrameType::IonJS, JitFrameLayout::Size()); masm.Push(argcreg); - masm.Push(calleereg); + masm.PushCalleeToken(calleereg, constructing); masm.Push(stackSpace); // descriptor Label underflow, rejoin; // Check whether the provided arguments satisfy target argc. if (!apply->hasSingleTarget()) { Register nformals = extraStackSpace; masm.load16ZeroExtend(Address(calleereg, JSFunction::offsetOfNargs()), @@ -5616,18 +5642,29 @@ void CodeGenerator::emitApplyGeneric(T* } // Handle uncompiled or native functions. { masm.bind(&invoke); emitCallInvokeFunction(apply, extraStackSpace); } + masm.bind(&end); + + // If the return value of the constructing function is Primitive, + // replace the return value with the Object from CreateThis. + if (constructing) { + Label notPrimitive; + masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, + ¬Primitive); + masm.loadValue(Address(masm.getStackPointer(), 0), JSReturnOperand); + masm.bind(¬Primitive); + } + // Pop arguments and continue. - masm.bind(&end); emitPopArguments(extraStackSpace); } void CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric* apply) { // Limit the number of parameters we can handle to a number that does not risk // us allocating too much stack, notably on Windows where there is a 4K guard // page that has to be touched to extend the stack. See bug 1351278. The // value "3000" is the size of the guard page minus an arbitrary, but large,
--- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -2807,16 +2807,18 @@ class MApplyArgs : public MTernaryInstru WrappedFunction* getSingleTarget() const { return target_; } bool maybeCrossRealm() const { return maybeCrossRealm_; } void setNotCrossRealm() { maybeCrossRealm_ = false; } bool ignoresReturnValue() const { return ignoresReturnValue_; } void setIgnoresReturnValue() { ignoresReturnValue_ = true; } + bool isConstructing() const { return false; } + bool possiblyCalls() const override { return true; } bool appendRoots(MRootList& roots) const override { if (target_) { return target_->appendRoots(roots); } return true; } @@ -2847,16 +2849,18 @@ class MApplyArray WrappedFunction* getSingleTarget() const { return target_; } bool maybeCrossRealm() const { return maybeCrossRealm_; } void setNotCrossRealm() { maybeCrossRealm_ = false; } bool ignoresReturnValue() const { return ignoresReturnValue_; } void setIgnoresReturnValue() { ignoresReturnValue_ = true; } + bool isConstructing() const { return false; } + bool possiblyCalls() const override { return true; } bool appendRoots(MRootList& roots) const override { if (target_) { return target_->appendRoots(roots); } return true; }