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