tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Stack.h (33654B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/HashFunctions.h"
     11 #include "mozilla/MemoryReporting.h"
     12 
     13 #include <algorithm>
     14 #include <type_traits>
     15 
     16 #include "js/ErrorReport.h"
     17 #include "js/friend/ErrorMessages.h"  // js::GetErrorMessage, JSMSG_*
     18 #include "js/RootingAPI.h"
     19 #include "js/TypeDecls.h"
     20 #include "js/ValueArray.h"
     21 #include "vm/ArgumentsObject.h"
     22 #include "vm/JSFunction.h"
     23 #include "vm/JSScript.h"
     24 #include "wasm/WasmDebugFrame.h"  // js::wasm::DebugFrame
     25 
     26 namespace js {
     27 
     28 class InterpreterRegs;
     29 class CallObject;
     30 class FrameIter;
     31 class ClassBodyScope;
     32 class EnvironmentObject;
     33 class BlockLexicalEnvironmentObject;
     34 class ExtensibleLexicalEnvironmentObject;
     35 class GeckoProfilerRuntime;
     36 class InterpreterFrame;
     37 class EnvironmentIter;
     38 class EnvironmentCoordinate;
     39 
     40 namespace jit {
     41 class CommonFrameLayout;
     42 }
     43 namespace wasm {
     44 class Instance;
     45 }  // namespace wasm
     46 
     47 // [SMDOC] VM stack layout
     48 //
     49 // A JSRuntime's stack consists of a linked list of activations. Every
     50 // activation contains a number of scripted frames that are either running in
     51 // the interpreter (InterpreterActivation) or JIT code (JitActivation). The
     52 // frames inside a single activation are contiguous: whenever C++ calls back
     53 // into JS, a new activation is pushed.
     54 //
     55 // Every activation is tied to a single JSContext and JS::Compartment. This
     56 // means we can reconstruct a given context's stack by skipping activations
     57 // belonging to other contexts. This happens whenever an embedding enters the JS
     58 // engine on cx1 and then, from a native called by the JS engine, reenters the
     59 // VM on cx2.
     60 
     61 // Interpreter frames (InterpreterFrame)
     62 //
     63 // Each interpreter script activation (global or function code) is given a
     64 // fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
     65 // information about the activation and links to the previous frame.
     66 //
     67 // The values after an InterpreterFrame in memory are its locals followed by its
     68 // expression stack. InterpreterFrame::argv_ points to the frame's arguments.
     69 // Missing formal arguments are padded with |undefined|, so the number of
     70 // arguments is always >= the number of formals.
     71 //
     72 // The top of an activation's current frame's expression stack is pointed to by
     73 // the activation's "current regs", which contains the stack pointer 'sp'. In
     74 // the interpreter, sp is adjusted as individual values are pushed and popped
     75 // from the stack and the InterpreterRegs struct (pointed to by the
     76 // InterpreterActivation) is a local var of js::Interpret.
     77 
     78 enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
     79 
     80 }  // namespace js
     81 
     82 /*****************************************************************************/
     83 
     84 namespace js {
     85 
     86 namespace jit {
     87 class BaselineFrame;
     88 class RematerializedFrame;
     89 }  // namespace jit
     90 
     91 /**
     92 * Pointer to a live JS or WASM stack frame.
     93 */
     94 class AbstractFramePtr {
     95  friend class FrameIter;
     96 
     97  uintptr_t ptr_;
     98 
     99  enum {
    100    Tag_InterpreterFrame = 0x0,
    101    Tag_BaselineFrame = 0x1,
    102    Tag_RematerializedFrame = 0x2,
    103    Tag_WasmDebugFrame = 0x3,
    104    TagMask = 0x3
    105  };
    106 
    107 public:
    108  AbstractFramePtr() : ptr_(0) {}
    109 
    110  MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp)
    111      : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0) {
    112    MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
    113  }
    114 
    115  MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp)
    116      : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0) {
    117    MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
    118  }
    119 
    120  MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp)
    121      : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0) {
    122    MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
    123  }
    124 
    125  MOZ_IMPLICIT AbstractFramePtr(wasm::DebugFrame* fp)
    126      : ptr_(fp ? uintptr_t(fp) | Tag_WasmDebugFrame : 0) {
    127    static_assert(wasm::DebugFrame::Alignment >= TagMask, "aligned");
    128    MOZ_ASSERT_IF(fp, asWasmDebugFrame() == fp);
    129  }
    130 
    131  bool isInterpreterFrame() const {
    132    return (ptr_ & TagMask) == Tag_InterpreterFrame;
    133  }
    134  InterpreterFrame* asInterpreterFrame() const {
    135    MOZ_ASSERT(isInterpreterFrame());
    136    InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask);
    137    MOZ_ASSERT(res);
    138    return res;
    139  }
    140  bool isBaselineFrame() const { return (ptr_ & TagMask) == Tag_BaselineFrame; }
    141  jit::BaselineFrame* asBaselineFrame() const {
    142    MOZ_ASSERT(isBaselineFrame());
    143    jit::BaselineFrame* res = (jit::BaselineFrame*)(ptr_ & ~TagMask);
    144    MOZ_ASSERT(res);
    145    return res;
    146  }
    147  bool isRematerializedFrame() const {
    148    return (ptr_ & TagMask) == Tag_RematerializedFrame;
    149  }
    150  jit::RematerializedFrame* asRematerializedFrame() const {
    151    MOZ_ASSERT(isRematerializedFrame());
    152    jit::RematerializedFrame* res =
    153        (jit::RematerializedFrame*)(ptr_ & ~TagMask);
    154    MOZ_ASSERT(res);
    155    return res;
    156  }
    157  bool isWasmDebugFrame() const {
    158    return (ptr_ & TagMask) == Tag_WasmDebugFrame;
    159  }
    160  wasm::DebugFrame* asWasmDebugFrame() const {
    161    MOZ_ASSERT(isWasmDebugFrame());
    162    wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask);
    163    MOZ_ASSERT(res);
    164    return res;
    165  }
    166 
    167  void* raw() const { return reinterpret_cast<void*>(ptr_); }
    168 
    169  bool operator==(const AbstractFramePtr& other) const {
    170    return ptr_ == other.ptr_;
    171  }
    172  bool operator!=(const AbstractFramePtr& other) const {
    173    return ptr_ != other.ptr_;
    174  }
    175 
    176  explicit operator bool() const { return !!ptr_; }
    177 
    178  inline JSObject* environmentChain() const;
    179  inline CallObject& callObj() const;
    180  inline bool initFunctionEnvironmentObjects(JSContext* cx);
    181  inline bool pushVarEnvironment(JSContext* cx, Handle<Scope*> scope);
    182  template <typename SpecificEnvironment>
    183  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
    184  template <typename SpecificEnvironment>
    185  inline void popOffEnvironmentChain();
    186 
    187  inline JS::Realm* realm() const;
    188 
    189  inline bool hasInitialEnvironment() const;
    190  inline bool isGlobalFrame() const;
    191  inline bool isModuleFrame() const;
    192  inline bool isEvalFrame() const;
    193  inline bool isDebuggerEvalFrame() const;
    194 
    195  inline bool hasScript() const;
    196  inline JSScript* script() const;
    197  inline wasm::Instance* wasmInstance() const;
    198  inline GlobalObject* global() const;
    199  inline bool hasGlobal(const GlobalObject* global) const;
    200  inline JSFunction* callee() const;
    201  inline Value calleev() const;
    202  inline Value& thisArgument() const;
    203 
    204  inline bool isConstructing() const;
    205 
    206  inline bool debuggerNeedsCheckPrimitiveReturn() const;
    207 
    208  inline bool isFunctionFrame() const;
    209  inline bool isGeneratorFrame() const;
    210 
    211  inline bool saveGeneratorSlots(JSContext* cx, unsigned nslots,
    212                                 ArrayObject* dest) const;
    213 
    214  inline bool hasCachedSavedFrame() const;
    215 
    216  inline unsigned numActualArgs() const;
    217  inline unsigned numFormalArgs() const;
    218 
    219  inline Value* argv() const;
    220 
    221  inline bool hasArgs() const;
    222  inline bool hasArgsObj() const;
    223  inline ArgumentsObject& argsObj() const;
    224  inline void initArgsObj(ArgumentsObject& argsobj) const;
    225 
    226  inline Value& unaliasedLocal(uint32_t i);
    227  inline Value& unaliasedFormal(
    228      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
    229  inline Value& unaliasedActual(
    230      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
    231  template <class Op>
    232  inline void unaliasedForEachActual(JSContext* cx, Op op);
    233 
    234  inline bool prevUpToDate() const;
    235  inline void setPrevUpToDate() const;
    236  inline void unsetPrevUpToDate() const;
    237 
    238  inline bool isDebuggee() const;
    239  inline void setIsDebuggee();
    240  inline void unsetIsDebuggee();
    241 
    242  inline HandleValue returnValue() const;
    243  inline void setReturnValue(const Value& rval) const;
    244 
    245  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, InterpreterFrame*);
    246  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
    247                                          jit::BaselineFrame*);
    248  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
    249                                          jit::RematerializedFrame*);
    250  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr& frame,
    251                                          wasm::DebugFrame* ptr);
    252 };
    253 
    254 class NullFramePtr : public AbstractFramePtr {
    255 public:
    256  NullFramePtr() = default;
    257 };
    258 
    259 enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
    260 
    261 /*****************************************************************************/
    262 
    263 class InterpreterFrame {
    264  enum Flags : uint32_t {
    265    CONSTRUCTING = 0x1, /* frame is for a constructor invocation */
    266 
    267    RESUMED_GENERATOR = 0x2, /* frame is for a resumed generator invocation */
    268 
    269    /* Function prologue state */
    270    HAS_INITIAL_ENV =
    271        0x4,            /* callobj created for function or var env for eval */
    272    HAS_ARGS_OBJ = 0x8, /* ArgumentsObject created for needsArgsObj script */
    273 
    274    /* Lazy frame initialization */
    275    HAS_RVAL = 0x10, /* frame has rval_ set */
    276 
    277    /* Debugger state */
    278    PREV_UP_TO_DATE = 0x20, /* see DebugScopes::updateLiveScopes */
    279 
    280    /*
    281     * See comment above 'isDebuggee' in Realm.h for explanation of
    282     * invariants of debuggee compartments, scripts, and frames.
    283     */
    284    DEBUGGEE = 0x40, /* Execution is being observed by Debugger */
    285 
    286    /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
    287    HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */
    288 
    289    /*
    290     * If set, we entered one of the JITs and ScriptFrameIter should skip
    291     * this frame.
    292     */
    293    RUNNING_IN_JIT = 0x100,
    294 
    295    /*
    296     * If set, this frame has been on the stack when
    297     * |js::SavedStacks::saveCurrentStack| was called, and so there is a
    298     * |js::SavedFrame| object cached for this frame.
    299     */
    300    HAS_CACHED_SAVED_FRAME = 0x200,
    301  };
    302 
    303  mutable uint32_t flags_; /* bits described by Flags */
    304  uint32_t nactual_;       /* number of actual arguments, for function frames */
    305  JSScript* script_;       /* the script we're executing */
    306  JSObject* envChain_;     /* current environment chain */
    307  Value rval_;             /* if HAS_RVAL, return value of the frame */
    308  ArgumentsObject* argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */
    309 
    310  /*
    311   * Previous frame and its pc and sp. Always nullptr for
    312   * InterpreterActivation's entry frame, always non-nullptr for inline
    313   * frames.
    314   */
    315  InterpreterFrame* prev_;
    316  jsbytecode* prevpc_;
    317  Value* prevsp_;
    318 
    319  /*
    320   * For an eval-in-frame DEBUGGER_EVAL frame, the frame in whose scope
    321   * we're evaluating code. Iteration treats this as our previous frame.
    322   */
    323  AbstractFramePtr evalInFramePrev_;
    324 
    325  Value* argv_;          /* If hasArgs(), points to frame's arguments. */
    326  LifoAlloc::Mark mark_; /* Used to release memory for this frame. */
    327 
    328  static void staticAsserts() {
    329    static_assert(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
    330    static_assert(sizeof(InterpreterFrame) % sizeof(Value) == 0);
    331  }
    332 
    333  /*
    334   * The utilities are private since they are not able to assert that only
    335   * unaliased vars/formals are accessed. Normal code should prefer the
    336   * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
    337   * the usual "depth is at least" assertions).
    338   */
    339  Value* slots() const { return (Value*)(this + 1); }
    340  Value* base() const { return slots() + script()->nfixed(); }
    341 
    342  friend class FrameIter;
    343  friend class InterpreterRegs;
    344  friend class InterpreterStack;
    345  friend class jit::BaselineFrame;
    346 
    347  /*
    348   * Frame initialization, called by InterpreterStack operations after acquiring
    349   * the raw memory for the frame:
    350   */
    351 
    352  /* Used for Invoke and Interpret. */
    353  void initCallFrame(InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
    354                     JSFunction& callee, JSScript* script, Value* argv,
    355                     uint32_t nactual, MaybeConstruct constructing);
    356 
    357  /* Used for eval, module or global frames. */
    358  void initExecuteFrame(JSContext* cx, HandleScript script,
    359                        AbstractFramePtr prev, HandleObject envChain);
    360 
    361 public:
    362  /*
    363   * Frame prologue/epilogue
    364   *
    365   * Every stack frame must have 'prologue' called before executing the
    366   * first op and 'epilogue' called after executing the last op and before
    367   * popping the frame (whether the exit is exceptional or not).
    368   *
    369   * For inline JS calls/returns, it is easy to call the prologue/epilogue
    370   * exactly once. When calling JS from C++, Invoke/Execute push the stack
    371   * frame but do *not* call the prologue/epilogue. That means Interpret
    372   * must call the prologue/epilogue for the entry frame. This scheme
    373   * simplifies jit compilation.
    374   *
    375   * An important corner case is what happens when an error occurs (OOM,
    376   * over-recursed) after pushing the stack frame but before 'prologue' is
    377   * called or completes fully. To simplify usage, 'epilogue' does not assume
    378   * 'prologue' has completed and handles all the intermediate state details.
    379   */
    380 
    381  bool prologue(JSContext* cx);
    382  void epilogue(JSContext* cx, jsbytecode* pc);
    383 
    384  bool checkReturn(JSContext* cx, HandleValue thisv, MutableHandleValue result);
    385 
    386  bool initFunctionEnvironmentObjects(JSContext* cx);
    387 
    388  /*
    389   * Initialize locals of newly-pushed frame to undefined.
    390   */
    391  void initLocals();
    392 
    393  /*
    394   * Stack frame type
    395   *
    396   * A stack frame may have one of four types, which determines which
    397   * members of the frame may be accessed and other invariants:
    398   *
    399   *  global frame:   execution of global code
    400   *  function frame: execution of function code
    401   *  module frame:   execution of a module
    402   *  eval frame:     execution of eval code
    403   */
    404 
    405  bool isGlobalFrame() const { return script_->isGlobalCode(); }
    406 
    407  bool isModuleFrame() const { return script_->isModule(); }
    408 
    409  bool isEvalFrame() const { return script_->isForEval(); }
    410 
    411  bool isFunctionFrame() const { return script_->isFunction(); }
    412 
    413  /*
    414   * Previous frame
    415   *
    416   * A frame's 'prev' frame is either null or the previous frame pointed to
    417   * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
    418   * frames, the next-frame is a function or eval that was called by the
    419   * prev-frame, but not always: the prev-frame may have called a native that
    420   * reentered the VM through JS_CallFunctionValue on the same context
    421   * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
    422   * 'prev' has little semantic meaning and basically just tells the VM what
    423   * to set cx->regs->fp to when this frame is popped.
    424   */
    425 
    426  InterpreterFrame* prev() const { return prev_; }
    427 
    428  AbstractFramePtr evalInFramePrev() const {
    429    MOZ_ASSERT(isEvalFrame());
    430    return evalInFramePrev_;
    431  }
    432 
    433  /*
    434   * (Unaliased) locals and arguments
    435   *
    436   * Only non-eval function frames have arguments. The arguments pushed by
    437   * the caller are the 'actual' arguments. The declared arguments of the
    438   * callee are the 'formal' arguments. When the caller passes less actual
    439   * arguments, missing formal arguments are padded with |undefined|.
    440   *
    441   * When a local/formal variable is aliased (accessed by nested closures,
    442   * environment operations, or 'arguments'), the canonical location for
    443   * that value is the slot of an environment object.  Aliased locals don't
    444   * have stack slots assigned to them.  These functions assert that
    445   * accesses to stack values are unaliased.
    446   */
    447 
    448  inline Value& unaliasedLocal(uint32_t i);
    449 
    450  bool hasArgs() const { return isFunctionFrame(); }
    451  inline Value& unaliasedFormal(unsigned i,
    452                                MaybeCheckAliasing = CHECK_ALIASING);
    453  inline Value& unaliasedActual(unsigned i,
    454                                MaybeCheckAliasing = CHECK_ALIASING);
    455  template <class Op>
    456  inline void unaliasedForEachActual(Op op);
    457 
    458  unsigned numFormalArgs() const {
    459    MOZ_ASSERT(hasArgs());
    460    return callee().nargs();
    461  }
    462  unsigned numActualArgs() const {
    463    MOZ_ASSERT(hasArgs());
    464    return nactual_;
    465  }
    466 
    467  /* Watch out, this exposes a pointer to the unaliased formal arg array. */
    468  Value* argv() const {
    469    MOZ_ASSERT(hasArgs());
    470    return argv_;
    471  }
    472 
    473  /*
    474   * Arguments object
    475   *
    476   * If a non-eval function has script->needsArgsObj, an arguments object is
    477   * created in the prologue and stored in the local variable for the
    478   * 'arguments' binding (script->argumentsLocal). Since this local is
    479   * mutable, the arguments object can be overwritten and we can "lose" the
    480   * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field
    481   * so that the original arguments object is always available.
    482   */
    483 
    484  ArgumentsObject& argsObj() const;
    485  void initArgsObj(ArgumentsObject& argsobj);
    486 
    487  ArrayObject* createRestParameter(JSContext* cx);
    488 
    489  /*
    490   * Environment chain
    491   *
    492   * In theory, the environment chain would contain an object for every
    493   * lexical scope. However, only objects that are required for dynamic
    494   * lookup are actually created.
    495   *
    496   * Given that an InterpreterFrame corresponds roughly to a ES Execution
    497   * Context (ES 10.3), GetVariablesObject corresponds to the
    498   * VariableEnvironment component of a Exection Context. Intuitively, the
    499   * variables object is where new bindings (variables and functions) are
    500   * stored. One might expect that this is either the Call object or
    501   * envChain.globalObj for function or global code, respectively, however
    502   * the JSAPI allows calls of Execute to specify a variables object on the
    503   * environment chain other than the call/global object. This allows
    504   * embeddings to run multiple scripts under the same global, each time
    505   * using a new variables object to collect and discard the script's global
    506   * variables.
    507   */
    508 
    509  inline HandleObject environmentChain() const;
    510 
    511  inline EnvironmentObject& aliasedEnvironment(EnvironmentCoordinate ec) const;
    512  inline EnvironmentObject& aliasedEnvironmentMaybeDebug(
    513      EnvironmentCoordinate ec) const;
    514  inline GlobalObject& global() const;
    515  inline CallObject& callObj() const;
    516  inline ExtensibleLexicalEnvironmentObject& extensibleLexicalEnvironment()
    517      const;
    518 
    519  template <typename SpecificEnvironment>
    520  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
    521  template <typename SpecificEnvironment>
    522  inline void popOffEnvironmentChain();
    523  inline void replaceInnermostEnvironment(BlockLexicalEnvironmentObject& env);
    524 
    525  // Push a VarEnvironmentObject for function frames of functions that have
    526  // parameter expressions with closed over var bindings.
    527  bool pushVarEnvironment(JSContext* cx, Handle<Scope*> scope);
    528 
    529  /*
    530   * For lexical envs with aliased locals, these interfaces push and pop
    531   * entries on the environment chain.  The "freshen" operation replaces the
    532   * current lexical env with a fresh copy of it, to implement semantics
    533   * providing distinct bindings per iteration of a for(;;) loop whose head
    534   * has a lexical declaration.  The "recreate" operation replaces the
    535   * current lexical env with a copy of it containing uninitialized
    536   * bindings, to implement semantics providing distinct bindings per
    537   * iteration of a for-in/of loop.
    538   */
    539 
    540  bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
    541  bool freshenLexicalEnvironment(JSContext* cx, jsbytecode* pc);
    542  bool recreateLexicalEnvironment(JSContext* cx, jsbytecode* pc);
    543 
    544  bool pushClassBodyEnvironment(JSContext* cx, Handle<ClassBodyScope*> scope);
    545 
    546  /*
    547   * Script
    548   *
    549   * All frames have an associated JSScript which holds the bytecode being
    550   * executed for the frame.
    551   */
    552 
    553  JSScript* script() const { return script_; }
    554 
    555  /* Return the previous frame's pc. */
    556  jsbytecode* prevpc() {
    557    MOZ_ASSERT(prev_);
    558    return prevpc_;
    559  }
    560 
    561  /* Return the previous frame's sp. */
    562  Value* prevsp() {
    563    MOZ_ASSERT(prev_);
    564    return prevsp_;
    565  }
    566 
    567  /*
    568   * Return the 'this' argument passed to a non-eval function frame. This is
    569   * not necessarily the frame's this-binding, for instance non-strict
    570   * functions will box primitive 'this' values and thisArgument() will
    571   * return the original, unboxed Value.
    572   */
    573  Value& thisArgument() const {
    574    MOZ_ASSERT(isFunctionFrame());
    575    return argv()[-1];
    576  }
    577 
    578  /*
    579   * Callee
    580   *
    581   * Only function frames have a true callee. An eval frame in a function has
    582   * the same callee as its containing function frame. An async module has to
    583   * create a wrapper callee to allow passing the script to generators for
    584   * pausing and resuming.
    585   */
    586 
    587  JSFunction& callee() const {
    588    MOZ_ASSERT(isFunctionFrame());
    589    return calleev().toObject().as<JSFunction>();
    590  }
    591 
    592  const Value& calleev() const {
    593    MOZ_ASSERT(isFunctionFrame());
    594    return argv()[-2];
    595  }
    596 
    597  /*
    598   * New Target
    599   *
    600   * Only non-arrow function frames have a meaningful newTarget.
    601   */
    602  Value newTarget() const {
    603    MOZ_ASSERT(isFunctionFrame());
    604    MOZ_ASSERT(!callee().isArrow());
    605 
    606    if (isConstructing()) {
    607      unsigned pushedArgs = std::max(numFormalArgs(), numActualArgs());
    608      return argv()[pushedArgs];
    609    }
    610    return UndefinedValue();
    611  }
    612 
    613  /* Profiler flags */
    614 
    615  bool hasPushedGeckoProfilerFrame() {
    616    return !!(flags_ & HAS_PUSHED_PROF_FRAME);
    617  }
    618 
    619  void setPushedGeckoProfilerFrame() { flags_ |= HAS_PUSHED_PROF_FRAME; }
    620 
    621  void unsetPushedGeckoProfilerFrame() { flags_ &= ~HAS_PUSHED_PROF_FRAME; }
    622 
    623  /* Return value */
    624 
    625  bool hasReturnValue() const { return flags_ & HAS_RVAL; }
    626 
    627  MutableHandleValue returnValue() {
    628    if (!hasReturnValue()) {
    629      rval_.setUndefined();
    630    }
    631    return MutableHandleValue::fromMarkedLocation(&rval_);
    632  }
    633 
    634  void markReturnValue() { flags_ |= HAS_RVAL; }
    635 
    636  void setReturnValue(const Value& v) {
    637    rval_ = v;
    638    markReturnValue();
    639  }
    640 
    641  // Copy values from this frame into a private Array, owned by the
    642  // GeneratorObject, for suspending.
    643  [[nodiscard]] inline bool saveGeneratorSlots(JSContext* cx, unsigned nslots,
    644                                               ArrayObject* dest) const;
    645 
    646  // Copy values from the Array into this stack frame, for resuming.
    647  inline void restoreGeneratorSlots(ArrayObject* src);
    648 
    649  void resumeGeneratorFrame(JSObject* envChain) {
    650    MOZ_ASSERT(script()->isGenerator() || script()->isAsync());
    651    MOZ_ASSERT_IF(!script()->isModule(), isFunctionFrame());
    652    flags_ |= HAS_INITIAL_ENV;
    653    envChain_ = envChain;
    654  }
    655 
    656  /*
    657   * Other flags
    658   */
    659 
    660  bool isConstructing() const { return !!(flags_ & CONSTRUCTING); }
    661 
    662  void setResumedGenerator() { flags_ |= RESUMED_GENERATOR; }
    663  bool isResumedGenerator() const { return !!(flags_ & RESUMED_GENERATOR); }
    664 
    665  /*
    666   * These two queries should not be used in general: the presence/absence of
    667   * the call/args object is determined by the static(ish) properties of the
    668   * JSFunction/JSScript. These queries should only be performed when probing
    669   * a stack frame that may be in the middle of the prologue (during which
    670   * time the call/args object are created).
    671   */
    672 
    673  inline bool hasInitialEnvironment() const;
    674 
    675  bool hasInitialEnvironmentUnchecked() const {
    676    return flags_ & HAS_INITIAL_ENV;
    677  }
    678 
    679  bool hasArgsObj() const {
    680    MOZ_ASSERT(script()->needsArgsObj());
    681    return flags_ & HAS_ARGS_OBJ;
    682  }
    683 
    684  /*
    685   * Debugger eval frames.
    686   *
    687   * - If evalInFramePrev_ is non-null, frame was created for an "eval in
    688   *   frame" call, which can push a successor to any live frame; so its
    689   *   logical "prev" frame is not necessarily the previous frame in memory.
    690   *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
    691   *
    692   * - Don't bother to JIT it, because it's probably short-lived.
    693   *
    694   * - It is required to have a environment chain object outside the
    695   *   js::EnvironmentObject hierarchy: either a global object, or a
    696   *   DebugEnvironmentProxy.
    697   */
    698  bool isDebuggerEvalFrame() const {
    699    return isEvalFrame() && !!evalInFramePrev_;
    700  }
    701 
    702  bool prevUpToDate() const { return !!(flags_ & PREV_UP_TO_DATE); }
    703 
    704  void setPrevUpToDate() { flags_ |= PREV_UP_TO_DATE; }
    705 
    706  void unsetPrevUpToDate() { flags_ &= ~PREV_UP_TO_DATE; }
    707 
    708  bool isDebuggee() const { return !!(flags_ & DEBUGGEE); }
    709 
    710  void setIsDebuggee() { flags_ |= DEBUGGEE; }
    711 
    712  inline void unsetIsDebuggee();
    713 
    714  bool hasCachedSavedFrame() const { return flags_ & HAS_CACHED_SAVED_FRAME; }
    715  void setHasCachedSavedFrame() { flags_ |= HAS_CACHED_SAVED_FRAME; }
    716  void clearHasCachedSavedFrame() { flags_ &= ~HAS_CACHED_SAVED_FRAME; }
    717 
    718 public:
    719  void trace(JSTracer* trc, Value* sp, jsbytecode* pc);
    720  void traceValues(JSTracer* trc, unsigned start, unsigned end);
    721 
    722  // Entered Baseline/Ion from the interpreter.
    723  bool runningInJit() const { return !!(flags_ & RUNNING_IN_JIT); }
    724  void setRunningInJit() { flags_ |= RUNNING_IN_JIT; }
    725  void clearRunningInJit() { flags_ &= ~RUNNING_IN_JIT; }
    726 };
    727 
    728 /*****************************************************************************/
    729 
    730 class InterpreterRegs {
    731 public:
    732  Value* sp;
    733  jsbytecode* pc;
    734 
    735 private:
    736  InterpreterFrame* fp_;
    737 
    738 public:
    739  InterpreterFrame* fp() const { return fp_; }
    740 
    741  unsigned stackDepth() const {
    742    MOZ_ASSERT(sp >= fp_->base());
    743    return sp - fp_->base();
    744  }
    745 
    746  Value* spForStackDepth(unsigned depth) const {
    747    MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
    748    return fp_->base() + depth;
    749  }
    750 
    751  void popInlineFrame() {
    752    pc = fp_->prevpc();
    753    unsigned spForNewTarget =
    754        fp_->isResumedGenerator() ? 0 : fp_->isConstructing();
    755    // This code is called when resuming from async and generator code.
    756    // In the case of modules, we don't have arguments, so we can't use
    757    // numActualArgs, which asserts 'hasArgs'.
    758    unsigned nActualArgs = fp_->isModuleFrame() ? 0 : fp_->numActualArgs();
    759    sp = fp_->prevsp() - nActualArgs - 1 - spForNewTarget;
    760    fp_ = fp_->prev();
    761    MOZ_ASSERT(fp_);
    762  }
    763  void prepareToRun(InterpreterFrame& fp, JSScript* script) {
    764    pc = script->code();
    765    sp = fp.slots() + script->nfixed();
    766    fp_ = &fp;
    767  }
    768 
    769  void setToEndOfScript();
    770 
    771  MutableHandleValue stackHandleAt(int i) {
    772    return MutableHandleValue::fromMarkedLocation(&sp[i]);
    773  }
    774 
    775  HandleValue stackHandleAt(int i) const {
    776    return HandleValue::fromMarkedLocation(&sp[i]);
    777  }
    778 
    779  friend void GDBTestInitInterpreterRegs(InterpreterRegs&,
    780                                         js::InterpreterFrame*, JS::Value*,
    781                                         uint8_t*);
    782 };
    783 
    784 /*****************************************************************************/
    785 
    786 class InterpreterStack {
    787  friend class InterpreterActivation;
    788 
    789  static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
    790  LifoAlloc allocator_;
    791 
    792  // Number of interpreter frames on the stack, for over-recursion checks.
    793  static const size_t MAX_FRAMES = 50 * 1000;
    794  static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
    795  size_t frameCount_;
    796 
    797  inline uint8_t* allocateFrame(JSContext* cx, size_t size);
    798 
    799  inline InterpreterFrame* getCallFrame(JSContext* cx, const CallArgs& args,
    800                                        HandleScript script,
    801                                        MaybeConstruct constructing,
    802                                        Value** pargv);
    803 
    804  void releaseFrame(InterpreterFrame* fp) {
    805    frameCount_--;
    806    allocator_.release(fp->mark_);
    807  }
    808 
    809 public:
    810  InterpreterStack()
    811      : allocator_(DEFAULT_CHUNK_SIZE, js::MallocArena), frameCount_(0) {}
    812 
    813  ~InterpreterStack() { MOZ_ASSERT(frameCount_ == 0); }
    814 
    815  // For execution of eval, module or global code.
    816  InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
    817                                     HandleObject envChain,
    818                                     AbstractFramePtr evalInFrame);
    819 
    820  // Called to invoke a function.
    821  InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
    822                                    MaybeConstruct constructing);
    823 
    824  // The interpreter can push light-weight, "inline" frames without entering a
    825  // new InterpreterActivation or recursively calling Interpret.
    826  bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs,
    827                       const CallArgs& args, HandleScript script,
    828                       MaybeConstruct constructing);
    829 
    830  void popInlineFrame(InterpreterRegs& regs);
    831 
    832  bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
    833                                HandleFunction callee, HandleObject envChain);
    834 
    835  inline void purge(JSRuntime* rt);
    836 
    837  size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
    838    return allocator_.sizeOfExcludingThis(mallocSizeOf);
    839  }
    840 };
    841 
    842 void TraceInterpreterActivations(JSContext* cx, JSTracer* trc);
    843 
    844 /*****************************************************************************/
    845 
    846 /** Base class for all function call args. */
    847 class AnyInvokeArgs : public JS::CallArgs {};
    848 
    849 /** Base class for all function construction args. */
    850 class AnyConstructArgs : public JS::CallArgs {
    851  // Only js::Construct (or internal methods that call the qualified CallArgs
    852  // versions) should do these things!
    853  void setCallee(const Value& v) = delete;
    854  void setThis(const Value& v) = delete;
    855  MutableHandleValue newTarget() const = delete;
    856  MutableHandleValue rval() const = delete;
    857 };
    858 
    859 namespace detail {
    860 
    861 /** Function call/construct args of statically-unknown count. */
    862 template <MaybeConstruct Construct>
    863 class GenericArgsBase
    864    : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> {
    865 protected:
    866  RootedValueVector v_;
    867 
    868  explicit GenericArgsBase(JSContext* cx) : v_(cx) {}
    869 
    870 public:
    871  bool init(JSContext* cx, uint64_t argc) {
    872    if (argc > ARGS_LENGTH_MAX) {
    873      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    874                                JSMSG_TOO_MANY_ARGUMENTS);
    875      return false;
    876    }
    877 
    878    // callee, this, arguments[, new.target iff constructing]
    879    size_t len = 2 + argc + uint32_t(Construct);
    880    MOZ_ASSERT(len > argc);  // no overflow
    881    if (!v_.resize(len)) {
    882      return false;
    883    }
    884 
    885    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
    886    this->constructing_ = Construct;
    887    if (Construct) {
    888      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
    889    }
    890    return true;
    891  }
    892 };
    893 
    894 /** Function call/construct args of statically-known count. */
    895 template <MaybeConstruct Construct, size_t N>
    896 class FixedArgsBase
    897    : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> {
    898  // Add +1 here to avoid noisy warning on gcc when N=0 (0 <= unsigned).
    899  static_assert(N + 1 <= ARGS_LENGTH_MAX + 1, "o/~ too many args o/~");
    900 
    901 protected:
    902  JS::RootedValueArray<2 + N + uint32_t(Construct)> v_;
    903 
    904  explicit FixedArgsBase(JSContext* cx) : v_(cx) {
    905    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
    906    this->constructing_ = Construct;
    907    if (Construct) {
    908      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
    909    }
    910  }
    911 };
    912 
    913 }  // namespace detail
    914 
    915 /** Function call args of statically-unknown count. */
    916 class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT> {
    917  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
    918 
    919 public:
    920  explicit InvokeArgs(JSContext* cx) : Base(cx) {}
    921 };
    922 
    923 /** Function call args of statically-unknown count. */
    924 class InvokeArgsMaybeIgnoresReturnValue
    925    : public detail::GenericArgsBase<NO_CONSTRUCT> {
    926  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
    927 
    928 public:
    929  explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx) : Base(cx) {}
    930 
    931  bool init(JSContext* cx, unsigned argc, bool ignoresReturnValue) {
    932    if (!Base::init(cx, argc)) {
    933      return false;
    934    }
    935    this->ignoresReturnValue_ = ignoresReturnValue;
    936    return true;
    937  }
    938 };
    939 
    940 /** Function call args of statically-known count. */
    941 template <size_t N>
    942 class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N> {
    943  using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>;
    944 
    945 public:
    946  explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {}
    947 };
    948 
    949 /** Function construct args of statically-unknown count. */
    950 class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT> {
    951  using Base = detail::GenericArgsBase<CONSTRUCT>;
    952 
    953 public:
    954  explicit ConstructArgs(JSContext* cx) : Base(cx) {}
    955 };
    956 
    957 /** Function call args of statically-known count. */
    958 template <size_t N>
    959 class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N> {
    960  using Base = detail::FixedArgsBase<CONSTRUCT, N>;
    961 
    962 public:
    963  explicit FixedConstructArgs(JSContext* cx) : Base(cx) {}
    964 };
    965 
    966 template <class Args, class Arraylike>
    967 inline bool FillArgumentsFromArraylike(JSContext* cx, Args& args,
    968                                       const Arraylike& arraylike) {
    969  uint32_t len = arraylike.length();
    970  if (!args.init(cx, len)) {
    971    return false;
    972  }
    973 
    974  for (uint32_t i = 0; i < len; i++) {
    975    args[i].set(arraylike[i]);
    976  }
    977 
    978  return true;
    979 }
    980 
    981 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
    982 struct PortableBaselineStack {
    983  static const size_t DEFAULT_SIZE = 512 * 1024;
    984 
    985  void* base;
    986  void* top;
    987 
    988  bool valid() { return base != nullptr; }
    989 
    990  PortableBaselineStack() {
    991    base = js_calloc(DEFAULT_SIZE);
    992    top = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base) +
    993                                  DEFAULT_SIZE);
    994  }
    995  ~PortableBaselineStack() { js_free(base); }
    996 };
    997 #endif  // ENABLE_PORTABLE_BASELINE_INTERP
    998 
    999 }  // namespace js
   1000 
   1001 namespace mozilla {
   1002 
   1003 template <>
   1004 struct DefaultHasher<js::AbstractFramePtr> {
   1005  using Lookup = js::AbstractFramePtr;
   1006 
   1007  static js::HashNumber hash(const Lookup& key) {
   1008    return mozilla::HashGeneric(key.raw());
   1009  }
   1010 
   1011  static bool match(const js::AbstractFramePtr& k, const Lookup& l) {
   1012    return k == l;
   1013  }
   1014 };
   1015 
   1016 }  // namespace mozilla
   1017 
   1018 #endif  // vm_Stack_h