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