LCOV - code coverage report
Current view: top level - js/src/vm - Stack.h (source / functions) Hit Total Coverage
Test: output.info Lines: 364 519 70.1 %
Date: 2017-07-14 16:53:18 Functions: 161 231 69.7 %
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             : #ifndef vm_Stack_h
       8             : #define vm_Stack_h
       9             : 
      10             : #include "mozilla/Atomics.h"
      11             : #include "mozilla/Maybe.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : #include "mozilla/Variant.h"
      14             : 
      15             : #include "jsfun.h"
      16             : #include "jsscript.h"
      17             : #include "jsutil.h"
      18             : 
      19             : #include "gc/Rooting.h"
      20             : #include "jit/JitFrameIterator.h"
      21             : #ifdef CHECK_OSIPOINT_REGISTERS
      22             : #include "jit/Registers.h" // for RegisterDump
      23             : #endif
      24             : #include "js/RootingAPI.h"
      25             : #include "vm/ArgumentsObject.h"
      26             : #include "vm/SavedFrame.h"
      27             : #include "wasm/WasmFrameIterator.h"
      28             : #include "wasm/WasmTypes.h"
      29             : 
      30             : struct JSCompartment;
      31             : 
      32             : namespace JS {
      33             : namespace dbg {
      34             : #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
      35             : #pragma GCC diagnostic push
      36             : #pragma GCC diagnostic ignored "-Wattributes"
      37             : #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
      38             : 
      39             : class JS_PUBLIC_API(AutoEntryMonitor);
      40             : 
      41             : #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
      42             : #pragma GCC diagnostic pop
      43             : #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
      44             : } // namespace dbg
      45             : } // namespace JS
      46             : 
      47             : namespace js {
      48             : 
      49             : class InterpreterRegs;
      50             : class CallObject;
      51             : class FrameIter;
      52             : class EnvironmentObject;
      53             : class ScriptFrameIter;
      54             : class GeckoProfiler;
      55             : class InterpreterFrame;
      56             : class LexicalEnvironmentObject;
      57             : class EnvironmentIter;
      58             : class EnvironmentCoordinate;
      59             : 
      60             : class SavedFrame;
      61             : 
      62             : namespace jit {
      63             : class CommonFrameLayout;
      64             : }
      65             : namespace wasm {
      66             : class DebugFrame;
      67             : class Instance;
      68             : }
      69             : 
      70             : // VM stack layout
      71             : //
      72             : // A JSRuntime's stack consists of a linked list of activations. Every activation
      73             : // contains a number of scripted frames that are either running in the interpreter
      74             : // (InterpreterActivation) or JIT code (JitActivation). The frames inside a single
      75             : // activation are contiguous: whenever C++ calls back into JS, a new activation is
      76             : // pushed.
      77             : //
      78             : // Every activation is tied to a single JSContext and JSCompartment. This means we
      79             : // can reconstruct a given context's stack by skipping activations belonging to other
      80             : // contexts. This happens whenever an embedding enters the JS engine on cx1 and
      81             : // then, from a native called by the JS engine, reenters the VM on cx2.
      82             : 
      83             : // Interpreter frames (InterpreterFrame)
      84             : //
      85             : // Each interpreter script activation (global or function code) is given a
      86             : // fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
      87             : // information about the activation and links to the previous frame.
      88             : //
      89             : // The values after an InterpreterFrame in memory are its locals followed by its
      90             : // expression stack. InterpreterFrame::argv_ points to the frame's arguments.
      91             : // Missing formal arguments are padded with |undefined|, so the number of
      92             : // arguments is always >= the number of formals.
      93             : //
      94             : // The top of an activation's current frame's expression stack is pointed to by
      95             : // the activation's "current regs", which contains the stack pointer 'sp'. In
      96             : // the interpreter, sp is adjusted as individual values are pushed and popped
      97             : // from the stack and the InterpreterRegs struct (pointed to by the
      98             : // InterpreterActivation) is a local var of js::Interpret.
      99             : 
     100             : enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
     101             : enum MaybeCheckTDZ { CheckTDZ = true, DontCheckTDZ = false };
     102             : 
     103             : /*****************************************************************************/
     104             : 
     105             : namespace jit {
     106             :     class BaselineFrame;
     107             :     class RematerializedFrame;
     108             : } // namespace jit
     109             : 
     110             : /*
     111             :  * Pointer to either a ScriptFrameIter::Data, an InterpreterFrame, or a Baseline
     112             :  * JIT frame.
     113             :  *
     114             :  * The Debugger may cache ScriptFrameIter::Data as a bookmark to reconstruct a
     115             :  * ScriptFrameIter without doing a full stack walk.
     116             :  *
     117             :  * There is no way to directly create such an AbstractFramePtr. To do so, the
     118             :  * user must call ScriptFrameIter::copyDataAsAbstractFramePtr().
     119             :  *
     120             :  * ScriptFrameIter::abstractFramePtr() will never return an AbstractFramePtr
     121             :  * that is in fact a ScriptFrameIter::Data.
     122             :  *
     123             :  * To recover a ScriptFrameIter settled at the location pointed to by an
     124             :  * AbstractFramePtr, use the THIS_FRAME_ITER macro in Debugger.cpp. As an
     125             :  * aside, no asScriptFrameIterData() is provided because C++ is stupid and
     126             :  * cannot forward declare inner classes.
     127             :  */
     128             : 
     129             : class AbstractFramePtr
     130             : {
     131             :     friend class FrameIter;
     132             : 
     133             :     uintptr_t ptr_;
     134             : 
     135             :     enum {
     136             :         Tag_ScriptFrameIterData = 0x0,
     137             :         Tag_InterpreterFrame = 0x1,
     138             :         Tag_BaselineFrame = 0x2,
     139             :         Tag_RematerializedFrame = 0x3,
     140             :         Tag_WasmDebugFrame = 0x4,
     141             :         TagMask = 0x7
     142             :     };
     143             : 
     144             :   public:
     145       12757 :     AbstractFramePtr()
     146       12757 :       : ptr_(0)
     147       12757 :     {}
     148             : 
     149       65008 :     MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp)
     150       65008 :       : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0)
     151             :     {
     152       65008 :         MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
     153       65008 :     }
     154             : 
     155       18261 :     MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp)
     156       18261 :       : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0)
     157             :     {
     158       18261 :         MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
     159       18261 :     }
     160             : 
     161           0 :     MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp)
     162           0 :       : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0)
     163             :     {
     164           0 :         MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
     165           0 :     }
     166             : 
     167           0 :     MOZ_IMPLICIT AbstractFramePtr(wasm::DebugFrame* fp)
     168           0 :       : ptr_(fp ? uintptr_t(fp) | Tag_WasmDebugFrame : 0)
     169             :     {
     170             :         static_assert(wasm::DebugFrame::Alignment >= TagMask, "aligned");
     171           0 :         MOZ_ASSERT_IF(fp, asWasmDebugFrame() == fp);
     172           0 :     }
     173             : 
     174           0 :     static AbstractFramePtr FromRaw(void* raw) {
     175           0 :         AbstractFramePtr frame;
     176           0 :         frame.ptr_ = uintptr_t(raw);
     177           0 :         return frame;
     178             :     }
     179             : 
     180           0 :     bool isScriptFrameIterData() const {
     181           0 :         return !!ptr_ && (ptr_ & TagMask) == Tag_ScriptFrameIterData;
     182             :     }
     183      574268 :     bool isInterpreterFrame() const {
     184      574268 :         return (ptr_ & TagMask) == Tag_InterpreterFrame;
     185             :     }
     186      290524 :     InterpreterFrame* asInterpreterFrame() const {
     187      290524 :         MOZ_ASSERT(isInterpreterFrame());
     188      290524 :         InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask);
     189      290524 :         MOZ_ASSERT(res);
     190      290524 :         return res;
     191             :     }
     192      134251 :     bool isBaselineFrame() const {
     193      134251 :         return (ptr_ & TagMask) == Tag_BaselineFrame;
     194             :     }
     195       76281 :     jit::BaselineFrame* asBaselineFrame() const {
     196       76281 :         MOZ_ASSERT(isBaselineFrame());
     197       76281 :         jit::BaselineFrame* res = (jit::BaselineFrame*)(ptr_ & ~TagMask);
     198       76281 :         MOZ_ASSERT(res);
     199       76281 :         return res;
     200             :     }
     201           0 :     bool isRematerializedFrame() const {
     202           0 :         return (ptr_ & TagMask) == Tag_RematerializedFrame;
     203             :     }
     204           0 :     jit::RematerializedFrame* asRematerializedFrame() const {
     205           0 :         MOZ_ASSERT(isRematerializedFrame());
     206           0 :         jit::RematerializedFrame* res = (jit::RematerializedFrame*)(ptr_ & ~TagMask);
     207           0 :         MOZ_ASSERT(res);
     208           0 :         return res;
     209             :     }
     210      111586 :     bool isWasmDebugFrame() const {
     211      111586 :         return (ptr_ & TagMask) == Tag_WasmDebugFrame;
     212             :     }
     213           0 :     wasm::DebugFrame* asWasmDebugFrame() const {
     214           0 :         MOZ_ASSERT(isWasmDebugFrame());
     215           0 :         wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask);
     216           0 :         MOZ_ASSERT(res);
     217           0 :         return res;
     218             :     }
     219             : 
     220           0 :     void* raw() const { return reinterpret_cast<void*>(ptr_); }
     221             : 
     222        1640 :     bool operator ==(const AbstractFramePtr& other) const { return ptr_ == other.ptr_; }
     223           0 :     bool operator !=(const AbstractFramePtr& other) const { return ptr_ != other.ptr_; }
     224             : 
     225      113007 :     explicit operator bool() const { return !!ptr_; }
     226             : 
     227             :     inline JSObject* environmentChain() const;
     228             :     inline CallObject& callObj() const;
     229             :     inline bool initFunctionEnvironmentObjects(JSContext* cx);
     230             :     inline bool pushVarEnvironment(JSContext* cx, HandleScope scope);
     231             :     template <typename SpecificEnvironment>
     232             :     inline void pushOnEnvironmentChain(SpecificEnvironment& env);
     233             :     template <typename SpecificEnvironment>
     234             :     inline void popOffEnvironmentChain();
     235             : 
     236             :     inline JSCompartment* compartment() const;
     237             : 
     238             :     inline bool hasInitialEnvironment() const;
     239             :     inline bool isGlobalFrame() const;
     240             :     inline bool isModuleFrame() const;
     241             :     inline bool isEvalFrame() const;
     242             :     inline bool isDebuggerEvalFrame() const;
     243             :     inline bool hasCachedSavedFrame() const;
     244             :     inline void setHasCachedSavedFrame();
     245             : 
     246             :     inline bool hasScript() const;
     247             :     inline JSScript* script() const;
     248             :     inline wasm::Instance* wasmInstance() const;
     249             :     inline GlobalObject* global() const;
     250             :     inline JSFunction* callee() const;
     251             :     inline Value calleev() const;
     252             :     inline Value& thisArgument() const;
     253             : 
     254             :     inline Value newTarget() const;
     255             : 
     256             :     inline bool debuggerNeedsCheckPrimitiveReturn() const;
     257             : 
     258             :     inline bool isFunctionFrame() const;
     259             :     inline bool isNonStrictDirectEvalFrame() const;
     260             :     inline bool isStrictEvalFrame() const;
     261             : 
     262             :     inline unsigned numActualArgs() const;
     263             :     inline unsigned numFormalArgs() const;
     264             : 
     265             :     inline Value* argv() const;
     266             : 
     267             :     inline bool hasArgs() const;
     268             :     inline bool hasArgsObj() const;
     269             :     inline ArgumentsObject& argsObj() const;
     270             :     inline void initArgsObj(ArgumentsObject& argsobj) const;
     271             :     inline bool createSingleton() const;
     272             : 
     273             :     inline Value& unaliasedLocal(uint32_t i);
     274             :     inline Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
     275             :     inline Value& unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
     276             :     template <class Op> inline void unaliasedForEachActual(JSContext* cx, Op op);
     277             : 
     278             :     inline bool prevUpToDate() const;
     279             :     inline void setPrevUpToDate() const;
     280             :     inline void unsetPrevUpToDate() const;
     281             : 
     282             :     inline bool isDebuggee() const;
     283             :     inline void setIsDebuggee();
     284             :     inline void unsetIsDebuggee();
     285             : 
     286             :     inline HandleValue returnValue() const;
     287             :     inline void setReturnValue(const Value& rval) const;
     288             : 
     289             :     friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, void*);
     290             :     friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, InterpreterFrame*);
     291             :     friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, jit::BaselineFrame*);
     292             :     friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, jit::RematerializedFrame*);
     293             :     friend void GDBTestInitAbstractFramePtr(AbstractFramePtr& frame, wasm::DebugFrame* ptr);
     294             : };
     295             : 
     296             : class NullFramePtr : public AbstractFramePtr
     297             : {
     298             :   public:
     299       12757 :     NullFramePtr()
     300       12757 :       : AbstractFramePtr()
     301       12757 :     { }
     302             : };
     303             : 
     304             : enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
     305             : 
     306             : /*****************************************************************************/
     307             : 
     308             : class InterpreterFrame
     309             : {
     310             :     enum Flags : uint32_t {
     311             :         CONSTRUCTING           =        0x1,  /* frame is for a constructor invocation */
     312             : 
     313             :         RESUMED_GENERATOR      =        0x2,  /* frame is for a resumed generator invocation */
     314             : 
     315             :         /* Function prologue state */
     316             :         HAS_INITIAL_ENV        =        0x4,  /* callobj created for function or var env for eval */
     317             :         HAS_ARGS_OBJ           =        0x8,  /* ArgumentsObject created for needsArgsObj script */
     318             : 
     319             :         /* Lazy frame initialization */
     320             :         HAS_RVAL               =       0x10,  /* frame has rval_ set */
     321             : 
     322             :         /* Debugger state */
     323             :         PREV_UP_TO_DATE        =       0x20,  /* see DebugScopes::updateLiveScopes */
     324             : 
     325             :         /*
     326             :          * See comment above 'isDebuggee' in jscompartment.h for explanation of
     327             :          * invariants of debuggee compartments, scripts, and frames.
     328             :          */
     329             :         DEBUGGEE               =       0x40,  /* Execution is being observed by Debugger */
     330             : 
     331             :         /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
     332             :         HAS_PUSHED_PROF_FRAME  =       0x80,  /* Gecko Profiler was notified of entry */
     333             : 
     334             :         /*
     335             :          * If set, we entered one of the JITs and ScriptFrameIter should skip
     336             :          * this frame.
     337             :          */
     338             :         RUNNING_IN_JIT         =      0x100,
     339             : 
     340             :         /* Miscellaneous state. */
     341             :         CREATE_SINGLETON       =      0x200,  /* Constructed |this| object should be singleton. */
     342             : 
     343             :         /*
     344             :          * If set, this frame has been on the stack when
     345             :          * |js::SavedStacks::saveCurrentStack| was called, and so there is a
     346             :          * |js::SavedFrame| object cached for this frame.
     347             :          */
     348             :         HAS_CACHED_SAVED_FRAME =      0x400,
     349             :     };
     350             : 
     351             :     mutable uint32_t    flags_;         /* bits described by Flags */
     352             :     uint32_t            nactual_;       /* number of actual arguments, for function frames */
     353             :     JSScript*           script_;        /* the script we're executing */
     354             :     JSObject*           envChain_;      /* current environment chain */
     355             :     Value               rval_;          /* if HAS_RVAL, return value of the frame */
     356             :     ArgumentsObject*    argsObj_;       /* if HAS_ARGS_OBJ, the call's arguments object */
     357             : 
     358             :     /*
     359             :      * Previous frame and its pc and sp. Always nullptr for
     360             :      * InterpreterActivation's entry frame, always non-nullptr for inline
     361             :      * frames.
     362             :      */
     363             :     InterpreterFrame*   prev_;
     364             :     jsbytecode*         prevpc_;
     365             :     Value*              prevsp_;
     366             : 
     367             :     void*               unused;
     368             : 
     369             :     /*
     370             :      * For an eval-in-frame DEBUGGER_EVAL frame, the frame in whose scope
     371             :      * we're evaluating code. Iteration treats this as our previous frame.
     372             :      */
     373             :     AbstractFramePtr    evalInFramePrev_;
     374             : 
     375             :     Value*              argv_;         /* If hasArgs(), points to frame's arguments. */
     376             :     LifoAlloc::Mark     mark_;          /* Used to release memory for this frame. */
     377             : 
     378             :     static void staticAsserts() {
     379             :         JS_STATIC_ASSERT(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
     380             :         JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(Value) == 0);
     381             :     }
     382             : 
     383             :     /*
     384             :      * The utilities are private since they are not able to assert that only
     385             :      * unaliased vars/formals are accessed. Normal code should prefer the
     386             :      * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
     387             :      * the usual "depth is at least" assertions).
     388             :      */
     389      304695 :     Value* slots() const { return (Value*)(this + 1); }
     390      194492 :     Value* base() const { return slots() + script()->nfixed(); }
     391             : 
     392             :     friend class FrameIter;
     393             :     friend class InterpreterRegs;
     394             :     friend class InterpreterStack;
     395             :     friend class jit::BaselineFrame;
     396             : 
     397             :     /*
     398             :      * Frame initialization, called by InterpreterStack operations after acquiring
     399             :      * the raw memory for the frame:
     400             :      */
     401             : 
     402             :     /* Used for Invoke and Interpret. */
     403             :     void initCallFrame(JSContext* cx, InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
     404             :                        JSFunction& callee, JSScript* script, Value* argv, uint32_t nactual,
     405             :                        MaybeConstruct constructing);
     406             : 
     407             :     /* Used for global and eval frames. */
     408             :     void initExecuteFrame(JSContext* cx, HandleScript script, AbstractFramePtr prev,
     409             :                           const Value& newTargetValue, HandleObject envChain);
     410             : 
     411             :   public:
     412             :     /*
     413             :      * Frame prologue/epilogue
     414             :      *
     415             :      * Every stack frame must have 'prologue' called before executing the
     416             :      * first op and 'epilogue' called after executing the last op and before
     417             :      * popping the frame (whether the exit is exceptional or not).
     418             :      *
     419             :      * For inline JS calls/returns, it is easy to call the prologue/epilogue
     420             :      * exactly once. When calling JS from C++, Invoke/Execute push the stack
     421             :      * frame but do *not* call the prologue/epilogue. That means Interpret
     422             :      * must call the prologue/epilogue for the entry frame. This scheme
     423             :      * simplifies jit compilation.
     424             :      *
     425             :      * An important corner case is what happens when an error occurs (OOM,
     426             :      * over-recursed) after pushing the stack frame but before 'prologue' is
     427             :      * called or completes fully. To simplify usage, 'epilogue' does not assume
     428             :      * 'prologue' has completed and handles all the intermediate state details.
     429             :      */
     430             : 
     431             :     bool prologue(JSContext* cx);
     432             :     void epilogue(JSContext* cx, jsbytecode* pc);
     433             : 
     434             :     bool checkReturn(JSContext* cx, HandleValue thisv);
     435             : 
     436             :     bool initFunctionEnvironmentObjects(JSContext* cx);
     437             : 
     438             :     /*
     439             :      * Initialize locals of newly-pushed frame to undefined.
     440             :      */
     441             :     void initLocals();
     442             : 
     443             :     /*
     444             :      * Stack frame type
     445             :      *
     446             :      * A stack frame may have one of four types, which determines which
     447             :      * members of the frame may be accessed and other invariants:
     448             :      *
     449             :      *  global frame:   execution of global code
     450             :      *  function frame: execution of function code
     451             :      *  module frame:   execution of a module
     452             :      *  eval frame:     execution of eval code
     453             :      */
     454             : 
     455       12585 :     bool isGlobalFrame() const {
     456       12585 :         return script_->isGlobalCode();
     457             :     }
     458             : 
     459       11603 :     bool isModuleFrame() const {
     460       11603 :         return script_->module();
     461             :     }
     462             : 
     463       46424 :     bool isEvalFrame() const {
     464       46424 :         return script_->isForEval();
     465             :     }
     466             : 
     467      405585 :     bool isFunctionFrame() const {
     468      405585 :         return script_->functionNonDelazifying();
     469             :     }
     470             : 
     471             :     inline bool isStrictEvalFrame() const {
     472             :         return isEvalFrame() && script()->strict();
     473             :     }
     474             : 
     475             :     bool isNonStrictEvalFrame() const {
     476             :         return isEvalFrame() && !script()->strict();
     477             :     }
     478             : 
     479             :     bool isNonGlobalEvalFrame() const;
     480             : 
     481             :     bool isNonStrictDirectEvalFrame() const {
     482             :         return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
     483             :     }
     484             : 
     485             :     /*
     486             :      * Previous frame
     487             :      *
     488             :      * A frame's 'prev' frame is either null or the previous frame pointed to
     489             :      * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
     490             :      * frames, the next-frame is a function or eval that was called by the
     491             :      * prev-frame, but not always: the prev-frame may have called a native that
     492             :      * reentered the VM through JS_CallFunctionValue on the same context
     493             :      * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
     494             :      * 'prev' has little semantic meaning and basically just tells the VM what
     495             :      * to set cx->regs->fp to when this frame is popped.
     496             :      */
     497             : 
     498        3222 :     InterpreterFrame* prev() const {
     499        3222 :         return prev_;
     500             :     }
     501             : 
     502           0 :     AbstractFramePtr evalInFramePrev() const {
     503           0 :         MOZ_ASSERT(isEvalFrame());
     504           0 :         return evalInFramePrev_;
     505             :     }
     506             : 
     507             :     /*
     508             :      * (Unaliased) locals and arguments
     509             :      *
     510             :      * Only non-eval function frames have arguments. The arguments pushed by
     511             :      * the caller are the 'actual' arguments. The declared arguments of the
     512             :      * callee are the 'formal' arguments. When the caller passes less actual
     513             :      * arguments, missing formal arguments are padded with |undefined|.
     514             :      *
     515             :      * When a local/formal variable is aliased (accessed by nested closures,
     516             :      * environment operations, or 'arguments'), the canonical location for
     517             :      * that value is the slot of an environment object.  Aliased locals don't
     518             :      * have stack slots assigned to them.  These functions assert that
     519             :      * accesses to stack values are unaliased.
     520             :      */
     521             : 
     522             :     inline Value& unaliasedLocal(uint32_t i);
     523             : 
     524      156778 :     bool hasArgs() const { return isFunctionFrame(); }
     525             :     inline Value& unaliasedFormal(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
     526             :     inline Value& unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
     527             :     template <class Op> inline void unaliasedForEachActual(Op op);
     528             : 
     529       24510 :     unsigned numFormalArgs() const { MOZ_ASSERT(hasArgs()); return callee().nargs(); }
     530        5546 :     unsigned numActualArgs() const { MOZ_ASSERT(hasArgs()); return nactual_; }
     531             : 
     532             :     /* Watch out, this exposes a pointer to the unaliased formal arg array. */
     533      126617 :     Value* argv() const { MOZ_ASSERT(hasArgs()); return argv_; }
     534             : 
     535             :     /*
     536             :      * Arguments object
     537             :      *
     538             :      * If a non-eval function has script->needsArgsObj, an arguments object is
     539             :      * created in the prologue and stored in the local variable for the
     540             :      * 'arguments' binding (script->argumentsLocal). Since this local is
     541             :      * mutable, the arguments object can be overwritten and we can "lose" the
     542             :      * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field so
     543             :      * that the original arguments object is always available.
     544             :      */
     545             : 
     546             :     ArgumentsObject& argsObj() const;
     547             :     void initArgsObj(ArgumentsObject& argsobj);
     548             : 
     549             :     JSObject* createRestParameter(JSContext* cx);
     550             : 
     551             :     /*
     552             :      * Environment chain
     553             :      *
     554             :      * In theory, the environment chain would contain an object for every
     555             :      * lexical scope. However, only objects that are required for dynamic
     556             :      * lookup are actually created.
     557             :      *
     558             :      * Given that an InterpreterFrame corresponds roughly to a ES Execution
     559             :      * Context (ES 10.3), InterpreterFrame::varObj corresponds to the
     560             :      * VariableEnvironment component of a Exection Context. Intuitively, the
     561             :      * variables object is where new bindings (variables and functions) are
     562             :      * stored. One might expect that this is either the Call object or
     563             :      * envChain.globalObj for function or global code, respectively, however
     564             :      * the JSAPI allows calls of Execute to specify a variables object on the
     565             :      * environment chain other than the call/global object. This allows
     566             :      * embeddings to run multiple scripts under the same global, each time
     567             :      * using a new variables object to collect and discard the script's global
     568             :      * variables.
     569             :      */
     570             : 
     571             :     inline HandleObject environmentChain() const;
     572             : 
     573             :     inline EnvironmentObject& aliasedEnvironment(EnvironmentCoordinate ec) const;
     574             :     inline GlobalObject& global() const;
     575             :     inline CallObject& callObj() const;
     576             :     inline JSObject& varObj() const;
     577             :     inline LexicalEnvironmentObject& extensibleLexicalEnvironment() const;
     578             : 
     579             :     template <typename SpecificEnvironment>
     580             :     inline void pushOnEnvironmentChain(SpecificEnvironment& env);
     581             :     template <typename SpecificEnvironment>
     582             :     inline void popOffEnvironmentChain();
     583             :     inline void replaceInnermostEnvironment(EnvironmentObject& env);
     584             : 
     585             :     // Push a VarEnvironmentObject for function frames of functions that have
     586             :     // parameter expressions with closed over var bindings.
     587             :     bool pushVarEnvironment(JSContext* cx, HandleScope scope);
     588             : 
     589             :     /*
     590             :      * For lexical envs with aliased locals, these interfaces push and pop
     591             :      * entries on the environment chain.  The "freshen" operation replaces the
     592             :      * current lexical env with a fresh copy of it, to implement semantics
     593             :      * providing distinct bindings per iteration of a for(;;) loop whose head
     594             :      * has a lexical declaration.  The "recreate" operation replaces the
     595             :      * current lexical env with a copy of it containing uninitialized
     596             :      * bindings, to implement semantics providing distinct bindings per
     597             :      * iteration of a for-in/of loop.
     598             :      */
     599             : 
     600             :     bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
     601             :     bool freshenLexicalEnvironment(JSContext* cx);
     602             :     bool recreateLexicalEnvironment(JSContext* cx);
     603             : 
     604             :     /*
     605             :      * Script
     606             :      *
     607             :      * All frames have an associated JSScript which holds the bytecode being
     608             :      * executed for the frame.
     609             :      */
     610             : 
     611      571927 :     JSScript* script() const {
     612      571927 :         return script_;
     613             :     }
     614             : 
     615             :     /* Return the previous frame's pc. */
     616        3222 :     jsbytecode* prevpc() {
     617        3222 :         MOZ_ASSERT(prev_);
     618        3222 :         return prevpc_;
     619             :     }
     620             : 
     621             :     /* Return the previous frame's sp. */
     622        3222 :     Value* prevsp() {
     623        3222 :         MOZ_ASSERT(prev_);
     624        3222 :         return prevsp_;
     625             :     }
     626             : 
     627             :     /*
     628             :      * Return the 'this' argument passed to a non-eval function frame. This is
     629             :      * not necessarily the frame's this-binding, for instance non-strict
     630             :      * functions will box primitive 'this' values and thisArgument() will
     631             :      * return the original, unboxed Value.
     632             :      */
     633       12470 :     Value& thisArgument() const {
     634       12470 :         MOZ_ASSERT(isFunctionFrame());
     635       12470 :         return argv()[-1];
     636             :     }
     637             : 
     638             :     /*
     639             :      * Callee
     640             :      *
     641             :      * Only function frames have a callee. An eval frame in a function has the
     642             :      * same callee as its containing function frame.
     643             :      */
     644             : 
     645       89472 :     JSFunction& callee() const {
     646       89472 :         MOZ_ASSERT(isFunctionFrame());
     647       89472 :         return calleev().toObject().as<JSFunction>();
     648             :     }
     649             : 
     650       89485 :     const Value& calleev() const {
     651       89485 :         MOZ_ASSERT(isFunctionFrame());
     652       89485 :         return argv()[-2];
     653             :     }
     654             : 
     655             :     /*
     656             :      * New Target
     657             :      *
     658             :      * Only function frames have a meaningful newTarget. An eval frame in a
     659             :      * function will have a copy of the newTarget of the enclosing function
     660             :      * frame.
     661             :      */
     662         693 :     Value newTarget() const {
     663         693 :         if (isEvalFrame())
     664           0 :             return ((Value*)this)[-1];
     665             : 
     666         693 :         MOZ_ASSERT(isFunctionFrame());
     667             : 
     668         693 :         if (callee().isArrow())
     669          96 :             return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
     670             : 
     671         597 :         if (isConstructing()) {
     672         113 :             unsigned pushedArgs = Max(numFormalArgs(), numActualArgs());
     673         113 :             return argv()[pushedArgs];
     674             :         }
     675         484 :         return UndefinedValue();
     676             :     }
     677             : 
     678             :     /* Profiler flags */
     679             : 
     680       44354 :     bool hasPushedGeckoProfilerFrame() {
     681       44354 :         return !!(flags_ & HAS_PUSHED_PROF_FRAME);
     682             :     }
     683             : 
     684           0 :     void setPushedGeckoProfilerFrame() {
     685           0 :         flags_ |= HAS_PUSHED_PROF_FRAME;
     686           0 :     }
     687             : 
     688             :     void unsetPushedGeckoProfilerFrame() {
     689             :         flags_ &= ~HAS_PUSHED_PROF_FRAME;
     690             :     }
     691             : 
     692             :     /* Return value */
     693             : 
     694       12963 :     bool hasReturnValue() const {
     695       12963 :         return flags_ & HAS_RVAL;
     696             :     }
     697             : 
     698       12717 :     MutableHandleValue returnValue() {
     699       12717 :         if (!hasReturnValue())
     700        3072 :             rval_.setUndefined();
     701       12717 :         return MutableHandleValue::fromMarkedLocation(&rval_);
     702             :     }
     703             : 
     704       10004 :     void markReturnValue() {
     705       10004 :         flags_ |= HAS_RVAL;
     706       10004 :     }
     707             : 
     708       10004 :     void setReturnValue(const Value& v) {
     709       10004 :         rval_ = v;
     710       10004 :         markReturnValue();
     711       10004 :     }
     712             : 
     713             :     void clearReturnValue() {
     714             :         rval_.setUndefined();
     715             :         markReturnValue();
     716             :     }
     717             : 
     718         198 :     void resumeGeneratorFrame(JSObject* envChain) {
     719         198 :         MOZ_ASSERT(script()->isStarGenerator() || script()->isLegacyGenerator() ||
     720             :                    script()->isAsync());
     721         198 :         MOZ_ASSERT(isFunctionFrame());
     722         198 :         flags_ |= HAS_INITIAL_ENV;
     723         198 :         envChain_ = envChain;
     724         198 :     }
     725             : 
     726             :     /*
     727             :      * Other flags
     728             :      */
     729             : 
     730       25572 :     bool isConstructing() const {
     731       25572 :         return !!(flags_ & CONSTRUCTING);
     732             :     }
     733             : 
     734         198 :     void setResumedGenerator() {
     735         198 :         flags_ |= RESUMED_GENERATOR;
     736         198 :     }
     737        1869 :     bool isResumedGenerator() const {
     738        1869 :         return !!(flags_ & RESUMED_GENERATOR);
     739             :     }
     740             : 
     741             :     /*
     742             :      * These two queries should not be used in general: the presence/absence of
     743             :      * the call/args object is determined by the static(ish) properties of the
     744             :      * JSFunction/JSScript. These queries should only be performed when probing
     745             :      * a stack frame that may be in the middle of the prologue (during which
     746             :      * time the call/args object are created).
     747             :      */
     748             : 
     749             :     inline bool hasInitialEnvironment() const;
     750             : 
     751         141 :     bool hasInitialEnvironmentUnchecked() const {
     752         141 :         return flags_ & HAS_INITIAL_ENV;
     753             :     }
     754             : 
     755           0 :     bool hasArgsObj() const {
     756           0 :         MOZ_ASSERT(script()->needsArgsObj());
     757           0 :         return flags_ & HAS_ARGS_OBJ;
     758             :     }
     759             : 
     760           0 :     void setCreateSingleton() {
     761           0 :         MOZ_ASSERT(isConstructing());
     762           0 :         flags_ |= CREATE_SINGLETON;
     763           0 :     }
     764           0 :     bool createSingleton() const {
     765           0 :         MOZ_ASSERT(isConstructing());
     766           0 :         return flags_ & CREATE_SINGLETON;
     767             :     }
     768             : 
     769             :     /*
     770             :      * Debugger eval frames.
     771             :      *
     772             :      * - If evalInFramePrev_ is non-null, frame was created for an "eval in
     773             :      *   frame" call, which can push a successor to any live frame; so its
     774             :      *   logical "prev" frame is not necessarily the previous frame in memory.
     775             :      *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
     776             :      *
     777             :      * - Don't bother to JIT it, because it's probably short-lived.
     778             :      *
     779             :      * - It is required to have a environment chain object outside the
     780             :      *   js::EnvironmentObject hierarchy: either a global object, or a
     781             :      *   DebugEnvironmentProxy.
     782             :      */
     783        9771 :     bool isDebuggerEvalFrame() const {
     784        9771 :         return isEvalFrame() && !!evalInFramePrev_;
     785             :     }
     786             : 
     787           0 :     bool prevUpToDate() const {
     788           0 :         return !!(flags_ & PREV_UP_TO_DATE);
     789             :     }
     790             : 
     791           0 :     void setPrevUpToDate() {
     792           0 :         flags_ |= PREV_UP_TO_DATE;
     793           0 :     }
     794             : 
     795           0 :     void unsetPrevUpToDate() {
     796           0 :         flags_ &= ~PREV_UP_TO_DATE;
     797           0 :     }
     798             : 
     799       26818 :     bool isDebuggee() const {
     800       26818 :         return !!(flags_ & DEBUGGEE);
     801             :     }
     802             : 
     803           0 :     void setIsDebuggee() {
     804           0 :         flags_ |= DEBUGGEE;
     805           0 :     }
     806             : 
     807             :     inline void unsetIsDebuggee();
     808             : 
     809        4900 :     bool hasCachedSavedFrame() const {
     810        4900 :         return flags_ & HAS_CACHED_SAVED_FRAME;
     811             :     }
     812        2170 :     void setHasCachedSavedFrame() {
     813        2170 :         flags_ |= HAS_CACHED_SAVED_FRAME;
     814        2170 :     }
     815             : 
     816             :   public:
     817             :     void trace(JSTracer* trc, Value* sp, jsbytecode* pc);
     818             :     void traceValues(JSTracer* trc, unsigned start, unsigned end);
     819             : 
     820             :     // Entered Baseline/Ion from the interpreter.
     821       40067 :     bool runningInJit() const {
     822       40067 :         return !!(flags_ & RUNNING_IN_JIT);
     823             :     }
     824         141 :     void setRunningInJit() {
     825         141 :         flags_ |= RUNNING_IN_JIT;
     826         141 :     }
     827         141 :     void clearRunningInJit() {
     828         141 :         flags_ &= ~RUNNING_IN_JIT;
     829         141 :     }
     830             : };
     831             : 
     832             : /*****************************************************************************/
     833             : 
     834             : class InterpreterRegs
     835             : {
     836             :   public:
     837             :     Value* sp;
     838             :     jsbytecode* pc;
     839             :   private:
     840             :     InterpreterFrame* fp_;
     841             :   public:
     842      366288 :     InterpreterFrame* fp() const { return fp_; }
     843             : 
     844       96996 :     unsigned stackDepth() const {
     845       96996 :         MOZ_ASSERT(sp >= fp_->base());
     846       96996 :         return sp - fp_->base();
     847             :     }
     848             : 
     849         482 :     Value* spForStackDepth(unsigned depth) const {
     850         482 :         MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
     851         482 :         return fp_->base() + depth;
     852             :     }
     853             : 
     854             :     /* For generators. */
     855             :     void rebaseFromTo(const InterpreterRegs& from, InterpreterFrame& to) {
     856             :         fp_ = &to;
     857             :         sp = to.slots() + (from.sp - from.fp_->slots());
     858             :         pc = from.pc;
     859             :         MOZ_ASSERT(fp_);
     860             :     }
     861             : 
     862        1869 :     void popInlineFrame() {
     863        1869 :         pc = fp_->prevpc();
     864        1869 :         unsigned spForNewTarget = fp_->isResumedGenerator() ? 0 : fp_->isConstructing();
     865        1869 :         sp = fp_->prevsp() - fp_->numActualArgs() - 1 - spForNewTarget;
     866        1869 :         fp_ = fp_->prev();
     867        1869 :         MOZ_ASSERT(fp_);
     868        1869 :     }
     869       12299 :     void prepareToRun(InterpreterFrame& fp, JSScript* script) {
     870       12299 :         pc = script->code();
     871       12299 :         sp = fp.slots() + script->nfixed();
     872       12299 :         fp_ = &fp;
     873       12299 :     }
     874             : 
     875             :     void setToEndOfScript();
     876             : 
     877      122265 :     MutableHandleValue stackHandleAt(int i) {
     878      122265 :         return MutableHandleValue::fromMarkedLocation(&sp[i]);
     879             :     }
     880             : 
     881             :     HandleValue stackHandleAt(int i) const {
     882             :         return HandleValue::fromMarkedLocation(&sp[i]);
     883             :     }
     884             : 
     885             :     friend void GDBTestInitInterpreterRegs(InterpreterRegs&, js::InterpreterFrame*,
     886             :                                            JS::Value*, uint8_t*);
     887             : };
     888             : 
     889             : /*****************************************************************************/
     890             : 
     891             : class InterpreterStack
     892             : {
     893             :     friend class InterpreterActivation;
     894             : 
     895             :     static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
     896             :     LifoAlloc allocator_;
     897             : 
     898             :     // Number of interpreter frames on the stack, for over-recursion checks.
     899             :     static const size_t MAX_FRAMES = 50 * 1000;
     900             :     static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
     901             :     size_t frameCount_;
     902             : 
     903             :     inline uint8_t* allocateFrame(JSContext* cx, size_t size);
     904             : 
     905             :     inline InterpreterFrame*
     906             :     getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script,
     907             :                  MaybeConstruct constructing, Value** pargv);
     908             : 
     909       12288 :     void releaseFrame(InterpreterFrame* fp) {
     910       12288 :         frameCount_--;
     911       12288 :         allocator_.release(fp->mark_);
     912       12288 :     }
     913             : 
     914             :   public:
     915          40 :     InterpreterStack()
     916          40 :       : allocator_(DEFAULT_CHUNK_SIZE),
     917          40 :         frameCount_(0)
     918          40 :     { }
     919             : 
     920           0 :     ~InterpreterStack() {
     921           0 :         MOZ_ASSERT(frameCount_ == 0);
     922           0 :     }
     923             : 
     924             :     // For execution of eval or global code.
     925             :     InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
     926             :                                        const Value& newTargetValue, HandleObject envChain,
     927             :                                        AbstractFramePtr evalInFrame);
     928             : 
     929             :     // Called to invoke a function.
     930             :     InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
     931             :                                       MaybeConstruct constructing);
     932             : 
     933             :     // The interpreter can push light-weight, "inline" frames without entering a
     934             :     // new InterpreterActivation or recursively calling Interpret.
     935             :     bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
     936             :                          HandleScript script, MaybeConstruct constructing);
     937             : 
     938             :     void popInlineFrame(InterpreterRegs& regs);
     939             : 
     940             :     bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
     941             :                                   HandleFunction callee, HandleValue newTarget,
     942             :                                   HandleObject envChain);
     943             : 
     944             :     inline void purge(JSRuntime* rt);
     945             : 
     946           0 :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     947           0 :         return allocator_.sizeOfExcludingThis(mallocSizeOf);
     948             :     }
     949             : };
     950             : 
     951             : // CooperatingContext is a wrapper for a JSContext that is participating in
     952             : // cooperative scheduling and may be different from the current thread. It is
     953             : // in place to make it clearer when we might be operating on another thread,
     954             : // and harder to accidentally pass in another thread's context to an API that
     955             : // expects the current thread's context.
     956             : class CooperatingContext
     957             : {
     958             :     JSContext* cx;
     959             : 
     960             :   public:
     961        5263 :     explicit CooperatingContext(JSContext* cx) : cx(cx) {}
     962     1030449 :     JSContext* context() const { return cx; }
     963             : 
     964             :     // For &cx. The address should not be taken for other CooperatingContexts.
     965             :     friend class ZoneGroup;
     966             : };
     967             : 
     968             : void TraceInterpreterActivations(JSContext* cx, const CooperatingContext& target, JSTracer* trc);
     969             : 
     970             : /*****************************************************************************/
     971             : 
     972             : /** Base class for all function call args. */
     973       15385 : class AnyInvokeArgs : public JS::CallArgs
     974             : {
     975             : };
     976             : 
     977             : /** Base class for all function construction args. */
     978         178 : class AnyConstructArgs : public JS::CallArgs
     979             : {
     980             :     // Only js::Construct (or internal methods that call the qualified CallArgs
     981             :     // versions) should do these things!
     982             :     void setCallee(const Value& v) = delete;
     983             :     void setThis(const Value& v) = delete;
     984             :     MutableHandleValue newTarget() const = delete;
     985             :     MutableHandleValue rval() const = delete;
     986             : };
     987             : 
     988             : namespace detail {
     989             : 
     990             : /** Function call/construct args of statically-unknown count. */
     991             : template <MaybeConstruct Construct>
     992        7595 : class GenericArgsBase
     993             :   : public mozilla::Conditional<Construct, AnyConstructArgs, AnyInvokeArgs>::Type
     994             : {
     995             :   protected:
     996             :     AutoValueVector v_;
     997             : 
     998        7597 :     explicit GenericArgsBase(JSContext* cx) : v_(cx) {}
     999             : 
    1000             :   public:
    1001        7597 :     bool init(JSContext* cx, unsigned argc) {
    1002        7597 :         if (argc > ARGS_LENGTH_MAX) {
    1003           0 :             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TOO_MANY_ARGUMENTS);
    1004           0 :             return false;
    1005             :         }
    1006             : 
    1007             :         // callee, this, arguments[, new.target iff constructing]
    1008        7597 :         size_t len = 2 + argc + uint32_t(Construct);
    1009        7597 :         MOZ_ASSERT(len > argc);  // no overflow
    1010        7597 :         if (!v_.resize(len))
    1011           0 :             return false;
    1012             : 
    1013        7597 :         *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
    1014        7597 :         this->constructing_ = Construct;
    1015             :         if (Construct)
    1016         175 :             this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
    1017        7597 :         return true;
    1018             :     }
    1019             : };
    1020             : 
    1021             : /** Function call/construct args of statically-known count. */
    1022             : template <MaybeConstruct Construct, size_t N>
    1023        7965 : class FixedArgsBase
    1024             :   : public mozilla::Conditional<Construct, AnyConstructArgs, AnyInvokeArgs>::Type
    1025             : {
    1026             :     static_assert(N <= ARGS_LENGTH_MAX, "o/~ too many args o/~");
    1027             : 
    1028             :   protected:
    1029             :     JS::AutoValueArray<2 + N + uint32_t(Construct)> v_;
    1030             : 
    1031        7966 :     explicit FixedArgsBase(JSContext* cx) : v_(cx) {
    1032        7966 :         *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
    1033        7966 :         this->constructing_ = Construct;
    1034             :         if (Construct)
    1035           3 :             this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
    1036        7966 :     }
    1037             : };
    1038             : 
    1039             : } // namespace detail
    1040             : 
    1041             : /** Function call args of statically-unknown count. */
    1042        7418 : class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT>
    1043             : {
    1044             :     using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
    1045             : 
    1046             :   public:
    1047        7420 :     explicit InvokeArgs(JSContext* cx) : Base(cx) {}
    1048             : };
    1049             : 
    1050             : /** Function call args of statically-unknown count. */
    1051           2 : class InvokeArgsMaybeIgnoresReturnValue : public detail::GenericArgsBase<NO_CONSTRUCT>
    1052             : {
    1053             :     using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
    1054             : 
    1055             :   public:
    1056           2 :     explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx, bool ignoresReturnValue) : Base(cx) {
    1057           2 :         this->ignoresReturnValue_ = ignoresReturnValue;
    1058           2 :     }
    1059             : };
    1060             : 
    1061             : /** Function call args of statically-known count. */
    1062             : template <size_t N>
    1063        7962 : class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N>
    1064             : {
    1065             :     using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>;
    1066             : 
    1067             :   public:
    1068        7963 :     explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {}
    1069             : };
    1070             : 
    1071             : /** Function construct args of statically-unknown count. */
    1072         175 : class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT>
    1073             : {
    1074             :     using Base = detail::GenericArgsBase<CONSTRUCT>;
    1075             : 
    1076             :   public:
    1077         175 :     explicit ConstructArgs(JSContext* cx) : Base(cx) {}
    1078             : };
    1079             : 
    1080             : /** Function call args of statically-known count. */
    1081             : template <size_t N>
    1082           3 : class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N>
    1083             : {
    1084             :     using Base = detail::FixedArgsBase<CONSTRUCT, N>;
    1085             : 
    1086             :   public:
    1087           3 :     explicit FixedConstructArgs(JSContext* cx) : Base(cx) {}
    1088             : };
    1089             : 
    1090             : template <class Args, class Arraylike>
    1091             : inline bool
    1092        6989 : FillArgumentsFromArraylike(JSContext* cx, Args& args, const Arraylike& arraylike)
    1093             : {
    1094        6989 :     uint32_t len = arraylike.length();
    1095        6989 :     if (!args.init(cx, len))
    1096           0 :         return false;
    1097             : 
    1098       17299 :     for (uint32_t i = 0; i < len; i++)
    1099       10310 :         args[i].set(arraylike[i]);
    1100             : 
    1101        6989 :     return true;
    1102             : }
    1103             : 
    1104             : template <>
    1105             : struct DefaultHasher<AbstractFramePtr> {
    1106             :     typedef AbstractFramePtr Lookup;
    1107             : 
    1108           0 :     static js::HashNumber hash(const Lookup& key) {
    1109           0 :         return size_t(key.raw());
    1110             :     }
    1111             : 
    1112           0 :     static bool match(const AbstractFramePtr& k, const Lookup& l) {
    1113           0 :         return k == l;
    1114             :     }
    1115             : };
    1116             : 
    1117             : /*****************************************************************************/
    1118             : 
    1119             : // SavedFrame caching to minimize stack walking.
    1120             : //
    1121             : // SavedFrames are hash consed to minimize expensive (with regards to both space
    1122             : // and time) allocations in the face of many stack frames that tend to share the
    1123             : // same older tail frames. Despite that, in scenarios where we are frequently
    1124             : // saving the same or similar stacks, such as when the Debugger's allocation
    1125             : // site tracking is enabled, these older stack frames still get walked
    1126             : // repeatedly just to create the lookup structs to find their corresponding
    1127             : // SavedFrames in the hash table. This stack walking is slow, and we would like
    1128             : // to minimize it.
    1129             : //
    1130             : // We have reserved a bit on most of SpiderMonkey's various frame
    1131             : // representations (the exceptions being asm and inlined ion frames). As we
    1132             : // create SavedFrame objects for live stack frames in SavedStacks::insertFrames,
    1133             : // we set this bit and append the SavedFrame object to the cache. As we walk the
    1134             : // stack, if we encounter a frame that has this bit set, that indicates that we
    1135             : // have already captured a SavedFrame object for the given stack frame (but not
    1136             : // necessarily the current pc) during a previous call to insertFrames. We know
    1137             : // that the frame's parent was also captured and has its bit set as well, but
    1138             : // additionally we know the parent was captured at its current pc. For the
    1139             : // parent, rather than continuing the expensive stack walk, we do a quick and
    1140             : // cache-friendly linear search through the frame cache. Upon finishing search
    1141             : // through the frame cache, stale entries are removed.
    1142             : //
    1143             : // The frame cache maintains the invariant that its first E[0] .. E[j-1]
    1144             : // entries are live and sorted from oldest to younger frames, where 0 < j < n
    1145             : // and n = the length of the cache. When searching the cache, we require
    1146             : // that we are considering the youngest live frame whose bit is set. Every
    1147             : // cache entry E[i] where i >= j is a stale entry. Consider the following
    1148             : // scenario:
    1149             : //
    1150             : //     P  >  Q  >  R  >  S          Initial stack, bits not set.
    1151             : //     P* >  Q* >  R* >  S*         Capture a SavedFrame stack, set bits.
    1152             : //     P* >  Q* >  R*               Return from S.
    1153             : //     P* >  Q*                     Return from R.
    1154             : //     P* >  Q* >  T                Call T, its bit is not set.
    1155             : //
    1156             : // The frame cache was populated with [P, Q, R, S] when we captured a
    1157             : // SavedFrame stack, but because we returned from frames R and S, their
    1158             : // entries in the frame cache are now stale. This fact is unbeknownst to us
    1159             : // because we do not observe frame pops. Upon capturing a second stack, we
    1160             : // start stack walking at the youngest frame T, which does not have its bit
    1161             : // set and must take the hash table lookup slow path rather than the frame
    1162             : // cache short circuit. Next we proceed to Q and find that it has its bit
    1163             : // set, and it is therefore the youngest live frame with its bit set. We
    1164             : // search through the frame cache from oldest to youngest and find the cache
    1165             : // entry matching Q. We know that T is the next younger live frame from Q
    1166             : // and that T does not have an entry in the frame cache because its bit was
    1167             : // not set. Therefore, we have found entry E[j-1] and the subsequent entries
    1168             : // are stale and should be purged from the frame cache.
    1169             : //
    1170             : // We have a LiveSavedFrameCache for each activation to minimize the number of
    1171             : // entries that must be scanned through, and to avoid the headaches of
    1172             : // maintaining a cache for each compartment and invalidating stale cache entries
    1173             : // in the presence of cross-compartment calls.
    1174             : class LiveSavedFrameCache
    1175             : {
    1176             :   public:
    1177             :     using FramePtr = mozilla::Variant<AbstractFramePtr, jit::CommonFrameLayout*>;
    1178             : 
    1179             :   private:
    1180        3769 :     struct Entry
    1181             :     {
    1182             :         FramePtr             framePtr;
    1183             :         jsbytecode*          pc;
    1184             :         HeapPtr<SavedFrame*> savedFrame;
    1185             : 
    1186        2641 :         Entry(FramePtr& framePtr, jsbytecode* pc, SavedFrame* savedFrame)
    1187        2641 :           : framePtr(framePtr)
    1188             :           , pc(pc)
    1189        2641 :           , savedFrame(savedFrame)
    1190        2641 :         { }
    1191             :     };
    1192             : 
    1193             :     using EntryVector = Vector<Entry, 0, SystemAllocPolicy>;
    1194             :     EntryVector* frames;
    1195             : 
    1196             :     LiveSavedFrameCache(const LiveSavedFrameCache&) = delete;
    1197             :     LiveSavedFrameCache& operator=(const LiveSavedFrameCache&) = delete;
    1198             : 
    1199             :   public:
    1200       18100 :     explicit LiveSavedFrameCache() : frames(nullptr) { }
    1201             : 
    1202       18100 :     LiveSavedFrameCache(LiveSavedFrameCache&& rhs)
    1203       18100 :         : frames(rhs.frames)
    1204             :     {
    1205       18100 :         MOZ_ASSERT(this != &rhs, "self-move disallowed");
    1206       18100 :         rhs.frames = nullptr;
    1207       18100 :     }
    1208             : 
    1209       72384 :     ~LiveSavedFrameCache() {
    1210       36192 :         if (frames) {
    1211         645 :             js_delete(frames);
    1212         645 :             frames = nullptr;
    1213             :         }
    1214       36192 :     }
    1215             : 
    1216        8422 :     bool initialized() const { return !!frames; }
    1217         645 :     bool init(JSContext* cx) {
    1218         645 :         frames = js_new<EntryVector>();
    1219         645 :         if (!frames) {
    1220           0 :             JS_ReportOutOfMemory(cx);
    1221           0 :             return false;
    1222             :         }
    1223         645 :         return true;
    1224             :     }
    1225             : 
    1226             :     static mozilla::Maybe<FramePtr> getFramePtr(FrameIter& iter);
    1227             :     void trace(JSTracer* trc);
    1228             : 
    1229             :     void find(JSContext* cx, FrameIter& frameIter, MutableHandleSavedFrame frame) const;
    1230             :     bool insert(JSContext* cx, FramePtr& framePtr, jsbytecode* pc, HandleSavedFrame savedFrame);
    1231             : };
    1232             : 
    1233             : static_assert(sizeof(LiveSavedFrameCache) == sizeof(uintptr_t),
    1234             :               "Every js::Activation has a LiveSavedFrameCache, so we need to be pretty careful "
    1235             :               "about avoiding bloat. If you're adding members to LiveSavedFrameCache, maybe you "
    1236             :               "should consider figuring out a way to make js::Activation have a "
    1237             :               "LiveSavedFrameCache* instead of a Rooted<LiveSavedFrameCache>.");
    1238             : 
    1239             : /*****************************************************************************/
    1240             : 
    1241             : class InterpreterActivation;
    1242             : class WasmActivation;
    1243             : 
    1244             : namespace jit {
    1245             :     class JitActivation;
    1246             : } // namespace jit
    1247             : 
    1248             : // This class is separate from Activation, because it calls JSCompartment::wrap()
    1249             : // which can GC and walk the stack. It's not safe to do that within the
    1250             : // JitActivation constructor.
    1251             : class MOZ_RAII ActivationEntryMonitor
    1252             : {
    1253             :     JSContext* cx_;
    1254             : 
    1255             :     // The entry point monitor that was set on cx_->runtime() when this
    1256             :     // ActivationEntryMonitor was created.
    1257             :     JS::dbg::AutoEntryMonitor* entryMonitor_;
    1258             : 
    1259             :     explicit ActivationEntryMonitor(JSContext* cx);
    1260             : 
    1261             :     ActivationEntryMonitor(const ActivationEntryMonitor& other) = delete;
    1262             :     void operator=(const ActivationEntryMonitor& other) = delete;
    1263             : 
    1264             :     Value asyncStack(JSContext* cx);
    1265             : 
    1266             :   public:
    1267             :     ActivationEntryMonitor(JSContext* cx, InterpreterFrame* entryFrame);
    1268             :     ActivationEntryMonitor(JSContext* cx, jit::CalleeToken entryToken);
    1269             :     inline ~ActivationEntryMonitor();
    1270             : };
    1271             : 
    1272             : class Activation
    1273             : {
    1274             :   protected:
    1275             :     JSContext* cx_;
    1276             :     JSCompartment* compartment_;
    1277             :     Activation* prev_;
    1278             :     Activation* prevProfiling_;
    1279             : 
    1280             :     // Counter incremented by JS::HideScriptedCaller and decremented by
    1281             :     // JS::UnhideScriptedCaller. If > 0 for the top activation,
    1282             :     // DescribeScriptedCaller will return null instead of querying that
    1283             :     // activation, which should prompt the caller to consult embedding-specific
    1284             :     // data structures instead.
    1285             :     size_t hideScriptedCallerCount_;
    1286             : 
    1287             :     // The cache of SavedFrame objects we have already captured when walking
    1288             :     // this activation's stack.
    1289             :     Rooted<LiveSavedFrameCache> frameCache_;
    1290             : 
    1291             :     // Youngest saved frame of an async stack that will be iterated during stack
    1292             :     // capture in place of the actual stack of previous activations. Note that
    1293             :     // the stack of this activation is captured entirely before this is used.
    1294             :     //
    1295             :     // Usually this is nullptr, meaning that normal stack capture will occur.
    1296             :     // When this is set, the stack of any previous activation is ignored.
    1297             :     Rooted<SavedFrame*> asyncStack_;
    1298             : 
    1299             :     // Value of asyncCause to be attached to asyncStack_.
    1300             :     const char* asyncCause_;
    1301             : 
    1302             :     // True if the async call was explicitly requested, e.g. via
    1303             :     // callFunctionWithAsyncStack.
    1304             :     bool asyncCallIsExplicit_;
    1305             : 
    1306             :     enum Kind { Interpreter, Jit, Wasm };
    1307             :     Kind kind_;
    1308             : 
    1309             :     inline Activation(JSContext* cx, Kind kind);
    1310             :     inline ~Activation();
    1311             : 
    1312             :   public:
    1313       31394 :     JSContext* cx() const {
    1314       31394 :         return cx_;
    1315             :     }
    1316       64994 :     JSCompartment* compartment() const {
    1317       64994 :         return compartment_;
    1318             :     }
    1319       14868 :     Activation* prev() const {
    1320       14868 :         return prev_;
    1321             :     }
    1322           0 :     Activation* prevProfiling() const { return prevProfiling_; }
    1323             :     inline Activation* mostRecentProfiling();
    1324             : 
    1325      179542 :     bool isInterpreter() const {
    1326      179542 :         return kind_ == Interpreter;
    1327             :     }
    1328      193164 :     bool isJit() const {
    1329      193164 :         return kind_ == Jit;
    1330             :     }
    1331       45924 :     bool isWasm() const {
    1332       45924 :         return kind_ == Wasm;
    1333             :     }
    1334             : 
    1335             :     inline bool isProfiling() const;
    1336             :     void registerProfiling();
    1337             :     void unregisterProfiling();
    1338             : 
    1339       90585 :     InterpreterActivation* asInterpreter() const {
    1340       90585 :         MOZ_ASSERT(isInterpreter());
    1341       90585 :         return (InterpreterActivation*)this;
    1342             :     }
    1343       65767 :     jit::JitActivation* asJit() const {
    1344       65767 :         MOZ_ASSERT(isJit());
    1345       65767 :         return (jit::JitActivation*)this;
    1346             :     }
    1347           0 :     WasmActivation* asWasm() const {
    1348           0 :         MOZ_ASSERT(isWasm());
    1349           0 :         return (WasmActivation*)this;
    1350             :     }
    1351             : 
    1352        2745 :     void hideScriptedCaller() {
    1353        2745 :         hideScriptedCallerCount_++;
    1354        2745 :     }
    1355        2742 :     void unhideScriptedCaller() {
    1356        2742 :         MOZ_ASSERT(hideScriptedCallerCount_ > 0);
    1357        2742 :         hideScriptedCallerCount_--;
    1358        2742 :     }
    1359         533 :     bool scriptedCallerIsHidden() const {
    1360         533 :         return hideScriptedCallerCount_ > 0;
    1361             :     }
    1362             : 
    1363           0 :     static size_t offsetOfPrev() {
    1364           0 :         return offsetof(Activation, prev_);
    1365             :     }
    1366           0 :     static size_t offsetOfPrevProfiling() {
    1367           0 :         return offsetof(Activation, prevProfiling_);
    1368             :     }
    1369             : 
    1370       12356 :     SavedFrame* asyncStack() {
    1371       12356 :         return asyncStack_;
    1372             :     }
    1373             : 
    1374         317 :     const char* asyncCause() const {
    1375         317 :         return asyncCause_;
    1376             :     }
    1377             : 
    1378          59 :     bool asyncCallIsExplicit() const {
    1379          59 :         return asyncCallIsExplicit_;
    1380             :     }
    1381             : 
    1382             :     inline LiveSavedFrameCache* getLiveSavedFrameCache(JSContext* cx);
    1383             : 
    1384             :   private:
    1385             :     Activation(const Activation& other) = delete;
    1386             :     void operator=(const Activation& other) = delete;
    1387             : };
    1388             : 
    1389             : // This variable holds a special opcode value which is greater than all normal
    1390             : // opcodes, and is chosen such that the bitwise or of this value with any
    1391             : // opcode is this value.
    1392             : static const jsbytecode EnableInterruptsPseudoOpcode = -1;
    1393             : 
    1394             : static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
    1395             :               "EnableInterruptsPseudoOpcode must be greater than any opcode");
    1396             : static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1),
    1397             :               "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
    1398             : 
    1399             : class InterpreterFrameIterator;
    1400             : class RunState;
    1401             : 
    1402             : class InterpreterActivation : public Activation
    1403             : {
    1404             :     friend class js::InterpreterFrameIterator;
    1405             : 
    1406             :     InterpreterRegs regs_;
    1407             :     InterpreterFrame* entryFrame_;
    1408             :     size_t opMask_; // For debugger interrupts, see js::Interpret.
    1409             : 
    1410             : #ifdef DEBUG
    1411             :     size_t oldFrameCount_;
    1412             : #endif
    1413             : 
    1414             :   public:
    1415             :     inline InterpreterActivation(RunState& state, JSContext* cx, InterpreterFrame* entryFrame);
    1416             :     inline ~InterpreterActivation();
    1417             : 
    1418             :     inline bool pushInlineFrame(const CallArgs& args, HandleScript script,
    1419             :                                 MaybeConstruct constructing);
    1420             :     inline void popInlineFrame(InterpreterFrame* frame);
    1421             : 
    1422             :     inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget,
    1423             :                                      HandleObject envChain);
    1424             : 
    1425       45982 :     InterpreterFrame* current() const {
    1426       45982 :         return regs_.fp();
    1427             :     }
    1428     3039906 :     InterpreterRegs& regs() {
    1429     3039906 :         return regs_;
    1430             :     }
    1431       43550 :     InterpreterFrame* entryFrame() const {
    1432       43550 :         return entryFrame_;
    1433             :     }
    1434      505969 :     size_t opMask() const {
    1435      505969 :         return opMask_;
    1436             :     }
    1437             : 
    1438       24141 :     bool isProfiling() const {
    1439       24141 :         return false;
    1440             :     }
    1441             : 
    1442             :     // If this js::Interpret frame is running |script|, enable interrupts.
    1443        3584 :     void enableInterruptsIfRunning(JSScript* script) {
    1444        3584 :         if (regs_.fp()->script() == script)
    1445         129 :             enableInterruptsUnconditionally();
    1446        3584 :     }
    1447         563 :     void enableInterruptsUnconditionally() {
    1448         563 :         opMask_ = EnableInterruptsPseudoOpcode;
    1449         563 :     }
    1450         473 :     void clearInterruptsMask() {
    1451         473 :         opMask_ = 0;
    1452         473 :     }
    1453             : };
    1454             : 
    1455             : // Iterates over a thread's activation list.
    1456             : class ActivationIterator
    1457             : {
    1458             :   protected:
    1459             :     Activation* activation_;
    1460             : 
    1461             :   private:
    1462             :     void settle();
    1463             : 
    1464             :   public:
    1465             :     explicit ActivationIterator(JSContext* cx);
    1466             : 
    1467             :     // ActivationIterator can be used to iterate over a different thread's
    1468             :     // activations, for use by the GC, invalidation, and other operations that
    1469             :     // don't have a user-visible effect on the target thread's JS behavior.
    1470             :     ActivationIterator(JSContext* cx, const CooperatingContext& target);
    1471             : 
    1472             :     ActivationIterator& operator++();
    1473             : 
    1474       61335 :     Activation* operator->() const {
    1475       61335 :         return activation_;
    1476             :     }
    1477       24624 :     Activation* activation() const {
    1478       24624 :         return activation_;
    1479             :     }
    1480       47012 :     bool done() const {
    1481       47012 :         return activation_ == nullptr;
    1482             :     }
    1483             : };
    1484             : 
    1485             : namespace jit {
    1486             : 
    1487             : class BailoutFrameInfo;
    1488             : 
    1489             : // A JitActivation is used for frames running in Baseline or Ion.
    1490             : class JitActivation : public Activation
    1491             : {
    1492             :     // If Baseline or Ion code is on the stack, and has called into C++, this
    1493             :     // will be aligned to an ExitFrame.
    1494             :     uint8_t* exitFP_;
    1495             : 
    1496             :     JitActivation* prevJitActivation_;
    1497             :     bool active_;
    1498             : 
    1499             :     // Rematerialized Ion frames which has info copied out of snapshots. Maps
    1500             :     // frame pointers (i.e. exitFP_) to a vector of rematerializations of all
    1501             :     // inline frames associated with that frame.
    1502             :     //
    1503             :     // This table is lazily initialized by calling getRematerializedFrame.
    1504             :     typedef GCVector<RematerializedFrame*> RematerializedFrameVector;
    1505             :     typedef HashMap<uint8_t*, RematerializedFrameVector> RematerializedFrameTable;
    1506             :     RematerializedFrameTable* rematerializedFrames_;
    1507             : 
    1508             :     // This vector is used to remember the outcome of the evaluation of recover
    1509             :     // instructions.
    1510             :     //
    1511             :     // RInstructionResults are appended into this vector when Snapshot values
    1512             :     // have to be read, or when the evaluation has to run before some mutating
    1513             :     // code.  Each RInstructionResults belongs to one frame which has to bailout
    1514             :     // as soon as we get back to it.
    1515             :     typedef Vector<RInstructionResults, 1> IonRecoveryMap;
    1516             :     IonRecoveryMap ionRecovery_;
    1517             : 
    1518             :     // If we are bailing out from Ion, then this field should be a non-null
    1519             :     // pointer which references the BailoutFrameInfo used to walk the inner
    1520             :     // frames. This field is used for all newly constructed JitFrameIterators to
    1521             :     // read the innermost frame information from this bailout data instead of
    1522             :     // reading it from the stack.
    1523             :     BailoutFrameInfo* bailoutData_;
    1524             : 
    1525             :     // When profiling is enabled, these fields will be updated to reflect the
    1526             :     // last pushed frame for this activation, and if that frame has been
    1527             :     // left for a call, the native code site of the call.
    1528             :     mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingFrame_;
    1529             :     mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingCallSite_;
    1530             :     static_assert(sizeof(mozilla::Atomic<void*, mozilla::Relaxed>) == sizeof(void*),
    1531             :                   "Atomic should have same memory format as underlying type.");
    1532             : 
    1533             :     void clearRematerializedFrames();
    1534             : 
    1535             : #ifdef CHECK_OSIPOINT_REGISTERS
    1536             :   protected:
    1537             :     // Used to verify that live registers don't change between a VM call and
    1538             :     // the OsiPoint that follows it. Protected to silence Clang warning.
    1539             :     uint32_t checkRegs_;
    1540             :     RegisterDump regs_;
    1541             : #endif
    1542             : 
    1543             :   public:
    1544             :     explicit JitActivation(JSContext* cx, bool active = true);
    1545             :     ~JitActivation();
    1546             : 
    1547       17242 :     bool isActive() const {
    1548       17242 :         return active_;
    1549             :     }
    1550             :     void setActive(JSContext* cx, bool active = true);
    1551             : 
    1552       34149 :     bool isProfiling() const {
    1553             :         // All JitActivations can be profiled.
    1554       34149 :         return true;
    1555             :     }
    1556             : 
    1557           0 :     JitActivation* prevJitActivation() const {
    1558           0 :         return prevJitActivation_;
    1559             :     }
    1560           0 :     static size_t offsetOfPrevJitActivation() {
    1561           0 :         return offsetof(JitActivation, prevJitActivation_);
    1562             :     }
    1563             : 
    1564          78 :     void setExitFP(uint8_t* fp) {
    1565          78 :         exitFP_ = fp;
    1566          78 :     }
    1567        9713 :     uint8_t* exitFP() const {
    1568        9713 :         return exitFP_;
    1569             :     }
    1570        1138 :     static size_t offsetOfExitFP() {
    1571        1138 :         return offsetof(JitActivation, exitFP_);
    1572             :     }
    1573             : 
    1574           0 :     static size_t offsetOfActiveUint8() {
    1575             :         MOZ_ASSERT(sizeof(bool) == 1);
    1576           0 :         return offsetof(JitActivation, active_);
    1577             :     }
    1578             : 
    1579             : #ifdef CHECK_OSIPOINT_REGISTERS
    1580           0 :     void setCheckRegs(bool check) {
    1581           0 :         checkRegs_ = check;
    1582           0 :     }
    1583           0 :     static size_t offsetOfCheckRegs() {
    1584           0 :         return offsetof(JitActivation, checkRegs_);
    1585             :     }
    1586           0 :     static size_t offsetOfRegs() {
    1587           0 :         return offsetof(JitActivation, regs_);
    1588             :     }
    1589             : #endif
    1590             : 
    1591             :     // Look up a rematerialized frame keyed by the fp, rematerializing the
    1592             :     // frame if one doesn't already exist. A frame can only be rematerialized
    1593             :     // if an IonFrameIterator pointing to the nearest uninlined frame can be
    1594             :     // provided, as values need to be read out of snapshots.
    1595             :     //
    1596             :     // The inlineDepth must be within bounds of the frame pointed to by iter.
    1597             :     RematerializedFrame* getRematerializedFrame(JSContext* cx, const JitFrameIterator& iter,
    1598             :                                                 size_t inlineDepth = 0);
    1599             : 
    1600             :     // Look up a rematerialized frame by the fp. If inlineDepth is out of
    1601             :     // bounds of what has been rematerialized, nullptr is returned.
    1602             :     RematerializedFrame* lookupRematerializedFrame(uint8_t* top, size_t inlineDepth = 0);
    1603             : 
    1604             :     // Remove all rematerialized frames associated with the fp top from the
    1605             :     // Debugger.
    1606             :     void removeRematerializedFramesFromDebugger(JSContext* cx, uint8_t* top);
    1607             : 
    1608           0 :     bool hasRematerializedFrame(uint8_t* top, size_t inlineDepth = 0) {
    1609           0 :         return !!lookupRematerializedFrame(top, inlineDepth);
    1610             :     }
    1611             : 
    1612             :     // Remove a previous rematerialization by fp.
    1613             :     void removeRematerializedFrame(uint8_t* top);
    1614             : 
    1615             :     void traceRematerializedFrames(JSTracer* trc);
    1616             : 
    1617             : 
    1618             :     // Register the results of on Ion frame recovery.
    1619             :     bool registerIonFrameRecovery(RInstructionResults&& results);
    1620             : 
    1621             :     // Return the pointer to the Ion frame recovery, if it is already registered.
    1622             :     RInstructionResults* maybeIonFrameRecovery(JitFrameLayout* fp);
    1623             : 
    1624             :     // If an Ion frame recovery exists for the |fp| frame exists, then remove it
    1625             :     // from the activation.
    1626             :     void removeIonFrameRecovery(JitFrameLayout* fp);
    1627             : 
    1628             :     void traceIonRecovery(JSTracer* trc);
    1629             : 
    1630             :     // Return the bailout information if it is registered.
    1631        9401 :     const BailoutFrameInfo* bailoutData() const { return bailoutData_; }
    1632             : 
    1633             :     // Register the bailout data when it is constructed.
    1634             :     void setBailoutData(BailoutFrameInfo* bailoutData);
    1635             : 
    1636             :     // Unregister the bailout data when the frame is reconstructed.
    1637             :     void cleanBailoutData();
    1638             : 
    1639         690 :     static size_t offsetOfLastProfilingFrame() {
    1640         690 :         return offsetof(JitActivation, lastProfilingFrame_);
    1641             :     }
    1642           0 :     void* lastProfilingFrame() {
    1643           0 :         return lastProfilingFrame_;
    1644             :     }
    1645           0 :     void setLastProfilingFrame(void* ptr) {
    1646           0 :         lastProfilingFrame_ = ptr;
    1647           0 :     }
    1648             : 
    1649         636 :     static size_t offsetOfLastProfilingCallSite() {
    1650         636 :         return offsetof(JitActivation, lastProfilingCallSite_);
    1651             :     }
    1652           0 :     void* lastProfilingCallSite() {
    1653           0 :         return lastProfilingCallSite_;
    1654             :     }
    1655           0 :     void setLastProfilingCallSite(void* ptr) {
    1656           0 :         lastProfilingCallSite_ = ptr;
    1657           0 :     }
    1658             : };
    1659             : 
    1660             : // A filtering of the ActivationIterator to only stop at JitActivations.
    1661             : class JitActivationIterator : public ActivationIterator
    1662             : {
    1663        4334 :     void settle() {
    1664        4498 :         while (!done() && !activation_->isJit())
    1665         164 :             ActivationIterator::operator++();
    1666        4170 :     }
    1667             : 
    1668             :   public:
    1669        4073 :     explicit JitActivationIterator(JSContext* cx)
    1670        4073 :       : ActivationIterator(cx)
    1671             :     {
    1672        4073 :         settle();
    1673        4073 :     }
    1674             : 
    1675          49 :     JitActivationIterator(JSContext* cx, const CooperatingContext& target)
    1676          49 :       : ActivationIterator(cx, target)
    1677             :     {
    1678          49 :         settle();
    1679          49 :     }
    1680             : 
    1681          48 :     JitActivationIterator& operator++() {
    1682          48 :         ActivationIterator::operator++();
    1683          48 :         settle();
    1684          48 :         return *this;
    1685             :     }
    1686             : 
    1687           0 :     uint8_t* exitFP() const {
    1688           0 :         MOZ_ASSERT(activation_->isJit());
    1689           0 :         return activation_->asJit()->exitFP();
    1690             :     }
    1691             : };
    1692             : 
    1693             : } // namespace jit
    1694             : 
    1695             : // Iterates over the frames of a single InterpreterActivation.
    1696             : class InterpreterFrameIterator
    1697             : {
    1698             :     InterpreterActivation* activation_;
    1699             :     InterpreterFrame* fp_;
    1700             :     jsbytecode* pc_;
    1701             :     Value* sp_;
    1702             : 
    1703             :   public:
    1704       11018 :     explicit InterpreterFrameIterator(InterpreterActivation* activation)
    1705       11018 :       : activation_(activation),
    1706             :         fp_(nullptr),
    1707             :         pc_(nullptr),
    1708       11018 :         sp_(nullptr)
    1709             :     {
    1710       11018 :         if (activation) {
    1711        7832 :             fp_ = activation->current();
    1712        7832 :             pc_ = activation->regs().pc;
    1713        7832 :             sp_ = activation->regs().sp;
    1714             :         }
    1715       11018 :     }
    1716             : 
    1717       87330 :     InterpreterFrame* frame() const {
    1718       87330 :         MOZ_ASSERT(!done());
    1719       87330 :         return fp_;
    1720             :     }
    1721        8027 :     jsbytecode* pc() const {
    1722        8027 :         MOZ_ASSERT(!done());
    1723        8027 :         return pc_;
    1724             :     }
    1725         109 :     Value* sp() const {
    1726         109 :         MOZ_ASSERT(!done());
    1727         109 :         return sp_;
    1728             :     }
    1729             : 
    1730             :     InterpreterFrameIterator& operator++();
    1731             : 
    1732      112712 :     bool done() const {
    1733      112712 :         return fp_ == nullptr;
    1734             :     }
    1735             : };
    1736             : 
    1737             : // An eventual goal is to remove WasmActivation and to run asm code in a
    1738             : // JitActivation interleaved with Ion/Baseline jit code. This would allow
    1739             : // efficient calls back and forth but requires that we can walk the stack for
    1740             : // all kinds of jit code.
    1741             : class WasmActivation : public Activation
    1742             : {
    1743             :     wasm::Frame* exitFP_;
    1744             : 
    1745             :   public:
    1746             :     explicit WasmActivation(JSContext* cx);
    1747             :     ~WasmActivation();
    1748             : 
    1749           0 :     bool isProfiling() const {
    1750           0 :         return true;
    1751             :     }
    1752             : 
    1753             :     // Returns null or the final wasm::Frame* when wasm exited this
    1754             :     // WasmActivation.
    1755           0 :     wasm::Frame* exitFP() const { return exitFP_; }
    1756             : 
    1757             :     // Written by JIT code:
    1758           0 :     static unsigned offsetOfExitFP() { return offsetof(WasmActivation, exitFP_); }
    1759             : 
    1760             :     // Interrupts are started from the interrupt signal handler (or the ARM
    1761             :     // simulator) and cleared by WasmHandleExecutionInterrupt or WasmHandleThrow
    1762             :     // when the interrupt is handled.
    1763             :     void startInterrupt(const JS::ProfilingFrameIterator::RegisterState& state);
    1764             :     void finishInterrupt();
    1765             :     bool interrupted() const;
    1766             :     void* unwindPC() const;
    1767             :     void* resumePC() const;
    1768             : 
    1769             :     // Used by wasm::FrameIterator during stack unwinding.
    1770             :     void unwindExitFP(wasm::Frame* exitFP);
    1771             : };
    1772             : 
    1773             : // A FrameIter walks over a context's stack of JS script activations,
    1774             : // abstracting over whether the JS scripts were running in the interpreter or
    1775             : // different modes of compiled code.
    1776             : //
    1777             : // FrameIter is parameterized by what it includes in the stack iteration:
    1778             : //  - When provided, the optional JSPrincipal argument will cause FrameIter to
    1779             : //    only show frames in globals whose JSPrincipals are subsumed (via
    1780             : //    JSSecurityCallbacks::subsume) by the given JSPrincipal.
    1781             : //
    1782             : // Additionally, there are derived FrameIter types that automatically skip
    1783             : // certain frames:
    1784             : //  - ScriptFrameIter only shows frames that have an associated JSScript
    1785             : //    (currently everything other than wasm stack frames). When !hasScript(),
    1786             : //    clients must stick to the portion of the
    1787             : //    interface marked below.
    1788             : //  - NonBuiltinScriptFrameIter additionally filters out builtin (self-hosted)
    1789             : //    scripts.
    1790        3186 : class FrameIter
    1791             : {
    1792             :   public:
    1793             :     enum DebuggerEvalOption { FOLLOW_DEBUGGER_EVAL_PREV_LINK,
    1794             :                               IGNORE_DEBUGGER_EVAL_PREV_LINK };
    1795             :     enum State { DONE, INTERP, JIT, WASM };
    1796             : 
    1797             :     // Unlike ScriptFrameIter itself, ScriptFrameIter::Data can be allocated on
    1798             :     // the heap, so this structure should not contain any GC things.
    1799             :     struct Data
    1800             :     {
    1801             :         JSContext * cx_;
    1802             :         DebuggerEvalOption  debuggerEvalOption_;
    1803             :         JSPrincipals *      principals_;
    1804             : 
    1805             :         State               state_;
    1806             : 
    1807             :         jsbytecode *        pc_;
    1808             : 
    1809             :         InterpreterFrameIterator interpFrames_;
    1810             :         ActivationIterator activations_;
    1811             : 
    1812             :         jit::JitFrameIterator jitFrames_;
    1813             :         unsigned ionInlineFrameNo_;
    1814             :         wasm::FrameIterator wasmFrames_;
    1815             : 
    1816             :         Data(JSContext* cx, DebuggerEvalOption debuggerEvalOption, JSPrincipals* principals);
    1817             :         Data(const Data& other);
    1818             :     };
    1819             : 
    1820             :     explicit FrameIter(JSContext* cx,
    1821             :                        DebuggerEvalOption = FOLLOW_DEBUGGER_EVAL_PREV_LINK);
    1822             :     FrameIter(JSContext* cx, DebuggerEvalOption, JSPrincipals*);
    1823             :     FrameIter(const FrameIter& iter);
    1824             :     MOZ_IMPLICIT FrameIter(const Data& data);
    1825             :     MOZ_IMPLICIT FrameIter(AbstractFramePtr frame);
    1826             : 
    1827      125224 :     bool done() const { return data_.state_ == DONE; }
    1828             : 
    1829             :     // -------------------------------------------------------
    1830             :     // The following functions can only be called when !done()
    1831             :     // -------------------------------------------------------
    1832             : 
    1833             :     FrameIter& operator++();
    1834             : 
    1835             :     JSCompartment* compartment() const;
    1836       13455 :     Activation* activation() const { return data_.activations_.activation(); }
    1837             : 
    1838           0 :     bool isInterp() const { MOZ_ASSERT(!done()); return data_.state_ == INTERP;  }
    1839        1682 :     bool isJit() const { MOZ_ASSERT(!done()); return data_.state_ == JIT; }
    1840       30924 :     bool isWasm() const { MOZ_ASSERT(!done()); return data_.state_ == WASM; }
    1841             :     inline bool isIon() const;
    1842             :     inline bool isBaseline() const;
    1843             :     inline bool isPhysicalIonFrame() const;
    1844             : 
    1845             :     bool isEvalFrame() const;
    1846             :     bool isFunctionFrame() const;
    1847           0 :     bool hasArgs() const { return isFunctionFrame(); }
    1848             : 
    1849             :     // These two methods may not be called with asm frames.
    1850             :     inline bool hasCachedSavedFrame() const;
    1851             :     inline void setHasCachedSavedFrame();
    1852             : 
    1853             :     ScriptSource* scriptSource() const;
    1854             :     const char* filename() const;
    1855             :     const char16_t* displayURL() const;
    1856             :     unsigned computeLine(uint32_t* column = nullptr) const;
    1857             :     JSAtom* functionDisplayAtom() const;
    1858             :     bool mutedErrors() const;
    1859             : 
    1860       12737 :     bool hasScript() const { return !isWasm(); }
    1861             : 
    1862             :     // -----------------------------------------------------------
    1863             :     //  The following functions can only be called when isWasm()
    1864             :     // -----------------------------------------------------------
    1865             : 
    1866             :     inline bool wasmDebugEnabled() const;
    1867             :     inline wasm::Instance* wasmInstance() const;
    1868             :     inline unsigned wasmBytecodeOffset() const;
    1869             :     void wasmUpdateBytecodeOffset();
    1870             : 
    1871             :     // -----------------------------------------------------------
    1872             :     // The following functions can only be called when hasScript()
    1873             :     // -----------------------------------------------------------
    1874             : 
    1875             :     inline JSScript* script() const;
    1876             : 
    1877             :     bool        isConstructing() const;
    1878       26473 :     jsbytecode* pc() const { MOZ_ASSERT(!done()); return data_.pc_; }
    1879             :     void        updatePcQuadratic();
    1880             : 
    1881             :     // The function |calleeTemplate()| returns either the function from which
    1882             :     // the current |callee| was cloned or the |callee| if it can be read. As
    1883             :     // long as we do not have to investigate the environment chain or build a
    1884             :     // new frame, we should prefer to use |calleeTemplate| instead of
    1885             :     // |callee|, as requesting the |callee| might cause the invalidation of
    1886             :     // the frame. (see js::Lambda)
    1887             :     JSFunction* calleeTemplate() const;
    1888             :     JSFunction* callee(JSContext* cx) const;
    1889             : 
    1890           0 :     JSFunction* maybeCallee(JSContext* cx) const {
    1891           0 :         return isFunctionFrame() ? callee(cx) : nullptr;
    1892             :     }
    1893             : 
    1894             :     bool        matchCallee(JSContext* cx, HandleFunction fun) const;
    1895             : 
    1896             :     unsigned    numActualArgs() const;
    1897             :     unsigned    numFormalArgs() const;
    1898             :     Value       unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING) const;
    1899             :     template <class Op> inline void unaliasedForEachActual(JSContext* cx, Op op);
    1900             : 
    1901             :     JSObject*  environmentChain(JSContext* cx) const;
    1902             :     CallObject& callObj(JSContext* cx) const;
    1903             : 
    1904             :     bool        hasArgsObj() const;
    1905             :     ArgumentsObject& argsObj() const;
    1906             : 
    1907             :     // Get the original |this| value passed to this function. May not be the
    1908             :     // actual this-binding (for instance, derived class constructors will
    1909             :     // change their this-value later and non-strict functions will box
    1910             :     // primitives).
    1911             :     Value       thisArgument(JSContext* cx) const;
    1912             : 
    1913             :     Value       newTarget() const;
    1914             : 
    1915             :     Value       returnValue() const;
    1916             :     void        setReturnValue(const Value& v);
    1917             : 
    1918             :     // These are only valid for the top frame.
    1919             :     size_t      numFrameSlots() const;
    1920             :     Value       frameSlotValue(size_t index) const;
    1921             : 
    1922             :     // Ensures that we have rematerialized the top frame and its associated
    1923             :     // inline frames. Can only be called when isIon().
    1924             :     bool ensureHasRematerializedFrame(JSContext* cx);
    1925             : 
    1926             :     // True when isInterp() or isBaseline(). True when isIon() if it
    1927             :     // has a rematerialized frame. False otherwise false otherwise.
    1928             :     bool hasUsableAbstractFramePtr() const;
    1929             : 
    1930             :     // -----------------------------------------------------------
    1931             :     // The following functions can only be called when isInterp(),
    1932             :     // isBaseline(), isWasm() or isIon(). Further, abstractFramePtr() can
    1933             :     // only be called when hasUsableAbstractFramePtr().
    1934             :     // -----------------------------------------------------------
    1935             : 
    1936             :     AbstractFramePtr abstractFramePtr() const;
    1937             :     AbstractFramePtr copyDataAsAbstractFramePtr() const;
    1938             :     Data* copyData() const;
    1939             : 
    1940             :     // This can only be called when isInterp():
    1941             :     inline InterpreterFrame* interpFrame() const;
    1942             : 
    1943             :     // This can only be called when isPhysicalIonFrame():
    1944             :     inline jit::CommonFrameLayout* physicalIonFrame() const;
    1945             : 
    1946             :     // This is used to provide a raw interface for debugging.
    1947             :     void* rawFramePtr() const;
    1948             : 
    1949             :   private:
    1950             :     Data data_;
    1951             :     jit::InlineFrameIterator ionInlineFrames_;
    1952             : 
    1953             :     void popActivation();
    1954             :     void popInterpreterFrame();
    1955             :     void nextJitFrame();
    1956             :     void popJitFrame();
    1957             :     void popWasmFrame();
    1958             :     void settleOnActivation();
    1959             : };
    1960             : 
    1961         120 : class ScriptFrameIter : public FrameIter
    1962             : {
    1963         120 :     void settle() {
    1964         120 :         while (!done() && !hasScript())
    1965           0 :             FrameIter::operator++();
    1966         120 :     }
    1967             : 
    1968             :   public:
    1969         120 :     explicit ScriptFrameIter(JSContext* cx,
    1970             :                              DebuggerEvalOption debuggerEvalOption = FOLLOW_DEBUGGER_EVAL_PREV_LINK)
    1971         120 :       : FrameIter(cx, debuggerEvalOption)
    1972             :     {
    1973         120 :         settle();
    1974         120 :     }
    1975             : 
    1976             :     ScriptFrameIter(JSContext* cx,
    1977             :                     DebuggerEvalOption debuggerEvalOption,
    1978             :                     JSPrincipals* prin)
    1979             :       : FrameIter(cx, debuggerEvalOption, prin)
    1980             :     {
    1981             :         settle();
    1982             :     }
    1983             : 
    1984             :     ScriptFrameIter(const ScriptFrameIter& iter) : FrameIter(iter) { settle(); }
    1985             :     explicit ScriptFrameIter(const FrameIter::Data& data) : FrameIter(data) { settle(); }
    1986             :     explicit ScriptFrameIter(AbstractFramePtr frame) : FrameIter(frame) { settle(); }
    1987             : 
    1988           0 :     ScriptFrameIter& operator++() {
    1989           0 :         FrameIter::operator++();
    1990           0 :         settle();
    1991           0 :         return *this;
    1992             :     }
    1993             : };
    1994             : 
    1995             : #ifdef DEBUG
    1996             : bool SelfHostedFramesVisible();
    1997             : #else
    1998             : static inline bool
    1999             : SelfHostedFramesVisible()
    2000             : {
    2001             :     return false;
    2002             : }
    2003             : #endif
    2004             : 
    2005             : /* A filtering of the FrameIter to only stop at non-self-hosted scripts. */
    2006         101 : class NonBuiltinFrameIter : public FrameIter
    2007             : {
    2008             :     void settle();
    2009             : 
    2010             :   public:
    2011          47 :     explicit NonBuiltinFrameIter(JSContext* cx,
    2012             :                                  FrameIter::DebuggerEvalOption debuggerEvalOption =
    2013             :                                  FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK)
    2014          47 :       : FrameIter(cx, debuggerEvalOption)
    2015             :     {
    2016          47 :         settle();
    2017          47 :     }
    2018             : 
    2019           0 :     NonBuiltinFrameIter(JSContext* cx,
    2020             :                         FrameIter::DebuggerEvalOption debuggerEvalOption,
    2021             :                         JSPrincipals* principals)
    2022           0 :       : FrameIter(cx, debuggerEvalOption, principals)
    2023             :     {
    2024           0 :         settle();
    2025           0 :     }
    2026             : 
    2027          54 :     NonBuiltinFrameIter(JSContext* cx, JSPrincipals* principals)
    2028          54 :       : FrameIter(cx, FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK, principals)
    2029             :     {
    2030          54 :         settle();
    2031          54 :     }
    2032             : 
    2033             :     explicit NonBuiltinFrameIter(const FrameIter::Data& data)
    2034             :       : FrameIter(data)
    2035             :     {}
    2036             : 
    2037             :     NonBuiltinFrameIter& operator++() {
    2038             :         FrameIter::operator++();
    2039             :         settle();
    2040             :         return *this;
    2041             :     }
    2042             : };
    2043             : 
    2044             : /* A filtering of the ScriptFrameIter to only stop at non-self-hosted scripts. */
    2045           0 : class NonBuiltinScriptFrameIter : public ScriptFrameIter
    2046             : {
    2047             :     void settle();
    2048             : 
    2049             :   public:
    2050           0 :     explicit NonBuiltinScriptFrameIter(JSContext* cx,
    2051             :                                        ScriptFrameIter::DebuggerEvalOption debuggerEvalOption =
    2052             :                                        ScriptFrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK)
    2053           0 :       : ScriptFrameIter(cx, debuggerEvalOption)
    2054             :     {
    2055           0 :         settle();
    2056           0 :     }
    2057             : 
    2058             :     NonBuiltinScriptFrameIter(JSContext* cx,
    2059             :                               ScriptFrameIter::DebuggerEvalOption debuggerEvalOption,
    2060             :                               JSPrincipals* principals)
    2061             :       : ScriptFrameIter(cx, debuggerEvalOption, principals)
    2062             :     {
    2063             :         settle();
    2064             :     }
    2065             : 
    2066             :     explicit NonBuiltinScriptFrameIter(const ScriptFrameIter::Data& data)
    2067             :       : ScriptFrameIter(data)
    2068             :     {}
    2069             : 
    2070           0 :     NonBuiltinScriptFrameIter& operator++() {
    2071           0 :         ScriptFrameIter::operator++();
    2072           0 :         settle();
    2073           0 :         return *this;
    2074             :     }
    2075             : };
    2076             : 
    2077             : /*
    2078             :  * Blindly iterate over all frames in the current thread's stack. These frames
    2079             :  * can be from different contexts and compartments, so beware.
    2080             :  */
    2081           0 : class AllFramesIter : public FrameIter
    2082             : {
    2083             :   public:
    2084           0 :     explicit AllFramesIter(JSContext* cx)
    2085           0 :       : FrameIter(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK)
    2086           0 :     {}
    2087             : };
    2088             : 
    2089             : /* Iterates over all script frame in the current thread's stack.
    2090             :  * See also AllFramesIter and ScriptFrameIter.
    2091             :  */
    2092           0 : class AllScriptFramesIter : public ScriptFrameIter
    2093             : {
    2094             :   public:
    2095           0 :     explicit AllScriptFramesIter(JSContext* cx)
    2096           0 :       : ScriptFrameIter(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK)
    2097           0 :     {}
    2098             : };
    2099             : 
    2100             : /* Popular inline definitions. */
    2101             : 
    2102             : inline JSScript*
    2103       15103 : FrameIter::script() const
    2104             : {
    2105       15103 :     MOZ_ASSERT(!done());
    2106       15103 :     if (data_.state_ == INTERP)
    2107        8331 :         return interpFrame()->script();
    2108        6772 :     MOZ_ASSERT(data_.state_ == JIT);
    2109        6772 :     if (data_.jitFrames_.isIonJS())
    2110        2520 :         return ionInlineFrames_.script();
    2111        4252 :     return data_.jitFrames_.script();
    2112             : }
    2113             : 
    2114             : inline bool
    2115           0 : FrameIter::wasmDebugEnabled() const
    2116             : {
    2117           0 :     MOZ_ASSERT(!done());
    2118           0 :     MOZ_ASSERT(data_.state_ == WASM);
    2119           0 :     return data_.wasmFrames_.debugEnabled();
    2120             : }
    2121             : 
    2122             : inline wasm::Instance*
    2123           0 : FrameIter::wasmInstance() const
    2124             : {
    2125           0 :     MOZ_ASSERT(!done());
    2126           0 :     MOZ_ASSERT(data_.state_ == WASM && wasmDebugEnabled());
    2127           0 :     return data_.wasmFrames_.instance();
    2128             : }
    2129             : 
    2130             : inline unsigned
    2131           0 : FrameIter::wasmBytecodeOffset() const
    2132             : {
    2133           0 :     MOZ_ASSERT(!done());
    2134           0 :     MOZ_ASSERT(data_.state_ == WASM);
    2135           0 :     return data_.wasmFrames_.lineOrBytecode();
    2136             : }
    2137             : 
    2138             : inline bool
    2139           2 : FrameIter::isIon() const
    2140             : {
    2141           2 :     return isJit() && data_.jitFrames_.isIonJS();
    2142             : }
    2143             : 
    2144             : inline bool
    2145           0 : FrameIter::isBaseline() const
    2146             : {
    2147           0 :     return isJit() && data_.jitFrames_.isBaselineJS();
    2148             : }
    2149             : 
    2150             : inline InterpreterFrame*
    2151       72840 : FrameIter::interpFrame() const
    2152             : {
    2153       72840 :     MOZ_ASSERT(data_.state_ == INTERP);
    2154       72840 :     return data_.interpFrames_.frame();
    2155             : }
    2156             : 
    2157             : inline bool
    2158        1680 : FrameIter::isPhysicalIonFrame() const
    2159             : {
    2160        3360 :     return isJit() &&
    2161        3360 :            data_.jitFrames_.isIonScripted() &&
    2162        3360 :            ionInlineFrames_.frameNo() == 0;
    2163             : }
    2164             : 
    2165             : inline jit::CommonFrameLayout*
    2166         840 : FrameIter::physicalIonFrame() const
    2167             : {
    2168         840 :     MOZ_ASSERT(isPhysicalIonFrame());
    2169         840 :     return data_.jitFrames_.current();
    2170             : }
    2171             : 
    2172             : }  /* namespace js */
    2173             : #endif /* vm_Stack_h */

Generated by: LCOV version 1.13