tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */