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