LCOV - code coverage report
Current view: top level - js/src/vm - Stack.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 434 1022 42.5 %
Date: 2017-07-14 16:53:18 Functions: 60 118 50.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "vm/Stack-inl.h"
       8             : 
       9             : #include "mozilla/PodOperations.h"
      10             : 
      11             : #include "jscntxt.h"
      12             : 
      13             : #include "gc/Marking.h"
      14             : #include "jit/BaselineFrame.h"
      15             : #include "jit/JitcodeMap.h"
      16             : #include "jit/JitCompartment.h"
      17             : #include "js/GCAPI.h"
      18             : #include "vm/Debugger.h"
      19             : #include "vm/Opcodes.h"
      20             : 
      21             : #include "jit/JitFrameIterator-inl.h"
      22             : #include "vm/EnvironmentObject-inl.h"
      23             : #include "vm/Interpreter-inl.h"
      24             : #include "vm/Probes-inl.h"
      25             : 
      26             : using namespace js;
      27             : 
      28             : using mozilla::ArrayLength;
      29             : using mozilla::DebugOnly;
      30             : using mozilla::Maybe;
      31             : using mozilla::PodCopy;
      32             : 
      33             : /*****************************************************************************/
      34             : 
      35             : void
      36         497 : InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script,
      37             :                                    AbstractFramePtr evalInFramePrev,
      38             :                                    const Value& newTargetValue, HandleObject envChain)
      39             : {
      40         497 :     flags_ = 0;
      41         497 :     script_ = script;
      42             : 
      43             :     // newTarget = NullValue is an initial sentinel for "please fill me in from the stack".
      44             :     // It should never be passed from Ion code.
      45         994 :     RootedValue newTarget(cx, newTargetValue);
      46         497 :     if (script->isDirectEvalInFunction()) {
      47           4 :         FrameIter iter(cx);
      48           2 :         MOZ_ASSERT(!iter.isWasm());
      49           4 :         if (newTarget.isNull() &&
      50           2 :             iter.script()->bodyScope()->hasOnChain(ScopeKind::Function))
      51             :         {
      52           2 :             newTarget = iter.newTarget();
      53             :         }
      54         495 :     } else if (evalInFramePrev) {
      55           0 :         if (newTarget.isNull() &&
      56           0 :             evalInFramePrev.script()->bodyScope()->hasOnChain(ScopeKind::Function))
      57             :         {
      58           0 :             newTarget = evalInFramePrev.newTarget();
      59             :         }
      60             :     }
      61             : 
      62         497 :     Value* dstvp = (Value*)this - 1;
      63         497 :     dstvp[0] = newTarget;
      64             : 
      65         497 :     envChain_ = envChain.get();
      66         497 :     prev_ = nullptr;
      67         497 :     prevpc_ = nullptr;
      68         497 :     prevsp_ = nullptr;
      69             : 
      70         497 :     evalInFramePrev_ = evalInFramePrev;
      71         497 :     MOZ_ASSERT_IF(evalInFramePrev, isDebuggerEvalFrame());
      72             : 
      73         497 :     if (script->isDebuggee())
      74           0 :         setIsDebuggee();
      75             : 
      76             : #ifdef DEBUG
      77         497 :     Debug_SetValueRangeToCrashOnTouch(&rval_, 1);
      78             : #endif
      79         497 : }
      80             : 
      81             : bool
      82           0 : InterpreterFrame::isNonGlobalEvalFrame() const
      83             : {
      84           0 :     return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
      85             : }
      86             : 
      87             : JSObject*
      88         241 : InterpreterFrame::createRestParameter(JSContext* cx)
      89             : {
      90         241 :     MOZ_ASSERT(script()->hasRest());
      91         241 :     unsigned nformal = callee().nargs() - 1, nactual = numActualArgs();
      92         241 :     unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
      93         241 :     Value* restvp = argv() + nformal;
      94         241 :     return ObjectGroup::newArrayObject(cx, restvp, nrest, GenericObject,
      95         241 :                                        ObjectGroup::NewArrayKind::UnknownIndex);
      96             : }
      97             : 
      98             : static inline void
      99       12896 : AssertScopeMatchesEnvironment(Scope* scope, JSObject* originalEnv)
     100             : {
     101             : #ifdef DEBUG
     102       12896 :     JSObject* env = originalEnv;
     103       31325 :     for (ScopeIter si(scope); si; si++) {
     104       18429 :         if (si.kind() == ScopeKind::NonSyntactic) {
     105        9785 :             while (env->is<WithEnvironmentObject>() ||
     106        6572 :                    env->is<NonSyntacticVariablesObject>() ||
     107        3184 :                    (env->is<LexicalEnvironmentObject>() &&
     108        1592 :                     !env->as<LexicalEnvironmentObject>().isSyntactic()))
     109             :             {
     110        2092 :                 MOZ_ASSERT(!IsSyntacticEnvironment(env));
     111        2092 :                 env = &env->as<EnvironmentObject>().enclosingEnvironment();
     112             :             }
     113       17633 :         } else if (si.hasSyntacticEnvironment()) {
     114       16165 :             switch (si.kind()) {
     115             :               case ScopeKind::Function:
     116        2800 :                 MOZ_ASSERT(env->as<CallObject>().callee().existingScriptNonDelazifying() ==
     117             :                            si.scope()->as<FunctionScope>().script());
     118        2800 :                 env = &env->as<CallObject>().enclosingEnvironment();
     119        2800 :                 break;
     120             : 
     121             :               case ScopeKind::FunctionBodyVar:
     122             :               case ScopeKind::ParameterExpressionVar:
     123          94 :                 MOZ_ASSERT(&env->as<VarEnvironmentObject>().scope() == si.scope());
     124          94 :                 env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
     125          94 :                 break;
     126             : 
     127             :               case ScopeKind::Lexical:
     128             :               case ScopeKind::SimpleCatch:
     129             :               case ScopeKind::Catch:
     130             :               case ScopeKind::NamedLambda:
     131             :               case ScopeKind::StrictNamedLambda:
     132        1102 :                 MOZ_ASSERT(&env->as<LexicalEnvironmentObject>().scope() == si.scope());
     133        1102 :                 env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
     134        1102 :                 break;
     135             : 
     136             :               case ScopeKind::With:
     137           0 :                 MOZ_ASSERT(&env->as<WithEnvironmentObject>().scope() == si.scope());
     138           0 :                 env = &env->as<WithEnvironmentObject>().enclosingEnvironment();
     139           0 :                 break;
     140             : 
     141             :               case ScopeKind::Eval:
     142             :               case ScopeKind::StrictEval:
     143          69 :                 env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
     144          69 :                 break;
     145             : 
     146             :               case ScopeKind::Global:
     147       12100 :                 MOZ_ASSERT(env->as<LexicalEnvironmentObject>().isGlobal());
     148       12100 :                 env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
     149       12100 :                 MOZ_ASSERT(env->is<GlobalObject>());
     150       12100 :                 break;
     151             : 
     152             :               case ScopeKind::NonSyntactic:
     153           0 :                 MOZ_CRASH("NonSyntactic should not have a syntactic environment");
     154             :                 break;
     155             : 
     156             :               case ScopeKind::Module:
     157           0 :                 MOZ_ASSERT(env->as<ModuleEnvironmentObject>().module().script() ==
     158             :                            si.scope()->as<ModuleScope>().script());
     159           0 :                 env = &env->as<ModuleEnvironmentObject>().enclosingEnvironment();
     160           0 :                 break;
     161             : 
     162             :               case ScopeKind::WasmFunction:
     163           0 :                 env = &env->as<WasmFunctionCallObject>().enclosingEnvironment();
     164           0 :                 break;
     165             :             }
     166             :         }
     167             :     }
     168             : 
     169             :     // In the case of a non-syntactic env chain, the immediate parent of the
     170             :     // outermost non-syntactic env may be the global lexical env, or, if
     171             :     // called from Debugger, a DebugEnvironmentProxy.
     172             :     //
     173             :     // In the case of a syntactic env chain, the outermost env is always a
     174             :     // GlobalObject.
     175       12896 :     MOZ_ASSERT(env->is<GlobalObject>() || IsGlobalLexicalEnvironment(env) ||
     176             :                env->is<DebugEnvironmentProxy>());
     177             : #endif
     178       12896 : }
     179             : 
     180             : static inline void
     181       12147 : AssertScopeMatchesEnvironment(InterpreterFrame* fp, jsbytecode* pc)
     182             : {
     183             : #ifdef DEBUG
     184             :     // If we OOMed before fully initializing the environment chain, the scope
     185             :     // and environment will definitely mismatch.
     186       12147 :     if (fp->script()->initialEnvironmentShape() && fp->hasInitialEnvironment())
     187        1293 :         AssertScopeMatchesEnvironment(fp->script()->innermostScope(pc), fp->environmentChain());
     188             : #endif
     189       12147 : }
     190             : 
     191             : bool
     192        1129 : InterpreterFrame::initFunctionEnvironmentObjects(JSContext* cx)
     193             : {
     194        1129 :     return js::InitFunctionEnvironmentObjects(cx, this);
     195             : }
     196             : 
     197             : bool
     198       12100 : InterpreterFrame::prologue(JSContext* cx)
     199             : {
     200       24200 :     RootedScript script(cx, this->script());
     201             : 
     202       12100 :     MOZ_ASSERT(cx->interpreterRegs().pc == script->code());
     203             : 
     204       12100 :     if (isEvalFrame()) {
     205           2 :         if (!script->bodyScope()->hasEnvironment()) {
     206           0 :             MOZ_ASSERT(!script->strict());
     207             :             // Non-strict eval may introduce var bindings that conflict with
     208             :             // lexical bindings in an enclosing lexical scope.
     209           0 :             RootedObject varObjRoot(cx, &varObj());
     210           0 :             if (!CheckEvalDeclarationConflicts(cx, script, environmentChain(), varObjRoot))
     211           0 :                 return false;
     212             :         }
     213           2 :         return probes::EnterScript(cx, script, nullptr, this);
     214             :     }
     215             : 
     216       12098 :     if (isGlobalFrame()) {
     217         990 :         Rooted<LexicalEnvironmentObject*> lexicalEnv(cx);
     218         990 :         RootedObject varObjRoot(cx);
     219         495 :         if (script->hasNonSyntacticScope()) {
     220         173 :             lexicalEnv = &extensibleLexicalEnvironment();
     221         173 :             varObjRoot = &varObj();
     222             :         } else {
     223         322 :             lexicalEnv = &cx->global()->lexicalEnvironment();
     224         322 :             varObjRoot = cx->global();
     225             :         }
     226         495 :         if (!CheckGlobalDeclarationConflicts(cx, script, lexicalEnv, varObjRoot))
     227           0 :             return false;
     228         495 :         return probes::EnterScript(cx, script, nullptr, this);
     229             :     }
     230             : 
     231       11603 :     if (isModuleFrame())
     232           0 :         return probes::EnterScript(cx, script, nullptr, this);
     233             : 
     234             :     // At this point, we've yet to push any environments. Check that they
     235             :     // match the enclosing scope.
     236       11603 :     AssertScopeMatchesEnvironment(script->enclosingScope(), environmentChain());
     237             : 
     238       11603 :     MOZ_ASSERT(isFunctionFrame());
     239       11603 :     if (callee().needsFunctionEnvironmentObjects() && !initFunctionEnvironmentObjects(cx))
     240           0 :         return false;
     241             : 
     242       11603 :     if (isConstructing()) {
     243         422 :         if (callee().isBoundFunction()) {
     244           0 :             thisArgument() = MagicValue(JS_UNINITIALIZED_LEXICAL);
     245         422 :         } else if (script->isDerivedClassConstructor()) {
     246          29 :             MOZ_ASSERT(callee().isClassConstructor());
     247          29 :             thisArgument() = MagicValue(JS_UNINITIALIZED_LEXICAL);
     248         393 :         } else if (thisArgument().isObject()) {
     249             :             // Nothing to do. Correctly set.
     250             :         } else {
     251           0 :             MOZ_ASSERT(thisArgument().isMagic(JS_IS_CONSTRUCTING));
     252           0 :             RootedObject callee(cx, &this->callee());
     253           0 :             RootedObject newTarget(cx, &this->newTarget().toObject());
     254           0 :             JSObject* obj = CreateThisForFunction(cx, callee, newTarget,
     255           0 :                                                   createSingleton() ? SingletonObject : GenericObject);
     256           0 :             if (!obj)
     257           0 :                 return false;
     258           0 :             thisArgument() = ObjectValue(*obj);
     259             :         }
     260             :     }
     261             : 
     262       11603 :     return probes::EnterScript(cx, script, script->functionNonDelazifying(), this);
     263             : }
     264             : 
     265             : void
     266       12147 : InterpreterFrame::epilogue(JSContext* cx, jsbytecode* pc)
     267             : {
     268       12636 :     RootedScript script(cx, this->script());
     269       12147 :     probes::ExitScript(cx, script, script->functionNonDelazifying(), hasPushedGeckoProfilerFrame());
     270             : 
     271             :     // Check that the scope matches the environment at the point of leaving
     272             :     // the frame.
     273       12147 :     AssertScopeMatchesEnvironment(this, pc);
     274             : 
     275       12636 :     EnvironmentIter ei(cx, this, pc);
     276       12147 :     UnwindAllEnvironmentsInFrame(cx, ei);
     277             : 
     278       12147 :     if (isFunctionFrame()) {
     279       57797 :         if (!callee().isStarGenerator() &&
     280       23106 :             !callee().isLegacyGenerator() &&
     281       22962 :             !callee().isAsync() &&
     282       11825 :             isConstructing() &&
     283       24508 :             thisArgument().isObject() &&
     284       12822 :             returnValue().isPrimitive())
     285             :         {
     286         370 :             setReturnValue(thisArgument());
     287             :         }
     288             : 
     289       11658 :         return;
     290             :     }
     291             : 
     292         489 :     MOZ_ASSERT(isEvalFrame() || isGlobalFrame() || isModuleFrame());
     293             : }
     294             : 
     295             : bool
     296          28 : InterpreterFrame::checkReturn(JSContext* cx, HandleValue thisv)
     297             : {
     298          28 :     MOZ_ASSERT(script()->isDerivedClassConstructor());
     299          28 :     MOZ_ASSERT(isFunctionFrame());
     300          28 :     MOZ_ASSERT(callee().isClassConstructor());
     301             : 
     302          28 :     HandleValue retVal = returnValue();
     303          28 :     if (retVal.isObject())
     304           0 :         return true;
     305             : 
     306          28 :     if (!retVal.isUndefined()) {
     307           0 :         ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, retVal, nullptr);
     308           0 :         return false;
     309             :     }
     310             : 
     311          28 :     if (thisv.isMagic(JS_UNINITIALIZED_LEXICAL))
     312           0 :         return ThrowUninitializedThis(cx, this);
     313             : 
     314          28 :     setReturnValue(thisv);
     315          28 :     return true;
     316             : }
     317             : 
     318             : bool
     319          32 : InterpreterFrame::pushVarEnvironment(JSContext* cx, HandleScope scope)
     320             : {
     321          32 :     return js::PushVarEnvironmentObject(cx, scope, this);
     322             : }
     323             : 
     324             : bool
     325         475 : InterpreterFrame::pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope)
     326             : {
     327         475 :     LexicalEnvironmentObject* env = LexicalEnvironmentObject::create(cx, scope, this);
     328         475 :     if (!env)
     329           0 :         return false;
     330             : 
     331         475 :     pushOnEnvironmentChain(*env);
     332         475 :     return true;
     333             : }
     334             : 
     335             : bool
     336           0 : InterpreterFrame::freshenLexicalEnvironment(JSContext* cx)
     337             : {
     338           0 :     Rooted<LexicalEnvironmentObject*> env(cx, &envChain_->as<LexicalEnvironmentObject>());
     339           0 :     LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::clone(cx, env);
     340           0 :     if (!fresh)
     341           0 :         return false;
     342             : 
     343           0 :     replaceInnermostEnvironment(*fresh);
     344           0 :     return true;
     345             : }
     346             : 
     347             : bool
     348          73 : InterpreterFrame::recreateLexicalEnvironment(JSContext* cx)
     349             : {
     350         146 :     Rooted<LexicalEnvironmentObject*> env(cx, &envChain_->as<LexicalEnvironmentObject>());
     351          73 :     LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::recreate(cx, env);
     352          73 :     if (!fresh)
     353           0 :         return false;
     354             : 
     355          73 :     replaceInnermostEnvironment(*fresh);
     356          73 :     return true;
     357             : }
     358             : 
     359             : void
     360         105 : InterpreterFrame::trace(JSTracer* trc, Value* sp, jsbytecode* pc)
     361             : {
     362         105 :     TraceRoot(trc, &envChain_, "env chain");
     363         105 :     TraceRoot(trc, &script_, "script");
     364             : 
     365         105 :     if (flags_ & HAS_ARGS_OBJ)
     366           3 :         TraceRoot(trc, &argsObj_, "arguments");
     367             : 
     368         105 :     if (hasReturnValue())
     369           4 :         TraceRoot(trc, &rval_, "rval");
     370             : 
     371         105 :     MOZ_ASSERT(sp >= slots());
     372             : 
     373         105 :     if (hasArgs()) {
     374             :         // Trace the callee and |this|. When we're doing a moving GC, we
     375             :         // need to fix up the callee pointer before we use it below, under
     376             :         // numFormalArgs() and script().
     377          88 :         TraceRootRange(trc, 2, argv_ - 2, "fp callee and this");
     378             : 
     379             :         // Trace arguments.
     380          88 :         unsigned argc = Max(numActualArgs(), numFormalArgs());
     381          88 :         TraceRootRange(trc, argc + isConstructing(), argv_, "fp argv");
     382             :     } else {
     383             :         // Trace newTarget.
     384          17 :         TraceRoot(trc, ((Value*)this) - 1, "stack newTarget");
     385             :     }
     386             : 
     387         105 :     JSScript* script = this->script();
     388         105 :     size_t nfixed = script->nfixed();
     389         105 :     size_t nlivefixed = script->calculateLiveFixed(pc);
     390             : 
     391         105 :     if (nfixed == nlivefixed) {
     392             :         // All locals are live.
     393          68 :         traceValues(trc, 0, sp - slots());
     394             :     } else {
     395             :         // Trace operand stack.
     396          37 :         traceValues(trc, nfixed, sp - slots());
     397             : 
     398             :         // Clear dead block-scoped locals.
     399         207 :         while (nfixed > nlivefixed)
     400          85 :             unaliasedLocal(--nfixed).setUndefined();
     401             : 
     402             :         // Trace live locals.
     403          37 :         traceValues(trc, 0, nlivefixed);
     404             :     }
     405             : 
     406         105 :     if (script->compartment()->debugEnvs)
     407           0 :         script->compartment()->debugEnvs->traceLiveFrame(trc, this);
     408         105 : }
     409             : 
     410             : void
     411         142 : InterpreterFrame::traceValues(JSTracer* trc, unsigned start, unsigned end)
     412             : {
     413         142 :     if (start < end)
     414         129 :         TraceRootRange(trc, end - start, slots() + start, "vm_stack");
     415         142 : }
     416             : 
     417             : static void
     418          82 : TraceInterpreterActivation(JSTracer* trc, InterpreterActivation* act)
     419             : {
     420         187 :     for (InterpreterFrameIterator frames(act); !frames.done(); ++frames) {
     421         105 :         InterpreterFrame* fp = frames.frame();
     422         105 :         fp->trace(trc, frames.sp(), frames.pc());
     423             :     }
     424          82 : }
     425             : 
     426             : void
     427          22 : js::TraceInterpreterActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc)
     428             : {
     429         128 :     for (ActivationIterator iter(cx, target); !iter.done(); ++iter) {
     430         106 :         Activation* act = iter.activation();
     431         106 :         if (act->isInterpreter())
     432          82 :             TraceInterpreterActivation(trc, act->asInterpreter());
     433             :     }
     434          22 : }
     435             : 
     436             : /*****************************************************************************/
     437             : 
     438             : // Unlike the other methods of this class, this method is defined here so that
     439             : // we don't have to #include jsautooplen.h in vm/Stack.h.
     440             : void
     441          12 : InterpreterRegs::setToEndOfScript()
     442             : {
     443          12 :     sp = fp()->base();
     444          12 : }
     445             : 
     446             : /*****************************************************************************/
     447             : 
     448             : InterpreterFrame*
     449        9929 : InterpreterStack::pushInvokeFrame(JSContext* cx, const CallArgs& args, MaybeConstruct constructing)
     450             : {
     451        9929 :     LifoAlloc::Mark mark = allocator_.mark();
     452             : 
     453       19858 :     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     454       19858 :     RootedScript script(cx, fun->nonLazyScript());
     455             : 
     456             :     Value* argv;
     457        9929 :     InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
     458        9929 :     if (!fp)
     459           0 :         return nullptr;
     460             : 
     461        9929 :     fp->mark_ = mark;
     462       19858 :     fp->initCallFrame(cx, nullptr, nullptr, nullptr, *fun, script, argv, args.length(),
     463       19858 :                       constructing);
     464        9929 :     return fp;
     465             : }
     466             : 
     467             : InterpreterFrame*
     468         497 : InterpreterStack::pushExecuteFrame(JSContext* cx, HandleScript script, const Value& newTargetValue,
     469             :                                    HandleObject envChain, AbstractFramePtr evalInFrame)
     470             : {
     471         497 :     LifoAlloc::Mark mark = allocator_.mark();
     472             : 
     473         497 :     unsigned nvars = 1 /* newTarget */ + script->nslots();
     474         497 :     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvars * sizeof(Value));
     475         497 :     if (!buffer)
     476           0 :         return nullptr;
     477             : 
     478         497 :     InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(buffer + 1 * sizeof(Value));
     479         497 :     fp->mark_ = mark;
     480         497 :     fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, envChain);
     481         497 :     fp->initLocals();
     482             : 
     483         497 :     return fp;
     484             : }
     485             : 
     486             : /*****************************************************************************/
     487             : 
     488             : void
     489        9218 : FrameIter::popActivation()
     490             : {
     491        9218 :     ++data_.activations_;
     492        9218 :     settleOnActivation();
     493        9218 : }
     494             : 
     495             : void
     496        7478 : FrameIter::popInterpreterFrame()
     497             : {
     498        7478 :     MOZ_ASSERT(data_.state_ == INTERP);
     499             : 
     500        7478 :     ++data_.interpFrames_;
     501             : 
     502        7478 :     if (data_.interpFrames_.done())
     503        6191 :         popActivation();
     504             :     else
     505        1287 :         data_.pc_ = data_.interpFrames_.pc();
     506        7478 : }
     507             : 
     508             : void
     509       13135 : FrameIter::settleOnActivation()
     510             : {
     511             :     while (true) {
     512       13135 :         if (data_.activations_.done()) {
     513        2664 :             data_.state_ = DONE;
     514        2664 :             return;
     515             :         }
     516             : 
     517       10471 :         Activation* activation = data_.activations_.activation();
     518             : 
     519             :         // If the caller supplied principals, only show activations which are subsumed (of the same
     520             :         // origin or of an origin accessible) by these principals.
     521       10471 :         if (data_.principals_) {
     522          54 :             JSContext* cx = data_.cx_;
     523          54 :             if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
     524          52 :                 if (!subsumes(data_.principals_, activation->compartment()->principals())) {
     525           0 :                     ++data_.activations_;
     526           0 :                     continue;
     527             :                 }
     528             :             }
     529             :         }
     530             : 
     531       10471 :         if (activation->isJit()) {
     532        3105 :             data_.jitFrames_ = jit::JitFrameIterator(data_.activations_);
     533             : 
     534             :             // Stop at the first scripted frame.
     535       15427 :             while (!data_.jitFrames_.isScripted() && !data_.jitFrames_.done())
     536        6161 :                 ++data_.jitFrames_;
     537             : 
     538             :             // It's possible to have an JitActivation with no scripted frames,
     539             :             // for instance if we hit an over-recursion during bailout.
     540        3105 :             if (data_.jitFrames_.done()) {
     541           0 :                 ++data_.activations_;
     542           0 :                 continue;
     543             :             }
     544             : 
     545        3105 :             nextJitFrame();
     546        3105 :             data_.state_ = JIT;
     547        3105 :             return;
     548             :         }
     549             : 
     550        7366 :         if (activation->isWasm()) {
     551           0 :             data_.wasmFrames_ = wasm::FrameIterator(data_.activations_->asWasm());
     552             : 
     553           0 :             if (data_.wasmFrames_.done()) {
     554           0 :                 ++data_.activations_;
     555           0 :                 continue;
     556             :             }
     557             : 
     558           0 :             data_.pc_ = nullptr;
     559           0 :             data_.state_ = WASM;
     560           0 :             return;
     561             :         }
     562             : 
     563        7366 :         MOZ_ASSERT(activation->isInterpreter());
     564             : 
     565        7366 :         InterpreterActivation* interpAct = activation->asInterpreter();
     566        7366 :         data_.interpFrames_ = InterpreterFrameIterator(interpAct);
     567             : 
     568             :         // If we OSR'ed into JIT code, skip the interpreter frame so that
     569             :         // the same frame is not reported twice.
     570        7366 :         if (data_.interpFrames_.frame()->runningInJit()) {
     571         774 :             ++data_.interpFrames_;
     572         774 :             if (data_.interpFrames_.done()) {
     573         731 :                 ++data_.activations_;
     574         731 :                 continue;
     575             :             }
     576             :         }
     577             : 
     578        6635 :         MOZ_ASSERT(!data_.interpFrames_.frame()->runningInJit());
     579        6635 :         data_.pc_ = data_.interpFrames_.pc();
     580        6635 :         data_.state_ = INTERP;
     581        6635 :         return;
     582         731 :     }
     583             : }
     584             : 
     585        3186 : FrameIter::Data::Data(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
     586        3186 :                       JSPrincipals* principals)
     587             :   : cx_(cx),
     588             :     debuggerEvalOption_(debuggerEvalOption),
     589             :     principals_(principals),
     590             :     state_(DONE),
     591             :     pc_(nullptr),
     592             :     interpFrames_(nullptr),
     593             :     activations_(cx),
     594             :     jitFrames_(),
     595             :     ionInlineFrameNo_(0),
     596        3186 :     wasmFrames_()
     597             : {
     598        3186 : }
     599             : 
     600           0 : FrameIter::Data::Data(const FrameIter::Data& other)
     601           0 :   : cx_(other.cx_),
     602           0 :     debuggerEvalOption_(other.debuggerEvalOption_),
     603           0 :     principals_(other.principals_),
     604           0 :     state_(other.state_),
     605           0 :     pc_(other.pc_),
     606             :     interpFrames_(other.interpFrames_),
     607             :     activations_(other.activations_),
     608             :     jitFrames_(other.jitFrames_),
     609           0 :     ionInlineFrameNo_(other.ionInlineFrameNo_),
     610           0 :     wasmFrames_(other.wasmFrames_)
     611             : {
     612           0 : }
     613             : 
     614        3132 : FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption)
     615             :   : data_(cx, debuggerEvalOption, nullptr),
     616        3132 :     ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
     617             : {
     618             :     // settleOnActivation can only GC if principals are given.
     619        6264 :     JS::AutoSuppressGCAnalysis nogc;
     620        3132 :     settleOnActivation();
     621        3132 : }
     622             : 
     623          54 : FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
     624          54 :                      JSPrincipals* principals)
     625             :   : data_(cx, debuggerEvalOption, principals),
     626          54 :     ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
     627             : {
     628          54 :     settleOnActivation();
     629          54 : }
     630             : 
     631           0 : FrameIter::FrameIter(const FrameIter& other)
     632             :   : data_(other.data_),
     633           0 :     ionInlineFrames_(other.data_.cx_,
     634           0 :                      data_.jitFrames_.isIonScripted() ? &other.ionInlineFrames_ : nullptr)
     635             : {
     636           0 : }
     637             : 
     638           0 : FrameIter::FrameIter(const Data& data)
     639             :   : data_(data),
     640           0 :     ionInlineFrames_(data.cx_, data_.jitFrames_.isIonScripted() ? &data_.jitFrames_ : nullptr)
     641             : {
     642           0 :     MOZ_ASSERT(data.cx_);
     643             : 
     644           0 :     if (data_.jitFrames_.isIonScripted()) {
     645           0 :         while (ionInlineFrames_.frameNo() != data.ionInlineFrameNo_)
     646           0 :             ++ionInlineFrames_;
     647             :     }
     648           0 : }
     649             : 
     650             : void
     651        5110 : FrameIter::nextJitFrame()
     652             : {
     653        5110 :     if (data_.jitFrames_.isIonScripted()) {
     654         840 :         ionInlineFrames_.resetOn(&data_.jitFrames_);
     655         840 :         data_.pc_ = ionInlineFrames_.pc();
     656             :     } else {
     657        4270 :         MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
     658        4270 :         data_.jitFrames_.baselineScriptAndPc(nullptr, &data_.pc_);
     659             :     }
     660        5110 : }
     661             : 
     662             : void
     663        5032 : FrameIter::popJitFrame()
     664             : {
     665        5032 :     MOZ_ASSERT(data_.state_ == JIT);
     666             : 
     667        5032 :     if (data_.jitFrames_.isIonScripted() && ionInlineFrames_.more()) {
     668           0 :         ++ionInlineFrames_;
     669           0 :         data_.pc_ = ionInlineFrames_.pc();
     670           0 :         return;
     671             :     }
     672             : 
     673        5032 :     ++data_.jitFrames_;
     674        7414 :     while (!data_.jitFrames_.done() && !data_.jitFrames_.isScripted())
     675        1191 :         ++data_.jitFrames_;
     676             : 
     677        5032 :     if (!data_.jitFrames_.done()) {
     678        2005 :         nextJitFrame();
     679        2005 :         return;
     680             :     }
     681             : 
     682        3027 :     popActivation();
     683             : }
     684             : 
     685             : void
     686           0 : FrameIter::popWasmFrame()
     687             : {
     688           0 :     MOZ_ASSERT(data_.state_ == WASM);
     689             : 
     690           0 :     ++data_.wasmFrames_;
     691           0 :     data_.pc_ = nullptr;
     692           0 :     if (data_.wasmFrames_.done())
     693           0 :         popActivation();
     694           0 : }
     695             : 
     696             : FrameIter&
     697       12510 : FrameIter::operator++()
     698             : {
     699       12510 :     switch (data_.state_) {
     700             :       case DONE:
     701           0 :         MOZ_CRASH("Unexpected state");
     702             :       case INTERP:
     703       29912 :         if (interpFrame()->isDebuggerEvalFrame() &&
     704       22434 :             interpFrame()->evalInFramePrev() &&
     705           0 :             data_.debuggerEvalOption_ == FOLLOW_DEBUGGER_EVAL_PREV_LINK)
     706             :         {
     707           0 :             AbstractFramePtr eifPrev = interpFrame()->evalInFramePrev();
     708             : 
     709           0 :             popInterpreterFrame();
     710             : 
     711           0 :             while (!hasUsableAbstractFramePtr() || abstractFramePtr() != eifPrev) {
     712           0 :                 if (data_.state_ == JIT)
     713           0 :                     popJitFrame();
     714           0 :                 else if (data_.state_ == WASM)
     715           0 :                     popWasmFrame();
     716             :                 else
     717           0 :                     popInterpreterFrame();
     718             :             }
     719             : 
     720           0 :             break;
     721             :         }
     722        7478 :         popInterpreterFrame();
     723        7478 :         break;
     724             :       case JIT:
     725        5032 :         popJitFrame();
     726        5032 :         break;
     727             :       case WASM:
     728           0 :         popWasmFrame();
     729           0 :         break;
     730             :     }
     731       12510 :     return *this;
     732             : }
     733             : 
     734             : FrameIter::Data*
     735           0 : FrameIter::copyData() const
     736             : {
     737           0 :     Data* data = data_.cx_->new_<Data>(data_);
     738           0 :     if (!data)
     739           0 :         return nullptr;
     740             : 
     741           0 :     if (data && data_.jitFrames_.isIonScripted())
     742           0 :         data->ionInlineFrameNo_ = ionInlineFrames_.frameNo();
     743           0 :     return data;
     744             : }
     745             : 
     746             : AbstractFramePtr
     747           0 : FrameIter::copyDataAsAbstractFramePtr() const
     748             : {
     749           0 :     AbstractFramePtr frame;
     750           0 :     if (Data* data = copyData())
     751           0 :         frame.ptr_ = uintptr_t(data);
     752           0 :     return frame;
     753             : }
     754             : 
     755             : void*
     756           0 : FrameIter::rawFramePtr() const
     757             : {
     758           0 :     switch (data_.state_) {
     759             :       case DONE:
     760           0 :         return nullptr;
     761             :       case JIT:
     762           0 :         return data_.jitFrames_.fp();
     763             :       case INTERP:
     764           0 :         return interpFrame();
     765             :       case WASM:
     766           0 :         return nullptr;
     767             :     }
     768           0 :     MOZ_CRASH("Unexpected state");
     769             : }
     770             : 
     771             : JSCompartment*
     772       37708 : FrameIter::compartment() const
     773             : {
     774       37708 :     switch (data_.state_) {
     775             :       case DONE:
     776           0 :         break;
     777             :       case INTERP:
     778             :       case JIT:
     779             :       case WASM:
     780       75416 :         return data_.activations_->compartment();
     781             :     }
     782           0 :     MOZ_CRASH("Unexpected state");
     783             : }
     784             : 
     785             : bool
     786           0 : FrameIter::isEvalFrame() const
     787             : {
     788           0 :     switch (data_.state_) {
     789             :       case DONE:
     790           0 :         break;
     791             :       case INTERP:
     792           0 :         return interpFrame()->isEvalFrame();
     793             :       case JIT:
     794           0 :         if (data_.jitFrames_.isBaselineJS())
     795           0 :             return data_.jitFrames_.baselineFrame()->isEvalFrame();
     796           0 :         MOZ_ASSERT(!script()->isForEval());
     797           0 :         return false;
     798             :       case WASM:
     799           0 :         return false;
     800             :     }
     801           0 :     MOZ_CRASH("Unexpected state");
     802             : }
     803             : 
     804             : bool
     805       32205 : FrameIter::isFunctionFrame() const
     806             : {
     807       32205 :     MOZ_ASSERT(!done());
     808       32205 :     switch (data_.state_) {
     809             :       case DONE:
     810           0 :         break;
     811             :       case INTERP:
     812       22169 :         return interpFrame()->isFunctionFrame();
     813             :       case JIT:
     814       10036 :         if (data_.jitFrames_.isBaselineJS())
     815        8356 :             return data_.jitFrames_.baselineFrame()->isFunctionFrame();
     816        1680 :         return script()->functionNonDelazifying();
     817             :       case WASM:
     818           0 :         return false;
     819             :     }
     820           0 :     MOZ_CRASH("Unexpected state");
     821             : }
     822             : 
     823             : JSAtom*
     824       12380 : FrameIter::functionDisplayAtom() const
     825             : {
     826       12380 :     switch (data_.state_) {
     827             :       case DONE:
     828           0 :         break;
     829             :       case INTERP:
     830             :       case JIT:
     831       12380 :         MOZ_ASSERT(isFunctionFrame());
     832       12380 :         return calleeTemplate()->displayAtom();
     833             :       case WASM:
     834           0 :         MOZ_ASSERT(isWasm());
     835           0 :         return data_.wasmFrames_.functionDisplayAtom();
     836             :     }
     837             : 
     838           0 :     MOZ_CRASH("Unexpected state");
     839             : }
     840             : 
     841             : ScriptSource*
     842          47 : FrameIter::scriptSource() const
     843             : {
     844          47 :     switch (data_.state_) {
     845             :       case DONE:
     846             :       case WASM:
     847           0 :         break;
     848             :       case INTERP:
     849             :       case JIT:
     850          94 :         return script()->scriptSource();
     851             :     }
     852             : 
     853           0 :     MOZ_CRASH("Unexpected state");
     854             : }
     855             : 
     856             : const char*
     857           7 : FrameIter::filename() const
     858             : {
     859           7 :     switch (data_.state_) {
     860             :       case DONE:
     861           0 :         break;
     862             :       case INTERP:
     863             :       case JIT:
     864           7 :         return script()->filename();
     865             :       case WASM:
     866           0 :         return data_.wasmFrames_.filename();
     867             :     }
     868             : 
     869           0 :     MOZ_CRASH("Unexpected state");
     870             : }
     871             : 
     872             : const char16_t*
     873         722 : FrameIter::displayURL() const
     874             : {
     875         722 :     switch (data_.state_) {
     876             :       case DONE:
     877           0 :         break;
     878             :       case INTERP:
     879             :       case JIT: {
     880         722 :         ScriptSource* ss = script()->scriptSource();
     881         722 :         return ss->hasDisplayURL() ? ss->displayURL() : nullptr;
     882             :       }
     883             :       case WASM:
     884           0 :         return data_.wasmFrames_.displayURL();
     885             :     }
     886           0 :     MOZ_CRASH("Unexpected state");
     887             : }
     888             : 
     889             : unsigned
     890          20 : FrameIter::computeLine(uint32_t* column) const
     891             : {
     892          20 :     switch (data_.state_) {
     893             :       case DONE:
     894           0 :         break;
     895             :       case INTERP:
     896             :       case JIT:
     897          20 :         return PCToLineNumber(script(), pc(), column);
     898             :       case WASM:
     899           0 :         if (column)
     900           0 :             *column = 0;
     901           0 :         return data_.wasmFrames_.lineOrBytecode();
     902             :     }
     903             : 
     904           0 :     MOZ_CRASH("Unexpected state");
     905             : }
     906             : 
     907             : bool
     908           6 : FrameIter::mutedErrors() const
     909             : {
     910           6 :     switch (data_.state_) {
     911             :       case DONE:
     912           0 :         break;
     913             :       case INTERP:
     914             :       case JIT:
     915           6 :         return script()->mutedErrors();
     916             :       case WASM:
     917           0 :         return data_.wasmFrames_.mutedErrors();
     918             :     }
     919           0 :     MOZ_CRASH("Unexpected state");
     920             : }
     921             : 
     922             : bool
     923         118 : FrameIter::isConstructing() const
     924             : {
     925         118 :     switch (data_.state_) {
     926             :       case DONE:
     927             :       case WASM:
     928           0 :         break;
     929             :       case JIT:
     930          50 :         if (data_.jitFrames_.isIonScripted())
     931           0 :             return ionInlineFrames_.isConstructing();
     932          50 :         MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
     933          50 :         return data_.jitFrames_.isConstructing();
     934             :       case INTERP:
     935          68 :         return interpFrame()->isConstructing();
     936             :     }
     937             : 
     938           0 :     MOZ_CRASH("Unexpected state");
     939             : }
     940             : 
     941             : bool
     942           0 : FrameIter::ensureHasRematerializedFrame(JSContext* cx)
     943             : {
     944           0 :     MOZ_ASSERT(isIon());
     945           0 :     return !!activation()->asJit()->getRematerializedFrame(cx, data_.jitFrames_);
     946             : }
     947             : 
     948             : bool
     949       38472 : FrameIter::hasUsableAbstractFramePtr() const
     950             : {
     951       38472 :     switch (data_.state_) {
     952             :       case DONE:
     953           0 :         return false;
     954             :       case JIT:
     955       11050 :         if (data_.jitFrames_.isBaselineJS())
     956       10210 :             return true;
     957             : 
     958         840 :         MOZ_ASSERT(data_.jitFrames_.isIonScripted());
     959         840 :         return !!activation()->asJit()->lookupRematerializedFrame(data_.jitFrames_.fp(),
     960         840 :                                                                   ionInlineFrames_.frameNo());
     961             :         break;
     962             :       case INTERP:
     963       27422 :         return true;
     964             :       case WASM:
     965           0 :         return data_.wasmFrames_.debugEnabled();
     966             :     }
     967           0 :     MOZ_CRASH("Unexpected state");
     968             : }
     969             : 
     970             : AbstractFramePtr
     971       18817 : FrameIter::abstractFramePtr() const
     972             : {
     973       18817 :     MOZ_ASSERT(hasUsableAbstractFramePtr());
     974       18817 :     switch (data_.state_) {
     975             :       case DONE:
     976           0 :         break;
     977             :       case JIT: {
     978        5105 :         if (data_.jitFrames_.isBaselineJS())
     979        5105 :             return data_.jitFrames_.baselineFrame();
     980             : 
     981           0 :         MOZ_ASSERT(data_.jitFrames_.isIonScripted());
     982             :         return activation()->asJit()->lookupRematerializedFrame(data_.jitFrames_.fp(),
     983           0 :                                                                 ionInlineFrames_.frameNo());
     984             :         break;
     985             :       }
     986             :       case INTERP:
     987       13712 :         MOZ_ASSERT(interpFrame());
     988       13712 :         return AbstractFramePtr(interpFrame());
     989             :       case WASM:
     990           0 :         MOZ_ASSERT(data_.wasmFrames_.debugEnabled());
     991           0 :         return data_.wasmFrames_.debugFrame();
     992             :     }
     993           0 :     MOZ_CRASH("Unexpected state");
     994             : }
     995             : 
     996             : void
     997           0 : FrameIter::updatePcQuadratic()
     998             : {
     999           0 :     switch (data_.state_) {
    1000             :       case WASM:
    1001             :       case DONE:
    1002           0 :         break;
    1003             :       case INTERP: {
    1004           0 :         InterpreterFrame* frame = interpFrame();
    1005           0 :         InterpreterActivation* activation = data_.activations_->asInterpreter();
    1006             : 
    1007             :         // Look for the current frame.
    1008           0 :         data_.interpFrames_ = InterpreterFrameIterator(activation);
    1009           0 :         while (data_.interpFrames_.frame() != frame)
    1010           0 :             ++data_.interpFrames_;
    1011             : 
    1012             :         // Update the pc.
    1013           0 :         MOZ_ASSERT(data_.interpFrames_.frame() == frame);
    1014           0 :         data_.pc_ = data_.interpFrames_.pc();
    1015           0 :         return;
    1016             :       }
    1017             :       case JIT:
    1018           0 :         if (data_.jitFrames_.isBaselineJS()) {
    1019           0 :             jit::BaselineFrame* frame = data_.jitFrames_.baselineFrame();
    1020           0 :             jit::JitActivation* activation = data_.activations_->asJit();
    1021             : 
    1022             :             // activation's exitFP may be invalid, so create a new
    1023             :             // activation iterator.
    1024           0 :             data_.activations_ = ActivationIterator(data_.cx_);
    1025           0 :             while (data_.activations_.activation() != activation)
    1026           0 :                 ++data_.activations_;
    1027             : 
    1028             :             // Look for the current frame.
    1029           0 :             data_.jitFrames_ = jit::JitFrameIterator(data_.activations_);
    1030           0 :             while (!data_.jitFrames_.isBaselineJS() || data_.jitFrames_.baselineFrame() != frame)
    1031           0 :                 ++data_.jitFrames_;
    1032             : 
    1033             :             // Update the pc.
    1034           0 :             MOZ_ASSERT(data_.jitFrames_.baselineFrame() == frame);
    1035           0 :             data_.jitFrames_.baselineScriptAndPc(nullptr, &data_.pc_);
    1036           0 :             return;
    1037             :         }
    1038           0 :         break;
    1039             :     }
    1040           0 :     MOZ_CRASH("Unexpected state");
    1041             : }
    1042             : 
    1043             : void
    1044           0 : FrameIter::wasmUpdateBytecodeOffset()
    1045             : {
    1046           0 :     MOZ_RELEASE_ASSERT(data_.state_ == WASM, "Unexpected state");
    1047             : 
    1048           0 :     wasm::DebugFrame* frame = data_.wasmFrames_.debugFrame();
    1049           0 :     WasmActivation* activation = data_.activations_->asWasm();
    1050             : 
    1051             :     // Relookup the current frame, updating the bytecode offset in the process.
    1052           0 :     data_.wasmFrames_ = wasm::FrameIterator(activation);
    1053           0 :     while (data_.wasmFrames_.debugFrame() != frame)
    1054           0 :         ++data_.wasmFrames_;
    1055             : 
    1056           0 :     MOZ_ASSERT(data_.wasmFrames_.debugFrame() == frame);
    1057           0 : }
    1058             : 
    1059             : JSFunction*
    1060       12380 : FrameIter::calleeTemplate() const
    1061             : {
    1062       12380 :     switch (data_.state_) {
    1063             :       case DONE:
    1064             :       case WASM:
    1065           0 :         break;
    1066             :       case INTERP:
    1067        7362 :         MOZ_ASSERT(isFunctionFrame());
    1068        7362 :         return &interpFrame()->callee();
    1069             :       case JIT:
    1070        5018 :         if (data_.jitFrames_.isBaselineJS())
    1071        4178 :             return data_.jitFrames_.callee();
    1072         840 :         MOZ_ASSERT(data_.jitFrames_.isIonScripted());
    1073         840 :         return ionInlineFrames_.calleeTemplate();
    1074             :     }
    1075           0 :     MOZ_CRASH("Unexpected state");
    1076             : }
    1077             : 
    1078             : JSFunction*
    1079           0 : FrameIter::callee(JSContext* cx) const
    1080             : {
    1081           0 :     switch (data_.state_) {
    1082             :       case DONE:
    1083             :       case WASM:
    1084           0 :         break;
    1085             :       case INTERP:
    1086           0 :         return calleeTemplate();
    1087             :       case JIT:
    1088           0 :         if (data_.jitFrames_.isIonScripted()) {
    1089           0 :             jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
    1090           0 :             return ionInlineFrames_.callee(recover);
    1091             :         }
    1092           0 :         MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
    1093           0 :         return calleeTemplate();
    1094             :     }
    1095           0 :     MOZ_CRASH("Unexpected state");
    1096             : }
    1097             : 
    1098             : bool
    1099           0 : FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const
    1100             : {
    1101           0 :     RootedFunction currentCallee(cx, calleeTemplate());
    1102             : 
    1103             :     // As we do not know if the calleeTemplate is the real function, or the
    1104             :     // template from which it would be cloned, we compare properties which are
    1105             :     // stable across the cloning of JSFunctions.
    1106           0 :     if (((currentCallee->flags() ^ fun->flags()) & JSFunction::STABLE_ACROSS_CLONES) != 0 ||
    1107           0 :         currentCallee->nargs() != fun->nargs())
    1108             :     {
    1109           0 :         return false;
    1110             :     }
    1111             : 
    1112             :     // Use the same condition as |js::CloneFunctionObject|, to know if we should
    1113             :     // expect both functions to have the same JSScript. If so, and if they are
    1114             :     // different, then they cannot be equal.
    1115           0 :     RootedObject global(cx, &fun->global());
    1116           0 :     bool useSameScript = CanReuseScriptForClone(fun->compartment(), currentCallee, global);
    1117           0 :     if (useSameScript &&
    1118           0 :         (currentCallee->hasScript() != fun->hasScript() ||
    1119           0 :          currentCallee->nonLazyScript() != fun->nonLazyScript()))
    1120             :     {
    1121           0 :         return false;
    1122             :     }
    1123             : 
    1124             :     // If none of the previous filters worked, then take the risk of
    1125             :     // invalidating the frame to identify the JSFunction.
    1126           0 :     return callee(cx) == fun;
    1127             : }
    1128             : 
    1129             : unsigned
    1130           0 : FrameIter::numActualArgs() const
    1131             : {
    1132           0 :     switch (data_.state_) {
    1133             :       case DONE:
    1134             :       case WASM:
    1135           0 :         break;
    1136             :       case INTERP:
    1137           0 :         MOZ_ASSERT(isFunctionFrame());
    1138           0 :         return interpFrame()->numActualArgs();
    1139             :       case JIT:
    1140           0 :         if (data_.jitFrames_.isIonScripted())
    1141           0 :             return ionInlineFrames_.numActualArgs();
    1142             : 
    1143           0 :         MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
    1144           0 :         return data_.jitFrames_.numActualArgs();
    1145             :     }
    1146           0 :     MOZ_CRASH("Unexpected state");
    1147             : }
    1148             : 
    1149             : unsigned
    1150           0 : FrameIter::numFormalArgs() const
    1151             : {
    1152           0 :     return script()->functionNonDelazifying()->nargs();
    1153             : }
    1154             : 
    1155             : Value
    1156           0 : FrameIter::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) const
    1157             : {
    1158           0 :     return abstractFramePtr().unaliasedActual(i, checkAliasing);
    1159             : }
    1160             : 
    1161             : JSObject*
    1162           0 : FrameIter::environmentChain(JSContext* cx) const
    1163             : {
    1164           0 :     switch (data_.state_) {
    1165             :       case DONE:
    1166             :       case WASM:
    1167           0 :         break;
    1168             :       case JIT:
    1169           0 :         if (data_.jitFrames_.isIonScripted()) {
    1170           0 :             jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
    1171           0 :             return ionInlineFrames_.environmentChain(recover);
    1172             :         }
    1173           0 :         return data_.jitFrames_.baselineFrame()->environmentChain();
    1174             :       case INTERP:
    1175           0 :         return interpFrame()->environmentChain();
    1176             :     }
    1177           0 :     MOZ_CRASH("Unexpected state");
    1178             : }
    1179             : 
    1180             : CallObject&
    1181           0 : FrameIter::callObj(JSContext* cx) const
    1182             : {
    1183           0 :     MOZ_ASSERT(calleeTemplate()->needsCallObject());
    1184             : 
    1185           0 :     JSObject* pobj = environmentChain(cx);
    1186           0 :     while (!pobj->is<CallObject>())
    1187           0 :         pobj = pobj->enclosingEnvironment();
    1188           0 :     return pobj->as<CallObject>();
    1189             : }
    1190             : 
    1191             : bool
    1192           0 : FrameIter::hasArgsObj() const
    1193             : {
    1194           0 :     return abstractFramePtr().hasArgsObj();
    1195             : }
    1196             : 
    1197             : ArgumentsObject&
    1198           0 : FrameIter::argsObj() const
    1199             : {
    1200           0 :     MOZ_ASSERT(hasArgsObj());
    1201           0 :     return abstractFramePtr().argsObj();
    1202             : }
    1203             : 
    1204             : Value
    1205           0 : FrameIter::thisArgument(JSContext* cx) const
    1206             : {
    1207           0 :     MOZ_ASSERT(isFunctionFrame());
    1208             : 
    1209           0 :     switch (data_.state_) {
    1210             :       case DONE:
    1211             :       case WASM:
    1212           0 :         break;
    1213             :       case JIT:
    1214           0 :         if (data_.jitFrames_.isIonScripted()) {
    1215           0 :             jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
    1216           0 :             return ionInlineFrames_.thisArgument(recover);
    1217             :         }
    1218           0 :         return data_.jitFrames_.baselineFrame()->thisArgument();
    1219             :       case INTERP:
    1220           0 :         return interpFrame()->thisArgument();
    1221             :     }
    1222           0 :     MOZ_CRASH("Unexpected state");
    1223             : }
    1224             : 
    1225             : Value
    1226           2 : FrameIter::newTarget() const
    1227             : {
    1228           2 :     switch (data_.state_) {
    1229             :       case DONE:
    1230             :       case WASM:
    1231           0 :         break;
    1232             :       case INTERP:
    1233           2 :         return interpFrame()->newTarget();
    1234             :       case JIT:
    1235           0 :         MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
    1236           0 :         return data_.jitFrames_.baselineFrame()->newTarget();
    1237             :     }
    1238           0 :     MOZ_CRASH("Unexpected state");
    1239             : }
    1240             : 
    1241             : Value
    1242           0 : FrameIter::returnValue() const
    1243             : {
    1244           0 :     switch (data_.state_) {
    1245             :       case DONE:
    1246             :       case WASM:
    1247           0 :         break;
    1248             :       case JIT:
    1249           0 :         if (data_.jitFrames_.isBaselineJS())
    1250           0 :             return data_.jitFrames_.baselineFrame()->returnValue();
    1251           0 :         break;
    1252             :       case INTERP:
    1253           0 :         return interpFrame()->returnValue();
    1254             :     }
    1255           0 :     MOZ_CRASH("Unexpected state");
    1256             : }
    1257             : 
    1258             : void
    1259           0 : FrameIter::setReturnValue(const Value& v)
    1260             : {
    1261           0 :     switch (data_.state_) {
    1262             :       case DONE:
    1263             :       case WASM:
    1264           0 :         break;
    1265             :       case JIT:
    1266           0 :         if (data_.jitFrames_.isBaselineJS()) {
    1267           0 :             data_.jitFrames_.baselineFrame()->setReturnValue(v);
    1268           0 :             return;
    1269             :         }
    1270           0 :         break;
    1271             :       case INTERP:
    1272           0 :         interpFrame()->setReturnValue(v);
    1273           0 :         return;
    1274             :     }
    1275           0 :     MOZ_CRASH("Unexpected state");
    1276             : }
    1277             : 
    1278             : size_t
    1279           2 : FrameIter::numFrameSlots() const
    1280             : {
    1281           2 :     switch (data_.state_) {
    1282             :       case DONE:
    1283             :       case WASM:
    1284           0 :         break;
    1285             :       case JIT: {
    1286           0 :         if (data_.jitFrames_.isIonScripted()) {
    1287           0 :             return ionInlineFrames_.snapshotIterator().numAllocations() -
    1288           0 :                 ionInlineFrames_.script()->nfixed();
    1289             :         }
    1290           0 :         jit::BaselineFrame* frame = data_.jitFrames_.baselineFrame();
    1291           0 :         return frame->numValueSlots() - data_.jitFrames_.script()->nfixed();
    1292             :       }
    1293             :       case INTERP:
    1294           2 :         MOZ_ASSERT(data_.interpFrames_.sp() >= interpFrame()->base());
    1295           2 :         return data_.interpFrames_.sp() - interpFrame()->base();
    1296             :     }
    1297           0 :     MOZ_CRASH("Unexpected state");
    1298             : }
    1299             : 
    1300             : Value
    1301           2 : FrameIter::frameSlotValue(size_t index) const
    1302             : {
    1303           2 :     switch (data_.state_) {
    1304             :       case DONE:
    1305             :       case WASM:
    1306           0 :         break;
    1307             :       case JIT:
    1308           0 :         if (data_.jitFrames_.isIonScripted()) {
    1309           0 :             jit::SnapshotIterator si(ionInlineFrames_.snapshotIterator());
    1310           0 :             index += ionInlineFrames_.script()->nfixed();
    1311           0 :             return si.maybeReadAllocByIndex(index);
    1312             :         }
    1313             : 
    1314           0 :         index += data_.jitFrames_.script()->nfixed();
    1315           0 :         return *data_.jitFrames_.baselineFrame()->valueSlot(index);
    1316             :       case INTERP:
    1317           2 :           return interpFrame()->base()[index];
    1318             :     }
    1319           0 :     MOZ_CRASH("Unexpected state");
    1320             : }
    1321             : 
    1322             : #ifdef DEBUG
    1323             : bool
    1324         101 : js::SelfHostedFramesVisible()
    1325             : {
    1326             :     static bool checked = false;
    1327             :     static bool visible = false;
    1328         101 :     if (!checked) {
    1329           2 :         checked = true;
    1330           2 :         char* env = getenv("MOZ_SHOW_ALL_JS_FRAMES");
    1331           2 :         visible = !!env;
    1332             :     }
    1333         101 :     return visible;
    1334             : }
    1335             : #endif
    1336             : 
    1337             : void
    1338         101 : NonBuiltinFrameIter::settle()
    1339             : {
    1340         101 :     if (!SelfHostedFramesVisible()) {
    1341         195 :         while (!done() && hasScript() && script()->selfHosted())
    1342          47 :             FrameIter::operator++();
    1343             :     }
    1344         101 : }
    1345             : 
    1346             : void
    1347           0 : NonBuiltinScriptFrameIter::settle()
    1348             : {
    1349           0 :     if (!SelfHostedFramesVisible()) {
    1350           0 :         while (!done() && script()->selfHosted())
    1351           0 :             ScriptFrameIter::operator++();
    1352             :     }
    1353           0 : }
    1354             : 
    1355       18099 : ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
    1356       18099 :   : cx_(cx), entryMonitor_(cx->entryMonitor)
    1357             : {
    1358       18099 :     cx->entryMonitor = nullptr;
    1359       18099 : }
    1360             : 
    1361             : Value
    1362           0 : ActivationEntryMonitor::asyncStack(JSContext* cx)
    1363             : {
    1364           0 :     RootedValue stack(cx, ObjectOrNullValue(cx->asyncStackForNewActivations()));
    1365           0 :     if (!cx->compartment()->wrap(cx, &stack)) {
    1366           0 :         cx->clearPendingException();
    1367           0 :         return UndefinedValue();
    1368             :     }
    1369           0 :     return stack;
    1370             : }
    1371             : 
    1372       10426 : ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx, InterpreterFrame* entryFrame)
    1373       10426 :   : ActivationEntryMonitor(cx)
    1374             : {
    1375       10426 :     if (entryMonitor_) {
    1376             :         // The InterpreterFrame is not yet part of an Activation, so it won't
    1377             :         // be traced if we trigger GC here. Suppress GC to avoid this.
    1378           0 :         gc::AutoSuppressGC suppressGC(cx);
    1379           0 :         RootedValue stack(cx, asyncStack(cx));
    1380           0 :         const char* asyncCause = cx->asyncCauseForNewActivations;
    1381           0 :         if (entryFrame->isFunctionFrame())
    1382           0 :             entryMonitor_->Entry(cx, &entryFrame->callee(), stack, asyncCause);
    1383             :         else
    1384           0 :             entryMonitor_->Entry(cx, entryFrame->script(), stack, asyncCause);
    1385             :     }
    1386       10426 : }
    1387             : 
    1388        7673 : ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx, jit::CalleeToken entryToken)
    1389        7673 :   : ActivationEntryMonitor(cx)
    1390             : {
    1391        7673 :     if (entryMonitor_) {
    1392             :         // The CalleeToken is not traced at this point and we also don't want
    1393             :         // a GC to discard the code we're about to enter, so we suppress GC.
    1394           0 :         gc::AutoSuppressGC suppressGC(cx);
    1395           0 :         RootedValue stack(cx, asyncStack(cx));
    1396           0 :         const char* asyncCause = cx->asyncCauseForNewActivations;
    1397           0 :         if (jit::CalleeTokenIsFunction(entryToken))
    1398           0 :             entryMonitor_->Entry(cx_, jit::CalleeTokenToFunction(entryToken), stack, asyncCause);
    1399             :         else
    1400           0 :             entryMonitor_->Entry(cx_, jit::CalleeTokenToScript(entryToken), stack, asyncCause);
    1401             :     }
    1402        7673 : }
    1403             : 
    1404             : /*****************************************************************************/
    1405             : 
    1406        7673 : jit::JitActivation::JitActivation(JSContext* cx, bool active)
    1407             :   : Activation(cx, Jit),
    1408             :     exitFP_(nullptr),
    1409             :     prevJitActivation_(cx->jitActivation),
    1410             :     active_(active),
    1411             :     rematerializedFrames_(nullptr),
    1412             :     ionRecovery_(cx),
    1413             :     bailoutData_(nullptr),
    1414             :     lastProfilingFrame_(nullptr),
    1415        7673 :     lastProfilingCallSite_(nullptr)
    1416             : {
    1417        7673 :     if (active) {
    1418        7673 :         cx->jitActivation = this;
    1419        7673 :         registerProfiling();
    1420             :     }
    1421        7673 : }
    1422             : 
    1423       15346 : jit::JitActivation::~JitActivation()
    1424             : {
    1425        7673 :     if (active_) {
    1426        7673 :         if (isProfiling())
    1427        7673 :             unregisterProfiling();
    1428        7673 :         cx_->jitActivation = prevJitActivation_;
    1429             :     } else {
    1430           0 :         MOZ_ASSERT(cx_->jitActivation == prevJitActivation_);
    1431             :     }
    1432             : 
    1433             :     // All reocvered value are taken from activation during the bailout.
    1434        7673 :     MOZ_ASSERT(ionRecovery_.empty());
    1435             : 
    1436             :     // The BailoutFrameInfo should have unregistered itself from the
    1437             :     // JitActivations.
    1438        7673 :     MOZ_ASSERT(!bailoutData_);
    1439             : 
    1440        7673 :     clearRematerializedFrames();
    1441        7673 :     js_delete(rematerializedFrames_);
    1442        7673 : }
    1443             : 
    1444             : void
    1445           0 : jit::JitActivation::setBailoutData(jit::BailoutFrameInfo* bailoutData)
    1446             : {
    1447           0 :     MOZ_ASSERT(!bailoutData_);
    1448           0 :     bailoutData_ = bailoutData;
    1449           0 : }
    1450             : 
    1451             : void
    1452           0 : jit::JitActivation::cleanBailoutData()
    1453             : {
    1454           0 :     MOZ_ASSERT(bailoutData_);
    1455           0 :     bailoutData_ = nullptr;
    1456           0 : }
    1457             : 
    1458             : // setActive() is inlined in GenerateJitExit() with explicit masm instructions so
    1459             : // changes to the logic here need to be reflected in GenerateJitExit() in the enable
    1460             : // and disable activation instruction sequences.
    1461             : void
    1462           0 : jit::JitActivation::setActive(JSContext* cx, bool active)
    1463             : {
    1464             :     // Only allowed to deactivate/activate if activation is top.
    1465             :     // (Not tested and will probably fail in other situations.)
    1466           0 :     MOZ_ASSERT(cx->activation_ == this);
    1467           0 :     MOZ_ASSERT(active != active_);
    1468             : 
    1469           0 :     if (active) {
    1470           0 :         *((volatile bool*) active_) = true;
    1471           0 :         MOZ_ASSERT(prevJitActivation_ == cx->jitActivation);
    1472           0 :         cx->jitActivation = this;
    1473             : 
    1474           0 :         registerProfiling();
    1475             :     } else {
    1476           0 :         unregisterProfiling();
    1477             : 
    1478           0 :         cx->jitActivation = prevJitActivation_;
    1479           0 :         *((volatile bool*) active_) = false;
    1480             :     }
    1481           0 : }
    1482             : 
    1483             : void
    1484           0 : jit::JitActivation::removeRematerializedFrame(uint8_t* top)
    1485             : {
    1486           0 :     if (!rematerializedFrames_)
    1487           0 :         return;
    1488             : 
    1489           0 :     if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
    1490           0 :         RematerializedFrame::FreeInVector(p->value());
    1491           0 :         rematerializedFrames_->remove(p);
    1492             :     }
    1493             : }
    1494             : 
    1495             : void
    1496        7673 : jit::JitActivation::clearRematerializedFrames()
    1497             : {
    1498        7673 :     if (!rematerializedFrames_)
    1499        7673 :         return;
    1500             : 
    1501           0 :     for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront()) {
    1502           0 :         RematerializedFrame::FreeInVector(e.front().value());
    1503           0 :         e.removeFront();
    1504             :     }
    1505             : }
    1506             : 
    1507             : jit::RematerializedFrame*
    1508           0 : jit::JitActivation::getRematerializedFrame(JSContext* cx, const JitFrameIterator& iter,
    1509             :                                            size_t inlineDepth)
    1510             : {
    1511           0 :     MOZ_ASSERT(iter.activation() == this);
    1512           0 :     MOZ_ASSERT(iter.isIonScripted());
    1513             : 
    1514           0 :     if (!rematerializedFrames_) {
    1515           0 :         rematerializedFrames_ = cx->new_<RematerializedFrameTable>(cx);
    1516           0 :         if (!rematerializedFrames_)
    1517           0 :             return nullptr;
    1518           0 :         if (!rematerializedFrames_->init()) {
    1519           0 :             rematerializedFrames_ = nullptr;
    1520           0 :             ReportOutOfMemory(cx);
    1521           0 :             return nullptr;
    1522             :         }
    1523             :     }
    1524             : 
    1525           0 :     uint8_t* top = iter.fp();
    1526           0 :     RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
    1527           0 :     if (!p) {
    1528           0 :         RematerializedFrameVector frames(cx);
    1529             : 
    1530             :         // The unit of rematerialization is an uninlined frame and its inlined
    1531             :         // frames. Since inlined frames do not exist outside of snapshots, it
    1532             :         // is impossible to synchronize their rematerialized copies to
    1533             :         // preserve identity. Therefore, we always rematerialize an uninlined
    1534             :         // frame and all its inlined frames at once.
    1535           0 :         InlineFrameIterator inlineIter(cx, &iter);
    1536           0 :         MaybeReadFallback recover(cx, this, &iter);
    1537             : 
    1538             :         // Frames are often rematerialized with the cx inside a Debugger's
    1539             :         // compartment. To recover slots and to create CallObjects, we need to
    1540             :         // be in the activation's compartment.
    1541           0 :         AutoCompartmentUnchecked ac(cx, compartment_);
    1542             : 
    1543           0 :         if (!RematerializedFrame::RematerializeInlineFrames(cx, top, inlineIter, recover, frames))
    1544           0 :             return nullptr;
    1545             : 
    1546           0 :         if (!rematerializedFrames_->add(p, top, Move(frames))) {
    1547           0 :             ReportOutOfMemory(cx);
    1548           0 :             return nullptr;
    1549             :         }
    1550             : 
    1551             :         // See comment in unsetPrevUpToDateUntil.
    1552           0 :         DebugEnvironments::unsetPrevUpToDateUntil(cx, p->value()[inlineDepth]);
    1553             :     }
    1554             : 
    1555           0 :     return p->value()[inlineDepth];
    1556             : }
    1557             : 
    1558             : jit::RematerializedFrame*
    1559         840 : jit::JitActivation::lookupRematerializedFrame(uint8_t* top, size_t inlineDepth)
    1560             : {
    1561         840 :     if (!rematerializedFrames_)
    1562         840 :         return nullptr;
    1563           0 :     if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top))
    1564           0 :         return inlineDepth < p->value().length() ? p->value()[inlineDepth] : nullptr;
    1565           0 :     return nullptr;
    1566             : }
    1567             : 
    1568             : void
    1569           0 : jit::JitActivation::removeRematerializedFramesFromDebugger(JSContext* cx, uint8_t* top)
    1570             : {
    1571             :     // Ion bailout can fail due to overrecursion and OOM. In such cases we
    1572             :     // cannot honor any further Debugger hooks on the frame, and need to
    1573             :     // ensure that its Debugger.Frame entry is cleaned up.
    1574           0 :     if (!cx->compartment()->isDebuggee() || !rematerializedFrames_)
    1575           0 :         return;
    1576           0 :     if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
    1577           0 :         for (uint32_t i = 0; i < p->value().length(); i++)
    1578           0 :             Debugger::handleUnrecoverableIonBailoutError(cx, p->value()[i]);
    1579             :     }
    1580             : }
    1581             : 
    1582             : void
    1583          24 : jit::JitActivation::traceRematerializedFrames(JSTracer* trc)
    1584             : {
    1585          24 :     if (!rematerializedFrames_)
    1586          24 :         return;
    1587           0 :     for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront())
    1588           0 :         e.front().value().trace(trc);
    1589             : }
    1590             : 
    1591             : bool
    1592           0 : jit::JitActivation::registerIonFrameRecovery(RInstructionResults&& results)
    1593             : {
    1594             :     // Check that there is no entry in the vector yet.
    1595           0 :     MOZ_ASSERT(!maybeIonFrameRecovery(results.frame()));
    1596           0 :     if (!ionRecovery_.append(mozilla::Move(results)))
    1597           0 :         return false;
    1598             : 
    1599           0 :     return true;
    1600             : }
    1601             : 
    1602             : jit::RInstructionResults*
    1603           0 : jit::JitActivation::maybeIonFrameRecovery(JitFrameLayout* fp)
    1604             : {
    1605           0 :     for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end(); ) {
    1606           0 :         if (it->frame() == fp)
    1607           0 :             return it;
    1608             :     }
    1609             : 
    1610           0 :     return nullptr;
    1611             : }
    1612             : 
    1613             : void
    1614           0 : jit::JitActivation::removeIonFrameRecovery(JitFrameLayout* fp)
    1615             : {
    1616           0 :     RInstructionResults* elem = maybeIonFrameRecovery(fp);
    1617           0 :     if (!elem)
    1618           0 :         return;
    1619             : 
    1620           0 :     ionRecovery_.erase(elem);
    1621             : }
    1622             : 
    1623             : void
    1624          24 : jit::JitActivation::traceIonRecovery(JSTracer* trc)
    1625             : {
    1626          24 :     for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end(); it++)
    1627           0 :         it->trace(trc);
    1628          24 : }
    1629             : 
    1630           0 : WasmActivation::WasmActivation(JSContext* cx)
    1631             :   : Activation(cx, Wasm),
    1632           0 :     exitFP_(nullptr)
    1633             : {
    1634             :     // Now that the WasmActivation is fully initialized, make it visible to
    1635             :     // asynchronous profiling.
    1636           0 :     registerProfiling();
    1637           0 : }
    1638             : 
    1639           0 : WasmActivation::~WasmActivation()
    1640             : {
    1641             :     // Hide this activation from the profiler before is is destroyed.
    1642           0 :     unregisterProfiling();
    1643             : 
    1644           0 :     MOZ_ASSERT(!interrupted());
    1645           0 :     MOZ_ASSERT(exitFP_ == nullptr);
    1646           0 : }
    1647             : 
    1648             : void
    1649           0 : WasmActivation::unwindExitFP(wasm::Frame* exitFP)
    1650             : {
    1651           0 :     exitFP_ = exitFP;
    1652           0 : }
    1653             : 
    1654             : void
    1655           0 : WasmActivation::startInterrupt(const JS::ProfilingFrameIterator::RegisterState& state)
    1656             : {
    1657           0 :     MOZ_ASSERT(state.pc);
    1658           0 :     MOZ_ASSERT(state.fp);
    1659             : 
    1660             :     // Execution can only be interrupted in function code. Afterwards, control
    1661             :     // flow does not reenter function code and thus there should be no
    1662             :     // interrupt-during-interrupt.
    1663           0 :     MOZ_ASSERT(!interrupted());
    1664             : 
    1665             :     bool ignoredUnwound;
    1666           0 :     wasm::UnwindState unwindState;
    1667           0 :     MOZ_ALWAYS_TRUE(wasm::StartUnwinding(*this, state, &unwindState, &ignoredUnwound));
    1668             : 
    1669           0 :     void* unwindPC = unwindState.pc;
    1670           0 :     MOZ_ASSERT(compartment()->wasm.lookupCode(unwindPC)->lookupRange(unwindPC)->isFunction());
    1671             : 
    1672           0 :     cx_->runtime()->startWasmInterrupt(state.pc, unwindPC);
    1673           0 :     exitFP_ = reinterpret_cast<wasm::Frame*>(unwindState.fp);
    1674             : 
    1675           0 :     MOZ_ASSERT(compartment() == exitFP_->tls->instance->compartment());
    1676           0 :     MOZ_ASSERT(interrupted());
    1677           0 : }
    1678             : 
    1679             : void
    1680           0 : WasmActivation::finishInterrupt()
    1681             : {
    1682           0 :     MOZ_ASSERT(interrupted());
    1683           0 :     MOZ_ASSERT(exitFP_);
    1684             : 
    1685           0 :     cx_->runtime()->finishWasmInterrupt();
    1686           0 :     exitFP_ = nullptr;
    1687           0 : }
    1688             : 
    1689             : bool
    1690           0 : WasmActivation::interrupted() const
    1691             : {
    1692           0 :     void* pc = cx_->runtime()->wasmUnwindPC();
    1693           0 :     if (!pc)
    1694           0 :         return false;
    1695             : 
    1696           0 :     Activation* act = cx_->activation();
    1697           0 :     while (act && !act->isWasm())
    1698           0 :         act = act->prev();
    1699             : 
    1700           0 :     if (act->asWasm() != this)
    1701           0 :         return false;
    1702             : 
    1703           0 :     DebugOnly<wasm::Frame*> fp = act->asWasm()->exitFP();
    1704           0 :     MOZ_ASSERT(fp && fp->instance()->code().containsFunctionPC(pc));
    1705           0 :     return true;
    1706             : }
    1707             : 
    1708             : void*
    1709           0 : WasmActivation::unwindPC() const
    1710             : {
    1711           0 :     MOZ_ASSERT(interrupted());
    1712           0 :     return cx_->runtime()->wasmUnwindPC();
    1713             : }
    1714             : 
    1715             : void*
    1716           0 : WasmActivation::resumePC() const
    1717             : {
    1718           0 :     MOZ_ASSERT(interrupted());
    1719           0 :     return cx_->runtime()->wasmResumePC();
    1720             : }
    1721             : 
    1722             : InterpreterFrameIterator&
    1723        8390 : InterpreterFrameIterator::operator++()
    1724             : {
    1725        8390 :     MOZ_ASSERT(!done());
    1726        8390 :     if (fp_ != activation_->entryFrame_) {
    1727        1353 :         pc_ = fp_->prevpc();
    1728        1353 :         sp_ = fp_->prevsp();
    1729        1353 :         fp_ = fp_->prev();
    1730             :     } else {
    1731        7037 :         pc_ = nullptr;
    1732        7037 :         sp_ = nullptr;
    1733        7037 :         fp_ = nullptr;
    1734             :     }
    1735        8390 :     return *this;
    1736             : }
    1737             : 
    1738             : void
    1739        7673 : Activation::registerProfiling()
    1740             : {
    1741        7673 :     MOZ_ASSERT(isProfiling());
    1742        7673 :     cx_->profilingActivation_ = this;
    1743        7673 : }
    1744             : 
    1745             : void
    1746        7673 : Activation::unregisterProfiling()
    1747             : {
    1748        7673 :     MOZ_ASSERT(isProfiling());
    1749        7673 :     MOZ_ASSERT(cx_->profilingActivation_ == this);
    1750             : 
    1751             :     // There may be a non-active jit activation in the linked list.  Skip past it.
    1752        7673 :     Activation* prevProfiling = prevProfiling_;
    1753        7673 :     while (prevProfiling && prevProfiling->isJit() && !prevProfiling->asJit()->isActive())
    1754           0 :         prevProfiling = prevProfiling->prevProfiling_;
    1755             : 
    1756        7673 :     cx_->profilingActivation_ = prevProfiling;
    1757        7673 : }
    1758             : 
    1759        8496 : ActivationIterator::ActivationIterator(JSContext* cx)
    1760        8496 :   : activation_(cx->activation_)
    1761             : {
    1762        8496 :     MOZ_ASSERT(cx == TlsContext.get());
    1763        8496 :     settle();
    1764        8496 : }
    1765             : 
    1766          93 : ActivationIterator::ActivationIterator(JSContext* cx, const CooperatingContext& target)
    1767             : {
    1768          93 :     MOZ_ASSERT(cx == TlsContext.get());
    1769             : 
    1770             :     // If target was specified --- even if it is the same as cx itself --- then
    1771             :     // we must be in a scope where changes of the active context are prohibited.
    1772             :     // Otherwise our state would be corrupted if the target thread resumed
    1773             :     // execution while we are iterating over its state.
    1774          93 :     MOZ_ASSERT(cx->runtime()->activeContextChangeProhibited() ||
    1775             :                !cx->runtime()->gc.canChangeActiveContext(cx));
    1776             : 
    1777             :     // Tolerate a null target context, in case we are iterating over the
    1778             :     // activations for a zone group that is not in use by any thread.
    1779          93 :     activation_ = target.context() ? target.context()->activation_.ref() : nullptr;
    1780             : 
    1781          93 :     settle();
    1782          93 : }
    1783             : 
    1784             : ActivationIterator&
    1785       14868 : ActivationIterator::operator++()
    1786             : {
    1787       14868 :     MOZ_ASSERT(activation_);
    1788       14868 :     activation_ = activation_->prev();
    1789       14868 :     settle();
    1790       14868 :     return *this;
    1791             : }
    1792             : 
    1793             : void
    1794       23457 : ActivationIterator::settle()
    1795             : {
    1796             :     // Stop at the next active activation.
    1797       23457 :     while (!done() && activation_->isJit() && !activation_->asJit()->isActive())
    1798           0 :         activation_ = activation_->prev();
    1799       23457 : }
    1800             : 
    1801           0 : JS::ProfilingFrameIterator::ProfilingFrameIterator(JSContext* cx, const RegisterState& state,
    1802           0 :                                                    uint32_t sampleBufferGen)
    1803             :   : cx_(cx),
    1804             :     sampleBufferGen_(sampleBufferGen),
    1805           0 :     activation_(nullptr)
    1806             : {
    1807           0 :     if (!cx->runtime()->geckoProfiler().enabled())
    1808           0 :         MOZ_CRASH("ProfilingFrameIterator called when geckoProfiler not enabled for runtime.");
    1809             : 
    1810           0 :     if (!cx->profilingActivation())
    1811           0 :         return;
    1812             : 
    1813             :     // If profiler sampling is not enabled, skip.
    1814           0 :     if (!cx->isProfilerSamplingEnabled())
    1815           0 :         return;
    1816             : 
    1817           0 :     activation_ = cx->profilingActivation();
    1818             : 
    1819           0 :     MOZ_ASSERT(activation_->isProfiling());
    1820             : 
    1821             :     static_assert(sizeof(wasm::ProfilingFrameIterator) <= StorageSpace &&
    1822             :                   sizeof(jit::JitProfilingFrameIterator) <= StorageSpace,
    1823             :                   "ProfilingFrameIterator::storage_ is too small");
    1824             :     static_assert(alignof(void*) >= alignof(wasm::ProfilingFrameIterator) &&
    1825             :                   alignof(void*) >= alignof(jit::JitProfilingFrameIterator),
    1826             :                   "ProfilingFrameIterator::storage_ is too weakly aligned");
    1827             : 
    1828           0 :     iteratorConstruct(state);
    1829           0 :     settle();
    1830             : }
    1831             : 
    1832           0 : JS::ProfilingFrameIterator::~ProfilingFrameIterator()
    1833             : {
    1834           0 :     if (!done()) {
    1835           0 :         MOZ_ASSERT(activation_->isProfiling());
    1836           0 :         iteratorDestroy();
    1837             :     }
    1838           0 : }
    1839             : 
    1840             : void
    1841           0 : JS::ProfilingFrameIterator::operator++()
    1842             : {
    1843           0 :     MOZ_ASSERT(!done());
    1844           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1845             : 
    1846           0 :     if (activation_->isWasm()) {
    1847           0 :         ++wasmIter();
    1848           0 :         settle();
    1849           0 :         return;
    1850             :     }
    1851             : 
    1852           0 :     ++jitIter();
    1853           0 :     settle();
    1854             : }
    1855             : 
    1856             : void
    1857           0 : JS::ProfilingFrameIterator::settle()
    1858             : {
    1859           0 :     while (iteratorDone()) {
    1860           0 :         iteratorDestroy();
    1861           0 :         activation_ = activation_->prevProfiling();
    1862             : 
    1863             :         // Skip past any non-active jit activations in the list.
    1864           0 :         while (activation_ && activation_->isJit() && !activation_->asJit()->isActive())
    1865           0 :             activation_ = activation_->prevProfiling();
    1866             : 
    1867           0 :         if (!activation_)
    1868           0 :             return;
    1869           0 :         iteratorConstruct();
    1870             :     }
    1871             : }
    1872             : 
    1873             : void
    1874           0 : JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState& state)
    1875             : {
    1876           0 :     MOZ_ASSERT(!done());
    1877           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1878             : 
    1879           0 :     if (activation_->isWasm()) {
    1880           0 :         new (storage()) wasm::ProfilingFrameIterator(*activation_->asWasm(), state);
    1881           0 :         return;
    1882             :     }
    1883             : 
    1884           0 :     MOZ_ASSERT(activation_->asJit()->isActive());
    1885           0 :     new (storage()) jit::JitProfilingFrameIterator(cx_, state);
    1886             : }
    1887             : 
    1888             : void
    1889           0 : JS::ProfilingFrameIterator::iteratorConstruct()
    1890             : {
    1891           0 :     MOZ_ASSERT(!done());
    1892           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1893             : 
    1894           0 :     if (activation_->isWasm()) {
    1895           0 :         new (storage()) wasm::ProfilingFrameIterator(*activation_->asWasm());
    1896           0 :         return;
    1897             :     }
    1898             : 
    1899           0 :     MOZ_ASSERT(activation_->asJit()->isActive());
    1900           0 :     new (storage()) jit::JitProfilingFrameIterator(activation_->asJit()->exitFP());
    1901             : }
    1902             : 
    1903             : void
    1904           0 : JS::ProfilingFrameIterator::iteratorDestroy()
    1905             : {
    1906           0 :     MOZ_ASSERT(!done());
    1907           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1908             : 
    1909           0 :     if (activation_->isWasm()) {
    1910           0 :         wasmIter().~ProfilingFrameIterator();
    1911           0 :         return;
    1912             :     }
    1913             : 
    1914           0 :     jitIter().~JitProfilingFrameIterator();
    1915             : }
    1916             : 
    1917             : bool
    1918           0 : JS::ProfilingFrameIterator::iteratorDone()
    1919             : {
    1920           0 :     MOZ_ASSERT(!done());
    1921           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1922             : 
    1923           0 :     if (activation_->isWasm())
    1924           0 :         return wasmIter().done();
    1925             : 
    1926           0 :     return jitIter().done();
    1927             : }
    1928             : 
    1929             : void*
    1930           0 : JS::ProfilingFrameIterator::stackAddress() const
    1931             : {
    1932           0 :     MOZ_ASSERT(!done());
    1933           0 :     MOZ_ASSERT(activation_->isWasm() || activation_->isJit());
    1934             : 
    1935           0 :     if (activation_->isWasm())
    1936           0 :         return wasmIter().stackAddress();
    1937             : 
    1938           0 :     return jitIter().stackAddress();
    1939             : }
    1940             : 
    1941             : Maybe<JS::ProfilingFrameIterator::Frame>
    1942           0 : JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(jit::JitcodeGlobalEntry* entry) const
    1943             : {
    1944           0 :     void* stackAddr = stackAddress();
    1945             : 
    1946           0 :     if (isWasm()) {
    1947             :         Frame frame;
    1948           0 :         frame.kind = Frame_Wasm;
    1949           0 :         frame.stackAddress = stackAddr;
    1950           0 :         frame.returnAddress = nullptr;
    1951           0 :         frame.activation = activation_;
    1952           0 :         frame.label = nullptr;
    1953           0 :         return mozilla::Some(frame);
    1954             :     }
    1955             : 
    1956           0 :     MOZ_ASSERT(isJit());
    1957             : 
    1958             :     // Look up an entry for the return address.
    1959           0 :     void* returnAddr = jitIter().returnAddressToFp();
    1960           0 :     jit::JitcodeGlobalTable* table = cx_->runtime()->jitRuntime()->getJitcodeGlobalTable();
    1961           0 :     if (hasSampleBufferGen())
    1962           0 :         *entry = table->lookupForSamplerInfallible(returnAddr, cx_->runtime(), sampleBufferGen_);
    1963             :     else
    1964           0 :         *entry = table->lookupInfallible(returnAddr);
    1965             : 
    1966           0 :     MOZ_ASSERT(entry->isIon() || entry->isIonCache() || entry->isBaseline() || entry->isDummy());
    1967             : 
    1968             :     // Dummy frames produce no stack frames.
    1969           0 :     if (entry->isDummy())
    1970           0 :         return mozilla::Nothing();
    1971             : 
    1972             :     Frame frame;
    1973           0 :     frame.kind = entry->isBaseline() ? Frame_Baseline : Frame_Ion;
    1974           0 :     frame.stackAddress = stackAddr;
    1975           0 :     frame.returnAddress = returnAddr;
    1976           0 :     frame.activation = activation_;
    1977           0 :     frame.label = nullptr;
    1978           0 :     return mozilla::Some(frame);
    1979             : }
    1980             : 
    1981             : uint32_t
    1982           0 : JS::ProfilingFrameIterator::extractStack(Frame* frames, uint32_t offset, uint32_t end) const
    1983             : {
    1984           0 :     if (offset >= end)
    1985           0 :         return 0;
    1986             : 
    1987           0 :     jit::JitcodeGlobalEntry entry;
    1988           0 :     Maybe<Frame> physicalFrame = getPhysicalFrameAndEntry(&entry);
    1989             : 
    1990             :     // Dummy frames produce no stack frames.
    1991           0 :     if (physicalFrame.isNothing())
    1992           0 :         return 0;
    1993             : 
    1994           0 :     if (isWasm()) {
    1995           0 :         frames[offset] = physicalFrame.value();
    1996           0 :         frames[offset].label = wasmIter().label();
    1997           0 :         return 1;
    1998             :     }
    1999             : 
    2000             :     // Extract the stack for the entry.  Assume maximum inlining depth is <64
    2001             :     const char* labels[64];
    2002           0 :     uint32_t depth = entry.callStackAtAddr(cx_->runtime(), jitIter().returnAddressToFp(),
    2003           0 :                                            labels, ArrayLength(labels));
    2004           0 :     MOZ_ASSERT(depth < ArrayLength(labels));
    2005           0 :     for (uint32_t i = 0; i < depth; i++) {
    2006           0 :         if (offset + i >= end)
    2007           0 :             return i;
    2008           0 :         frames[offset + i] = physicalFrame.value();
    2009           0 :         frames[offset + i].label = labels[i];
    2010             :     }
    2011             : 
    2012           0 :     return depth;
    2013             : }
    2014             : 
    2015             : Maybe<JS::ProfilingFrameIterator::Frame>
    2016           0 : JS::ProfilingFrameIterator::getPhysicalFrameWithoutLabel() const
    2017             : {
    2018           0 :     jit::JitcodeGlobalEntry unused;
    2019           0 :     return getPhysicalFrameAndEntry(&unused);
    2020             : }
    2021             : 
    2022             : bool
    2023           0 : JS::ProfilingFrameIterator::isWasm() const
    2024             : {
    2025           0 :     MOZ_ASSERT(!done());
    2026           0 :     return activation_->isWasm();
    2027             : }
    2028             : 
    2029             : bool
    2030           0 : JS::ProfilingFrameIterator::isJit() const
    2031             : {
    2032           0 :     return activation_->isJit();
    2033             : }

Generated by: LCOV version 1.13