author | Jan de Mooij <jdemooij@mozilla.com> |
Thu, 13 Nov 2014 17:39:49 +0100 | |
changeset 215528 | 5e645894f6bf0b32c5d17823b44c91863c1b3beb |
parent 215527 | e2be5d0449c5eea1f4395c737c53baf3f4e4780a |
child 215529 | 8792056f152cf79804df03bc7d130ad68ae0ded7 |
push id | 27818 |
push user | ryanvm@gmail.com |
push date | Thu, 13 Nov 2014 20:19:09 +0000 |
treeherder | mozilla-central@292ed84594c1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | wingo |
bugs | 1093573 |
milestone | 36.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/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -3291,65 +3291,117 @@ BaselineCompiler::addYieldOffset() } static_assert(JSOP_INITIALYIELD_LENGTH == JSOP_YIELD_LENGTH, "code below assumes INITIALYIELD and YIELD have same length"); yieldOffsets_[yieldIndex] = script->pcToOffset(pc + JSOP_YIELD_LENGTH); return true; } -typedef bool (*InitialSuspendFn)(JSContext *, HandleObject, BaselineFrame *, jsbytecode *); -static const VMFunction InitialSuspendInfo = FunctionInfo<InitialSuspendFn>(jit::InitialSuspend); - bool BaselineCompiler::emit_JSOP_INITIALYIELD() { if (!addYieldOffset()) return false; frame.syncStack(0); - - // Store generator in R0, BaselineFrame pointer in R1. - masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg()); - masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg()); - - prepareVMCall(); - pushArg(ImmPtr(pc)); - pushArg(R1.scratchReg()); - pushArg(R0.scratchReg()); - - if (!callVM(InitialSuspendInfo)) - return false; - - masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), JSReturnOperand); + MOZ_ASSERT(frame.stackDepth() == 1); + + Register genObj = R2.scratchReg(); + masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), genObj); + + MOZ_ASSERT(GET_UINT24(pc) == 0); + masm.storeValue(Int32Value(0), Address(genObj, GeneratorObject::offsetOfYieldIndexSlot())); + + Register scopeObj = R0.scratchReg(); + Address scopeChainSlot(genObj, GeneratorObject::offsetOfScopeChainSlot()); + masm.loadPtr(frame.addressOfScopeChain(), scopeObj); + masm.patchableCallPreBarrier(scopeChainSlot, MIRType_Value); + masm.storeValue(JSVAL_TYPE_OBJECT, scopeObj, scopeChainSlot); + +#ifdef JSGC_GENERATIONAL + Register temp = R1.scratchReg(); + Label skipBarrier; + masm.branchPtrInNurseryRange(Assembler::Equal, genObj, temp, &skipBarrier); + masm.branchPtrInNurseryRange(Assembler::NotEqual, scopeObj, temp, &skipBarrier); + masm.push(genObj); + MOZ_ASSERT(genObj == R2.scratchReg()); + masm.call(&postBarrierSlot_); + masm.pop(genObj); + masm.bind(&skipBarrier); +#endif + + masm.tagValue(JSVAL_TYPE_OBJECT, genObj, JSReturnOperand); return emitReturn(); } typedef bool (*NormalSuspendFn)(JSContext *, HandleObject, BaselineFrame *, jsbytecode *, uint32_t); static const VMFunction NormalSuspendInfo = FunctionInfo<NormalSuspendFn>(jit::NormalSuspend); bool BaselineCompiler::emit_JSOP_YIELD() { if (!addYieldOffset()) return false; - // Store generator in R0, BaselineFrame pointer in R1. + // Store generator in R0. frame.popRegsAndSync(1); - masm.unboxObject(R0, R0.scratchReg()); - masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg()); - - prepareVMCall(); - pushArg(Imm32(frame.stackDepth())); - pushArg(ImmPtr(pc)); - pushArg(R1.scratchReg()); - pushArg(R0.scratchReg()); - - if (!callVM(NormalSuspendInfo)) - return false; + + Register genObj = R2.scratchReg(); + masm.unboxObject(R0, genObj); + + MOZ_ASSERT(frame.stackDepth() >= 1); + + if (frame.stackDepth() == 1) { + // If the expression stack is empty, we can inline the YIELD. For legacy + // generators we normally check if we're in the closing state and throw + // an exception, but we don't have to do anything here as the expression + // stack is never empty in finally blocks. In debug builds, we assert + // we're not in the closing state. +#ifdef DEBUG + if (script->isLegacyGenerator()) { + Label ok; + masm.unboxInt32(Address(genObj, GeneratorObject::offsetOfYieldIndexSlot()), + R0.scratchReg()); + masm.branch32(Assembler::NotEqual, R0.scratchReg(), + Imm32(GeneratorObject::YIELD_INDEX_CLOSING), &ok); + masm.assumeUnreachable("Inline yield with closing generator"); + masm.bind(&ok); + } +#endif + masm.storeValue(Int32Value(GET_UINT24(pc)), + Address(genObj, GeneratorObject::offsetOfYieldIndexSlot())); + + Register scopeObj = R0.scratchReg(); + Address scopeChainSlot(genObj, GeneratorObject::offsetOfScopeChainSlot()); + masm.loadPtr(frame.addressOfScopeChain(), scopeObj); + masm.patchableCallPreBarrier(scopeChainSlot, MIRType_Value); + masm.storeValue(JSVAL_TYPE_OBJECT, scopeObj, scopeChainSlot); + +#ifdef JSGC_GENERATIONAL + Register temp = R1.scratchReg(); + Label skipBarrier; + masm.branchPtrInNurseryRange(Assembler::Equal, genObj, temp, &skipBarrier); + masm.branchPtrInNurseryRange(Assembler::NotEqual, scopeObj, temp, &skipBarrier); + MOZ_ASSERT(genObj == R2.scratchReg()); + masm.call(&postBarrierSlot_); + masm.bind(&skipBarrier); +#endif + } else { + masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg()); + + prepareVMCall(); + pushArg(Imm32(frame.stackDepth())); + pushArg(ImmPtr(pc)); + pushArg(R1.scratchReg()); + pushArg(genObj); + + if (!callVM(NormalSuspendInfo)) + return false; + } masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), JSReturnOperand); return emitReturn(); } typedef bool (*FinalSuspendFn)(JSContext *, HandleObject, BaselineFrame *, jsbytecode *); static const VMFunction FinalSuspendInfo = FunctionInfo<FinalSuspendFn>(jit::FinalSuspend);
--- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -827,23 +827,16 @@ DebugEpilogue(JSContext *cx, BaselineFra JSObject * CreateGenerator(JSContext *cx, BaselineFrame *frame) { return GeneratorObject::create(cx, frame); } bool -InitialSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc) -{ - MOZ_ASSERT(*pc == JSOP_INITIALYIELD); - return GeneratorObject::initialSuspend(cx, obj, frame, pc); -} - -bool NormalSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc, uint32_t stackDepth) { MOZ_ASSERT(*pc == JSOP_YIELD); // Return value is still on the stack. MOZ_ASSERT(stackDepth >= 1);
--- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -702,17 +702,16 @@ void PostGlobalWriteBarrier(JSRuntime *r uint32_t GetIndexFromString(JSString *str); bool DebugPrologue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn); bool DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok); bool DebugEpilogueOnBaselineReturn(JSContext *cx, BaselineFrame *frame, jsbytecode *pc); JSObject *CreateGenerator(JSContext *cx, BaselineFrame *frame); -bool InitialSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc); bool NormalSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc, uint32_t stackDepth); bool FinalSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc); bool InterpretResume(JSContext *cx, HandleObject obj, HandleValue val, HandlePropertyName kind, MutableHandleValue rval); bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame); bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame);
--- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -65,17 +65,17 @@ GeneratorObject::suspend(JSContext *cx, MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD); Rooted<GeneratorObject*> genObj(cx, &obj->as<GeneratorObject>()); MOZ_ASSERT(!genObj->hasExpressionStack()); if (*pc == JSOP_YIELD && genObj->isClosing()) { MOZ_ASSERT(genObj->is<LegacyGeneratorObject>()); RootedValue val(cx, ObjectValue(*frame.callee())); - js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, val, NullPtr()); + js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_IGNORE_STACK, val, NullPtr()); return false; } uint32_t yieldIndex = GET_UINT24(pc); MOZ_ASSERT((*pc == JSOP_INITIALYIELD) == (yieldIndex == 0)); // isNewborn() relies on this. genObj->setYieldIndex(yieldIndex); genObj->setScopeChain(*frame.scopeChain());