Stack.h (33654B)
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/HashFunctions.h" 11 #include "mozilla/MemoryReporting.h" 12 13 #include <algorithm> 14 #include <type_traits> 15 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 25 26 namespace js { 27 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; 39 40 namespace jit { 41 class CommonFrameLayout; 42 } 43 namespace wasm { 44 class Instance; 45 } // namespace wasm 46 47 // [SMDOC] VM stack layout 48 // 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. 54 // 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. 60 61 // Interpreter frames (InterpreterFrame) 62 // 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. 66 // 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. 71 // 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. 77 78 enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false }; 79 80 } // namespace js 81 82 /*****************************************************************************/ 83 84 namespace js { 85 86 namespace jit { 87 class BaselineFrame; 88 class RematerializedFrame; 89 } // namespace jit 90 91 /** 92 * Pointer to a live JS or WASM stack frame. 93 */ 94 class AbstractFramePtr { 95 friend class FrameIter; 96 97 uintptr_t ptr_; 98 99 enum { 100 Tag_InterpreterFrame = 0x0, 101 Tag_BaselineFrame = 0x1, 102 Tag_RematerializedFrame = 0x2, 103 Tag_WasmDebugFrame = 0x3, 104 TagMask = 0x3 105 }; 106 107 public: 108 AbstractFramePtr() : ptr_(0) {} 109 110 MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp) 111 : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0) { 112 MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp); 113 } 114 115 MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp) 116 : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0) { 117 MOZ_ASSERT_IF(fp, asBaselineFrame() == fp); 118 } 119 120 MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp) 121 : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0) { 122 MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp); 123 } 124 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); 129 } 130 131 bool isInterpreterFrame() const { 132 return (ptr_ & TagMask) == Tag_InterpreterFrame; 133 } 134 InterpreterFrame* asInterpreterFrame() const { 135 MOZ_ASSERT(isInterpreterFrame()); 136 InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask); 137 MOZ_ASSERT(res); 138 return res; 139 } 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; 146 } 147 bool isRematerializedFrame() const { 148 return (ptr_ & TagMask) == Tag_RematerializedFrame; 149 } 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; 156 } 157 bool isWasmDebugFrame() const { 158 return (ptr_ & TagMask) == Tag_WasmDebugFrame; 159 } 160 wasm::DebugFrame* asWasmDebugFrame() const { 161 MOZ_ASSERT(isWasmDebugFrame()); 162 wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask); 163 MOZ_ASSERT(res); 164 return res; 165 } 166 167 void* raw() const { return reinterpret_cast<void*>(ptr_); } 168 169 bool operator==(const AbstractFramePtr& other) const { 170 return ptr_ == other.ptr_; 171 } 172 bool operator!=(const AbstractFramePtr& other) const { 173 return ptr_ != other.ptr_; 174 } 175 176 explicit operator bool() const { return !!ptr_; } 177 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(); 186 187 inline JS::Realm* realm() const; 188 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; 194 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; 203 204 inline bool isConstructing() const; 205 206 inline bool debuggerNeedsCheckPrimitiveReturn() const; 207 208 inline bool isFunctionFrame() const; 209 inline bool isGeneratorFrame() const; 210 211 inline bool saveGeneratorSlots(JSContext* cx, unsigned nslots, 212 ArrayObject* dest) const; 213 214 inline bool hasCachedSavedFrame() const; 215 216 inline unsigned numActualArgs() const; 217 inline unsigned numFormalArgs() const; 218 219 inline Value* argv() const; 220 221 inline bool hasArgs() const; 222 inline bool hasArgsObj() const; 223 inline ArgumentsObject& argsObj() const; 224 inline void initArgsObj(ArgumentsObject& argsobj) const; 225 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); 233 234 inline bool prevUpToDate() const; 235 inline void setPrevUpToDate() const; 236 inline void unsetPrevUpToDate() const; 237 238 inline bool isDebuggee() const; 239 inline void setIsDebuggee(); 240 inline void unsetIsDebuggee(); 241 242 inline HandleValue returnValue() const; 243 inline void setReturnValue(const Value& rval) const; 244 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); 252 }; 253 254 class NullFramePtr : public AbstractFramePtr { 255 public: 256 NullFramePtr() = default; 257 }; 258 259 enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true }; 260 261 /*****************************************************************************/ 262 263 class InterpreterFrame { 264 enum Flags : uint32_t { 265 CONSTRUCTING = 0x1, /* frame is for a constructor invocation */ 266 267 RESUMED_GENERATOR = 0x2, /* frame is for a resumed generator invocation */ 268 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 */ 273 274 /* Lazy frame initialization */ 275 HAS_RVAL = 0x10, /* frame has rval_ set */ 276 277 /* Debugger state */ 278 PREV_UP_TO_DATE = 0x20, /* see DebugScopes::updateLiveScopes */ 279 280 /* 281 * See comment above 'isDebuggee' in Realm.h for explanation of 282 * invariants of debuggee compartments, scripts, and frames. 283 */ 284 DEBUGGEE = 0x40, /* Execution is being observed by Debugger */ 285 286 /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */ 287 HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */ 288 289 /* 290 * If set, we entered one of the JITs and ScriptFrameIter should skip 291 * this frame. 292 */ 293 RUNNING_IN_JIT = 0x100, 294 295 /* 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. 299 */ 300 HAS_CACHED_SAVED_FRAME = 0x200, 301 }; 302 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 */ 309 310 /* 311 * Previous frame and its pc and sp. Always nullptr for 312 * InterpreterActivation's entry frame, always non-nullptr for inline 313 * frames. 314 */ 315 InterpreterFrame* prev_; 316 jsbytecode* prevpc_; 317 Value* prevsp_; 318 319 /* 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. 322 */ 323 AbstractFramePtr evalInFramePrev_; 324 325 Value* argv_; /* If hasArgs(), points to frame's arguments. */ 326 LifoAlloc::Mark mark_; /* Used to release memory for this frame. */ 327 328 static void staticAsserts() { 329 static_assert(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0); 330 static_assert(sizeof(InterpreterFrame) % sizeof(Value) == 0); 331 } 332 333 /* 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). 338 */ 339 Value* slots() const { return (Value*)(this + 1); } 340 Value* base() const { return slots() + script()->nfixed(); } 341 342 friend class FrameIter; 343 friend class InterpreterRegs; 344 friend class InterpreterStack; 345 friend class jit::BaselineFrame; 346 347 /* 348 * Frame initialization, called by InterpreterStack operations after acquiring 349 * the raw memory for the frame: 350 */ 351 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); 356 357 /* Used for eval, module or global frames. */ 358 void initExecuteFrame(JSContext* cx, HandleScript script, 359 AbstractFramePtr prev, HandleObject envChain); 360 361 public: 362 /* 363 * Frame prologue/epilogue 364 * 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). 368 * 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. 374 * 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. 379 */ 380 381 bool prologue(JSContext* cx); 382 void epilogue(JSContext* cx, jsbytecode* pc); 383 384 bool checkReturn(JSContext* cx, HandleValue thisv, MutableHandleValue result); 385 386 bool initFunctionEnvironmentObjects(JSContext* cx); 387 388 /* 389 * Initialize locals of newly-pushed frame to undefined. 390 */ 391 void initLocals(); 392 393 /* 394 * Stack frame type 395 * 396 * A stack frame may have one of four types, which determines which 397 * members of the frame may be accessed and other invariants: 398 * 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 403 */ 404 405 bool isGlobalFrame() const { return script_->isGlobalCode(); } 406 407 bool isModuleFrame() const { return script_->isModule(); } 408 409 bool isEvalFrame() const { return script_->isForEval(); } 410 411 bool isFunctionFrame() const { return script_->isFunction(); } 412 413 /* 414 * Previous frame 415 * 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. 424 */ 425 426 InterpreterFrame* prev() const { return prev_; } 427 428 AbstractFramePtr evalInFramePrev() const { 429 MOZ_ASSERT(isEvalFrame()); 430 return evalInFramePrev_; 431 } 432 433 /* 434 * (Unaliased) locals and arguments 435 * 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|. 440 * 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. 446 */ 447 448 inline Value& unaliasedLocal(uint32_t i); 449 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); 457 458 unsigned numFormalArgs() const { 459 MOZ_ASSERT(hasArgs()); 460 return callee().nargs(); 461 } 462 unsigned numActualArgs() const { 463 MOZ_ASSERT(hasArgs()); 464 return nactual_; 465 } 466 467 /* Watch out, this exposes a pointer to the unaliased formal arg array. */ 468 Value* argv() const { 469 MOZ_ASSERT(hasArgs()); 470 return argv_; 471 } 472 473 /* 474 * Arguments object 475 * 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. 482 */ 483 484 ArgumentsObject& argsObj() const; 485 void initArgsObj(ArgumentsObject& argsobj); 486 487 ArrayObject* createRestParameter(JSContext* cx); 488 489 /* 490 * Environment chain 491 * 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. 495 * 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. 507 */ 508 509 inline HandleObject environmentChain() const; 510 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; 518 519 template <typename SpecificEnvironment> 520 inline void pushOnEnvironmentChain(SpecificEnvironment& env); 521 template <typename SpecificEnvironment> 522 inline void popOffEnvironmentChain(); 523 inline void replaceInnermostEnvironment(BlockLexicalEnvironmentObject& env); 524 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); 528 529 /* 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. 538 */ 539 540 bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope); 541 bool freshenLexicalEnvironment(JSContext* cx, jsbytecode* pc); 542 bool recreateLexicalEnvironment(JSContext* cx, jsbytecode* pc); 543 544 bool pushClassBodyEnvironment(JSContext* cx, Handle<ClassBodyScope*> scope); 545 546 /* 547 * Script 548 * 549 * All frames have an associated JSScript which holds the bytecode being 550 * executed for the frame. 551 */ 552 553 JSScript* script() const { return script_; } 554 555 /* Return the previous frame's pc. */ 556 jsbytecode* prevpc() { 557 MOZ_ASSERT(prev_); 558 return prevpc_; 559 } 560 561 /* Return the previous frame's sp. */ 562 Value* prevsp() { 563 MOZ_ASSERT(prev_); 564 return prevsp_; 565 } 566 567 /* 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. 572 */ 573 Value& thisArgument() const { 574 MOZ_ASSERT(isFunctionFrame()); 575 return argv()[-1]; 576 } 577 578 /* 579 * Callee 580 * 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. 585 */ 586 587 JSFunction& callee() const { 588 MOZ_ASSERT(isFunctionFrame()); 589 return calleev().toObject().as<JSFunction>(); 590 } 591 592 const Value& calleev() const { 593 MOZ_ASSERT(isFunctionFrame()); 594 return argv()[-2]; 595 } 596 597 /* 598 * New Target 599 * 600 * Only non-arrow function frames have a meaningful newTarget. 601 */ 602 Value newTarget() const { 603 MOZ_ASSERT(isFunctionFrame()); 604 MOZ_ASSERT(!callee().isArrow()); 605 606 if (isConstructing()) { 607 unsigned pushedArgs = std::max(numFormalArgs(), numActualArgs()); 608 return argv()[pushedArgs]; 609 } 610 return UndefinedValue(); 611 } 612 613 /* Profiler flags */ 614 615 bool hasPushedGeckoProfilerFrame() { 616 return !!(flags_ & HAS_PUSHED_PROF_FRAME); 617 } 618 619 void setPushedGeckoProfilerFrame() { flags_ |= HAS_PUSHED_PROF_FRAME; } 620 621 void unsetPushedGeckoProfilerFrame() { flags_ &= ~HAS_PUSHED_PROF_FRAME; } 622 623 /* Return value */ 624 625 bool hasReturnValue() const { return flags_ & HAS_RVAL; } 626 627 MutableHandleValue returnValue() { 628 if (!hasReturnValue()) { 629 rval_.setUndefined(); 630 } 631 return MutableHandleValue::fromMarkedLocation(&rval_); 632 } 633 634 void markReturnValue() { flags_ |= HAS_RVAL; } 635 636 void setReturnValue(const Value& v) { 637 rval_ = v; 638 markReturnValue(); 639 } 640 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; 645 646 // Copy values from the Array into this stack frame, for resuming. 647 inline void restoreGeneratorSlots(ArrayObject* src); 648 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; 654 } 655 656 /* 657 * Other flags 658 */ 659 660 bool isConstructing() const { return !!(flags_ & CONSTRUCTING); } 661 662 void setResumedGenerator() { flags_ |= RESUMED_GENERATOR; } 663 bool isResumedGenerator() const { return !!(flags_ & RESUMED_GENERATOR); } 664 665 /* 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). 671 */ 672 673 inline bool hasInitialEnvironment() const; 674 675 bool hasInitialEnvironmentUnchecked() const { 676 return flags_ & HAS_INITIAL_ENV; 677 } 678 679 bool hasArgsObj() const { 680 MOZ_ASSERT(script()->needsArgsObj()); 681 return flags_ & HAS_ARGS_OBJ; 682 } 683 684 /* 685 * Debugger eval frames. 686 * 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. 691 * 692 * - Don't bother to JIT it, because it's probably short-lived. 693 * 694 * - It is required to have a environment chain object outside the 695 * js::EnvironmentObject hierarchy: either a global object, or a 696 * DebugEnvironmentProxy. 697 */ 698 bool isDebuggerEvalFrame() const { 699 return isEvalFrame() && !!evalInFramePrev_; 700 } 701 702 bool prevUpToDate() const { return !!(flags_ & PREV_UP_TO_DATE); } 703 704 void setPrevUpToDate() { flags_ |= PREV_UP_TO_DATE; } 705 706 void unsetPrevUpToDate() { flags_ &= ~PREV_UP_TO_DATE; } 707 708 bool isDebuggee() const { return !!(flags_ & DEBUGGEE); } 709 710 void setIsDebuggee() { flags_ |= DEBUGGEE; } 711 712 inline void unsetIsDebuggee(); 713 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; } 717 718 public: 719 void trace(JSTracer* trc, Value* sp, jsbytecode* pc); 720 void traceValues(JSTracer* trc, unsigned start, unsigned end); 721 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; } 726 }; 727 728 /*****************************************************************************/ 729 730 class InterpreterRegs { 731 public: 732 Value* sp; 733 jsbytecode* pc; 734 735 private: 736 InterpreterFrame* fp_; 737 738 public: 739 InterpreterFrame* fp() const { return fp_; } 740 741 unsigned stackDepth() const { 742 MOZ_ASSERT(sp >= fp_->base()); 743 return sp - fp_->base(); 744 } 745 746 Value* spForStackDepth(unsigned depth) const { 747 MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots()); 748 return fp_->base() + depth; 749 } 750 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_); 762 } 763 void prepareToRun(InterpreterFrame& fp, JSScript* script) { 764 pc = script->code(); 765 sp = fp.slots() + script->nfixed(); 766 fp_ = &fp; 767 } 768 769 void setToEndOfScript(); 770 771 MutableHandleValue stackHandleAt(int i) { 772 return MutableHandleValue::fromMarkedLocation(&sp[i]); 773 } 774 775 HandleValue stackHandleAt(int i) const { 776 return HandleValue::fromMarkedLocation(&sp[i]); 777 } 778 779 friend void GDBTestInitInterpreterRegs(InterpreterRegs&, 780 js::InterpreterFrame*, JS::Value*, 781 uint8_t*); 782 }; 783 784 /*****************************************************************************/ 785 786 class InterpreterStack { 787 friend class InterpreterActivation; 788 789 static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024; 790 LifoAlloc allocator_; 791 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_; 796 797 inline uint8_t* allocateFrame(JSContext* cx, size_t size); 798 799 inline InterpreterFrame* getCallFrame(JSContext* cx, const CallArgs& args, 800 HandleScript script, 801 MaybeConstruct constructing, 802 Value** pargv); 803 804 void releaseFrame(InterpreterFrame* fp) { 805 frameCount_--; 806 allocator_.release(fp->mark_); 807 } 808 809 public: 810 InterpreterStack() 811 : allocator_(DEFAULT_CHUNK_SIZE, js::MallocArena), frameCount_(0) {} 812 813 ~InterpreterStack() { MOZ_ASSERT(frameCount_ == 0); } 814 815 // For execution of eval, module or global code. 816 InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script, 817 HandleObject envChain, 818 AbstractFramePtr evalInFrame); 819 820 // Called to invoke a function. 821 InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args, 822 MaybeConstruct constructing); 823 824 // The interpreter can push light-weight, "inline" frames without entering a 825 // new InterpreterActivation or recursively calling Interpret. 826 bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs, 827 const CallArgs& args, HandleScript script, 828 MaybeConstruct constructing); 829 830 void popInlineFrame(InterpreterRegs& regs); 831 832 bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, 833 HandleFunction callee, HandleObject envChain); 834 835 inline void purge(JSRuntime* rt); 836 837 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { 838 return allocator_.sizeOfExcludingThis(mallocSizeOf); 839 } 840 }; 841 842 void TraceInterpreterActivations(JSContext* cx, JSTracer* trc); 843 844 /*****************************************************************************/ 845 846 /** Base class for all function call args. */ 847 class AnyInvokeArgs : public JS::CallArgs {}; 848 849 /** Base class for all function construction args. */ 850 class AnyConstructArgs : public JS::CallArgs { 851 // Only js::Construct (or internal methods that call the qualified CallArgs 852 // versions) should do these things! 853 void setCallee(const Value& v) = delete; 854 void setThis(const Value& v) = delete; 855 MutableHandleValue newTarget() const = delete; 856 MutableHandleValue rval() const = delete; 857 }; 858 859 namespace detail { 860 861 /** Function call/construct args of statically-unknown count. */ 862 template <MaybeConstruct Construct> 863 class GenericArgsBase 864 : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> { 865 protected: 866 RootedValueVector v_; 867 868 explicit GenericArgsBase(JSContext* cx) : v_(cx) {} 869 870 public: 871 bool init(JSContext* cx, uint64_t argc) { 872 if (argc > ARGS_LENGTH_MAX) { 873 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 874 JSMSG_TOO_MANY_ARGUMENTS); 875 return false; 876 } 877 878 // callee, this, arguments[, new.target iff constructing] 879 size_t len = 2 + argc + uint32_t(Construct); 880 MOZ_ASSERT(len > argc); // no overflow 881 if (!v_.resize(len)) { 882 return false; 883 } 884 885 *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin()); 886 this->constructing_ = Construct; 887 if (Construct) { 888 this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING)); 889 } 890 return true; 891 } 892 }; 893 894 /** Function call/construct args of statically-known count. */ 895 template <MaybeConstruct Construct, size_t N> 896 class FixedArgsBase 897 : public std::conditional_t<Construct, AnyConstructArgs, AnyInvokeArgs> { 898 // Add +1 here to avoid noisy warning on gcc when N=0 (0 <= unsigned). 899 static_assert(N + 1 <= ARGS_LENGTH_MAX + 1, "o/~ too many args o/~"); 900 901 protected: 902 JS::RootedValueArray<2 + N + uint32_t(Construct)> v_; 903 904 explicit FixedArgsBase(JSContext* cx) : v_(cx) { 905 *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin()); 906 this->constructing_ = Construct; 907 if (Construct) { 908 this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING)); 909 } 910 } 911 }; 912 913 } // namespace detail 914 915 /** Function call args of statically-unknown count. */ 916 class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT> { 917 using Base = detail::GenericArgsBase<NO_CONSTRUCT>; 918 919 public: 920 explicit InvokeArgs(JSContext* cx) : Base(cx) {} 921 }; 922 923 /** Function call args of statically-unknown count. */ 924 class InvokeArgsMaybeIgnoresReturnValue 925 : public detail::GenericArgsBase<NO_CONSTRUCT> { 926 using Base = detail::GenericArgsBase<NO_CONSTRUCT>; 927 928 public: 929 explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx) : Base(cx) {} 930 931 bool init(JSContext* cx, unsigned argc, bool ignoresReturnValue) { 932 if (!Base::init(cx, argc)) { 933 return false; 934 } 935 this->ignoresReturnValue_ = ignoresReturnValue; 936 return true; 937 } 938 }; 939 940 /** Function call args of statically-known count. */ 941 template <size_t N> 942 class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N> { 943 using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>; 944 945 public: 946 explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {} 947 }; 948 949 /** Function construct args of statically-unknown count. */ 950 class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT> { 951 using Base = detail::GenericArgsBase<CONSTRUCT>; 952 953 public: 954 explicit ConstructArgs(JSContext* cx) : Base(cx) {} 955 }; 956 957 /** Function call args of statically-known count. */ 958 template <size_t N> 959 class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N> { 960 using Base = detail::FixedArgsBase<CONSTRUCT, N>; 961 962 public: 963 explicit FixedConstructArgs(JSContext* cx) : Base(cx) {} 964 }; 965 966 template <class Args, class Arraylike> 967 inline bool FillArgumentsFromArraylike(JSContext* cx, Args& args, 968 const Arraylike& arraylike) { 969 uint32_t len = arraylike.length(); 970 if (!args.init(cx, len)) { 971 return false; 972 } 973 974 for (uint32_t i = 0; i < len; i++) { 975 args[i].set(arraylike[i]); 976 } 977 978 return true; 979 } 980 981 #ifdef ENABLE_PORTABLE_BASELINE_INTERP 982 struct PortableBaselineStack { 983 static const size_t DEFAULT_SIZE = 512 * 1024; 984 985 void* base; 986 void* top; 987 988 bool valid() { return base != nullptr; } 989 990 PortableBaselineStack() { 991 base = js_calloc(DEFAULT_SIZE); 992 top = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base) + 993 DEFAULT_SIZE); 994 } 995 ~PortableBaselineStack() { js_free(base); } 996 }; 997 #endif // ENABLE_PORTABLE_BASELINE_INTERP 998 999 } // namespace js 1000 1001 namespace mozilla { 1002 1003 template <> 1004 struct DefaultHasher<js::AbstractFramePtr> { 1005 using Lookup = js::AbstractFramePtr; 1006 1007 static js::HashNumber hash(const Lookup& key) { 1008 return mozilla::HashGeneric(key.raw()); 1009 } 1010 1011 static bool match(const js::AbstractFramePtr& k, const Lookup& l) { 1012 return k == l; 1013 } 1014 }; 1015 1016 } // namespace mozilla 1017 1018 #endif // vm_Stack_h