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