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/. */
6 
7 #ifndef vm_Stack_h
8 #define vm_Stack_h
9 
10 #include "mozilla/Atomics.h"
11 #include "mozilla/HashFunctions.h"
12 #include "mozilla/Maybe.h"
13 #include "mozilla/MemoryReporting.h"
14 #include "mozilla/Span.h"  // for Span
15 
16 #include <algorithm>
17 #include <type_traits>
18 
19 #include "gc/Rooting.h"
20 #include "js/friend/ErrorMessages.h"  // js::GetErrorMessage, JSMSG_*
21 #include "js/RootingAPI.h"
22 #include "js/TypeDecls.h"
23 #include "js/UniquePtr.h"
24 #include "vm/ArgumentsObject.h"
25 #include "vm/JSFunction.h"
26 #include "vm/JSScript.h"
27 #include "vm/SavedFrame.h"
28 #include "wasm/WasmFrame.h"  // js::wasm::DebugFrame
29 
30 namespace js {
31 
32 class InterpreterRegs;
33 class CallObject;
34 class FrameIter;
35 class ClassBodyScope;
36 class EnvironmentObject;
37 class BlockLexicalEnvironmentObject;
38 class ExtensibleLexicalEnvironmentObject;
39 class GeckoProfilerRuntime;
40 class InterpreterFrame;
41 class EnvironmentIter;
42 class EnvironmentCoordinate;
43 
44 class SavedFrame;
45 
46 namespace jit {
47 class CommonFrameLayout;
48 }
49 namespace wasm {
50 class Instance;
51 }  // namespace wasm
52 
53 // [SMDOC] VM stack layout
54 //
55 // A JSRuntime's stack consists of a linked list of activations. Every
56 // activation contains a number of scripted frames that are either running in
57 // the interpreter (InterpreterActivation) or JIT code (JitActivation). The
58 // frames inside a single activation are contiguous: whenever C++ calls back
59 // into JS, a new activation is pushed.
60 //
61 // Every activation is tied to a single JSContext and JS::Compartment. This
62 // means we can reconstruct a given context's stack by skipping activations
63 // belonging to other contexts. This happens whenever an embedding enters the JS
64 // engine on cx1 and then, from a native called by the JS engine, reenters the
65 // VM on cx2.
66 
67 // Interpreter frames (InterpreterFrame)
68 //
69 // Each interpreter script activation (global or function code) is given a
70 // fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
71 // information about the activation and links to the previous frame.
72 //
73 // The values after an InterpreterFrame in memory are its locals followed by its
74 // expression stack. InterpreterFrame::argv_ points to the frame's arguments.
75 // Missing formal arguments are padded with |undefined|, so the number of
76 // arguments is always >= the number of formals.
77 //
78 // The top of an activation's current frame's expression stack is pointed to by
79 // the activation's "current regs", which contains the stack pointer 'sp'. In
80 // the interpreter, sp is adjusted as individual values are pushed and popped
81 // from the stack and the InterpreterRegs struct (pointed to by the
82 // InterpreterActivation) is a local var of js::Interpret.
83 
84 enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
85 enum MaybeCheckTDZ { CheckTDZ = true, DontCheckTDZ = false };
86 
87 }  // namespace js
88 
89 /*****************************************************************************/
90 
91 namespace js {
92 
93 namespace jit {
94 class BaselineFrame;
95 class RematerializedFrame;
96 }  // namespace jit
97 
98 /**
99  * Pointer to a live JS or WASM stack frame.
100  */
101 class AbstractFramePtr {
102   friend class FrameIter;
103 
104   uintptr_t ptr_;
105 
106   enum {
107     Tag_InterpreterFrame = 0x1,
108     Tag_BaselineFrame = 0x2,
109     Tag_RematerializedFrame = 0x3,
110     Tag_WasmDebugFrame = 0x4,
111     TagMask = 0x7
112   };
113 
114  public:
AbstractFramePtr()115   AbstractFramePtr() : ptr_(0) {}
116 
AbstractFramePtr(InterpreterFrame * fp)117   MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp)
118       : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0) {
119     MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
120   }
121 
AbstractFramePtr(jit::BaselineFrame * fp)122   MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp)
123       : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0) {
124     MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
125   }
126 
AbstractFramePtr(jit::RematerializedFrame * fp)127   MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp)
128       : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0) {
129     MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
130   }
131 
AbstractFramePtr(wasm::DebugFrame * fp)132   MOZ_IMPLICIT AbstractFramePtr(wasm::DebugFrame* fp)
133       : ptr_(fp ? uintptr_t(fp) | Tag_WasmDebugFrame : 0) {
134     static_assert(wasm::DebugFrame::Alignment >= TagMask, "aligned");
135     MOZ_ASSERT_IF(fp, asWasmDebugFrame() == fp);
136   }
137 
isInterpreterFrame()138   bool isInterpreterFrame() const {
139     return (ptr_ & TagMask) == Tag_InterpreterFrame;
140   }
asInterpreterFrame()141   InterpreterFrame* asInterpreterFrame() const {
142     MOZ_ASSERT(isInterpreterFrame());
143     InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask);
144     MOZ_ASSERT(res);
145     return res;
146   }
isBaselineFrame()147   bool isBaselineFrame() const { return (ptr_ & TagMask) == Tag_BaselineFrame; }
asBaselineFrame()148   jit::BaselineFrame* asBaselineFrame() const {
149     MOZ_ASSERT(isBaselineFrame());
150     jit::BaselineFrame* res = (jit::BaselineFrame*)(ptr_ & ~TagMask);
151     MOZ_ASSERT(res);
152     return res;
153   }
isRematerializedFrame()154   bool isRematerializedFrame() const {
155     return (ptr_ & TagMask) == Tag_RematerializedFrame;
156   }
asRematerializedFrame()157   jit::RematerializedFrame* asRematerializedFrame() const {
158     MOZ_ASSERT(isRematerializedFrame());
159     jit::RematerializedFrame* res =
160         (jit::RematerializedFrame*)(ptr_ & ~TagMask);
161     MOZ_ASSERT(res);
162     return res;
163   }
isWasmDebugFrame()164   bool isWasmDebugFrame() const {
165     return (ptr_ & TagMask) == Tag_WasmDebugFrame;
166   }
asWasmDebugFrame()167   wasm::DebugFrame* asWasmDebugFrame() const {
168     MOZ_ASSERT(isWasmDebugFrame());
169     wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask);
170     MOZ_ASSERT(res);
171     return res;
172   }
173 
raw()174   void* raw() const { return reinterpret_cast<void*>(ptr_); }
175 
176   bool operator==(const AbstractFramePtr& other) const {
177     return ptr_ == other.ptr_;
178   }
179   bool operator!=(const AbstractFramePtr& other) const {
180     return ptr_ != other.ptr_;
181   }
182 
183   explicit operator bool() const { return !!ptr_; }
184 
185   inline JSObject* environmentChain() const;
186   inline CallObject& callObj() const;
187   inline bool initFunctionEnvironmentObjects(JSContext* cx);
188   inline bool pushVarEnvironment(JSContext* cx, HandleScope scope);
189   template <typename SpecificEnvironment>
190   inline void pushOnEnvironmentChain(SpecificEnvironment& env);
191   template <typename SpecificEnvironment>
192   inline void popOffEnvironmentChain();
193 
194   inline JS::Realm* realm() const;
195 
196   inline bool hasInitialEnvironment() const;
197   inline bool isGlobalFrame() const;
198   inline bool isModuleFrame() const;
199   inline bool isEvalFrame() const;
200   inline bool isDebuggerEvalFrame() const;
201 
202   inline bool hasScript() const;
203   inline JSScript* script() const;
204   inline wasm::Instance* wasmInstance() const;
205   inline GlobalObject* global() const;
206   inline bool hasGlobal(const GlobalObject* global) const;
207   inline JSFunction* callee() const;
208   inline Value calleev() const;
209   inline Value& thisArgument() const;
210 
211   inline bool isConstructing() const;
212   inline Value newTarget() const;
213 
214   inline bool debuggerNeedsCheckPrimitiveReturn() const;
215 
216   inline bool isFunctionFrame() const;
217   inline bool isGeneratorFrame() const;
218 
219   inline bool saveGeneratorSlots(JSContext* cx, unsigned nslots,
220                                  ArrayObject* dest) const;
221 
222   inline unsigned numActualArgs() const;
223   inline unsigned numFormalArgs() const;
224 
225   inline Value* argv() const;
226 
227   inline bool hasArgs() const;
228   inline bool hasArgsObj() const;
229   inline ArgumentsObject& argsObj() const;
230   inline void initArgsObj(ArgumentsObject& argsobj) const;
231 
232   inline Value& unaliasedLocal(uint32_t i);
233   inline Value& unaliasedFormal(
234       unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
235   inline Value& unaliasedActual(
236       unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
237   template <class Op>
238   inline void unaliasedForEachActual(JSContext* cx, Op op);
239 
240   inline bool prevUpToDate() const;
241   inline void setPrevUpToDate() const;
242   inline void unsetPrevUpToDate() const;
243 
244   inline bool isDebuggee() const;
245   inline void setIsDebuggee();
246   inline void unsetIsDebuggee();
247 
248   inline HandleValue returnValue() const;
249   inline void setReturnValue(const Value& rval) const;
250 
251   friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, InterpreterFrame*);
252   friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
253                                           jit::BaselineFrame*);
254   friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
255                                           jit::RematerializedFrame*);
256   friend void GDBTestInitAbstractFramePtr(AbstractFramePtr& frame,
257                                           wasm::DebugFrame* ptr);
258 };
259 
260 class NullFramePtr : public AbstractFramePtr {
261  public:
NullFramePtr()262   NullFramePtr() : AbstractFramePtr() {}
263 };
264 
265 enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
266 
267 /*****************************************************************************/
268 
269 class InterpreterFrame {
270   enum Flags : uint32_t {
271     CONSTRUCTING = 0x1, /* frame is for a constructor invocation */
272 
273     RESUMED_GENERATOR = 0x2, /* frame is for a resumed generator invocation */
274 
275     /* Function prologue state */
276     HAS_INITIAL_ENV =
277         0x4,            /* callobj created for function or var env for eval */
278     HAS_ARGS_OBJ = 0x8, /* ArgumentsObject created for needsArgsObj script */
279 
280     /* Lazy frame initialization */
281     HAS_RVAL = 0x10, /* frame has rval_ set */
282 
283     /* Debugger state */
284     PREV_UP_TO_DATE = 0x20, /* see DebugScopes::updateLiveScopes */
285 
286     /*
287      * See comment above 'isDebuggee' in Realm.h for explanation of
288      * invariants of debuggee compartments, scripts, and frames.
289      */
290     DEBUGGEE = 0x40, /* Execution is being observed by Debugger */
291 
292     /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
293     HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */
294 
295     /*
296      * If set, we entered one of the JITs and ScriptFrameIter should skip
297      * this frame.
298      */
299     RUNNING_IN_JIT = 0x100,
300 
301     /*
302      * If set, this frame has been on the stack when
303      * |js::SavedStacks::saveCurrentStack| was called, and so there is a
304      * |js::SavedFrame| object cached for this frame.
305      */
306     HAS_CACHED_SAVED_FRAME = 0x200,
307   };
308 
309   mutable uint32_t flags_; /* bits described by Flags */
310   uint32_t nactual_;       /* number of actual arguments, for function frames */
311   JSScript* script_;       /* the script we're executing */
312   JSObject* envChain_;     /* current environment chain */
313   Value rval_;             /* if HAS_RVAL, return value of the frame */
314   ArgumentsObject* argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */
315 
316   /*
317    * Previous frame and its pc and sp. Always nullptr for
318    * InterpreterActivation's entry frame, always non-nullptr for inline
319    * frames.
320    */
321   InterpreterFrame* prev_;
322   jsbytecode* prevpc_;
323   Value* prevsp_;
324 
325   /*
326    * For an eval-in-frame DEBUGGER_EVAL frame, the frame in whose scope
327    * we're evaluating code. Iteration treats this as our previous frame.
328    */
329   AbstractFramePtr evalInFramePrev_;
330 
331   Value* argv_;          /* If hasArgs(), points to frame's arguments. */
332   LifoAlloc::Mark mark_; /* Used to release memory for this frame. */
333 
staticAsserts()334   static void staticAsserts() {
335     static_assert(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
336     static_assert(sizeof(InterpreterFrame) % sizeof(Value) == 0);
337   }
338 
339   /*
340    * The utilities are private since they are not able to assert that only
341    * unaliased vars/formals are accessed. Normal code should prefer the
342    * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
343    * the usual "depth is at least" assertions).
344    */
slots()345   Value* slots() const { return (Value*)(this + 1); }
base()346   Value* base() const { return slots() + script()->nfixed(); }
347 
348   friend class FrameIter;
349   friend class InterpreterRegs;
350   friend class InterpreterStack;
351   friend class jit::BaselineFrame;
352 
353   /*
354    * Frame initialization, called by InterpreterStack operations after acquiring
355    * the raw memory for the frame:
356    */
357 
358   /* Used for Invoke and Interpret. */
359   void initCallFrame(InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
360                      JSFunction& callee, JSScript* script, Value* argv,
361                      uint32_t nactual, MaybeConstruct constructing);
362 
363   /* Used for eval, module or global frames. */
364   void initExecuteFrame(JSContext* cx, HandleScript script,
365                         AbstractFramePtr prev, HandleValue newTargetValue,
366                         HandleObject envChain);
367 
368  public:
369   /*
370    * Frame prologue/epilogue
371    *
372    * Every stack frame must have 'prologue' called before executing the
373    * first op and 'epilogue' called after executing the last op and before
374    * popping the frame (whether the exit is exceptional or not).
375    *
376    * For inline JS calls/returns, it is easy to call the prologue/epilogue
377    * exactly once. When calling JS from C++, Invoke/Execute push the stack
378    * frame but do *not* call the prologue/epilogue. That means Interpret
379    * must call the prologue/epilogue for the entry frame. This scheme
380    * simplifies jit compilation.
381    *
382    * An important corner case is what happens when an error occurs (OOM,
383    * over-recursed) after pushing the stack frame but before 'prologue' is
384    * called or completes fully. To simplify usage, 'epilogue' does not assume
385    * 'prologue' has completed and handles all the intermediate state details.
386    */
387 
388   bool prologue(JSContext* cx);
389   void epilogue(JSContext* cx, jsbytecode* pc);
390 
391   bool checkReturn(JSContext* cx, HandleValue thisv);
392 
393   bool initFunctionEnvironmentObjects(JSContext* cx);
394 
395   /*
396    * Initialize locals of newly-pushed frame to undefined.
397    */
398   void initLocals();
399 
400   /*
401    * Stack frame type
402    *
403    * A stack frame may have one of four types, which determines which
404    * members of the frame may be accessed and other invariants:
405    *
406    *  global frame:   execution of global code
407    *  function frame: execution of function code
408    *  module frame:   execution of a module
409    *  eval frame:     execution of eval code
410    */
411 
isGlobalFrame()412   bool isGlobalFrame() const { return script_->isGlobalCode(); }
413 
isModuleFrame()414   bool isModuleFrame() const { return script_->isModule(); }
415 
isEvalFrame()416   bool isEvalFrame() const { return script_->isForEval(); }
417 
isFunctionFrame()418   bool isFunctionFrame() const { return script_->isFunction(); }
419 
420   /*
421    * Previous frame
422    *
423    * A frame's 'prev' frame is either null or the previous frame pointed to
424    * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
425    * frames, the next-frame is a function or eval that was called by the
426    * prev-frame, but not always: the prev-frame may have called a native that
427    * reentered the VM through JS_CallFunctionValue on the same context
428    * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
429    * 'prev' has little semantic meaning and basically just tells the VM what
430    * to set cx->regs->fp to when this frame is popped.
431    */
432 
prev()433   InterpreterFrame* prev() const { return prev_; }
434 
evalInFramePrev()435   AbstractFramePtr evalInFramePrev() const {
436     MOZ_ASSERT(isEvalFrame());
437     return evalInFramePrev_;
438   }
439 
440   /*
441    * (Unaliased) locals and arguments
442    *
443    * Only non-eval function frames have arguments. The arguments pushed by
444    * the caller are the 'actual' arguments. The declared arguments of the
445    * callee are the 'formal' arguments. When the caller passes less actual
446    * arguments, missing formal arguments are padded with |undefined|.
447    *
448    * When a local/formal variable is aliased (accessed by nested closures,
449    * environment operations, or 'arguments'), the canonical location for
450    * that value is the slot of an environment object.  Aliased locals don't
451    * have stack slots assigned to them.  These functions assert that
452    * accesses to stack values are unaliased.
453    */
454 
455   inline Value& unaliasedLocal(uint32_t i);
456 
hasArgs()457   bool hasArgs() const { return isFunctionFrame(); }
458   inline Value& unaliasedFormal(unsigned i,
459                                 MaybeCheckAliasing = CHECK_ALIASING);
460   inline Value& unaliasedActual(unsigned i,
461                                 MaybeCheckAliasing = CHECK_ALIASING);
462   template <class Op>
463   inline void unaliasedForEachActual(Op op);
464 
numFormalArgs()465   unsigned numFormalArgs() const {
466     MOZ_ASSERT(hasArgs());
467     return callee().nargs();
468   }
numActualArgs()469   unsigned numActualArgs() const {
470     MOZ_ASSERT(hasArgs());
471     return nactual_;
472   }
473 
474   /* Watch out, this exposes a pointer to the unaliased formal arg array. */
argv()475   Value* argv() const {
476     MOZ_ASSERT(hasArgs());
477     return argv_;
478   }
479 
480   /*
481    * Arguments object
482    *
483    * If a non-eval function has script->needsArgsObj, an arguments object is
484    * created in the prologue and stored in the local variable for the
485    * 'arguments' binding (script->argumentsLocal). Since this local is
486    * mutable, the arguments object can be overwritten and we can "lose" the
487    * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field
488    * so that the original arguments object is always available.
489    */
490 
491   ArgumentsObject& argsObj() const;
492   void initArgsObj(ArgumentsObject& argsobj);
493 
494   ArrayObject* createRestParameter(JSContext* cx);
495 
496   /*
497    * Environment chain
498    *
499    * In theory, the environment chain would contain an object for every
500    * lexical scope. However, only objects that are required for dynamic
501    * lookup are actually created.
502    *
503    * Given that an InterpreterFrame corresponds roughly to a ES Execution
504    * Context (ES 10.3), GetVariablesObject corresponds to the
505    * VariableEnvironment component of a Exection Context. Intuitively, the
506    * variables object is where new bindings (variables and functions) are
507    * stored. One might expect that this is either the Call object or
508    * envChain.globalObj for function or global code, respectively, however
509    * the JSAPI allows calls of Execute to specify a variables object on the
510    * environment chain other than the call/global object. This allows
511    * embeddings to run multiple scripts under the same global, each time
512    * using a new variables object to collect and discard the script's global
513    * variables.
514    */
515 
516   inline HandleObject environmentChain() const;
517 
518   inline EnvironmentObject& aliasedEnvironment(EnvironmentCoordinate ec) const;
519   inline EnvironmentObject& aliasedEnvironmentMaybeDebug(
520       EnvironmentCoordinate ec) const;
521   inline GlobalObject& global() const;
522   inline CallObject& callObj() const;
523   inline ExtensibleLexicalEnvironmentObject& extensibleLexicalEnvironment()
524       const;
525 
526   template <typename SpecificEnvironment>
527   inline void pushOnEnvironmentChain(SpecificEnvironment& env);
528   template <typename SpecificEnvironment>
529   inline void popOffEnvironmentChain();
530   inline void replaceInnermostEnvironment(BlockLexicalEnvironmentObject& env);
531 
532   // Push a VarEnvironmentObject for function frames of functions that have
533   // parameter expressions with closed over var bindings.
534   bool pushVarEnvironment(JSContext* cx, HandleScope scope);
535 
536   /*
537    * For lexical envs with aliased locals, these interfaces push and pop
538    * entries on the environment chain.  The "freshen" operation replaces the
539    * current lexical env with a fresh copy of it, to implement semantics
540    * providing distinct bindings per iteration of a for(;;) loop whose head
541    * has a lexical declaration.  The "recreate" operation replaces the
542    * current lexical env with a copy of it containing uninitialized
543    * bindings, to implement semantics providing distinct bindings per
544    * iteration of a for-in/of loop.
545    */
546 
547   bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
548   bool freshenLexicalEnvironment(JSContext* cx);
549   bool recreateLexicalEnvironment(JSContext* cx);
550 
551   bool pushClassBodyEnvironment(JSContext* cx, Handle<ClassBodyScope*> scope);
552 
553   /*
554    * Script
555    *
556    * All frames have an associated JSScript which holds the bytecode being
557    * executed for the frame.
558    */
559 
script()560   JSScript* script() const { return script_; }
561 
562   /* Return the previous frame's pc. */
prevpc()563   jsbytecode* prevpc() {
564     MOZ_ASSERT(prev_);
565     return prevpc_;
566   }
567 
568   /* Return the previous frame's sp. */
prevsp()569   Value* prevsp() {
570     MOZ_ASSERT(prev_);
571     return prevsp_;
572   }
573 
574   /*
575    * Return the 'this' argument passed to a non-eval function frame. This is
576    * not necessarily the frame's this-binding, for instance non-strict
577    * functions will box primitive 'this' values and thisArgument() will
578    * return the original, unboxed Value.
579    */
thisArgument()580   Value& thisArgument() const {
581     MOZ_ASSERT(isFunctionFrame());
582     return argv()[-1];
583   }
584 
585   /*
586    * Callee
587    *
588    * Only function frames have a true callee. An eval frame in a function has
589    * the same callee as its containing function frame. An async module has to
590    * create a wrapper callee to allow passing the script to generators for
591    * pausing and resuming.
592    */
593 
callee()594   JSFunction& callee() const {
595     MOZ_ASSERT(isFunctionFrame());
596     return calleev().toObject().as<JSFunction>();
597   }
598 
calleev()599   const Value& calleev() const {
600     MOZ_ASSERT(isFunctionFrame());
601     return argv()[-2];
602   }
603 
604   /*
605    * New Target
606    *
607    * Only function frames have a meaningful newTarget. An eval frame in a
608    * function will have a copy of the newTarget of the enclosing function
609    * frame.
610    */
newTarget()611   Value newTarget() const {
612     if (isEvalFrame()) {
613       return ((Value*)this)[-1];
614     }
615 
616     MOZ_ASSERT(isFunctionFrame());
617 
618     if (callee().isArrow()) {
619       return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
620     }
621 
622     if (isConstructing()) {
623       unsigned pushedArgs = std::max(numFormalArgs(), numActualArgs());
624       return argv()[pushedArgs];
625     }
626     return UndefinedValue();
627   }
628 
629   /* Profiler flags */
630 
hasPushedGeckoProfilerFrame()631   bool hasPushedGeckoProfilerFrame() {
632     return !!(flags_ & HAS_PUSHED_PROF_FRAME);
633   }
634 
setPushedGeckoProfilerFrame()635   void setPushedGeckoProfilerFrame() { flags_ |= HAS_PUSHED_PROF_FRAME; }
636 
unsetPushedGeckoProfilerFrame()637   void unsetPushedGeckoProfilerFrame() { flags_ &= ~HAS_PUSHED_PROF_FRAME; }
638 
639   /* Return value */
640 
hasReturnValue()641   bool hasReturnValue() const { return flags_ & HAS_RVAL; }
642 
returnValue()643   MutableHandleValue returnValue() {
644     if (!hasReturnValue()) {
645       rval_.setUndefined();
646     }
647     return MutableHandleValue::fromMarkedLocation(&rval_);
648   }
649 
markReturnValue()650   void markReturnValue() { flags_ |= HAS_RVAL; }
651 
setReturnValue(const Value & v)652   void setReturnValue(const Value& v) {
653     rval_ = v;
654     markReturnValue();
655   }
656 
657   // Copy values from this frame into a private Array, owned by the
658   // GeneratorObject, for suspending.
659   [[nodiscard]] inline bool saveGeneratorSlots(JSContext* cx, unsigned nslots,
660                                                ArrayObject* dest) const;
661 
662   // Copy values from the Array into this stack frame, for resuming.
663   inline void restoreGeneratorSlots(ArrayObject* src);
664 
resumeGeneratorFrame(JSObject * envChain)665   void resumeGeneratorFrame(JSObject* envChain) {
666     MOZ_ASSERT(script()->isGenerator() || script()->isAsync());
667     MOZ_ASSERT_IF(!script()->isModule(), isFunctionFrame());
668     flags_ |= HAS_INITIAL_ENV;
669     envChain_ = envChain;
670   }
671 
672   /*
673    * Other flags
674    */
675 
isConstructing()676   bool isConstructing() const { return !!(flags_ & CONSTRUCTING); }
677 
setResumedGenerator()678   void setResumedGenerator() { flags_ |= RESUMED_GENERATOR; }
isResumedGenerator()679   bool isResumedGenerator() const { return !!(flags_ & RESUMED_GENERATOR); }
680 
681   /*
682    * These two queries should not be used in general: the presence/absence of
683    * the call/args object is determined by the static(ish) properties of the
684    * JSFunction/JSScript. These queries should only be performed when probing
685    * a stack frame that may be in the middle of the prologue (during which
686    * time the call/args object are created).
687    */
688 
689   inline bool hasInitialEnvironment() const;
690 
hasInitialEnvironmentUnchecked()691   bool hasInitialEnvironmentUnchecked() const {
692     return flags_ & HAS_INITIAL_ENV;
693   }
694 
hasArgsObj()695   bool hasArgsObj() const {
696     MOZ_ASSERT(script()->needsArgsObj());
697     return flags_ & HAS_ARGS_OBJ;
698   }
699 
700   /*
701    * Debugger eval frames.
702    *
703    * - If evalInFramePrev_ is non-null, frame was created for an "eval in
704    *   frame" call, which can push a successor to any live frame; so its
705    *   logical "prev" frame is not necessarily the previous frame in memory.
706    *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
707    *
708    * - Don't bother to JIT it, because it's probably short-lived.
709    *
710    * - It is required to have a environment chain object outside the
711    *   js::EnvironmentObject hierarchy: either a global object, or a
712    *   DebugEnvironmentProxy.
713    */
isDebuggerEvalFrame()714   bool isDebuggerEvalFrame() const {
715     return isEvalFrame() && !!evalInFramePrev_;
716   }
717 
prevUpToDate()718   bool prevUpToDate() const { return !!(flags_ & PREV_UP_TO_DATE); }
719 
setPrevUpToDate()720   void setPrevUpToDate() { flags_ |= PREV_UP_TO_DATE; }
721 
unsetPrevUpToDate()722   void unsetPrevUpToDate() { flags_ &= ~PREV_UP_TO_DATE; }
723 
isDebuggee()724   bool isDebuggee() const { return !!(flags_ & DEBUGGEE); }
725 
setIsDebuggee()726   void setIsDebuggee() { flags_ |= DEBUGGEE; }
727 
728   inline void unsetIsDebuggee();
729 
hasCachedSavedFrame()730   bool hasCachedSavedFrame() const { return flags_ & HAS_CACHED_SAVED_FRAME; }
setHasCachedSavedFrame()731   void setHasCachedSavedFrame() { flags_ |= HAS_CACHED_SAVED_FRAME; }
clearHasCachedSavedFrame()732   void clearHasCachedSavedFrame() { flags_ &= ~HAS_CACHED_SAVED_FRAME; }
733 
734  public:
735   void trace(JSTracer* trc, Value* sp, jsbytecode* pc);
736   void traceValues(JSTracer* trc, unsigned start, unsigned end);
737 
738   // Entered Baseline/Ion from the interpreter.
runningInJit()739   bool runningInJit() const { return !!(flags_ & RUNNING_IN_JIT); }
setRunningInJit()740   void setRunningInJit() { flags_ |= RUNNING_IN_JIT; }
clearRunningInJit()741   void clearRunningInJit() { flags_ &= ~RUNNING_IN_JIT; }
742 };
743 
744 /*****************************************************************************/
745 
746 class InterpreterRegs {
747  public:
748   Value* sp;
749   jsbytecode* pc;
750 
751  private:
752   InterpreterFrame* fp_;
753 
754  public:
fp()755   InterpreterFrame* fp() const { return fp_; }
756 
stackDepth()757   unsigned stackDepth() const {
758     MOZ_ASSERT(sp >= fp_->base());
759     return sp - fp_->base();
760   }
761 
spForStackDepth(unsigned depth)762   Value* spForStackDepth(unsigned depth) const {
763     MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
764     return fp_->base() + depth;
765   }
766 
popInlineFrame()767   void popInlineFrame() {
768     pc = fp_->prevpc();
769     unsigned spForNewTarget =
770         fp_->isResumedGenerator() ? 0 : fp_->isConstructing();
771     // This code is called when resuming from async and generator code.
772     // In the case of modules, we don't have arguments, so we can't use
773     // numActualArgs, which asserts 'hasArgs'.
774     unsigned nActualArgs = fp_->isModuleFrame() ? 0 : fp_->numActualArgs();
775     sp = fp_->prevsp() - nActualArgs - 1 - spForNewTarget;
776     fp_ = fp_->prev();
777     MOZ_ASSERT(fp_);
778   }
prepareToRun(InterpreterFrame & fp,JSScript * script)779   void prepareToRun(InterpreterFrame& fp, JSScript* script) {
780     pc = script->code();
781     sp = fp.slots() + script->nfixed();
782     fp_ = &fp;
783   }
784 
785   void setToEndOfScript();
786 
stackHandleAt(int i)787   MutableHandleValue stackHandleAt(int i) {
788     return MutableHandleValue::fromMarkedLocation(&sp[i]);
789   }
790 
stackHandleAt(int i)791   HandleValue stackHandleAt(int i) const {
792     return HandleValue::fromMarkedLocation(&sp[i]);
793   }
794 
795   friend void GDBTestInitInterpreterRegs(InterpreterRegs&,
796                                          js::InterpreterFrame*, JS::Value*,
797                                          uint8_t*);
798 };
799 
800 /*****************************************************************************/
801 
802 class InterpreterStack {
803   friend class InterpreterActivation;
804 
805   static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
806   LifoAlloc allocator_;
807 
808   // Number of interpreter frames on the stack, for over-recursion checks.
809   static const size_t MAX_FRAMES = 50 * 1000;
810   static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
811   size_t frameCount_;
812 
813   inline uint8_t* allocateFrame(JSContext* cx, size_t size);
814 
815   inline InterpreterFrame* getCallFrame(JSContext* cx, const CallArgs& args,
816                                         HandleScript script,
817                                         MaybeConstruct constructing,
818                                         Value** pargv);
819 
releaseFrame(InterpreterFrame * fp)820   void releaseFrame(InterpreterFrame* fp) {
821     frameCount_--;
822     allocator_.release(fp->mark_);
823   }
824 
825  public:
InterpreterStack()826   InterpreterStack() : allocator_(DEFAULT_CHUNK_SIZE), frameCount_(0) {}
827 
~InterpreterStack()828   ~InterpreterStack() { MOZ_ASSERT(frameCount_ == 0); }
829 
830   // For execution of eval, module or global code.
831   InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
832                                      HandleValue newTargetValue,
833                                      HandleObject envChain,
834                                      AbstractFramePtr evalInFrame);
835 
836   // Called to invoke a function.
837   InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
838                                     MaybeConstruct constructing);
839 
840   // The interpreter can push light-weight, "inline" frames without entering a
841   // new InterpreterActivation or recursively calling Interpret.
842   bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs,
843                        const CallArgs& args, HandleScript script,
844                        MaybeConstruct constructing);
845 
846   void popInlineFrame(InterpreterRegs& regs);
847 
848   bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
849                                 HandleFunction callee, HandleObject envChain);
850 
851   inline void purge(JSRuntime* rt);
852 
sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)853   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
854     return allocator_.sizeOfExcludingThis(mallocSizeOf);
855   }
856 };
857 
858 void TraceInterpreterActivations(JSContext* cx, JSTracer* trc);
859 
860 /*****************************************************************************/
861 
862 /** Base class for all function call args. */
863 class AnyInvokeArgs : public JS::CallArgs {};
864 
865 /** Base class for all function construction args. */
866 class AnyConstructArgs : public JS::CallArgs {
867   // Only js::Construct (or internal methods that call the qualified CallArgs
868   // versions) should do these things!
869   void setCallee(const Value& v) = delete;
870   void setThis(const Value& v) = delete;
871   MutableHandleValue newTarget() const = delete;
872   MutableHandleValue rval() const = delete;
873 };
874 
875 namespace detail {
876 
877 /** Function call/construct args of statically-unknown count. */
878 template <MaybeConstruct Construct>
879 class GenericArgsBase
880     : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> {
881  protected:
882   RootedValueVector v_;
883 
GenericArgsBase(JSContext * cx)884   explicit GenericArgsBase(JSContext* cx) : v_(cx) {}
885 
886  public:
init(JSContext * cx,uint64_t argc)887   bool init(JSContext* cx, uint64_t argc) {
888     if (argc > ARGS_LENGTH_MAX) {
889       JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
890                                 JSMSG_TOO_MANY_ARGUMENTS);
891       return false;
892     }
893 
894     // callee, this, arguments[, new.target iff constructing]
895     size_t len = 2 + argc + uint32_t(Construct);
896     MOZ_ASSERT(len > argc);  // no overflow
897     if (!v_.resize(len)) {
898       return false;
899     }
900 
901     *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
902     this->constructing_ = Construct;
903     if (Construct) {
904       this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
905     }
906     return true;
907   }
908 };
909 
910 /** Function call/construct args of statically-known count. */
911 template <MaybeConstruct Construct, size_t N>
912 class FixedArgsBase
913     : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> {
914   // Add +1 here to avoid noisy warning on gcc when N=0 (0 <= unsigned).
915   static_assert(N + 1 <= ARGS_LENGTH_MAX + 1, "o/~ too many args o/~");
916 
917  protected:
918   JS::RootedValueArray<2 + N + uint32_t(Construct)> v_;
919 
FixedArgsBase(JSContext * cx)920   explicit FixedArgsBase(JSContext* cx) : v_(cx) {
921     *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
922     this->constructing_ = Construct;
923     if (Construct) {
924       this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
925     }
926   }
927 };
928 
929 }  // namespace detail
930 
931 /** Function call args of statically-unknown count. */
932 class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT> {
933   using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
934 
935  public:
InvokeArgs(JSContext * cx)936   explicit InvokeArgs(JSContext* cx) : Base(cx) {}
937 };
938 
939 /** Function call args of statically-unknown count. */
940 class InvokeArgsMaybeIgnoresReturnValue
941     : public detail::GenericArgsBase<NO_CONSTRUCT> {
942   using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
943 
944  public:
InvokeArgsMaybeIgnoresReturnValue(JSContext * cx)945   explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx) : Base(cx) {}
946 
init(JSContext * cx,unsigned argc,bool ignoresReturnValue)947   bool init(JSContext* cx, unsigned argc, bool ignoresReturnValue) {
948     if (!Base::init(cx, argc)) {
949       return false;
950     }
951     this->ignoresReturnValue_ = ignoresReturnValue;
952     return true;
953   }
954 };
955 
956 /** Function call args of statically-known count. */
957 template <size_t N>
958 class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N> {
959   using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>;
960 
961  public:
FixedInvokeArgs(JSContext * cx)962   explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {}
963 };
964 
965 /** Function construct args of statically-unknown count. */
966 class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT> {
967   using Base = detail::GenericArgsBase<CONSTRUCT>;
968 
969  public:
ConstructArgs(JSContext * cx)970   explicit ConstructArgs(JSContext* cx) : Base(cx) {}
971 };
972 
973 /** Function call args of statically-known count. */
974 template <size_t N>
975 class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N> {
976   using Base = detail::FixedArgsBase<CONSTRUCT, N>;
977 
978  public:
FixedConstructArgs(JSContext * cx)979   explicit FixedConstructArgs(JSContext* cx) : Base(cx) {}
980 };
981 
982 template <class Args, class Arraylike>
FillArgumentsFromArraylike(JSContext * cx,Args & args,const Arraylike & arraylike)983 inline bool FillArgumentsFromArraylike(JSContext* cx, Args& args,
984                                        const Arraylike& arraylike) {
985   uint32_t len = arraylike.length();
986   if (!args.init(cx, len)) {
987     return false;
988   }
989 
990   for (uint32_t i = 0; i < len; i++) {
991     args[i].set(arraylike[i]);
992   }
993 
994   return true;
995 }
996 
997 }  // namespace js
998 
999 namespace mozilla {
1000 
1001 template <>
1002 struct DefaultHasher<js::AbstractFramePtr> {
1003   using Lookup = js::AbstractFramePtr;
1004 
1005   static js::HashNumber hash(const Lookup& key) {
1006     return mozilla::HashGeneric(key.raw());
1007   }
1008 
1009   static bool match(const js::AbstractFramePtr& k, const Lookup& l) {
1010     return k == l;
1011   }
1012 };
1013 
1014 }  // namespace mozilla
1015 
1016 #endif  // vm_Stack_h
1017