Stack-inl.h (25124B)
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_inl_h 8 #define vm_Stack_inl_h 9 10 #include "vm/Stack.h" 11 12 #include "mozilla/PodOperations.h" 13 14 #include "jit/BaselineFrame.h" 15 #include "jit/RematerializedFrame.h" 16 #include "js/friend/StackLimits.h" // js::ReportOverRecursed 17 #include "vm/EnvironmentObject.h" 18 #include "vm/Interpreter.h" 19 #include "vm/JSContext.h" 20 #include "vm/JSScript.h" 21 22 #include "jit/BaselineFrame-inl.h" 23 #include "jit/RematerializedFrame-inl.h" // js::jit::RematerializedFrame::unsetIsDebuggee 24 #include "vm/JSScript-inl.h" 25 #include "vm/NativeObject-inl.h" 26 27 namespace js { 28 29 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* vec, size_t len) { 30 for (size_t i = 0; i < len; i++) { 31 vec[i].setUndefined(); 32 } 33 } 34 35 inline HandleObject InterpreterFrame::environmentChain() const { 36 return HandleObject::fromMarkedLocation(&envChain_); 37 } 38 39 inline GlobalObject& InterpreterFrame::global() const { 40 return script()->global(); 41 } 42 43 inline ExtensibleLexicalEnvironmentObject& 44 InterpreterFrame::extensibleLexicalEnvironment() const { 45 return NearestEnclosingExtensibleLexicalEnvironment(environmentChain()); 46 } 47 48 inline void InterpreterFrame::initCallFrame(InterpreterFrame* prev, 49 jsbytecode* prevpc, Value* prevsp, 50 JSFunction& callee, 51 JSScript* script, Value* argv, 52 uint32_t nactual, 53 MaybeConstruct constructing) { 54 MOZ_ASSERT(callee.baseScript() == script); 55 56 /* Initialize stack frame members. */ 57 flags_ = 0; 58 if (constructing) { 59 flags_ |= CONSTRUCTING; 60 } 61 argv_ = argv; 62 script_ = script; 63 nactual_ = nactual; 64 envChain_ = callee.environment(); 65 prev_ = prev; 66 prevpc_ = prevpc; 67 prevsp_ = prevsp; 68 69 if (script->isDebuggee()) { 70 setIsDebuggee(); 71 } 72 73 initLocals(); 74 } 75 76 inline void InterpreterFrame::initLocals() { 77 SetValueRangeToUndefined(slots(), script()->nfixed()); 78 } 79 80 inline Value& InterpreterFrame::unaliasedLocal(uint32_t i) { 81 MOZ_ASSERT(i < script()->nfixed()); 82 return slots()[i]; 83 } 84 85 inline Value& InterpreterFrame::unaliasedFormal( 86 unsigned i, MaybeCheckAliasing checkAliasing) { 87 MOZ_ASSERT(i < numFormalArgs()); 88 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals()); 89 MOZ_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i)); 90 return argv()[i]; 91 } 92 93 inline Value& InterpreterFrame::unaliasedActual( 94 unsigned i, MaybeCheckAliasing checkAliasing) { 95 MOZ_ASSERT(i < numActualArgs()); 96 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals()); 97 MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), 98 !script()->formalIsAliased(i)); 99 return argv()[i]; 100 } 101 102 template <class Op> 103 inline void InterpreterFrame::unaliasedForEachActual(Op op) { 104 // Don't assert !script()->funHasAnyAliasedFormal() since this function is 105 // called from ArgumentsObject::createUnexpected() which can access aliased 106 // slots. 107 108 const Value* argsEnd = argv() + numActualArgs(); 109 for (const Value* p = argv(); p < argsEnd; ++p) { 110 op(*p); 111 } 112 } 113 114 inline ArgumentsObject& InterpreterFrame::argsObj() const { 115 MOZ_ASSERT(script()->needsArgsObj()); 116 MOZ_ASSERT(flags_ & HAS_ARGS_OBJ); 117 return *argsObj_; 118 } 119 120 inline void InterpreterFrame::initArgsObj(ArgumentsObject& argsobj) { 121 MOZ_ASSERT(script()->needsArgsObj()); 122 flags_ |= HAS_ARGS_OBJ; 123 argsObj_ = &argsobj; 124 } 125 126 inline EnvironmentObject& InterpreterFrame::aliasedEnvironment( 127 EnvironmentCoordinate ec) const { 128 JSObject* env = &environmentChain()->as<EnvironmentObject>(); 129 for (unsigned i = ec.hops(); i; i--) { 130 env = &env->as<EnvironmentObject>().enclosingEnvironment(); 131 } 132 return env->as<EnvironmentObject>(); 133 } 134 135 inline EnvironmentObject& InterpreterFrame::aliasedEnvironmentMaybeDebug( 136 EnvironmentCoordinate ec) const { 137 JSObject* env = environmentChain(); 138 for (unsigned i = ec.hops(); i; i--) { 139 if (env->is<EnvironmentObject>()) { 140 env = &env->as<EnvironmentObject>().enclosingEnvironment(); 141 } else { 142 MOZ_ASSERT(env->is<DebugEnvironmentProxy>()); 143 env = &env->as<DebugEnvironmentProxy>().enclosingEnvironment(); 144 } 145 } 146 return env->is<EnvironmentObject>() 147 ? env->as<EnvironmentObject>() 148 : env->as<DebugEnvironmentProxy>().environment(); 149 } 150 151 template <typename SpecificEnvironment> 152 inline void InterpreterFrame::pushOnEnvironmentChain(SpecificEnvironment& env) { 153 MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment()); 154 envChain_ = &env; 155 if (IsFrameInitialEnvironment(this, env)) { 156 flags_ |= HAS_INITIAL_ENV; 157 } 158 } 159 160 template <typename SpecificEnvironment> 161 inline void InterpreterFrame::popOffEnvironmentChain() { 162 MOZ_ASSERT(envChain_->is<SpecificEnvironment>()); 163 envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment(); 164 } 165 166 inline void InterpreterFrame::replaceInnermostEnvironment( 167 BlockLexicalEnvironmentObject& env) { 168 MOZ_ASSERT( 169 env.enclosingEnvironment() == 170 envChain_->as<BlockLexicalEnvironmentObject>().enclosingEnvironment()); 171 envChain_ = &env; 172 } 173 174 bool InterpreterFrame::hasInitialEnvironment() const { 175 MOZ_ASSERT(script()->initialEnvironmentShape()); 176 return flags_ & HAS_INITIAL_ENV; 177 } 178 179 inline CallObject& InterpreterFrame::callObj() const { 180 MOZ_ASSERT(callee().needsCallObject()); 181 182 JSObject* pobj = environmentChain(); 183 while (MOZ_UNLIKELY(!pobj->is<CallObject>())) { 184 pobj = pobj->enclosingEnvironment(); 185 } 186 return pobj->as<CallObject>(); 187 } 188 189 inline void InterpreterFrame::unsetIsDebuggee() { 190 MOZ_ASSERT(!script()->isDebuggee()); 191 flags_ &= ~DEBUGGEE; 192 } 193 194 inline bool InterpreterFrame::saveGeneratorSlots(JSContext* cx, unsigned nslots, 195 ArrayObject* dest) const { 196 return dest->initDenseElementsFromRange(cx, slots(), slots() + nslots); 197 } 198 199 inline void InterpreterFrame::restoreGeneratorSlots(ArrayObject* src) { 200 MOZ_ASSERT(script()->nfixed() <= src->length()); 201 MOZ_ASSERT(src->length() <= script()->nslots()); 202 MOZ_ASSERT(src->getDenseInitializedLength() == src->length()); 203 const Value* srcElements = src->getDenseElements(); 204 mozilla::PodCopy(slots(), srcElements, src->length()); 205 } 206 207 /*****************************************************************************/ 208 209 inline void InterpreterStack::purge(JSRuntime* rt) { 210 rt->gc.queueUnusedLifoBlocksForFree(&allocator_); 211 } 212 213 uint8_t* InterpreterStack::allocateFrame(JSContext* cx, size_t size) { 214 size_t maxFrames; 215 if (cx->realm()->principals() == cx->runtime()->trustedPrincipals()) { 216 maxFrames = MAX_FRAMES_TRUSTED; 217 } else { 218 maxFrames = MAX_FRAMES; 219 } 220 221 if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) { 222 ReportOverRecursed(cx); 223 return nullptr; 224 } 225 226 uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size)); 227 if (!buffer) { 228 ReportOutOfMemory(cx); 229 return nullptr; 230 } 231 232 frameCount_++; 233 return buffer; 234 } 235 236 MOZ_ALWAYS_INLINE InterpreterFrame* InterpreterStack::getCallFrame( 237 JSContext* cx, const CallArgs& args, HandleScript script, 238 MaybeConstruct constructing, Value** pargv) { 239 JSFunction* fun = &args.callee().as<JSFunction>(); 240 241 MOZ_ASSERT(fun->baseScript() == script); 242 unsigned nformal = fun->nargs(); 243 unsigned nvals = script->nslots(); 244 245 if (args.length() >= nformal) { 246 *pargv = args.array(); 247 uint8_t* buffer = 248 allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); 249 return reinterpret_cast<InterpreterFrame*>(buffer); 250 } 251 252 // Pad any missing arguments with |undefined|. 253 MOZ_ASSERT(args.length() < nformal); 254 255 unsigned nfunctionState = 2 + constructing; // callee, |this|, |new.target| 256 257 nvals += nformal + nfunctionState; 258 uint8_t* buffer = 259 allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); 260 if (!buffer) { 261 return nullptr; 262 } 263 264 Value* argv = reinterpret_cast<Value*>(buffer); 265 unsigned nmissing = nformal - args.length(); 266 267 mozilla::PodCopy(argv, args.base(), 2 + args.length()); 268 SetValueRangeToUndefined(argv + 2 + args.length(), nmissing); 269 270 if (constructing) { 271 argv[2 + nformal] = args.newTarget(); 272 } 273 274 *pargv = argv + 2; 275 return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal); 276 } 277 278 MOZ_ALWAYS_INLINE bool InterpreterStack::pushInlineFrame( 279 JSContext* cx, InterpreterRegs& regs, const CallArgs& args, 280 HandleScript script, MaybeConstruct constructing) { 281 RootedFunction callee(cx, &args.callee().as<JSFunction>()); 282 MOZ_ASSERT(regs.sp == args.end()); 283 MOZ_ASSERT(callee->baseScript() == script); 284 285 InterpreterFrame* prev = regs.fp(); 286 jsbytecode* prevpc = regs.pc; 287 Value* prevsp = regs.sp; 288 MOZ_ASSERT(prev); 289 290 LifoAlloc::Mark mark = allocator_.mark(); 291 292 Value* argv; 293 InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv); 294 if (!fp) { 295 return false; 296 } 297 298 fp->mark_ = mark; 299 300 /* Initialize frame, locals, regs. */ 301 fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, args.length(), 302 constructing); 303 304 regs.prepareToRun(*fp, script); 305 return true; 306 } 307 308 MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame( 309 JSContext* cx, InterpreterRegs& regs, HandleFunction callee, 310 HandleObject envChain) { 311 MOZ_ASSERT(callee->isGenerator() || callee->isAsync()); 312 RootedScript script(cx, callee->nonLazyScript()); 313 InterpreterFrame* prev = regs.fp(); 314 jsbytecode* prevpc = regs.pc; 315 Value* prevsp = regs.sp; 316 MOZ_ASSERT(prev); 317 318 LifoAlloc::Mark mark = allocator_.mark(); 319 320 // (Async) generators and async functions are not constructors. 321 MOZ_ASSERT(!callee->isConstructor()); 322 323 // Include callee, |this|, and maybe |new.target| 324 unsigned nformal = callee->nargs(); 325 unsigned nvals = 2 + nformal + script->nslots(); 326 327 uint8_t* buffer = 328 allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); 329 if (!buffer) { 330 return false; 331 } 332 333 Value* argv = reinterpret_cast<Value*>(buffer) + 2; 334 argv[-2] = ObjectValue(*callee); 335 argv[-1] = UndefinedValue(); 336 SetValueRangeToUndefined(argv, nformal); 337 338 InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal); 339 fp->mark_ = mark; 340 fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0, 341 NO_CONSTRUCT); 342 fp->resumeGeneratorFrame(envChain); 343 344 regs.prepareToRun(*fp, script); 345 return true; 346 } 347 348 MOZ_ALWAYS_INLINE void InterpreterStack::popInlineFrame(InterpreterRegs& regs) { 349 InterpreterFrame* fp = regs.fp(); 350 regs.popInlineFrame(); 351 regs.sp[-1] = fp->returnValue(); 352 releaseFrame(fp); 353 MOZ_ASSERT(regs.fp()); 354 } 355 356 inline HandleValue AbstractFramePtr::returnValue() const { 357 if (isInterpreterFrame()) { 358 return asInterpreterFrame()->returnValue(); 359 } 360 if (isWasmDebugFrame()) { 361 return asWasmDebugFrame()->returnValue(); 362 } 363 return asBaselineFrame()->returnValue(); 364 } 365 366 inline void AbstractFramePtr::setReturnValue(const Value& rval) const { 367 if (isInterpreterFrame()) { 368 asInterpreterFrame()->setReturnValue(rval); 369 return; 370 } 371 if (isBaselineFrame()) { 372 asBaselineFrame()->setReturnValue(rval); 373 return; 374 } 375 if (isWasmDebugFrame()) { 376 // TODO handle wasm function return value 377 // The function is called from Debugger::slowPathOnLeaveFrame -- 378 // ignoring value for wasm. 379 return; 380 } 381 asRematerializedFrame()->setReturnValue(rval); 382 } 383 384 inline JSObject* AbstractFramePtr::environmentChain() const { 385 if (isInterpreterFrame()) { 386 return asInterpreterFrame()->environmentChain(); 387 } 388 if (isBaselineFrame()) { 389 return asBaselineFrame()->environmentChain(); 390 } 391 if (isWasmDebugFrame()) { 392 return &global()->lexicalEnvironment(); 393 } 394 return asRematerializedFrame()->environmentChain(); 395 } 396 397 template <typename SpecificEnvironment> 398 inline void AbstractFramePtr::pushOnEnvironmentChain(SpecificEnvironment& env) { 399 if (isInterpreterFrame()) { 400 asInterpreterFrame()->pushOnEnvironmentChain(env); 401 return; 402 } 403 if (isBaselineFrame()) { 404 asBaselineFrame()->pushOnEnvironmentChain(env); 405 return; 406 } 407 asRematerializedFrame()->pushOnEnvironmentChain(env); 408 } 409 410 template <typename SpecificEnvironment> 411 inline void AbstractFramePtr::popOffEnvironmentChain() { 412 if (isInterpreterFrame()) { 413 asInterpreterFrame()->popOffEnvironmentChain<SpecificEnvironment>(); 414 return; 415 } 416 if (isBaselineFrame()) { 417 asBaselineFrame()->popOffEnvironmentChain<SpecificEnvironment>(); 418 return; 419 } 420 asRematerializedFrame()->popOffEnvironmentChain<SpecificEnvironment>(); 421 } 422 423 inline CallObject& AbstractFramePtr::callObj() const { 424 if (isInterpreterFrame()) { 425 return asInterpreterFrame()->callObj(); 426 } 427 if (isBaselineFrame()) { 428 return asBaselineFrame()->callObj(); 429 } 430 return asRematerializedFrame()->callObj(); 431 } 432 433 inline bool AbstractFramePtr::initFunctionEnvironmentObjects(JSContext* cx) { 434 return js::InitFunctionEnvironmentObjects(cx, *this); 435 } 436 437 inline bool AbstractFramePtr::pushVarEnvironment(JSContext* cx, 438 Handle<Scope*> scope) { 439 return js::PushVarEnvironmentObject(cx, scope, *this); 440 } 441 442 inline JS::Realm* AbstractFramePtr::realm() const { 443 return environmentChain()->nonCCWRealm(); 444 } 445 446 inline unsigned AbstractFramePtr::numActualArgs() const { 447 if (isInterpreterFrame()) { 448 return asInterpreterFrame()->numActualArgs(); 449 } 450 if (isBaselineFrame()) { 451 return asBaselineFrame()->numActualArgs(); 452 } 453 return asRematerializedFrame()->numActualArgs(); 454 } 455 456 inline unsigned AbstractFramePtr::numFormalArgs() const { 457 if (isInterpreterFrame()) { 458 return asInterpreterFrame()->numFormalArgs(); 459 } 460 if (isBaselineFrame()) { 461 return asBaselineFrame()->numFormalArgs(); 462 } 463 return asRematerializedFrame()->numFormalArgs(); 464 } 465 466 inline Value& AbstractFramePtr::unaliasedLocal(uint32_t i) { 467 if (isInterpreterFrame()) { 468 return asInterpreterFrame()->unaliasedLocal(i); 469 } 470 if (isBaselineFrame()) { 471 return asBaselineFrame()->unaliasedLocal(i); 472 } 473 return asRematerializedFrame()->unaliasedLocal(i); 474 } 475 476 inline Value& AbstractFramePtr::unaliasedFormal( 477 unsigned i, MaybeCheckAliasing checkAliasing) { 478 if (isInterpreterFrame()) { 479 return asInterpreterFrame()->unaliasedFormal(i, checkAliasing); 480 } 481 if (isBaselineFrame()) { 482 return asBaselineFrame()->unaliasedFormal(i, checkAliasing); 483 } 484 return asRematerializedFrame()->unaliasedFormal(i, checkAliasing); 485 } 486 487 inline Value& AbstractFramePtr::unaliasedActual( 488 unsigned i, MaybeCheckAliasing checkAliasing) { 489 if (isInterpreterFrame()) { 490 return asInterpreterFrame()->unaliasedActual(i, checkAliasing); 491 } 492 if (isBaselineFrame()) { 493 return asBaselineFrame()->unaliasedActual(i, checkAliasing); 494 } 495 return asRematerializedFrame()->unaliasedActual(i, checkAliasing); 496 } 497 498 inline bool AbstractFramePtr::hasInitialEnvironment() const { 499 if (isInterpreterFrame()) { 500 return asInterpreterFrame()->hasInitialEnvironment(); 501 } 502 if (isBaselineFrame()) { 503 return asBaselineFrame()->hasInitialEnvironment(); 504 } 505 return asRematerializedFrame()->hasInitialEnvironment(); 506 } 507 508 inline bool AbstractFramePtr::isGlobalFrame() const { 509 if (isInterpreterFrame()) { 510 return asInterpreterFrame()->isGlobalFrame(); 511 } 512 if (isBaselineFrame()) { 513 return asBaselineFrame()->isGlobalFrame(); 514 } 515 if (isWasmDebugFrame()) { 516 return false; 517 } 518 return asRematerializedFrame()->isGlobalFrame(); 519 } 520 521 inline bool AbstractFramePtr::isModuleFrame() const { 522 if (isInterpreterFrame()) { 523 return asInterpreterFrame()->isModuleFrame(); 524 } 525 if (isBaselineFrame()) { 526 return asBaselineFrame()->isModuleFrame(); 527 } 528 if (isWasmDebugFrame()) { 529 return false; 530 } 531 return asRematerializedFrame()->isModuleFrame(); 532 } 533 534 inline bool AbstractFramePtr::isEvalFrame() const { 535 if (isInterpreterFrame()) { 536 return asInterpreterFrame()->isEvalFrame(); 537 } 538 if (isBaselineFrame()) { 539 return asBaselineFrame()->isEvalFrame(); 540 } 541 if (isWasmDebugFrame()) { 542 return false; 543 } 544 MOZ_ASSERT(isRematerializedFrame()); 545 return false; 546 } 547 548 inline bool AbstractFramePtr::isDebuggerEvalFrame() const { 549 if (isInterpreterFrame()) { 550 return asInterpreterFrame()->isDebuggerEvalFrame(); 551 } 552 if (isBaselineFrame()) { 553 return asBaselineFrame()->isDebuggerEvalFrame(); 554 } 555 MOZ_ASSERT(isRematerializedFrame()); 556 return false; 557 } 558 559 inline bool AbstractFramePtr::isDebuggee() const { 560 if (isInterpreterFrame()) { 561 return asInterpreterFrame()->isDebuggee(); 562 } 563 if (isBaselineFrame()) { 564 return asBaselineFrame()->isDebuggee(); 565 } 566 if (isWasmDebugFrame()) { 567 return asWasmDebugFrame()->isDebuggee(); 568 } 569 return asRematerializedFrame()->isDebuggee(); 570 } 571 572 inline void AbstractFramePtr::setIsDebuggee() { 573 if (isInterpreterFrame()) { 574 asInterpreterFrame()->setIsDebuggee(); 575 } else if (isBaselineFrame()) { 576 asBaselineFrame()->setIsDebuggee(); 577 } else if (isWasmDebugFrame()) { 578 asWasmDebugFrame()->setIsDebuggee(); 579 } else { 580 asRematerializedFrame()->setIsDebuggee(); 581 } 582 } 583 584 inline void AbstractFramePtr::unsetIsDebuggee() { 585 if (isInterpreterFrame()) { 586 asInterpreterFrame()->unsetIsDebuggee(); 587 } else if (isBaselineFrame()) { 588 asBaselineFrame()->unsetIsDebuggee(); 589 } else if (isWasmDebugFrame()) { 590 asWasmDebugFrame()->unsetIsDebuggee(); 591 } else { 592 asRematerializedFrame()->unsetIsDebuggee(); 593 } 594 } 595 596 inline bool AbstractFramePtr::isConstructing() const { 597 if (isInterpreterFrame()) { 598 return asInterpreterFrame()->isConstructing(); 599 } 600 if (isBaselineFrame()) { 601 return asBaselineFrame()->isConstructing(); 602 } 603 if (isRematerializedFrame()) { 604 return asRematerializedFrame()->isConstructing(); 605 } 606 MOZ_CRASH("Unexpected frame"); 607 } 608 609 inline bool AbstractFramePtr::hasCachedSavedFrame() const { 610 if (isInterpreterFrame()) { 611 return asInterpreterFrame()->hasCachedSavedFrame(); 612 } 613 if (isBaselineFrame()) { 614 return asBaselineFrame()->framePrefix()->hasCachedSavedFrame(); 615 } 616 if (isWasmDebugFrame()) { 617 return asWasmDebugFrame()->hasCachedSavedFrame(); 618 } 619 return asRematerializedFrame()->hasCachedSavedFrame(); 620 } 621 622 inline bool AbstractFramePtr::hasArgs() const { return isFunctionFrame(); } 623 624 inline bool AbstractFramePtr::hasScript() const { return !isWasmDebugFrame(); } 625 626 inline JSScript* AbstractFramePtr::script() const { 627 if (isInterpreterFrame()) { 628 return asInterpreterFrame()->script(); 629 } 630 if (isBaselineFrame()) { 631 return asBaselineFrame()->script(); 632 } 633 return asRematerializedFrame()->script(); 634 } 635 636 inline wasm::Instance* AbstractFramePtr::wasmInstance() const { 637 return asWasmDebugFrame()->instance(); 638 } 639 640 inline GlobalObject* AbstractFramePtr::global() const { 641 if (isWasmDebugFrame()) { 642 return asWasmDebugFrame()->global(); 643 } 644 return &script()->global(); 645 } 646 647 inline bool AbstractFramePtr::hasGlobal(const GlobalObject* global) const { 648 if (isWasmDebugFrame()) { 649 return asWasmDebugFrame()->hasGlobal(global); 650 } 651 return script()->hasGlobal(global); 652 } 653 654 inline JSFunction* AbstractFramePtr::callee() const { 655 if (isInterpreterFrame()) { 656 return &asInterpreterFrame()->callee(); 657 } 658 if (isBaselineFrame()) { 659 return asBaselineFrame()->callee(); 660 } 661 return asRematerializedFrame()->callee(); 662 } 663 664 inline Value AbstractFramePtr::calleev() const { 665 if (isInterpreterFrame()) { 666 return asInterpreterFrame()->calleev(); 667 } 668 if (isBaselineFrame()) { 669 return asBaselineFrame()->calleev(); 670 } 671 return asRematerializedFrame()->calleev(); 672 } 673 674 inline bool AbstractFramePtr::isFunctionFrame() const { 675 if (isInterpreterFrame()) { 676 return asInterpreterFrame()->isFunctionFrame(); 677 } 678 if (isBaselineFrame()) { 679 return asBaselineFrame()->isFunctionFrame(); 680 } 681 if (isWasmDebugFrame()) { 682 return false; 683 } 684 return asRematerializedFrame()->isFunctionFrame(); 685 } 686 687 inline bool AbstractFramePtr::isGeneratorFrame() const { 688 if (!isFunctionFrame() && !isModuleFrame()) { 689 return false; 690 } 691 JSScript* s = script(); 692 return s->isGenerator() || s->isAsync(); 693 } 694 695 inline bool AbstractFramePtr::saveGeneratorSlots(JSContext* cx, unsigned nslots, 696 ArrayObject* dest) const { 697 MOZ_ASSERT(isGeneratorFrame()); 698 if (isInterpreterFrame()) { 699 return asInterpreterFrame()->saveGeneratorSlots(cx, nslots, dest); 700 } 701 MOZ_ASSERT(isBaselineFrame(), "unexpected generator frame in Ion"); 702 return asBaselineFrame()->saveGeneratorSlots(cx, nslots, dest); 703 } 704 705 inline Value* AbstractFramePtr::argv() const { 706 if (isInterpreterFrame()) { 707 return asInterpreterFrame()->argv(); 708 } 709 if (isBaselineFrame()) { 710 return asBaselineFrame()->argv(); 711 } 712 return asRematerializedFrame()->argv(); 713 } 714 715 inline bool AbstractFramePtr::hasArgsObj() const { 716 if (isInterpreterFrame()) { 717 return asInterpreterFrame()->hasArgsObj(); 718 } 719 if (isBaselineFrame()) { 720 return asBaselineFrame()->hasArgsObj(); 721 } 722 return asRematerializedFrame()->hasArgsObj(); 723 } 724 725 inline ArgumentsObject& AbstractFramePtr::argsObj() const { 726 if (isInterpreterFrame()) { 727 return asInterpreterFrame()->argsObj(); 728 } 729 if (isBaselineFrame()) { 730 return asBaselineFrame()->argsObj(); 731 } 732 return asRematerializedFrame()->argsObj(); 733 } 734 735 inline void AbstractFramePtr::initArgsObj(ArgumentsObject& argsobj) const { 736 if (isInterpreterFrame()) { 737 asInterpreterFrame()->initArgsObj(argsobj); 738 return; 739 } 740 asBaselineFrame()->initArgsObj(argsobj); 741 } 742 743 inline bool AbstractFramePtr::prevUpToDate() const { 744 if (isInterpreterFrame()) { 745 return asInterpreterFrame()->prevUpToDate(); 746 } 747 if (isBaselineFrame()) { 748 return asBaselineFrame()->prevUpToDate(); 749 } 750 if (isWasmDebugFrame()) { 751 return asWasmDebugFrame()->prevUpToDate(); 752 } 753 return asRematerializedFrame()->prevUpToDate(); 754 } 755 756 inline void AbstractFramePtr::setPrevUpToDate() const { 757 if (isInterpreterFrame()) { 758 asInterpreterFrame()->setPrevUpToDate(); 759 return; 760 } 761 if (isBaselineFrame()) { 762 asBaselineFrame()->setPrevUpToDate(); 763 return; 764 } 765 if (isWasmDebugFrame()) { 766 asWasmDebugFrame()->setPrevUpToDate(); 767 return; 768 } 769 asRematerializedFrame()->setPrevUpToDate(); 770 } 771 772 inline void AbstractFramePtr::unsetPrevUpToDate() const { 773 if (isInterpreterFrame()) { 774 asInterpreterFrame()->unsetPrevUpToDate(); 775 return; 776 } 777 if (isBaselineFrame()) { 778 asBaselineFrame()->unsetPrevUpToDate(); 779 return; 780 } 781 if (isWasmDebugFrame()) { 782 asWasmDebugFrame()->unsetPrevUpToDate(); 783 return; 784 } 785 asRematerializedFrame()->unsetPrevUpToDate(); 786 } 787 788 inline Value& AbstractFramePtr::thisArgument() const { 789 if (isInterpreterFrame()) { 790 return asInterpreterFrame()->thisArgument(); 791 } 792 if (isBaselineFrame()) { 793 return asBaselineFrame()->thisArgument(); 794 } 795 return asRematerializedFrame()->thisArgument(); 796 } 797 798 inline bool AbstractFramePtr::debuggerNeedsCheckPrimitiveReturn() const { 799 if (isWasmDebugFrame()) { 800 return false; 801 } 802 return script()->isDerivedClassConstructor(); 803 } 804 805 InterpreterActivation::InterpreterActivation(RunState& state, JSContext* cx, 806 InterpreterFrame* entryFrame) 807 : Activation(cx, Interpreter), 808 entryFrame_(entryFrame), 809 opMask_(0) 810 #ifdef DEBUG 811 , 812 oldFrameCount_(cx->interpreterStack().frameCount_) 813 #endif 814 { 815 regs_.prepareToRun(*entryFrame, state.script()); 816 MOZ_ASSERT(regs_.pc == state.script()->code()); 817 } 818 819 InterpreterActivation::~InterpreterActivation() { 820 // Pop all inline frames. 821 while (regs_.fp() != entryFrame_) { 822 popInlineFrame(regs_.fp()); 823 } 824 825 MOZ_ASSERT(oldFrameCount_ == cx_->interpreterStack().frameCount_); 826 MOZ_ASSERT_IF(oldFrameCount_ == 0, 827 cx_->interpreterStack().allocator_.used() == 0); 828 829 if (entryFrame_) { 830 cx_->interpreterStack().releaseFrame(entryFrame_); 831 } 832 } 833 834 inline bool InterpreterActivation::pushInlineFrame( 835 const CallArgs& args, HandleScript script, MaybeConstruct constructing) { 836 if (!cx_->interpreterStack().pushInlineFrame(cx_, regs_, args, script, 837 constructing)) { 838 return false; 839 } 840 MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment()); 841 return true; 842 } 843 844 inline void InterpreterActivation::popInlineFrame(InterpreterFrame* frame) { 845 (void)frame; // Quell compiler warning. 846 MOZ_ASSERT(regs_.fp() == frame); 847 MOZ_ASSERT(regs_.fp() != entryFrame_); 848 849 cx_->interpreterStack().popInlineFrame(regs_); 850 } 851 852 inline bool InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, 853 HandleObject envChain) { 854 InterpreterStack& stack = cx_->interpreterStack(); 855 if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, envChain)) { 856 return false; 857 } 858 859 MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_); 860 return true; 861 } 862 863 } /* namespace js */ 864 865 #endif /* vm_Stack_inl_h */