void InterpreterFrame::markValues(JSTracer *trc, Value *sp, jsbytecode *pc) { MOZ_ASSERT(sp >= slots()); JSScript *script = this->script(); size_t nfixed = script->nfixed(); size_t nlivefixed = script->nbodyfixed(); if (nfixed != nlivefixed) { NestedScopeObject *staticScope = script->getStaticScope(pc); while (staticScope && !staticScope->is<StaticBlockObject>()) staticScope = staticScope->enclosingNestedScope(); if (staticScope) { StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>(); nlivefixed = blockObj.localOffset() + blockObj.numVariables(); } } MOZ_ASSERT(nlivefixed <= nfixed); MOZ_ASSERT(nlivefixed >= script->nbodyfixed()); if (nfixed == nlivefixed) { // All locals are live. markValues(trc, 0, sp - slots()); } else { // Mark operand stack. markValues(trc, nfixed, sp - slots()); // Clear dead block-scoped locals. while (nfixed > nlivefixed) unaliasedLocal(--nfixed).setMagic(JS_UNINITIALIZED_LEXICAL); // Mark live locals. markValues(trc, 0, nlivefixed); } if (hasArgs()) { // Mark callee, |this| and arguments. unsigned argc = Max(numActualArgs(), numFormalArgs()); gc::MarkValueRootRange(trc, argc + 2, argv_ - 2, "fp argv"); } else { // Mark callee and |this| gc::MarkValueRootRange(trc, 2, ((Value *)this) - 2, "stack callee and this"); } }
void BaselineFrame::trace(JSTracer *trc, JitFrameIterator &frameIterator) { replaceCalleeToken(MarkCalleeToken(trc, calleeToken())); gc::MarkValueRoot(trc, &thisValue(), "baseline-this"); // Mark actual and formal args. if (isNonEvalFunctionFrame()) { unsigned numArgs = js::Max(numActualArgs(), numFormalArgs()); gc::MarkValueRootRange(trc, numArgs, argv(), "baseline-args"); } // Mark scope chain, if it exists. if (scopeChain_) gc::MarkObjectRoot(trc, &scopeChain_, "baseline-scopechain"); // Mark return value. if (hasReturnValue()) gc::MarkValueRoot(trc, returnValue().address(), "baseline-rval"); if (isEvalFrame()) gc::MarkScriptRoot(trc, &evalScript_, "baseline-evalscript"); if (hasArgsObj()) gc::MarkObjectRoot(trc, &argsObj_, "baseline-args-obj"); // Mark locals and stack values. JSScript *script = this->script(); size_t nfixed = script->nfixed(); size_t nlivefixed = script->nbodyfixed(); if (nfixed != nlivefixed) { jsbytecode *pc; frameIterator.baselineScriptAndPc(nullptr, &pc); NestedScopeObject *staticScope = script->getStaticScope(pc); while (staticScope && !staticScope->is<StaticBlockObject>()) staticScope = staticScope->enclosingNestedScope(); if (staticScope) { StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>(); nlivefixed = blockObj.localOffset() + blockObj.numVariables(); } } MOZ_ASSERT(nlivefixed <= nfixed); MOZ_ASSERT(nlivefixed >= script->nbodyfixed()); // NB: It is possible that numValueSlots() could be zero, even if nfixed is // nonzero. This is the case if the function has an early stack check. if (numValueSlots() == 0) return; MOZ_ASSERT(nfixed <= numValueSlots()); if (nfixed == nlivefixed) { // All locals are live. MarkLocals(this, trc, 0, numValueSlots()); } else { // Mark operand stack. MarkLocals(this, trc, nfixed, numValueSlots()); // Clear dead block-scoped locals. while (nfixed > nlivefixed) unaliasedLocal(--nfixed).setMagic(JS_UNINITIALIZED_LEXICAL); // Mark live locals. MarkLocals(this, trc, 0, nlivefixed); } }