js/src/vm/Stack.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef vm_Stack_h
     8 #define vm_Stack_h
    10 #include "mozilla/MemoryReporting.h"
    12 #include "jsfun.h"
    13 #include "jsscript.h"
    15 #include "jit/AsmJSLink.h"
    16 #include "jit/JitFrameIterator.h"
    17 #ifdef CHECK_OSIPOINT_REGISTERS
    18 #include "jit/Registers.h" // for RegisterDump
    19 #endif
    20 #include "js/OldDebugAPI.h"
    22 struct JSCompartment;
    23 struct JSGenerator;
    25 namespace js {
    27 class ArgumentsObject;
    28 class AsmJSModule;
    29 class InterpreterRegs;
    30 class ScopeObject;
    31 class ScriptFrameIter;
    32 class SPSProfiler;
    33 class InterpreterFrame;
    34 class StaticBlockObject;
    36 struct ScopeCoordinate;
    38 // VM stack layout
    39 //
    40 // A JSRuntime's stack consists of a linked list of activations. Every activation
    41 // contains a number of scripted frames that are either running in the interpreter
    42 // (InterpreterActivation) or JIT code (JitActivation). The frames inside a single
    43 // activation are contiguous: whenever C++ calls back into JS, a new activation is
    44 // pushed.
    45 //
    46 // Every activation is tied to a single JSContext and JSCompartment. This means we
    47 // can reconstruct a given context's stack by skipping activations belonging to other
    48 // contexts. This happens whenever an embedding enters the JS engine on cx1 and
    49 // then, from a native called by the JS engine, reenters the VM on cx2.
    51 // Interpreter frames (InterpreterFrame)
    52 //
    53 // Each interpreter script activation (global or function code) is given a
    54 // fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
    55 // information about the activation and links to the previous frame.
    56 //
    57 // The values after an InterpreterFrame in memory are its locals followed by its
    58 // expression stack. InterpreterFrame::argv_ points to the frame's arguments.
    59 // Missing formal arguments are padded with |undefined|, so the number of
    60 // arguments is always >= the number of formals.
    61 //
    62 // The top of an activation's current frame's expression stack is pointed to by
    63 // the activation's "current regs", which contains the stack pointer 'sp'. In
    64 // the interpreter, sp is adjusted as individual values are pushed and popped
    65 // from the stack and the InterpreterRegs struct (pointed to by the
    66 // InterpreterActivation) is a local var of js::Interpret.
    68 enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
    70 /*****************************************************************************/
    72 #ifdef DEBUG
    73 extern void
    74 CheckLocalUnaliased(MaybeCheckAliasing checkAliasing, JSScript *script, uint32_t i);
    75 #endif
    77 namespace jit {
    78     class BaselineFrame;
    79     class RematerializedFrame;
    80 }
    82 /*
    83  * Pointer to either a ScriptFrameIter::Data, an InterpreterFrame, or a Baseline
    84  * JIT frame.
    85  *
    86  * The Debugger may cache ScriptFrameIter::Data as a bookmark to reconstruct a
    87  * ScriptFrameIter without doing a full stack walk.
    88  *
    89  * There is no way to directly create such an AbstractFramePtr. To do so, the
    90  * user must call ScriptFrameIter::copyDataAsAbstractFramePtr().
    91  *
    92  * ScriptFrameIter::abstractFramePtr() will never return an AbstractFramePtr
    93  * that is in fact a ScriptFrameIter::Data.
    94  *
    95  * To recover a ScriptFrameIter settled at the location pointed to by an
    96  * AbstractFramePtr, use the THIS_FRAME_ITER macro in Debugger.cpp. As an
    97  * aside, no asScriptFrameIterData() is provided because C++ is stupid and
    98  * cannot forward declare inner classes.
    99  */
   101 class AbstractFramePtr
   102 {
   103     friend class FrameIter;
   105     uintptr_t ptr_;
   107     enum {
   108         Tag_ScriptFrameIterData = 0x0,
   109         Tag_InterpreterFrame = 0x1,
   110         Tag_BaselineFrame = 0x2,
   111         Tag_RematerializedFrame = 0x3,
   112         TagMask = 0x3
   113     };
   115   public:
   116     AbstractFramePtr()
   117       : ptr_(0)
   118     {}
   120     AbstractFramePtr(InterpreterFrame *fp)
   121       : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0)
   122     {
   123         MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
   124     }
   126     AbstractFramePtr(jit::BaselineFrame *fp)
   127       : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0)
   128     {
   129         MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
   130     }
   132     AbstractFramePtr(jit::RematerializedFrame *fp)
   133       : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0)
   134     {
   135         MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
   136     }
   138     explicit AbstractFramePtr(JSAbstractFramePtr frame)
   139         : ptr_(uintptr_t(frame.raw()))
   140     {
   141     }
   143     static AbstractFramePtr FromRaw(void *raw) {
   144         AbstractFramePtr frame;
   145         frame.ptr_ = uintptr_t(raw);
   146         return frame;
   147     }
   149     bool isScriptFrameIterData() const {
   150         return !!ptr_ && (ptr_ & TagMask) == Tag_ScriptFrameIterData;
   151     }
   152     bool isInterpreterFrame() const {
   153         return (ptr_ & TagMask) == Tag_InterpreterFrame;
   154     }
   155     InterpreterFrame *asInterpreterFrame() const {
   156         JS_ASSERT(isInterpreterFrame());
   157         InterpreterFrame *res = (InterpreterFrame *)(ptr_ & ~TagMask);
   158         JS_ASSERT(res);
   159         return res;
   160     }
   161     bool isBaselineFrame() const {
   162         return (ptr_ & TagMask) == Tag_BaselineFrame;
   163     }
   164     jit::BaselineFrame *asBaselineFrame() const {
   165         JS_ASSERT(isBaselineFrame());
   166         jit::BaselineFrame *res = (jit::BaselineFrame *)(ptr_ & ~TagMask);
   167         JS_ASSERT(res);
   168         return res;
   169     }
   170     bool isRematerializedFrame() const {
   171         return (ptr_ & TagMask) == Tag_RematerializedFrame;
   172     }
   173     jit::RematerializedFrame *asRematerializedFrame() const {
   174         JS_ASSERT(isRematerializedFrame());
   175         jit::RematerializedFrame *res = (jit::RematerializedFrame *)(ptr_ & ~TagMask);
   176         JS_ASSERT(res);
   177         return res;
   178     }
   180     void *raw() const { return reinterpret_cast<void *>(ptr_); }
   182     bool operator ==(const AbstractFramePtr &other) const { return ptr_ == other.ptr_; }
   183     bool operator !=(const AbstractFramePtr &other) const { return ptr_ != other.ptr_; }
   185     operator bool() const { return !!ptr_; }
   187     inline JSObject *scopeChain() const;
   188     inline CallObject &callObj() const;
   189     inline bool initFunctionScopeObjects(JSContext *cx);
   190     inline void pushOnScopeChain(ScopeObject &scope);
   192     inline JSCompartment *compartment() const;
   194     inline bool hasCallObj() const;
   195     inline bool isGeneratorFrame() const;
   196     inline bool isYielding() const;
   197     inline bool isFunctionFrame() const;
   198     inline bool isGlobalFrame() const;
   199     inline bool isEvalFrame() const;
   200     inline bool isFramePushedByExecute() const;
   201     inline bool isDebuggerFrame() const;
   203     inline JSScript *script() const;
   204     inline JSFunction *fun() const;
   205     inline JSFunction *maybeFun() const;
   206     inline JSFunction *callee() const;
   207     inline Value calleev() const;
   208     inline Value &thisValue() const;
   210     inline bool isNonEvalFunctionFrame() const;
   211     inline bool isNonStrictDirectEvalFrame() const;
   212     inline bool isStrictEvalFrame() const;
   214     inline unsigned numActualArgs() const;
   215     inline unsigned numFormalArgs() const;
   217     inline Value *argv() const;
   219     inline bool hasArgs() const;
   220     inline bool hasArgsObj() const;
   221     inline ArgumentsObject &argsObj() const;
   222     inline void initArgsObj(ArgumentsObject &argsobj) const;
   223     inline bool useNewType() const;
   225     inline bool copyRawFrameSlots(AutoValueVector *vec) const;
   227     inline Value &unaliasedVar(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
   228     inline Value &unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
   229     inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
   230     inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
   231     template <class Op> inline void unaliasedForEachActual(JSContext *cx, Op op);
   233     inline bool prevUpToDate() const;
   234     inline void setPrevUpToDate() const;
   236     JSObject *evalPrevScopeChain(JSContext *cx) const;
   238     inline void *maybeHookData() const;
   239     inline void setHookData(void *data) const;
   240     inline HandleValue returnValue() const;
   241     inline void setReturnValue(const Value &rval) const;
   243     bool hasPushedSPSFrame() const;
   245     inline void popBlock(JSContext *cx) const;
   246     inline void popWith(JSContext *cx) const;
   247 };
   249 class NullFramePtr : public AbstractFramePtr
   250 {
   251   public:
   252     NullFramePtr()
   253       : AbstractFramePtr()
   254     { }
   255 };
   257 /*****************************************************************************/
   259 /* Flags specified for a frame as it is constructed. */
   260 enum InitialFrameFlags {
   261     INITIAL_NONE           =          0,
   262     INITIAL_CONSTRUCT      =       0x20, /* == InterpreterFrame::CONSTRUCTING, asserted below */
   263 };
   265 enum ExecuteType {
   266     EXECUTE_GLOBAL         =        0x1, /* == InterpreterFrame::GLOBAL */
   267     EXECUTE_DIRECT_EVAL    =        0x4, /* == InterpreterFrame::EVAL */
   268     EXECUTE_INDIRECT_EVAL  =        0x5, /* == InterpreterFrame::GLOBAL | EVAL */
   269     EXECUTE_DEBUG          =        0xc, /* == InterpreterFrame::EVAL | DEBUGGER */
   270     EXECUTE_DEBUG_GLOBAL   =        0xd  /* == InterpreterFrame::EVAL | DEBUGGER | GLOBAL */
   271 };
   273 /*****************************************************************************/
   275 class InterpreterFrame
   276 {
   277   public:
   278     enum Flags {
   279         /* Primary frame type */
   280         GLOBAL             =        0x1,  /* frame pushed for a global script */
   281         FUNCTION           =        0x2,  /* frame pushed for a scripted call */
   283         /* Frame subtypes */
   284         EVAL               =        0x4,  /* frame pushed for eval() or debugger eval */
   287         /*
   288          * Frame pushed for debugger eval.
   289          * - Don't bother to JIT it, because it's probably short-lived.
   290          * - It is required to have a scope chain object outside the
   291          *   js::ScopeObject hierarchy: either a global object, or a
   292          *   DebugScopeObject (not a ScopeObject, despite the name)
   293          * - If evalInFramePrev_ is set, then this frame was created for an
   294          *   "eval in frame" call, which can push a successor to any live
   295          *   frame; so its logical "prev" frame is not necessarily the
   296          *   previous frame in memory. Iteration should treat
   297          *   evalInFramePrev_ as this frame's previous frame.
   298          */
   299         DEBUGGER           =        0x8,
   301         GENERATOR          =       0x10,  /* frame is associated with a generator */
   302         CONSTRUCTING       =       0x20,  /* frame is for a constructor invocation */
   304         /*
   305          * Generator frame state
   306          *
   307          * YIELDING and SUSPENDED are similar, but there are differences. After
   308          * a generator yields, SendToGenerator immediately clears the YIELDING
   309          * flag, but the frame will still have the SUSPENDED flag. Also, when the
   310          * generator returns but before it's GC'ed, YIELDING is not set but
   311          * SUSPENDED is.
   312          */
   313         YIELDING           =       0x40,  /* Interpret dispatched JSOP_YIELD */
   314         SUSPENDED          =       0x80,  /* Generator is not running. */
   316         /* Function prologue state */
   317         HAS_CALL_OBJ       =      0x100,  /* CallObject created for heavyweight fun */
   318         HAS_ARGS_OBJ       =      0x200,  /* ArgumentsObject created for needsArgsObj script */
   320         /* Lazy frame initialization */
   321         HAS_HOOK_DATA      =      0x400,  /* frame has hookData_ set */
   322         HAS_RVAL           =      0x800,  /* frame has rval_ set */
   323         HAS_SCOPECHAIN     =     0x1000,  /* frame has scopeChain_ set */
   325         /* Debugger state */
   326         PREV_UP_TO_DATE    =     0x4000,  /* see DebugScopes::updateLiveScopes */
   328         /* Used in tracking calls and profiling (see vm/SPSProfiler.cpp) */
   329         HAS_PUSHED_SPS_FRAME =   0x8000,  /* SPS was notified of enty */
   331         /*
   332          * If set, we entered one of the JITs and ScriptFrameIter should skip
   333          * this frame.
   334          */
   335         RUNNING_IN_JIT     =    0x10000,
   337         /* Miscellaneous state. */
   338         USE_NEW_TYPE       =    0x20000   /* Use new type for constructed |this| object. */
   339     };
   341   private:
   342     mutable uint32_t    flags_;         /* bits described by Flags */
   343     union {                             /* describes what code is executing in a */
   344         JSScript        *script;        /*   global frame */
   345         JSFunction      *fun;           /*   function frame, pre GetScopeChain */
   346     } exec;
   347     union {                             /* describes the arguments of a function */
   348         unsigned        nactual;        /*   for non-eval frames */
   349         JSScript        *evalScript;    /*   the script of an eval-in-function */
   350     } u;
   351     mutable JSObject    *scopeChain_;   /* if HAS_SCOPECHAIN, current scope chain */
   352     Value               rval_;          /* if HAS_RVAL, return value of the frame */
   353     ArgumentsObject     *argsObj_;      /* if HAS_ARGS_OBJ, the call's arguments object */
   355     /*
   356      * Previous frame and its pc and sp. Always nullptr for
   357      * InterpreterActivation's entry frame, always non-nullptr for inline
   358      * frames.
   359      */
   360     InterpreterFrame    *prev_;
   361     jsbytecode          *prevpc_;
   362     Value               *prevsp_;
   364     void                *hookData_;     /* if HAS_HOOK_DATA, closure returned by call hook */
   366     /*
   367      * For an eval-in-frame DEBUGGER frame, the frame in whose scope we're
   368      * evaluating code. Iteration treats this as our previous frame.
   369      */
   370     AbstractFramePtr    evalInFramePrev_;
   372     Value               *argv_;         /* If hasArgs(), points to frame's arguments. */
   373     LifoAlloc::Mark     mark_;          /* Used to release memory for this frame. */
   375     static void staticAsserts() {
   376         JS_STATIC_ASSERT(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
   377         JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(Value) == 0);
   378     }
   380     void writeBarrierPost();
   382     /*
   383      * The utilities are private since they are not able to assert that only
   384      * unaliased vars/formals are accessed. Normal code should prefer the
   385      * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
   386      * the usual "depth is at least" assertions).
   387      */
   388     Value *slots() const { return (Value *)(this + 1); }
   389     Value *base() const { return slots() + script()->nfixed(); }
   391     friend class FrameIter;
   392     friend class InterpreterRegs;
   393     friend class InterpreterStack;
   394     friend class jit::BaselineFrame;
   396     /*
   397      * Frame initialization, called by InterpreterStack operations after acquiring
   398      * the raw memory for the frame:
   399      */
   401     /* Used for Invoke and Interpret. */
   402     void initCallFrame(JSContext *cx, InterpreterFrame *prev, jsbytecode *prevpc, Value *prevsp,
   403                        JSFunction &callee, JSScript *script, Value *argv, uint32_t nactual,
   404                        InterpreterFrame::Flags flags);
   406     /* Used for global and eval frames. */
   407     void initExecuteFrame(JSContext *cx, JSScript *script, AbstractFramePtr prev,
   408                           const Value &thisv, JSObject &scopeChain, ExecuteType type);
   410   public:
   411     /*
   412      * Frame prologue/epilogue
   413      *
   414      * Every stack frame must have 'prologue' called before executing the
   415      * first op and 'epilogue' called after executing the last op and before
   416      * popping the frame (whether the exit is exceptional or not).
   417      *
   418      * For inline JS calls/returns, it is easy to call the prologue/epilogue
   419      * exactly once. When calling JS from C++, Invoke/Execute push the stack
   420      * frame but do *not* call the prologue/epilogue. That means Interpret
   421      * must call the prologue/epilogue for the entry frame. This scheme
   422      * simplifies jit compilation.
   423      *
   424      * An important corner case is what happens when an error occurs (OOM,
   425      * over-recursed) after pushing the stack frame but before 'prologue' is
   426      * called or completes fully. To simplify usage, 'epilogue' does not assume
   427      * 'prologue' has completed and handles all the intermediate state details.
   428      */
   430     bool prologue(JSContext *cx);
   431     void epilogue(JSContext *cx);
   433     bool initFunctionScopeObjects(JSContext *cx);
   435     /* Initialize local variables of newly-pushed frame. */
   436     void initVarsToUndefined();
   438     /*
   439      * Stack frame type
   440      *
   441      * A stack frame may have one of three types, which determines which
   442      * members of the frame may be accessed and other invariants:
   443      *
   444      *  global frame:   execution of global code or an eval in global code
   445      *  function frame: execution of function code or an eval in a function
   446      */
   448     bool isFunctionFrame() const {
   449         return !!(flags_ & FUNCTION);
   450     }
   452     bool isGlobalFrame() const {
   453         return !!(flags_ & GLOBAL);
   454     }
   456     /*
   457      * Eval frames
   458      *
   459      * As noted above, global and function frames may optionally be 'eval
   460      * frames'. Eval code shares its parent's arguments which means that the
   461      * arg-access members of InterpreterFrame may not be used for eval frames.
   462      * Search for 'hasArgs' below for more details.
   463      *
   464      * A further sub-classification of eval frames is whether the frame was
   465      * pushed for an ES5 strict-mode eval().
   466      */
   468     bool isEvalFrame() const {
   469         return flags_ & EVAL;
   470     }
   472     bool isEvalInFunction() const {
   473         return (flags_ & (EVAL | FUNCTION)) == (EVAL | FUNCTION);
   474     }
   476     bool isNonEvalFunctionFrame() const {
   477         return (flags_ & (FUNCTION | EVAL)) == FUNCTION;
   478     }
   480     inline bool isStrictEvalFrame() const {
   481         return isEvalFrame() && script()->strict();
   482     }
   484     bool isNonStrictEvalFrame() const {
   485         return isEvalFrame() && !script()->strict();
   486     }
   488     bool isDirectEvalFrame() const {
   489         return isEvalFrame() && script()->staticLevel() > 0;
   490     }
   492     bool isNonStrictDirectEvalFrame() const {
   493         return isNonStrictEvalFrame() && isDirectEvalFrame();
   494     }
   496     /*
   497      * Previous frame
   498      *
   499      * A frame's 'prev' frame is either null or the previous frame pointed to
   500      * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
   501      * frames, the next-frame is a function or eval that was called by the
   502      * prev-frame, but not always: the prev-frame may have called a native that
   503      * reentered the VM through JS_CallFunctionValue on the same context
   504      * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
   505      * 'prev' has little semantic meaning and basically just tells the VM what
   506      * to set cx->regs->fp to when this frame is popped.
   507      */
   509     InterpreterFrame *prev() const {
   510         return prev_;
   511     }
   513     AbstractFramePtr evalInFramePrev() const {
   514         JS_ASSERT(isEvalFrame());
   515         return evalInFramePrev_;
   516     }
   518     /*
   519      * (Unaliased) locals and arguments
   520      *
   521      * Only non-eval function frames have arguments. The arguments pushed by
   522      * the caller are the 'actual' arguments. The declared arguments of the
   523      * callee are the 'formal' arguments. When the caller passes less actual
   524      * arguments, missing formal arguments are padded with |undefined|.
   525      *
   526      * When a local/formal variable is "aliased" (accessed by nested closures,
   527      * dynamic scope operations, or 'arguments), the canonical location for
   528      * that value is the slot of an activation object (scope or arguments).
   529      * Currently, all variables are given slots in *both* the stack frame and
   530      * heap objects, even though, as just described, only one should ever be
   531      * accessed. Thus, it is up to the code performing an access to access the
   532      * correct value. These functions assert that accesses to stack values are
   533      * unaliased. For more about canonical values locations.
   534      */
   536     inline Value &unaliasedVar(uint32_t i, MaybeCheckAliasing = CHECK_ALIASING);
   537     inline Value &unaliasedLocal(uint32_t i, MaybeCheckAliasing = CHECK_ALIASING);
   539     bool hasArgs() const { return isNonEvalFunctionFrame(); }
   540     inline Value &unaliasedFormal(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
   541     inline Value &unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING);
   542     template <class Op> inline void unaliasedForEachActual(Op op);
   544     bool copyRawFrameSlots(AutoValueVector *v);
   546     unsigned numFormalArgs() const { JS_ASSERT(hasArgs()); return fun()->nargs(); }
   547     unsigned numActualArgs() const { JS_ASSERT(hasArgs()); return u.nactual; }
   549     /* Watch out, this exposes a pointer to the unaliased formal arg array. */
   550     Value *argv() const { return argv_; }
   552     /*
   553      * Arguments object
   554      *
   555      * If a non-eval function has script->needsArgsObj, an arguments object is
   556      * created in the prologue and stored in the local variable for the
   557      * 'arguments' binding (script->argumentsLocal). Since this local is
   558      * mutable, the arguments object can be overwritten and we can "lose" the
   559      * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field so
   560      * that the original arguments object is always available.
   561      */
   563     ArgumentsObject &argsObj() const;
   564     void initArgsObj(ArgumentsObject &argsobj);
   566     JSObject *createRestParameter(JSContext *cx);
   568     /*
   569      * Scope chain
   570      *
   571      * In theory, the scope chain would contain an object for every lexical
   572      * scope. However, only objects that are required for dynamic lookup are
   573      * actually created.
   574      *
   575      * Given that an InterpreterFrame corresponds roughly to a ES5 Execution Context
   576      * (ES5 10.3), InterpreterFrame::varObj corresponds to the VariableEnvironment
   577      * component of a Exection Context. Intuitively, the variables object is
   578      * where new bindings (variables and functions) are stored. One might
   579      * expect that this is either the Call object or scopeChain.globalObj for
   580      * function or global code, respectively, however the JSAPI allows calls of
   581      * Execute to specify a variables object on the scope chain other than the
   582      * call/global object. This allows embeddings to run multiple scripts under
   583      * the same global, each time using a new variables object to collect and
   584      * discard the script's global variables.
   585      */
   587     inline HandleObject scopeChain() const;
   589     inline ScopeObject &aliasedVarScope(ScopeCoordinate sc) const;
   590     inline GlobalObject &global() const;
   591     inline CallObject &callObj() const;
   592     inline JSObject &varObj();
   594     inline void pushOnScopeChain(ScopeObject &scope);
   595     inline void popOffScopeChain();
   597     /*
   598      * For blocks with aliased locals, these interfaces push and pop entries on
   599      * the scope chain.
   600      */
   602     bool pushBlock(JSContext *cx, StaticBlockObject &block);
   603     void popBlock(JSContext *cx);
   605     /*
   606      * With
   607      *
   608      * Entering/leaving a |with| block pushes/pops an object on the scope chain.
   609      * Pushing uses pushOnScopeChain, popping should use popWith.
   610      */
   612     void popWith(JSContext *cx);
   614     /*
   615      * Script
   616      *
   617      * All function and global frames have an associated JSScript which holds
   618      * the bytecode being executed for the frame. This script/bytecode does
   619      * not reflect any inlining that has been performed by the method JIT.
   620      * If other frames were inlined into this one, the script/pc reflect the
   621      * point of the outermost call. Inlined frame invariants:
   622      *
   623      * - Inlined frames have the same scope chain as the outer frame.
   624      * - Inlined frames have the same strictness as the outer frame.
   625      * - Inlined frames can only make calls to other JIT frames associated with
   626      *   the same VMFrame. Other calls force expansion of the inlined frames.
   627      */
   629     JSScript *script() const {
   630         return isFunctionFrame()
   631                ? isEvalFrame()
   632                  ? u.evalScript
   633                  : fun()->nonLazyScript()
   634                : exec.script;
   635     }
   637     /* Return the previous frame's pc. */
   638     jsbytecode *prevpc() {
   639         JS_ASSERT(prev_);
   640         return prevpc_;
   641     }
   643     /* Return the previous frame's sp. */
   644     Value *prevsp() {
   645         JS_ASSERT(prev_);
   646         return prevsp_;
   647     }
   649     /*
   650      * Function
   651      *
   652      * All function frames have an associated interpreted JSFunction. The
   653      * function returned by fun() and maybeFun() is not necessarily the
   654      * original canonical function which the frame's script was compiled
   655      * against.
   656      */
   658     JSFunction* fun() const {
   659         JS_ASSERT(isFunctionFrame());
   660         return exec.fun;
   661     }
   663     JSFunction* maybeFun() const {
   664         return isFunctionFrame() ? fun() : nullptr;
   665     }
   667     /*
   668      * This value
   669      *
   670      * Every frame has a this value although, until 'this' is computed, the
   671      * value may not be the semantically-correct 'this' value.
   672      *
   673      * The 'this' value is stored before the formal arguments for function
   674      * frames and directly before the frame for global frames. The *Args
   675      * members assert !isEvalFrame(), so we implement specialized inline
   676      * methods for accessing 'this'. When the caller has static knowledge that
   677      * a frame is a function, 'functionThis' allows more efficient access.
   678      */
   680     Value &functionThis() const {
   681         JS_ASSERT(isFunctionFrame());
   682         if (isEvalFrame())
   683             return ((Value *)this)[-1];
   684         return argv()[-1];
   685     }
   687     JSObject &constructorThis() const {
   688         JS_ASSERT(hasArgs());
   689         return argv()[-1].toObject();
   690     }
   692     Value &thisValue() const {
   693         if (flags_ & (EVAL | GLOBAL))
   694             return ((Value *)this)[-1];
   695         return argv()[-1];
   696     }
   698     /*
   699      * Callee
   700      *
   701      * Only function frames have a callee. An eval frame in a function has the
   702      * same callee as its containing function frame. maybeCalleev can be used
   703      * to return a value that is either the callee object (for function frames) or
   704      * null (for global frames).
   705      */
   707     JSFunction &callee() const {
   708         JS_ASSERT(isFunctionFrame());
   709         return calleev().toObject().as<JSFunction>();
   710     }
   712     const Value &calleev() const {
   713         JS_ASSERT(isFunctionFrame());
   714         return mutableCalleev();
   715     }
   717     const Value &maybeCalleev() const {
   718         Value &calleev = flags_ & (EVAL | GLOBAL)
   719                          ? ((Value *)this)[-2]
   720                          : argv()[-2];
   721         JS_ASSERT(calleev.isObjectOrNull());
   722         return calleev;
   723     }
   725     Value &mutableCalleev() const {
   726         JS_ASSERT(isFunctionFrame());
   727         if (isEvalFrame())
   728             return ((Value *)this)[-2];
   729         return argv()[-2];
   730     }
   732     CallReceiver callReceiver() const {
   733         return CallReceiverFromArgv(argv());
   734     }
   736     /*
   737      * Frame compartment
   738      *
   739      * A stack frame's compartment is the frame's containing context's
   740      * compartment when the frame was pushed.
   741      */
   743     inline JSCompartment *compartment() const;
   745     /* Debugger hook data */
   747     bool hasHookData() const {
   748         return !!(flags_ & HAS_HOOK_DATA);
   749     }
   751     void* hookData() const {
   752         JS_ASSERT(hasHookData());
   753         return hookData_;
   754     }
   756     void* maybeHookData() const {
   757         return hasHookData() ? hookData_ : nullptr;
   758     }
   760     void setHookData(void *v) {
   761         hookData_ = v;
   762         flags_ |= HAS_HOOK_DATA;
   763     }
   765     bool hasPushedSPSFrame() {
   766         return !!(flags_ & HAS_PUSHED_SPS_FRAME);
   767     }
   769     void setPushedSPSFrame() {
   770         flags_ |= HAS_PUSHED_SPS_FRAME;
   771     }
   773     void unsetPushedSPSFrame() {
   774         flags_ &= ~HAS_PUSHED_SPS_FRAME;
   775     }
   777     /* Return value */
   779     bool hasReturnValue() const {
   780         return !!(flags_ & HAS_RVAL);
   781     }
   783     MutableHandleValue returnValue() {
   784         if (!(flags_ & HAS_RVAL))
   785             rval_.setUndefined();
   786         return MutableHandleValue::fromMarkedLocation(&rval_);
   787     }
   789     void markReturnValue() {
   790         flags_ |= HAS_RVAL;
   791     }
   793     void setReturnValue(const Value &v) {
   794         rval_ = v;
   795         markReturnValue();
   796     }
   798     void clearReturnValue() {
   799         rval_.setUndefined();
   800         markReturnValue();
   801     }
   803     /*
   804      * A "generator" frame is a function frame associated with a generator.
   805      * Since generators are not executed LIFO, the VM copies a single abstract
   806      * generator frame back and forth between the LIFO VM stack (when the
   807      * generator is active) and a snapshot stored in JSGenerator (when the
   808      * generator is inactive). A generator frame is comprised of an
   809      * InterpreterFrame structure and the values that make up the arguments,
   810      * locals, and expression stack. The layout in the JSGenerator snapshot
   811      * matches the layout on the stack (see the "VM stack layout" comment
   812      * above).
   813      */
   815     bool isGeneratorFrame() const {
   816         bool ret = flags_ & GENERATOR;
   817         JS_ASSERT_IF(ret, isNonEvalFunctionFrame());
   818         return ret;
   819     }
   821     void initGeneratorFrame() const {
   822         JS_ASSERT(!isGeneratorFrame());
   823         JS_ASSERT(isNonEvalFunctionFrame());
   824         flags_ |= GENERATOR;
   825     }
   827     Value *generatorArgsSnapshotBegin() const {
   828         JS_ASSERT(isGeneratorFrame());
   829         return argv() - 2;
   830     }
   832     Value *generatorArgsSnapshotEnd() const {
   833         JS_ASSERT(isGeneratorFrame());
   834         return argv() + js::Max(numActualArgs(), numFormalArgs());
   835     }
   837     Value *generatorSlotsSnapshotBegin() const {
   838         JS_ASSERT(isGeneratorFrame());
   839         return (Value *)(this + 1);
   840     }
   842     enum TriggerPostBarriers {
   843         DoPostBarrier = true,
   844         NoPostBarrier = false
   845     };
   846     template <TriggerPostBarriers doPostBarrier>
   847     void copyFrameAndValues(JSContext *cx, Value *vp, InterpreterFrame *otherfp,
   848                             const Value *othervp, Value *othersp);
   850     /*
   851      * js::Execute pushes both global and function frames (since eval() in a
   852      * function pushes a frame with isFunctionFrame() && isEvalFrame()). Most
   853      * code should not care where a frame was pushed, but if it is necessary to
   854      * pick out frames pushed by js::Execute, this is the right query:
   855      */
   857     bool isFramePushedByExecute() const {
   858         return !!(flags_ & (GLOBAL | EVAL));
   859     }
   861     /*
   862      * Other flags
   863      */
   865     InitialFrameFlags initialFlags() const {
   866         JS_STATIC_ASSERT((int)INITIAL_NONE == 0);
   867         JS_STATIC_ASSERT((int)INITIAL_CONSTRUCT == (int)CONSTRUCTING);
   868         uint32_t mask = CONSTRUCTING;
   869         JS_ASSERT((flags_ & mask) != mask);
   870         return InitialFrameFlags(flags_ & mask);
   871     }
   873     void setConstructing() {
   874         flags_ |= CONSTRUCTING;
   875     }
   877     bool isConstructing() const {
   878         return !!(flags_ & CONSTRUCTING);
   879     }
   881     /*
   882      * These two queries should not be used in general: the presence/absence of
   883      * the call/args object is determined by the static(ish) properties of the
   884      * JSFunction/JSScript. These queries should only be performed when probing
   885      * a stack frame that may be in the middle of the prologue (during which
   886      * time the call/args object are created).
   887      */
   889     inline bool hasCallObj() const;
   891     bool hasCallObjUnchecked() const {
   892         return flags_ & HAS_CALL_OBJ;
   893     }
   895     bool hasArgsObj() const {
   896         JS_ASSERT(script()->needsArgsObj());
   897         return flags_ & HAS_ARGS_OBJ;
   898     }
   900     void setUseNewType() {
   901         JS_ASSERT(isConstructing());
   902         flags_ |= USE_NEW_TYPE;
   903     }
   904     bool useNewType() const {
   905         JS_ASSERT(isConstructing());
   906         return flags_ & USE_NEW_TYPE;
   907     }
   909     bool isDebuggerFrame() const {
   910         return !!(flags_ & DEBUGGER);
   911     }
   913     bool prevUpToDate() const {
   914         return !!(flags_ & PREV_UP_TO_DATE);
   915     }
   917     void setPrevUpToDate() {
   918         flags_ |= PREV_UP_TO_DATE;
   919     }
   921     bool isYielding() {
   922         return !!(flags_ & YIELDING);
   923     }
   925     void setYielding() {
   926         flags_ |= YIELDING;
   927     }
   929     void clearYielding() {
   930         flags_ &= ~YIELDING;
   931     }
   933     bool isSuspended() const {
   934         JS_ASSERT(isGeneratorFrame());
   935         return flags_ & SUSPENDED;
   936     }
   938     void setSuspended() {
   939         JS_ASSERT(isGeneratorFrame());
   940         flags_ |= SUSPENDED;
   941     }
   943     void clearSuspended() {
   944         JS_ASSERT(isGeneratorFrame());
   945         flags_ &= ~SUSPENDED;
   946     }
   948   public:
   949     void mark(JSTracer *trc);
   950     void markValues(JSTracer *trc, unsigned start, unsigned end);
   951     void markValues(JSTracer *trc, Value *sp, jsbytecode *pc);
   953     // Entered Baseline/Ion from the interpreter.
   954     bool runningInJit() const {
   955         return !!(flags_ & RUNNING_IN_JIT);
   956     }
   957     void setRunningInJit() {
   958         flags_ |= RUNNING_IN_JIT;
   959     }
   960     void clearRunningInJit() {
   961         flags_ &= ~RUNNING_IN_JIT;
   962     }
   963 };
   965 static const size_t VALUES_PER_STACK_FRAME = sizeof(InterpreterFrame) / sizeof(Value);
   967 static inline InterpreterFrame::Flags
   968 ToFrameFlags(InitialFrameFlags initial)
   969 {
   970     return InterpreterFrame::Flags(initial);
   971 }
   973 static inline InitialFrameFlags
   974 InitialFrameFlagsFromConstructing(bool b)
   975 {
   976     return b ? INITIAL_CONSTRUCT : INITIAL_NONE;
   977 }
   979 static inline bool
   980 InitialFrameFlagsAreConstructing(InitialFrameFlags initial)
   981 {
   982     return !!(initial & INITIAL_CONSTRUCT);
   983 }
   985 /*****************************************************************************/
   987 class InterpreterRegs
   988 {
   989   public:
   990     Value *sp;
   991     jsbytecode *pc;
   992   private:
   993     InterpreterFrame *fp_;
   994   public:
   995     InterpreterFrame *fp() const { return fp_; }
   997     unsigned stackDepth() const {
   998         JS_ASSERT(sp >= fp_->base());
   999         return sp - fp_->base();
  1002     Value *spForStackDepth(unsigned depth) const {
  1003         JS_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
  1004         return fp_->base() + depth;
  1007     /* For generators. */
  1008     void rebaseFromTo(const InterpreterRegs &from, InterpreterFrame &to) {
  1009         fp_ = &to;
  1010         sp = to.slots() + (from.sp - from.fp_->slots());
  1011         pc = from.pc;
  1012         JS_ASSERT(fp_);
  1015     void popInlineFrame() {
  1016         pc = fp_->prevpc();
  1017         sp = fp_->prevsp() - fp_->numActualArgs() - 1;
  1018         fp_ = fp_->prev();
  1019         JS_ASSERT(fp_);
  1021     void prepareToRun(InterpreterFrame &fp, JSScript *script) {
  1022         pc = script->code();
  1023         sp = fp.slots() + script->nfixed();
  1024         fp_ = &fp;
  1027     void setToEndOfScript();
  1029     MutableHandleValue stackHandleAt(int i) {
  1030         return MutableHandleValue::fromMarkedLocation(&sp[i]);
  1033     HandleValue stackHandleAt(int i) const {
  1034         return HandleValue::fromMarkedLocation(&sp[i]);
  1036 };
  1038 /*****************************************************************************/
  1040 class InterpreterStack
  1042     friend class InterpreterActivation;
  1044     static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
  1045     LifoAlloc allocator_;
  1047     // Number of interpreter frames on the stack, for over-recursion checks.
  1048     static const size_t MAX_FRAMES = 50 * 1000;
  1049     static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
  1050     size_t frameCount_;
  1052     inline uint8_t *allocateFrame(JSContext *cx, size_t size);
  1054     inline InterpreterFrame *
  1055     getCallFrame(JSContext *cx, const CallArgs &args, HandleScript script,
  1056                  InterpreterFrame::Flags *pflags, Value **pargv);
  1058     void releaseFrame(InterpreterFrame *fp) {
  1059         frameCount_--;
  1060         allocator_.release(fp->mark_);
  1063   public:
  1064     InterpreterStack()
  1065       : allocator_(DEFAULT_CHUNK_SIZE),
  1066         frameCount_(0)
  1067     { }
  1069     ~InterpreterStack() {
  1070         JS_ASSERT(frameCount_ == 0);
  1073     // For execution of eval or global code.
  1074     InterpreterFrame *pushExecuteFrame(JSContext *cx, HandleScript script, const Value &thisv,
  1075                                  HandleObject scopeChain, ExecuteType type,
  1076                                  AbstractFramePtr evalInFrame);
  1078     // Called to invoke a function.
  1079     InterpreterFrame *pushInvokeFrame(JSContext *cx, const CallArgs &args,
  1080                                       InitialFrameFlags initial);
  1082     // The interpreter can push light-weight, "inline" frames without entering a
  1083     // new InterpreterActivation or recursively calling Interpret.
  1084     bool pushInlineFrame(JSContext *cx, InterpreterRegs &regs, const CallArgs &args,
  1085                          HandleScript script, InitialFrameFlags initial);
  1087     void popInlineFrame(InterpreterRegs &regs);
  1089     inline void purge(JSRuntime *rt);
  1091     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
  1092         return allocator_.sizeOfExcludingThis(mallocSizeOf);
  1094 };
  1096 void MarkInterpreterActivations(JSRuntime *rt, JSTracer *trc);
  1098 /*****************************************************************************/
  1100 class InvokeArgs : public JS::CallArgs
  1102     AutoValueVector v_;
  1104   public:
  1105     InvokeArgs(JSContext *cx) : v_(cx) {}
  1107     bool init(unsigned argc) {
  1108         if (!v_.resize(2 + argc))
  1109             return false;
  1110         ImplicitCast<CallArgs>(*this) = CallArgsFromVp(argc, v_.begin());
  1111         return true;
  1113 };
  1115 template <>
  1116 struct DefaultHasher<AbstractFramePtr> {
  1117     typedef AbstractFramePtr Lookup;
  1119     static js::HashNumber hash(const Lookup &key) {
  1120         return size_t(key.raw());
  1123     static bool match(const AbstractFramePtr &k, const Lookup &l) {
  1124         return k == l;
  1126 };
  1128 /*****************************************************************************/
  1130 class InterpreterActivation;
  1131 class ForkJoinActivation;
  1132 class AsmJSActivation;
  1134 namespace jit {
  1135     class JitActivation;
  1136 };
  1138 class Activation
  1140   protected:
  1141     JSContext *cx_;
  1142     JSCompartment *compartment_;
  1143     Activation *prev_;
  1145     // Counter incremented by JS_SaveFrameChain on the top-most activation and
  1146     // decremented by JS_RestoreFrameChain. If > 0, ScriptFrameIter should stop
  1147     // iterating when it reaches this activation (if GO_THROUGH_SAVED is not
  1148     // set).
  1149     size_t savedFrameChain_;
  1151     // Counter incremented by JS::HideScriptedCaller and decremented by
  1152     // JS::UnhideScriptedCaller. If > 0 for the top activation,
  1153     // DescribeScriptedCaller will return null instead of querying that
  1154     // activation, which should prompt the caller to consult embedding-specific
  1155     // data structures instead.
  1156     size_t hideScriptedCallerCount_;
  1158     enum Kind { Interpreter, Jit, ForkJoin, AsmJS };
  1159     Kind kind_;
  1161     inline Activation(JSContext *cx, Kind kind_);
  1162     inline ~Activation();
  1164   public:
  1165     JSContext *cx() const {
  1166         return cx_;
  1168     JSCompartment *compartment() const {
  1169         return compartment_;
  1171     Activation *prev() const {
  1172         return prev_;
  1175     bool isInterpreter() const {
  1176         return kind_ == Interpreter;
  1178     bool isJit() const {
  1179         return kind_ == Jit;
  1181     bool isForkJoin() const {
  1182         return kind_ == ForkJoin;
  1184     bool isAsmJS() const {
  1185         return kind_ == AsmJS;
  1188     InterpreterActivation *asInterpreter() const {
  1189         JS_ASSERT(isInterpreter());
  1190         return (InterpreterActivation *)this;
  1192     jit::JitActivation *asJit() const {
  1193         JS_ASSERT(isJit());
  1194         return (jit::JitActivation *)this;
  1196     ForkJoinActivation *asForkJoin() const {
  1197         JS_ASSERT(isForkJoin());
  1198         return (ForkJoinActivation *)this;
  1200     AsmJSActivation *asAsmJS() const {
  1201         JS_ASSERT(isAsmJS());
  1202         return (AsmJSActivation *)this;
  1205     void saveFrameChain() {
  1206         savedFrameChain_++;
  1208     void restoreFrameChain() {
  1209         JS_ASSERT(savedFrameChain_ > 0);
  1210         savedFrameChain_--;
  1212     bool hasSavedFrameChain() const {
  1213         return savedFrameChain_ > 0;
  1216     void hideScriptedCaller() {
  1217         hideScriptedCallerCount_++;
  1219     void unhideScriptedCaller() {
  1220         JS_ASSERT(hideScriptedCallerCount_ > 0);
  1221         hideScriptedCallerCount_--;
  1223     bool scriptedCallerIsHidden() const {
  1224         return hideScriptedCallerCount_ > 0;
  1227   private:
  1228     Activation(const Activation &other) MOZ_DELETE;
  1229     void operator=(const Activation &other) MOZ_DELETE;
  1230 };
  1232 // This variable holds a special opcode value which is greater than all normal
  1233 // opcodes, and is chosen such that the bitwise or of this value with any
  1234 // opcode is this value.
  1235 static const jsbytecode EnableInterruptsPseudoOpcode = -1;
  1237 static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
  1238               "EnableInterruptsPseudoOpcode must be greater than any opcode");
  1239 static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1),
  1240               "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
  1242 class InterpreterFrameIterator;
  1243 class RunState;
  1245 class InterpreterActivation : public Activation
  1247     friend class js::InterpreterFrameIterator;
  1249     RunState &state_;
  1250     InterpreterRegs regs_;
  1251     InterpreterFrame *entryFrame_;
  1252     size_t opMask_; // For debugger interrupts, see js::Interpret.
  1254 #ifdef DEBUG
  1255     size_t oldFrameCount_;
  1256 #endif
  1258   public:
  1259     inline InterpreterActivation(RunState &state, JSContext *cx, InterpreterFrame *entryFrame);
  1260     inline ~InterpreterActivation();
  1262     inline bool pushInlineFrame(const CallArgs &args, HandleScript script,
  1263                                 InitialFrameFlags initial);
  1264     inline void popInlineFrame(InterpreterFrame *frame);
  1266     InterpreterFrame *current() const {
  1267         return regs_.fp();
  1269     InterpreterRegs &regs() {
  1270         return regs_;
  1272     InterpreterFrame *entryFrame() const {
  1273         return entryFrame_;
  1275     size_t opMask() const {
  1276         return opMask_;
  1279     // If this js::Interpret frame is running |script|, enable interrupts.
  1280     void enableInterruptsIfRunning(JSScript *script) {
  1281         if (regs_.fp()->script() == script)
  1282             enableInterruptsUnconditionally();
  1284     void enableInterruptsUnconditionally() {
  1285         opMask_ = EnableInterruptsPseudoOpcode;
  1287     void clearInterruptsMask() {
  1288         opMask_ = 0;
  1290 };
  1292 // Iterates over a runtime's activation list.
  1293 class ActivationIterator
  1295     uint8_t *jitTop_;
  1297   protected:
  1298     Activation *activation_;
  1300   private:
  1301     void settle();
  1303   public:
  1304     explicit ActivationIterator(JSRuntime *rt);
  1306     ActivationIterator &operator++();
  1308     Activation *operator->() const {
  1309         return activation_;
  1311     Activation *activation() const {
  1312         return activation_;
  1314     uint8_t *jitTop() const {
  1315         JS_ASSERT(activation_->isJit());
  1316         return jitTop_;
  1318     bool done() const {
  1319         return activation_ == nullptr;
  1321 };
  1323 namespace jit {
  1325 // A JitActivation is used for frames running in Baseline or Ion.
  1326 class JitActivation : public Activation
  1328     uint8_t *prevIonTop_;
  1329     JSContext *prevJitJSContext_;
  1330     bool firstFrameIsConstructing_;
  1331     bool active_;
  1333 #ifdef JS_ION
  1334     // Rematerialized Ion frames which has info copied out of snapshots. Maps
  1335     // frame pointers (i.e. ionTop) to a vector of rematerializations of all
  1336     // inline frames associated with that frame.
  1337     //
  1338     // This table is lazily initialized by calling getRematerializedFrame.
  1339     typedef Vector<RematerializedFrame *, 1> RematerializedFrameVector;
  1340     typedef HashMap<uint8_t *, RematerializedFrameVector> RematerializedFrameTable;
  1341     RematerializedFrameTable rematerializedFrames_;
  1343     void freeRematerializedFramesInVector(RematerializedFrameVector &frames);
  1344     void clearRematerializedFrames();
  1345 #endif
  1347 #ifdef CHECK_OSIPOINT_REGISTERS
  1348   protected:
  1349     // Used to verify that live registers don't change between a VM call and
  1350     // the OsiPoint that follows it. Protected to silence Clang warning.
  1351     uint32_t checkRegs_;
  1352     RegisterDump regs_;
  1353 #endif
  1355   public:
  1356     JitActivation(JSContext *cx, bool firstFrameIsConstructing, bool active = true);
  1357     ~JitActivation();
  1359     bool isActive() const {
  1360         return active_;
  1362     void setActive(JSContext *cx, bool active = true);
  1364     uint8_t *prevIonTop() const {
  1365         return prevIonTop_;
  1367     JSCompartment *compartment() const {
  1368         return compartment_;
  1370     bool firstFrameIsConstructing() const {
  1371         return firstFrameIsConstructing_;
  1373     static size_t offsetOfPrevIonTop() {
  1374         return offsetof(JitActivation, prevIonTop_);
  1376     static size_t offsetOfPrevJitJSContext() {
  1377         return offsetof(JitActivation, prevJitJSContext_);
  1379     static size_t offsetOfActiveUint8() {
  1380         JS_ASSERT(sizeof(bool) == 1);
  1381         return offsetof(JitActivation, active_);
  1384 #ifdef CHECK_OSIPOINT_REGISTERS
  1385     void setCheckRegs(bool check) {
  1386         checkRegs_ = check;
  1388     static size_t offsetOfCheckRegs() {
  1389         return offsetof(JitActivation, checkRegs_);
  1391     static size_t offsetOfRegs() {
  1392         return offsetof(JitActivation, regs_);
  1394 #endif
  1396 #ifdef JS_ION
  1397     // Look up a rematerialized frame keyed by the fp, rematerializing the
  1398     // frame if one doesn't already exist. A frame can only be rematerialized
  1399     // if an IonFrameIterator pointing to the nearest uninlined frame can be
  1400     // provided, as values need to be read out of snapshots.
  1401     //
  1402     // The inlineDepth must be within bounds of the frame pointed to by iter.
  1403     RematerializedFrame *getRematerializedFrame(JSContext *cx, JitFrameIterator &iter,
  1404                                                 size_t inlineDepth = 0);
  1406     // Look up a rematerialized frame by the fp. If inlineDepth is out of
  1407     // bounds of what has been rematerialized, nullptr is returned.
  1408     RematerializedFrame *lookupRematerializedFrame(uint8_t *top, size_t inlineDepth = 0);
  1410     bool hasRematerializedFrame(uint8_t *top, size_t inlineDepth = 0) {
  1411         return !!lookupRematerializedFrame(top, inlineDepth);
  1414     // Remove a previous rematerialization by fp.
  1415     void removeRematerializedFrame(uint8_t *top);
  1417     void markRematerializedFrames(JSTracer *trc);
  1418 #endif
  1419 };
  1421 // A filtering of the ActivationIterator to only stop at JitActivations.
  1422 class JitActivationIterator : public ActivationIterator
  1424     void settle() {
  1425         while (!done() && !activation_->isJit())
  1426             ActivationIterator::operator++();
  1429   public:
  1430     explicit JitActivationIterator(JSRuntime *rt)
  1431       : ActivationIterator(rt)
  1433         settle();
  1436     JitActivationIterator &operator++() {
  1437         ActivationIterator::operator++();
  1438         settle();
  1439         return *this;
  1442     // Returns the bottom and top addresses of the current JitActivation.
  1443     void jitStackRange(uintptr_t *&min, uintptr_t *&end);
  1444 };
  1446 } // namespace jit
  1448 // Iterates over the frames of a single InterpreterActivation.
  1449 class InterpreterFrameIterator
  1451     InterpreterActivation *activation_;
  1452     InterpreterFrame *fp_;
  1453     jsbytecode *pc_;
  1454     Value *sp_;
  1456   public:
  1457     explicit InterpreterFrameIterator(InterpreterActivation *activation)
  1458       : activation_(activation),
  1459         fp_(nullptr),
  1460         pc_(nullptr),
  1461         sp_(nullptr)
  1463         if (activation) {
  1464             fp_ = activation->current();
  1465             pc_ = activation->regs().pc;
  1466             sp_ = activation->regs().sp;
  1470     InterpreterFrame *frame() const {
  1471         JS_ASSERT(!done());
  1472         return fp_;
  1474     jsbytecode *pc() const {
  1475         JS_ASSERT(!done());
  1476         return pc_;
  1478     Value *sp() const {
  1479         JS_ASSERT(!done());
  1480         return sp_;
  1483     InterpreterFrameIterator &operator++();
  1485     bool done() const {
  1486         return fp_ == nullptr;
  1488 };
  1490 // An AsmJSActivation is part of two activation linked lists:
  1491 //  - the normal Activation list used by FrameIter
  1492 //  - a list of only AsmJSActivations that is signal-safe since it is accessed
  1493 //    from the profiler at arbitrary points
  1494 //
  1495 // An eventual goal is to remove AsmJSActivation and to run asm.js code in a
  1496 // JitActivation interleaved with Ion/Baseline jit code. This would allow
  1497 // efficient calls back and forth but requires that we can walk the stack for
  1498 // all kinds of jit code.
  1499 class AsmJSActivation : public Activation
  1501     AsmJSModule &module_;
  1502     AsmJSActivation *prevAsmJS_;
  1503     void *errorRejoinSP_;
  1504     SPSProfiler *profiler_;
  1505     void *resumePC_;
  1506     uint8_t *exitSP_;
  1508     static const intptr_t InterruptedSP = -1;
  1510   public:
  1511     AsmJSActivation(JSContext *cx, AsmJSModule &module);
  1512     ~AsmJSActivation();
  1514     JSContext *cx() { return cx_; }
  1515     AsmJSModule &module() const { return module_; }
  1516     AsmJSActivation *prevAsmJS() const { return prevAsmJS_; }
  1518     // Read by JIT code:
  1519     static unsigned offsetOfContext() { return offsetof(AsmJSActivation, cx_); }
  1520     static unsigned offsetOfResumePC() { return offsetof(AsmJSActivation, resumePC_); }
  1522     // Initialized by JIT code:
  1523     static unsigned offsetOfErrorRejoinSP() { return offsetof(AsmJSActivation, errorRejoinSP_); }
  1524     static unsigned offsetOfExitSP() { return offsetof(AsmJSActivation, exitSP_); }
  1526     // Set from SIGSEGV handler:
  1527     void setInterrupted(void *pc) { resumePC_ = pc; exitSP_ = (uint8_t*)InterruptedSP; }
  1528     bool isInterruptedSP() const { return exitSP_ == (uint8_t*)InterruptedSP; }
  1530     // Note: exitSP is the sp right before the call instruction. On x86, this
  1531     // means before the return address is pushed on the stack, on ARM, this
  1532     // means after.
  1533     uint8_t *exitSP() const { JS_ASSERT(!isInterruptedSP()); return exitSP_; }
  1534 };
  1536 // A FrameIter walks over the runtime's stack of JS script activations,
  1537 // abstracting over whether the JS scripts were running in the interpreter or
  1538 // different modes of compiled code.
  1539 //
  1540 // FrameIter is parameterized by what it includes in the stack iteration:
  1541 //  - The SavedOption controls whether FrameIter stops when it finds an
  1542 //    activation that was set aside via JS_SaveFrameChain (and not yet retored
  1543 //    by JS_RestoreFrameChain). (Hopefully this will go away.)
  1544 //  - The ContextOption determines whether the iteration will view frames from
  1545 //    all JSContexts or just the given JSContext. (Hopefully this will go away.)
  1546 //  - When provided, the optional JSPrincipal argument will cause FrameIter to
  1547 //    only show frames in globals whose JSPrincipals are subsumed (via
  1548 //    JSSecurityCallbacks::subsume) by the given JSPrincipal.
  1549 //
  1550 // Additionally, there are derived FrameIter types that automatically skip
  1551 // certain frames:
  1552 //  - ScriptFrameIter only shows frames that have an associated JSScript
  1553 //    (currently everything other than asm.js stack frames). When !hasScript(),
  1554 //    clients must stick to the portion of the
  1555 //    interface marked below.
  1556 //  - NonBuiltinScriptFrameIter additionally filters out builtin (self-hosted)
  1557 //    scripts.
  1558 class FrameIter
  1560   public:
  1561     enum SavedOption { STOP_AT_SAVED, GO_THROUGH_SAVED };
  1562     enum ContextOption { CURRENT_CONTEXT, ALL_CONTEXTS };
  1563     enum State { DONE, INTERP, JIT, ASMJS };
  1565     // Unlike ScriptFrameIter itself, ScriptFrameIter::Data can be allocated on
  1566     // the heap, so this structure should not contain any GC things.
  1567     struct Data
  1569         JSContext *     cx_;
  1570         SavedOption     savedOption_;
  1571         ContextOption   contextOption_;
  1572         JSPrincipals *  principals_;
  1574         State           state_;
  1576         jsbytecode *    pc_;
  1578         InterpreterFrameIterator interpFrames_;
  1579         ActivationIterator activations_;
  1581 #ifdef JS_ION
  1582         jit::JitFrameIterator jitFrames_;
  1583         unsigned ionInlineFrameNo_;
  1584         AsmJSFrameIterator asmJSFrames_;
  1585 #endif
  1587         Data(JSContext *cx, SavedOption savedOption, ContextOption contextOption,
  1588              JSPrincipals *principals);
  1589         Data(const Data &other);
  1590     };
  1592     FrameIter(JSContext *cx, SavedOption = STOP_AT_SAVED);
  1593     FrameIter(JSContext *cx, ContextOption, SavedOption, JSPrincipals* = nullptr);
  1594     FrameIter(const FrameIter &iter);
  1595     FrameIter(const Data &data);
  1596     FrameIter(AbstractFramePtr frame);
  1598     bool done() const { return data_.state_ == DONE; }
  1600     // -------------------------------------------------------
  1601     // The following functions can only be called when !done()
  1602     // -------------------------------------------------------
  1604     FrameIter &operator++();
  1606     JSCompartment *compartment() const;
  1607     Activation *activation() const { return data_.activations_.activation(); }
  1609     bool isInterp() const { JS_ASSERT(!done()); return data_.state_ == INTERP;  }
  1610     bool isJit() const { JS_ASSERT(!done()); return data_.state_ == JIT; }
  1611     bool isAsmJS() const { JS_ASSERT(!done()); return data_.state_ == ASMJS; }
  1612     inline bool isIon() const;
  1613     inline bool isBaseline() const;
  1615     bool isFunctionFrame() const;
  1616     bool isGlobalFrame() const;
  1617     bool isEvalFrame() const;
  1618     bool isNonEvalFunctionFrame() const;
  1619     bool isGeneratorFrame() const;
  1620     bool hasArgs() const { return isNonEvalFunctionFrame(); }
  1622     /*
  1623      * Get an abstract frame pointer dispatching to either an interpreter,
  1624      * baseline, or rematerialized optimized frame.
  1625      */
  1626     ScriptSource *scriptSource() const;
  1627     const char *scriptFilename() const;
  1628     unsigned computeLine(uint32_t *column = nullptr) const;
  1629     JSAtom *functionDisplayAtom() const;
  1630     JSPrincipals *originPrincipals() const;
  1632     bool hasScript() const { return !isAsmJS(); }
  1634     // -----------------------------------------------------------
  1635     // The following functions can only be called when hasScript()
  1636     // -----------------------------------------------------------
  1638     inline JSScript *script() const;
  1640     bool        isConstructing() const;
  1641     jsbytecode *pc() const { JS_ASSERT(!done()); return data_.pc_; }
  1642     void        updatePcQuadratic();
  1643     JSFunction *callee() const;
  1644     Value       calleev() const;
  1645     unsigned    numActualArgs() const;
  1646     unsigned    numFormalArgs() const;
  1647     Value       unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING) const;
  1648     template <class Op> inline void unaliasedForEachActual(JSContext *cx, Op op);
  1650     JSObject   *scopeChain() const;
  1651     CallObject &callObj() const;
  1653     bool        hasArgsObj() const;
  1654     ArgumentsObject &argsObj() const;
  1656     // Ensure that computedThisValue is correct, see ComputeThis.
  1657     bool        computeThis(JSContext *cx) const;
  1658     // thisv() may not always be correct, even after computeThis. In case when
  1659     // the frame is an Ion frame, the computed this value cannot be saved to
  1660     // the Ion frame but is instead saved in the RematerializedFrame for use
  1661     // by Debugger.
  1662     //
  1663     // Both methods exist because of speed. thisv() will never rematerialize
  1664     // an Ion frame, whereas computedThisValue() will.
  1665     Value       computedThisValue() const;
  1666     Value       thisv() const;
  1668     Value       returnValue() const;
  1669     void        setReturnValue(const Value &v);
  1671     JSFunction *maybeCallee() const {
  1672         return isFunctionFrame() ? callee() : nullptr;
  1675     // These are only valid for the top frame.
  1676     size_t      numFrameSlots() const;
  1677     Value       frameSlotValue(size_t index) const;
  1679     // Ensures that we have rematerialized the top frame and its associated
  1680     // inline frames. Can only be called when isIon().
  1681     bool ensureHasRematerializedFrame();
  1683     // True when isInterp() or isBaseline(). True when isIon() if it
  1684     // has a rematerialized frame. False otherwise false otherwise.
  1685     bool hasUsableAbstractFramePtr() const;
  1687     // -----------------------------------------------------------
  1688     // The following functions can only be called when isInterp(),
  1689     // isBaseline(), or isIon(). Further, abstractFramePtr() can
  1690     // only be called when hasUsableAbstractFramePtr().
  1691     // -----------------------------------------------------------
  1693     AbstractFramePtr abstractFramePtr() const;
  1694     AbstractFramePtr copyDataAsAbstractFramePtr() const;
  1695     Data *copyData() const;
  1697     // This can only be called when isInterp():
  1698     inline InterpreterFrame *interpFrame() const;
  1700   private:
  1701     Data data_;
  1702 #ifdef JS_ION
  1703     jit::InlineFrameIterator ionInlineFrames_;
  1704 #endif
  1706     void popActivation();
  1707     void popInterpreterFrame();
  1708 #ifdef JS_ION
  1709     void nextJitFrame();
  1710     void popJitFrame();
  1711     void popAsmJSFrame();
  1712 #endif
  1713     void settleOnActivation();
  1715     friend class ::JSBrokenFrameIterator;
  1716 };
  1718 class ScriptFrameIter : public FrameIter
  1720     void settle() {
  1721         while (!done() && !hasScript())
  1722             FrameIter::operator++();
  1725   public:
  1726     ScriptFrameIter(JSContext *cx, SavedOption savedOption = STOP_AT_SAVED)
  1727       : FrameIter(cx, savedOption)
  1729         settle();
  1732     ScriptFrameIter(JSContext *cx,
  1733                     ContextOption cxOption,
  1734                     SavedOption savedOption,
  1735                     JSPrincipals *prin = nullptr)
  1736       : FrameIter(cx, cxOption, savedOption, prin)
  1738         settle();
  1741     ScriptFrameIter(const ScriptFrameIter &iter) : FrameIter(iter) { settle(); }
  1742     ScriptFrameIter(const FrameIter::Data &data) : FrameIter(data) { settle(); }
  1743     ScriptFrameIter(AbstractFramePtr frame) : FrameIter(frame) { settle(); }
  1745     ScriptFrameIter &operator++() {
  1746         FrameIter::operator++();
  1747         settle();
  1748         return *this;
  1750 };
  1752 #ifdef DEBUG
  1753 bool SelfHostedFramesVisible();
  1754 #else
  1755 static inline bool
  1756 SelfHostedFramesVisible()
  1758     return false;
  1760 #endif
  1762 /* A filtering of the FrameIter to only stop at non-self-hosted scripts. */
  1763 class NonBuiltinFrameIter : public FrameIter
  1765     void settle();
  1767   public:
  1768     NonBuiltinFrameIter(JSContext *cx,
  1769                         FrameIter::SavedOption opt = FrameIter::STOP_AT_SAVED)
  1770       : FrameIter(cx, opt)
  1772         settle();
  1775     NonBuiltinFrameIter(JSContext *cx,
  1776                         FrameIter::ContextOption contextOption,
  1777                         FrameIter::SavedOption savedOption,
  1778                         JSPrincipals *principals = nullptr)
  1779       : FrameIter(cx, contextOption, savedOption, principals)
  1781         settle();
  1784     NonBuiltinFrameIter(const FrameIter::Data &data)
  1785       : FrameIter(data)
  1786     {}
  1788     NonBuiltinFrameIter &operator++() {
  1789         FrameIter::operator++();
  1790         settle();
  1791         return *this;
  1793 };
  1795 /* A filtering of the ScriptFrameIter to only stop at non-self-hosted scripts. */
  1796 class NonBuiltinScriptFrameIter : public ScriptFrameIter
  1798     void settle();
  1800   public:
  1801     NonBuiltinScriptFrameIter(JSContext *cx,
  1802                               ScriptFrameIter::SavedOption opt = ScriptFrameIter::STOP_AT_SAVED)
  1803       : ScriptFrameIter(cx, opt)
  1805         settle();
  1808     NonBuiltinScriptFrameIter(JSContext *cx,
  1809                               ScriptFrameIter::ContextOption contextOption,
  1810                               ScriptFrameIter::SavedOption savedOption,
  1811                               JSPrincipals *principals = nullptr)
  1812       : ScriptFrameIter(cx, contextOption, savedOption, principals)
  1814         settle();
  1817     NonBuiltinScriptFrameIter(const ScriptFrameIter::Data &data)
  1818       : ScriptFrameIter(data)
  1819     {}
  1821     NonBuiltinScriptFrameIter &operator++() {
  1822         ScriptFrameIter::operator++();
  1823         settle();
  1824         return *this;
  1826 };
  1828 /*
  1829  * Blindly iterate over all frames in the current thread's stack. These frames
  1830  * can be from different contexts and compartments, so beware.
  1831  */
  1832 class AllFramesIter : public ScriptFrameIter
  1834   public:
  1835     AllFramesIter(JSContext *cx)
  1836       : ScriptFrameIter(cx, ScriptFrameIter::ALL_CONTEXTS, ScriptFrameIter::GO_THROUGH_SAVED)
  1837     {}
  1838 };
  1840 /* Popular inline definitions. */
  1842 inline JSScript *
  1843 FrameIter::script() const
  1845     JS_ASSERT(!done());
  1846     if (data_.state_ == INTERP)
  1847         return interpFrame()->script();
  1848 #ifdef JS_ION
  1849     JS_ASSERT(data_.state_ == JIT);
  1850     if (data_.jitFrames_.isIonJS())
  1851         return ionInlineFrames_.script();
  1852     return data_.jitFrames_.script();
  1853 #else
  1854     return nullptr;
  1855 #endif
  1858 inline bool
  1859 FrameIter::isIon() const
  1861 #ifdef JS_ION
  1862     return isJit() && data_.jitFrames_.isIonJS();
  1863 #else
  1864     return false;
  1865 #endif
  1868 inline bool
  1869 FrameIter::isBaseline() const
  1871 #ifdef JS_ION
  1872     return isJit() && data_.jitFrames_.isBaselineJS();
  1873 #else
  1874     return false;
  1875 #endif
  1878 inline InterpreterFrame *
  1879 FrameIter::interpFrame() const
  1881     JS_ASSERT(data_.state_ == INTERP);
  1882     return data_.interpFrames_.frame();
  1885 }  /* namespace js */
  1886 #endif /* vm_Stack_h */

mercurial