author | Hannes Verschore <hv1989@gmail.com> |
Tue, 27 Nov 2012 22:03:37 +0100 | |
changeset 114283 | 5158d648702ecfe12338765a1c5de00d993189c9 |
parent 114282 | 8aa207f87eb6e4055c649ffcd2f6ceee7cc296c3 |
child 114284 | 7e5deb571bbe010e990cf4f41ce9eafd36310caf |
push id | 23913 |
push user | emorley@mozilla.com |
push date | Wed, 28 Nov 2012 17:11:31 +0000 |
treeherder | mozilla-central@17c267a881cf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nbp, sstangl |
bugs | 813773 |
milestone | 20.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
|
--- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -826,18 +826,16 @@ CodeGenerator::visitCallGeneric(LCallGen Register calleereg = ToRegister(call->getFunction()); Register objreg = ToRegister(call->getTempObject()); Register nargsreg = ToRegister(call->getNargsReg()); uint32 unusedStack = StackOffsetOfPassedArg(call->argslot()); Label invoke, thunk, makeCall, end; // Known-target case is handled by LCallKnown. JS_ASSERT(!call->hasSingleTarget()); - // Unknown constructor case is handled by LCallConstructor. - JS_ASSERT(!call->mir()->isConstructing()); // Generate an ArgumentsRectifier. IonCompartment *ion = gen->ionCompartment(); IonCode *argumentsRectifier = ion->getArgumentsRectifier(); masm.checkStackAlignment(); // Guard that calleereg is actually a function object. @@ -898,16 +896,26 @@ CodeGenerator::visitCallGeneric(LCallGen masm.jump(&end); // Handle uncompiled or native functions. masm.bind(&invoke); if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack)) return false; masm.bind(&end); + + // If the return value of the constructing function is Primitive, + // replace the return value with the Object from CreateThis. + if (call->mir()->isConstructing()) { + Label notPrimitive; + masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, ¬Primitive); + masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand); + masm.bind(¬Primitive); + } + dropArguments(call->numStackArgs() + 1); return true; } bool CodeGenerator::visitCallKnown(LCallKnown *call) { JSContext *cx = GetIonContext()->cx; @@ -988,49 +996,16 @@ CodeGenerator::visitCallKnown(LCallKnown masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand); masm.bind(¬Primitive); } dropArguments(call->numStackArgs() + 1); return true; } -typedef bool (*InvokeConstructorFn)(JSContext *, JSObject *, uint32, Value *, Value *); -static const VMFunction InvokeConstructorInfo = - FunctionInfo<InvokeConstructorFn>(ion::InvokeConstructor); - -bool -CodeGenerator::visitCallConstructor(LCallConstructor *call) -{ - JS_ASSERT(call->mir()->isConstructing()); - - // Holds the function object. - const LAllocation *callee = call->getFunction(); - Register calleereg = ToRegister(callee); - - uint32 callargslot = call->argslot(); - uint32 unusedStack = StackOffsetOfPassedArg(callargslot); - - // Nestle %esp up to the argument vector. - masm.freeStack(unusedStack); - - pushArg(StackPointer); // argv. - pushArg(Imm32(call->numActualArgs())); // argc. - pushArg(calleereg); // JSFunction *. - - if (!callVM(InvokeConstructorInfo, call)) - return false; - - // Un-nestle %esp from the argument vector. No prefix was pushed. - masm.reserveStack(unusedStack); - - dropArguments(call->numStackArgs() + 1); - return true; -} - bool CodeGenerator::emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize) { Register objreg = ToRegister(apply->getTempObject()); JS_ASSERT(objreg != extraStackSize); // Push the space used by the arguments. masm.movePtr(StackPointer, objreg);
--- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -74,17 +74,16 @@ class CodeGenerator : public CodeGenerat bool visitElements(LElements *lir); bool visitTypeBarrier(LTypeBarrier *lir); bool visitMonitorTypes(LMonitorTypes *lir); bool visitCallNative(LCallNative *call); bool emitCallInvokeFunction(LInstruction *call, Register callereg, uint32 argc, uint32 unusedStack); bool visitCallGeneric(LCallGeneric *call); bool visitCallKnown(LCallKnown *call); - bool visitCallConstructor(LCallConstructor *call); bool emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize); void emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSpace); void emitPopArguments(LApplyArgsGeneric *apply, Register extraStackSize); bool visitApplyArgsGeneric(LApplyArgsGeneric *apply); bool visitDoubleToInt32(LDoubleToInt32 *lir); bool visitNewSlots(LNewSlots *lir); bool visitNewArrayCallVM(LNewArray *lir); bool visitNewArray(LNewArray *lir);
--- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -3574,34 +3574,37 @@ IonBuilder::createThisScriptedSingleton( current->add(createThis); return createThis; } MDefinition * IonBuilder::createThis(HandleFunction target, MDefinition *callee) { + // Create this for unknown target + if (!target) + return createThisScripted(callee); + + // Create this for native function if (target->isNative()) { if (!target->isNativeConstructor()) return NULL; return createThisNative(); } - MDefinition *createThis = NULL; + // Create this with known prototype. RootedObject proto(cx, getSingletonPrototype(target)); - - // Try baking in the prototype. - if (proto) - createThis = createThisScriptedSingleton(target, proto, callee); + if (proto) { + MDefinition *createThis = createThisScriptedSingleton(target, proto, callee); + if (createThis) + return createThis; + } // If the prototype could not be hardcoded, emit a GETPROP. - if (!createThis) - createThis = createThisScripted(callee); - - return createThis; + return createThisScripted(callee); } bool IonBuilder::jsop_funcall(uint32 argc) { // Stack for JSOP_FUNCALL: // 1: MPassArg(arg0) // ... @@ -3792,18 +3795,18 @@ IonBuilder::makeCallHelper(HandleFunctio // potentially perform rearrangement. MPrepareCall *start = new MPrepareCall; MPassArg *firstArg = current->peek(-1)->toPassArg(); firstArg->block()->insertBefore(firstArg, start); call->initPrepareCall(start); MPassArg *thisArg = current->pop()->toPassArg(); - // If the target is known, inline the constructor on the caller-side. - if (constructing && target) { + // Inline the constructor on the caller-side. + if (constructing) { MDefinition *callee = current->peek(-1); MDefinition *create = createThis(target, callee); if (!create) { abort("Failure inlining constructor for call."); return NULL; } MPassArg *newThis = MPassArg::New(create);
--- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -660,34 +660,16 @@ class LCallDOMNative : public LJSCallIns const LAllocation *getArgArgc() { return getTemp(3)->output(); } const LAllocation *getArgVp() { return getTemp(4)->output(); } }; -// Generates a polymorphic callsite for |new|, where |this| has not been -// pre-allocated by the caller. -class LCallConstructor : public LJSCallInstructionHelper<BOX_PIECES, 1, 0> -{ - public: - LIR_HEADER(CallConstructor); - - LCallConstructor(const LAllocation &func, uint32 argslot) - : JSCallHelper(argslot) - { - setOperand(0, func); - } - - const LAllocation *getFunction() { - return getOperand(0); - } -}; - template <size_t defs, size_t ops> class LDOMPropertyInstructionHelper : public LCallInstructionHelper<defs, 1 + ops, 3> { protected: LDOMPropertyInstructionHelper(const LDefinition &JSContextReg, const LAllocation &ObjectReg, const LDefinition &PrivReg, const LDefinition &ValueReg) { this->setOperand(0, ObjectReg);
--- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -29,17 +29,16 @@ _(NewStringObject) \ _(InitProp) \ _(CheckOverRecursed) \ _(RecompileCheck) \ _(DefVar) \ _(CallKnown) \ _(CallGeneric) \ _(CallNative) \ - _(CallConstructor) \ _(ApplyArgsGeneric) \ _(StackArgT) \ _(StackArgV) \ _(CreateThis) \ _(CreateThisVM) \ _(ReturnFromCtor) \ _(BitNotI) \ _(BitNotV) \
--- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -285,23 +285,16 @@ LIRGenerator::visitCall(MCall *call) return (defineReturn(lir, call) && assignSafepoint(lir, call)); } LCallKnown *lir = new LCallKnown(useFixed(call->getFunction(), CallTempReg0), argslot, tempFixed(CallTempReg2)); return (defineReturn(lir, call) && assignSafepoint(lir, call)); } - // Call unknown constructors. - if (call->isConstructing()) { - LCallConstructor *lir = new LCallConstructor(useFixed(call->getFunction(), - CallTempReg0), argslot); - return (defineVMReturn(lir, call) && assignSafepoint(lir, call)); - } - // Call anything, using the most generic code. LCallGeneric *lir = new LCallGeneric(useFixed(call->getFunction(), CallTempReg0), argslot, tempFixed(ArgumentsRectifierReg), tempFixed(CallTempReg2)); return (assignSnapshot(lir) && defineReturn(lir, call) && assignSafepoint(lir, call)); } bool LIRGenerator::visitApplyArgs(MApplyArgs *apply)
--- a/js/src/ion/VMFunctions.cpp +++ b/js/src/ion/VMFunctions.cpp @@ -83,45 +83,16 @@ InvokeFunction(JSContext *cx, JSFunction // Run the function in the interpreter. bool ok = Invoke(cx, thisv, fval, argc, argvWithoutThis, rval); if (ok && needsMonitor) types::TypeScript::Monitor(cx, *rval); return ok; } -bool -InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value *rval) -{ - Value fval = ObjectValue(*obj); - - // See the comment in InvokeFunction. - bool needsMonitor; - - if (obj->isFunction()) { - if (obj->toFunction()->isInterpretedLazy() && - !obj->toFunction()->getOrCreateScript(cx).unsafeGet()) - { - return false; - } - needsMonitor = ShouldMonitorReturnType(obj->toFunction()); - } else { - needsMonitor = true; - } - - // Data in the argument vector is arranged for a JIT -> JIT call. - Value *argvWithoutThis = argv + 1; - - bool ok = js::InvokeConstructor(cx, fval, argc, argvWithoutThis, rval); - if (ok && needsMonitor) - types::TypeScript::Monitor(cx, *rval); - - return ok; -} - JSObject * NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize) { return gc::NewGCThing<JSObject>(cx, allocKind, thingSize); } bool CheckOverRecursed(JSContext *cx)
--- a/js/src/ion/VMFunctions.h +++ b/js/src/ion/VMFunctions.h @@ -405,17 +405,16 @@ class AutoDetectInvalidation ~AutoDetectInvalidation() { if (!disabled_ && ionScript_->invalidated()) cx_->runtime->setIonReturnOverride(*rval_); } }; bool InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *rval); -bool InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value *rval); JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize); bool CheckOverRecursed(JSContext *cx); bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value); template<bool Equal>