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