void BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator) { replaceCalleeToken(MarkCalleeToken(trc, calleeToken())); TraceRoot(trc, &thisValue(), "baseline-this"); // Mark actual and formal args. if (isNonEvalFunctionFrame()) { unsigned numArgs = js::Max(numActualArgs(), numFormalArgs()); TraceRootRange(trc, numArgs + isConstructing(), argv(), "baseline-args"); } // Mark scope chain, if it exists. if (scopeChain_) TraceRoot(trc, &scopeChain_, "baseline-scopechain"); // Mark return value. if (hasReturnValue()) TraceRoot(trc, returnValue().address(), "baseline-rval"); if (isEvalFrame()) { TraceRoot(trc, &evalScript_, "baseline-evalscript"); if (isFunctionFrame()) TraceRoot(trc, evalNewTargetAddress(), "baseline-evalNewTarget"); } if (hasArgsObj()) TraceRoot(trc, &argsObj_, "baseline-args-obj"); // Mark locals and stack values. JSScript* script = this->script(); size_t nfixed = script->nfixed(); jsbytecode* pc; frameIterator.baselineScriptAndPc(nullptr, &pc); size_t nlivefixed = script->calculateLiveFixed(pc); // 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); } }