LCOV - code coverage report
Current view: top level - js/src/vm - Stack-inl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 334 539 62.0 %
Date: 2017-07-14 16:53:18 Functions: 68 98 69.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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 "jscntxt.h"
      15             : #include "jsscript.h"
      16             : 
      17             : #include "jit/BaselineFrame.h"
      18             : #include "jit/RematerializedFrame.h"
      19             : #include "js/Debug.h"
      20             : #include "vm/EnvironmentObject.h"
      21             : #include "vm/GeneratorObject.h"
      22             : #include "wasm/WasmInstance.h"
      23             : 
      24             : #include "jsobjinlines.h"
      25             : #include "jsscriptinlines.h"
      26             : 
      27             : #include "jit/BaselineFrame-inl.h"
      28             : 
      29             : namespace js {
      30             : 
      31             : /*
      32             :  * We cache name lookup results only for the global object or for native
      33             :  * non-global objects without prototype or with prototype that never mutates,
      34             :  * see bug 462734 and bug 487039.
      35             :  */
      36             : static inline bool
      37         437 : IsCacheableEnvironment(JSObject* obj)
      38             : {
      39         437 :     bool cacheable = obj->is<CallObject>() || obj->is<LexicalEnvironmentObject>();
      40             : 
      41         437 :     MOZ_ASSERT_IF(cacheable, !obj->getOpsLookupProperty());
      42         437 :     return cacheable;
      43             : }
      44             : 
      45             : inline HandleObject
      46       83550 : InterpreterFrame::environmentChain() const
      47             : {
      48       83550 :     return HandleObject::fromMarkedLocation(&envChain_);
      49             : }
      50             : 
      51             : inline GlobalObject&
      52         691 : InterpreterFrame::global() const
      53             : {
      54         691 :     return environmentChain()->global();
      55             : }
      56             : 
      57             : inline JSObject&
      58        1141 : InterpreterFrame::varObj() const
      59             : {
      60        1141 :     JSObject* obj = environmentChain();
      61        3423 :     while (!obj->isQualifiedVarObj())
      62        1141 :         obj = obj->enclosingEnvironment();
      63        1141 :     return *obj;
      64             : }
      65             : 
      66             : inline LexicalEnvironmentObject&
      67         677 : InterpreterFrame::extensibleLexicalEnvironment() const
      68             : {
      69         677 :     return NearestEnclosingExtensibleLexicalEnvironment(environmentChain());
      70             : }
      71             : 
      72             : inline void
      73       11801 : InterpreterFrame::initCallFrame(JSContext* cx, InterpreterFrame* prev, jsbytecode* prevpc,
      74             :                                 Value* prevsp, JSFunction& callee, JSScript* script, Value* argv,
      75             :                                 uint32_t nactual, MaybeConstruct constructing)
      76             : {
      77       11801 :     MOZ_ASSERT(callee.nonLazyScript() == script);
      78             : 
      79             :     /* Initialize stack frame members. */
      80       11801 :     flags_ = 0;
      81       11801 :     if (constructing)
      82         422 :         flags_ |= CONSTRUCTING;
      83       11801 :     argv_ = argv;
      84       11801 :     script_ = script;
      85       11801 :     nactual_ = nactual;
      86       11801 :     envChain_ = callee.environment();
      87       11801 :     prev_ = prev;
      88       11801 :     prevpc_ = prevpc;
      89       11801 :     prevsp_ = prevsp;
      90             : 
      91       11801 :     if (script->isDebuggee())
      92           0 :         setIsDebuggee();
      93             : 
      94       11801 :     initLocals();
      95       11801 : }
      96             : 
      97             : inline void
      98       12299 : InterpreterFrame::initLocals()
      99             : {
     100       12299 :     SetValueRangeToUndefined(slots(), script()->nfixed());
     101       12299 : }
     102             : 
     103             : inline Value&
     104       84367 : InterpreterFrame::unaliasedLocal(uint32_t i)
     105             : {
     106       84367 :     MOZ_ASSERT(i < script()->nfixed());
     107       84367 :     return slots()[i];
     108             : }
     109             : 
     110             : inline Value&
     111       23961 : InterpreterFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
     112             : {
     113       23961 :     MOZ_ASSERT(i < numFormalArgs());
     114       23961 :     MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
     115       23961 :     MOZ_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
     116       23961 :     return argv()[i];
     117             : }
     118             : 
     119             : inline Value&
     120         135 : InterpreterFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
     121             : {
     122         135 :     MOZ_ASSERT(i < numActualArgs());
     123         135 :     MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
     124         135 :     MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
     125         135 :     return argv()[i];
     126             : }
     127             : 
     128             : template <class Op>
     129             : inline void
     130           0 : InterpreterFrame::unaliasedForEachActual(Op op)
     131             : {
     132             :     // Don't assert !script()->funHasAnyAliasedFormal() since this function is
     133             :     // called from ArgumentsObject::createUnexpected() which can access aliased
     134             :     // slots.
     135             : 
     136           0 :     const Value* argsEnd = argv() + numActualArgs();
     137           0 :     for (const Value* p = argv(); p < argsEnd; ++p)
     138           0 :         op(*p);
     139           0 : }
     140             : 
     141             : struct CopyTo
     142             : {
     143             :     Value* dst;
     144           0 :     explicit CopyTo(Value* dst) : dst(dst) {}
     145           0 :     void operator()(const Value& src) { *dst++ = src; }
     146             : };
     147             : 
     148             : struct CopyToHeap
     149             : {
     150             :     GCPtrValue* dst;
     151           0 :     explicit CopyToHeap(GCPtrValue* dst) : dst(dst) {}
     152           0 :     void operator()(const Value& src) { dst->init(src); ++dst; }
     153             : };
     154             : 
     155             : inline ArgumentsObject&
     156           9 : InterpreterFrame::argsObj() const
     157             : {
     158           9 :     MOZ_ASSERT(script()->needsArgsObj());
     159           9 :     MOZ_ASSERT(flags_ & HAS_ARGS_OBJ);
     160           9 :     return *argsObj_;
     161             : }
     162             : 
     163             : inline void
     164          77 : InterpreterFrame::initArgsObj(ArgumentsObject& argsobj)
     165             : {
     166          77 :     MOZ_ASSERT(script()->needsArgsObj());
     167          77 :     flags_ |= HAS_ARGS_OBJ;
     168          77 :     argsObj_ = &argsobj;
     169          77 : }
     170             : 
     171             : inline EnvironmentObject&
     172        8186 : InterpreterFrame::aliasedEnvironment(EnvironmentCoordinate ec) const
     173             : {
     174        8186 :     JSObject* env = &environmentChain()->as<EnvironmentObject>();
     175       10853 :     for (unsigned i = ec.hops(); i; i--)
     176        2667 :         env = &env->as<EnvironmentObject>().enclosingEnvironment();
     177        8186 :     return env->as<EnvironmentObject>();
     178             : }
     179             : 
     180             : template <typename SpecificEnvironment>
     181             : inline void
     182        1638 : InterpreterFrame::pushOnEnvironmentChain(SpecificEnvironment& env)
     183             : {
     184        1638 :     MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
     185        1638 :     envChain_ = &env;
     186        1638 :     if (IsFrameInitialEnvironment(this, env))
     187        1131 :         flags_ |= HAS_INITIAL_ENV;
     188        1638 : }
     189             : 
     190             : template <typename SpecificEnvironment>
     191             : inline void
     192        1881 : InterpreterFrame::popOffEnvironmentChain()
     193             : {
     194        1881 :     MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
     195        1881 :     envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
     196        1881 : }
     197             : 
     198             : inline void
     199          73 : InterpreterFrame::replaceInnermostEnvironment(EnvironmentObject& env)
     200             : {
     201          73 :     MOZ_ASSERT(env.enclosingEnvironment() ==
     202             :                envChain_->as<EnvironmentObject>().enclosingEnvironment());
     203          73 :     envChain_ = &env;
     204          73 : }
     205             : 
     206             : bool
     207        4304 : InterpreterFrame::hasInitialEnvironment() const
     208             : {
     209        4304 :     MOZ_ASSERT(script()->initialEnvironmentShape());
     210        4304 :     return flags_ & HAS_INITIAL_ENV;
     211             : }
     212             : 
     213             : inline CallObject&
     214           6 : InterpreterFrame::callObj() const
     215             : {
     216           6 :     MOZ_ASSERT(callee().needsCallObject());
     217             : 
     218           6 :     JSObject* pobj = environmentChain();
     219           6 :     while (MOZ_UNLIKELY(!pobj->is<CallObject>()))
     220           0 :         pobj = pobj->enclosingEnvironment();
     221           6 :     return pobj->as<CallObject>();
     222             : }
     223             : 
     224             : inline void
     225           0 : InterpreterFrame::unsetIsDebuggee()
     226             : {
     227           0 :     MOZ_ASSERT(!script()->isDebuggee());
     228           0 :     flags_ &= ~DEBUGGEE;
     229           0 : }
     230             : 
     231             : /*****************************************************************************/
     232             : 
     233             : inline void
     234           1 : InterpreterStack::purge(JSRuntime* rt)
     235             : {
     236           1 :     rt->gc.freeUnusedLifoBlocksAfterSweeping(&allocator_);
     237           1 : }
     238             : 
     239             : uint8_t*
     240       12299 : InterpreterStack::allocateFrame(JSContext* cx, size_t size)
     241             : {
     242             :     size_t maxFrames;
     243       12299 :     if (cx->compartment()->principals() == cx->runtime()->trustedPrincipals())
     244       12154 :         maxFrames = MAX_FRAMES_TRUSTED;
     245             :     else
     246         145 :         maxFrames = MAX_FRAMES;
     247             : 
     248       12299 :     if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) {
     249           0 :         ReportOverRecursed(cx);
     250           0 :         return nullptr;
     251             :     }
     252             : 
     253       12299 :     uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size));
     254       12299 :     if (!buffer) {
     255           0 :         ReportOutOfMemory(cx);
     256           0 :         return nullptr;
     257             :     }
     258             : 
     259       12299 :     frameCount_++;
     260       12299 :     return buffer;
     261             : }
     262             : 
     263             : MOZ_ALWAYS_INLINE InterpreterFrame*
     264       11603 : InterpreterStack::getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script,
     265             :                                MaybeConstruct constructing, Value** pargv)
     266             : {
     267       11603 :     JSFunction* fun = &args.callee().as<JSFunction>();
     268             : 
     269       11603 :     MOZ_ASSERT(fun->nonLazyScript() == script);
     270       11603 :     unsigned nformal = fun->nargs();
     271       11603 :     unsigned nvals = script->nslots();
     272             : 
     273       11603 :     if (args.length() >= nformal) {
     274       10943 :         *pargv = args.array();
     275       10943 :         uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     276       10943 :         return reinterpret_cast<InterpreterFrame*>(buffer);
     277             :     }
     278             : 
     279             :     // Pad any missing arguments with |undefined|.
     280         660 :     MOZ_ASSERT(args.length() < nformal);
     281             : 
     282         660 :     unsigned nfunctionState = 2 + constructing; // callee, |this|, |new.target|
     283             : 
     284         660 :     nvals += nformal + nfunctionState;
     285         660 :     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     286         660 :     if (!buffer)
     287           0 :         return nullptr;
     288             : 
     289         660 :     Value* argv = reinterpret_cast<Value*>(buffer);
     290         660 :     unsigned nmissing = nformal - args.length();
     291             : 
     292         660 :     mozilla::PodCopy(argv, args.base(), 2 + args.length());
     293         660 :     SetValueRangeToUndefined(argv + 2 + args.length(), nmissing);
     294             : 
     295         660 :     if (constructing)
     296          37 :         argv[2 + nformal] = args.newTarget();
     297             : 
     298         660 :     *pargv = argv + 2;
     299         660 :     return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal);
     300             : }
     301             : 
     302             : MOZ_ALWAYS_INLINE bool
     303        1674 : InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
     304             :                                   HandleScript script, MaybeConstruct constructing)
     305             : {
     306        3348 :     RootedFunction callee(cx, &args.callee().as<JSFunction>());
     307        1674 :     MOZ_ASSERT(regs.sp == args.end());
     308        1674 :     MOZ_ASSERT(callee->nonLazyScript() == script);
     309             : 
     310        1674 :     script->ensureNonLazyCanonicalFunction();
     311             : 
     312        1674 :     InterpreterFrame* prev = regs.fp();
     313        1674 :     jsbytecode* prevpc = regs.pc;
     314        1674 :     Value* prevsp = regs.sp;
     315        1674 :     MOZ_ASSERT(prev);
     316             : 
     317        1674 :     LifoAlloc::Mark mark = allocator_.mark();
     318             : 
     319             :     Value* argv;
     320        1674 :     InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
     321        1674 :     if (!fp)
     322           0 :         return false;
     323             : 
     324        1674 :     fp->mark_ = mark;
     325             : 
     326             :     /* Initialize frame, locals, regs. */
     327        3348 :     fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, args.length(),
     328        3348 :                       constructing);
     329             : 
     330        1674 :     regs.prepareToRun(*fp, script);
     331        1674 :     return true;
     332             : }
     333             : 
     334             : MOZ_ALWAYS_INLINE bool
     335         198 : InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
     336             :                                            HandleFunction callee, HandleValue newTarget,
     337             :                                            HandleObject envChain)
     338             : {
     339         198 :     MOZ_ASSERT(callee->isStarGenerator() || callee->isLegacyGenerator() || callee->isAsync());
     340         396 :     RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
     341         198 :     InterpreterFrame* prev = regs.fp();
     342         198 :     jsbytecode* prevpc = regs.pc;
     343         198 :     Value* prevsp = regs.sp;
     344         198 :     MOZ_ASSERT(prev);
     345             : 
     346         198 :     script->ensureNonLazyCanonicalFunction();
     347             : 
     348         198 :     LifoAlloc::Mark mark = allocator_.mark();
     349             : 
     350         198 :     MaybeConstruct constructing = MaybeConstruct(newTarget.isObject());
     351             : 
     352             :     // Include callee, |this|, and maybe |new.target|
     353         198 :     unsigned nformal = callee->nargs();
     354         198 :     unsigned nvals = 2 + constructing + nformal + script->nslots();
     355             : 
     356         198 :     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     357         198 :     if (!buffer)
     358           0 :         return false;
     359             : 
     360         198 :     Value* argv = reinterpret_cast<Value*>(buffer) + 2;
     361         198 :     argv[-2] = ObjectValue(*callee);
     362         198 :     argv[-1] = UndefinedValue();
     363         198 :     SetValueRangeToUndefined(argv, nformal);
     364         198 :     if (constructing)
     365           0 :         argv[nformal] = newTarget;
     366             : 
     367         198 :     InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal + constructing);
     368         198 :     fp->mark_ = mark;
     369         198 :     fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, 0, constructing);
     370         198 :     fp->resumeGeneratorFrame(envChain);
     371             : 
     372         198 :     regs.prepareToRun(*fp, script);
     373         198 :     return true;
     374             : }
     375             : 
     376             : MOZ_ALWAYS_INLINE void
     377        1869 : InterpreterStack::popInlineFrame(InterpreterRegs& regs)
     378             : {
     379        1869 :     InterpreterFrame* fp = regs.fp();
     380        1869 :     regs.popInlineFrame();
     381        1869 :     regs.sp[-1] = fp->returnValue();
     382        1869 :     releaseFrame(fp);
     383        1869 :     MOZ_ASSERT(regs.fp());
     384        1869 : }
     385             : 
     386             : template <class Op>
     387             : inline void
     388           0 : FrameIter::unaliasedForEachActual(JSContext* cx, Op op)
     389             : {
     390           0 :     switch (data_.state_) {
     391             :       case DONE:
     392             :       case WASM:
     393           0 :         break;
     394             :       case INTERP:
     395           0 :         interpFrame()->unaliasedForEachActual(op);
     396           0 :         return;
     397             :       case JIT:
     398           0 :         if (data_.jitFrames_.isIonJS()) {
     399           0 :             jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
     400           0 :             ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, recover);
     401           0 :         } else if (data_.jitFrames_.isBailoutJS()) {
     402             :             // :TODO: (Bug 1070962) If we are introspecting the frame which is
     403             :             // being bailed, then we might be in the middle of recovering
     404             :             // instructions. Stacking computeInstructionResults implies that we
     405             :             // might be recovering result twice. In the mean time, to avoid
     406             :             // that, we just return Undefined values for instruction results
     407             :             // which are not yet recovered.
     408           0 :             jit::MaybeReadFallback fallback;
     409           0 :             ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, fallback);
     410             :         } else {
     411           0 :             MOZ_ASSERT(data_.jitFrames_.isBaselineJS());
     412           0 :             data_.jitFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals);
     413             :         }
     414           0 :         return;
     415             :     }
     416           0 :     MOZ_CRASH("Unexpected state");
     417             : }
     418             : 
     419             : inline HandleValue
     420           0 : AbstractFramePtr::returnValue() const
     421             : {
     422           0 :     if (isInterpreterFrame())
     423           0 :         return asInterpreterFrame()->returnValue();
     424           0 :     if (isWasmDebugFrame())
     425           0 :         return asWasmDebugFrame()->returnValue();
     426           0 :     return asBaselineFrame()->returnValue();
     427             : }
     428             : 
     429             : inline void
     430           0 : AbstractFramePtr::setReturnValue(const Value& rval) const
     431             : {
     432           0 :     if (isInterpreterFrame()) {
     433           0 :         asInterpreterFrame()->setReturnValue(rval);
     434           0 :         return;
     435             :     }
     436           0 :     if (isBaselineFrame()) {
     437           0 :         asBaselineFrame()->setReturnValue(rval);
     438           0 :         return;
     439             :     }
     440           0 :     if (isWasmDebugFrame()) {
     441             :         // TODO handle wasm function return value
     442             :         // The function is called from Debugger::slowPathOnLeaveFrame --
     443             :         // ignoring value for wasm.
     444           0 :         return;
     445             :     }
     446           0 :     asRematerializedFrame()->setReturnValue(rval);
     447             : }
     448             : 
     449             : inline JSObject*
     450       39463 : AbstractFramePtr::environmentChain() const
     451             : {
     452       39463 :     if (isInterpreterFrame())
     453       27551 :         return asInterpreterFrame()->environmentChain();
     454       11912 :     if (isBaselineFrame())
     455       11912 :         return asBaselineFrame()->environmentChain();
     456           0 :     if (isWasmDebugFrame())
     457           0 :         return &global()->lexicalEnvironment();
     458           0 :     return asRematerializedFrame()->environmentChain();
     459             : }
     460             : 
     461             : template <typename SpecificEnvironment>
     462             : inline void
     463        4296 : AbstractFramePtr::pushOnEnvironmentChain(SpecificEnvironment& env)
     464             : {
     465        4296 :     if (isInterpreterFrame()) {
     466        1163 :         asInterpreterFrame()->pushOnEnvironmentChain(env);
     467        1163 :         return;
     468             :     }
     469        3133 :     if (isBaselineFrame()) {
     470        3133 :         asBaselineFrame()->pushOnEnvironmentChain(env);
     471        3133 :         return;
     472             :     }
     473           0 :     asRematerializedFrame()->pushOnEnvironmentChain(env);
     474             : }
     475             : 
     476             : template <typename SpecificEnvironment>
     477             : inline void
     478        1457 : AbstractFramePtr::popOffEnvironmentChain()
     479             : {
     480        1457 :     if (isInterpreterFrame()) {
     481        1457 :         asInterpreterFrame()->popOffEnvironmentChain<SpecificEnvironment>();
     482        1457 :         return;
     483             :     }
     484           0 :     if (isBaselineFrame()) {
     485           0 :         asBaselineFrame()->popOffEnvironmentChain<SpecificEnvironment>();
     486           0 :         return;
     487             :     }
     488           0 :     asRematerializedFrame()->popOffEnvironmentChain<SpecificEnvironment>();
     489             : }
     490             : 
     491             : inline CallObject&
     492           6 : AbstractFramePtr::callObj() const
     493             : {
     494           6 :     if (isInterpreterFrame())
     495           6 :         return asInterpreterFrame()->callObj();
     496           0 :     if (isBaselineFrame())
     497           0 :         return asBaselineFrame()->callObj();
     498           0 :     return asRematerializedFrame()->callObj();
     499             : }
     500             : 
     501             : inline bool
     502           0 : AbstractFramePtr::initFunctionEnvironmentObjects(JSContext* cx)
     503             : {
     504           0 :     return js::InitFunctionEnvironmentObjects(cx, *this);
     505             : }
     506             : 
     507             : inline bool
     508             : AbstractFramePtr::pushVarEnvironment(JSContext* cx, HandleScope scope)
     509             : {
     510             :     return js::PushVarEnvironmentObject(cx, scope, *this);
     511             : }
     512             : 
     513             : inline JSCompartment*
     514           2 : AbstractFramePtr::compartment() const
     515             : {
     516           2 :     return environmentChain()->compartment();
     517             : }
     518             : 
     519             : inline unsigned
     520         405 : AbstractFramePtr::numActualArgs() const
     521             : {
     522         405 :     if (isInterpreterFrame())
     523         289 :         return asInterpreterFrame()->numActualArgs();
     524         116 :     if (isBaselineFrame())
     525         116 :         return asBaselineFrame()->numActualArgs();
     526           0 :     return asRematerializedFrame()->numActualArgs();
     527             : }
     528             : 
     529             : inline unsigned
     530         127 : AbstractFramePtr::numFormalArgs() const
     531             : {
     532         127 :     if (isInterpreterFrame())
     533          77 :         return asInterpreterFrame()->numFormalArgs();
     534          50 :     if (isBaselineFrame())
     535          50 :         return asBaselineFrame()->numFormalArgs();
     536           0 :     return asRematerializedFrame()->numFormalArgs();
     537             : }
     538             : 
     539             : inline Value&
     540           0 : AbstractFramePtr::unaliasedLocal(uint32_t i)
     541             : {
     542           0 :     if (isInterpreterFrame())
     543           0 :         return asInterpreterFrame()->unaliasedLocal(i);
     544           0 :     if (isBaselineFrame())
     545           0 :         return asBaselineFrame()->unaliasedLocal(i);
     546           0 :     return asRematerializedFrame()->unaliasedLocal(i);
     547             : }
     548             : 
     549             : inline Value&
     550        9526 : AbstractFramePtr::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing)
     551             : {
     552        9526 :     if (isInterpreterFrame())
     553        1563 :         return asInterpreterFrame()->unaliasedFormal(i, checkAliasing);
     554        7963 :     if (isBaselineFrame())
     555        7963 :         return asBaselineFrame()->unaliasedFormal(i, checkAliasing);
     556           0 :     return asRematerializedFrame()->unaliasedFormal(i, checkAliasing);
     557             : }
     558             : 
     559             : inline Value&
     560         151 : AbstractFramePtr::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing)
     561             : {
     562         151 :     if (isInterpreterFrame())
     563         135 :         return asInterpreterFrame()->unaliasedActual(i, checkAliasing);
     564          16 :     if (isBaselineFrame())
     565          16 :         return asBaselineFrame()->unaliasedActual(i, checkAliasing);
     566           0 :     return asRematerializedFrame()->unaliasedActual(i, checkAliasing);
     567             : }
     568             : 
     569             : inline bool
     570        3011 : AbstractFramePtr::hasInitialEnvironment() const
     571             : {
     572        3011 :     if (isInterpreterFrame())
     573        3011 :         return asInterpreterFrame()->hasInitialEnvironment();
     574           0 :     if (isBaselineFrame())
     575           0 :         return asBaselineFrame()->hasInitialEnvironment();
     576           0 :     return asRematerializedFrame()->hasInitialEnvironment();
     577             : }
     578             : 
     579             : inline bool
     580             : AbstractFramePtr::createSingleton() const
     581             : {
     582             :     if (isInterpreterFrame())
     583             :         return asInterpreterFrame()->createSingleton();
     584             :     return false;
     585             : }
     586             : 
     587             : inline bool
     588           0 : AbstractFramePtr::isGlobalFrame() const
     589             : {
     590           0 :     if (isInterpreterFrame())
     591           0 :         return asInterpreterFrame()->isGlobalFrame();
     592           0 :     if (isBaselineFrame())
     593           0 :         return asBaselineFrame()->isGlobalFrame();
     594           0 :     if (isWasmDebugFrame())
     595           0 :         return false;
     596           0 :     return asRematerializedFrame()->isGlobalFrame();
     597             : }
     598             : 
     599             : inline bool
     600           0 : AbstractFramePtr::isModuleFrame() const
     601             : {
     602           0 :     if (isInterpreterFrame())
     603           0 :         return asInterpreterFrame()->isModuleFrame();
     604           0 :     if (isBaselineFrame())
     605           0 :         return asBaselineFrame()->isModuleFrame();
     606           0 :     if (isWasmDebugFrame())
     607           0 :         return false;
     608           0 :     return asRematerializedFrame()->isModuleFrame();
     609             : }
     610             : 
     611             : inline bool
     612       12397 : AbstractFramePtr::isEvalFrame() const
     613             : {
     614       12397 :     if (isInterpreterFrame())
     615       12223 :         return asInterpreterFrame()->isEvalFrame();
     616         174 :     if (isBaselineFrame())
     617         174 :         return asBaselineFrame()->isEvalFrame();
     618           0 :     if (isWasmDebugFrame())
     619           0 :         return false;
     620           0 :     MOZ_ASSERT(isRematerializedFrame());
     621           0 :     return false;
     622             : }
     623             : 
     624             : inline bool
     625           0 : AbstractFramePtr::isDebuggerEvalFrame() const
     626             : {
     627           0 :     if (isInterpreterFrame())
     628           0 :         return asInterpreterFrame()->isDebuggerEvalFrame();
     629           0 :     if (isBaselineFrame())
     630           0 :         return asBaselineFrame()->isDebuggerEvalFrame();
     631           0 :     MOZ_ASSERT(isRematerializedFrame());
     632           0 :     return false;
     633             : }
     634             : 
     635             : inline bool
     636        5675 : AbstractFramePtr::hasCachedSavedFrame() const
     637             : {
     638        5675 :     if (isInterpreterFrame())
     639        4900 :         return asInterpreterFrame()->hasCachedSavedFrame();
     640         775 :     if (isBaselineFrame())
     641         775 :         return asBaselineFrame()->hasCachedSavedFrame();
     642           0 :     if (isWasmDebugFrame())
     643           0 :         return asWasmDebugFrame()->hasCachedSavedFrame();
     644           0 :     return asRematerializedFrame()->hasCachedSavedFrame();
     645             : }
     646             : 
     647             : inline void
     648        2641 : AbstractFramePtr::setHasCachedSavedFrame()
     649             : {
     650        2641 :     if (isInterpreterFrame())
     651        2170 :         asInterpreterFrame()->setHasCachedSavedFrame();
     652         471 :     else if (isBaselineFrame())
     653         471 :         asBaselineFrame()->setHasCachedSavedFrame();
     654           0 :     else if (isWasmDebugFrame())
     655           0 :         asWasmDebugFrame()->setHasCachedSavedFrame();
     656             :     else
     657           0 :         asRematerializedFrame()->setHasCachedSavedFrame();
     658        2641 : }
     659             : 
     660             : inline bool
     661       24416 : AbstractFramePtr::isDebuggee() const
     662             : {
     663       24416 :     if (isInterpreterFrame())
     664       24260 :         return asInterpreterFrame()->isDebuggee();
     665         156 :     if (isBaselineFrame())
     666         156 :         return asBaselineFrame()->isDebuggee();
     667           0 :     if (isWasmDebugFrame())
     668           0 :         return asWasmDebugFrame()->isDebuggee();
     669           0 :     return asRematerializedFrame()->isDebuggee();
     670             : }
     671             : 
     672             : inline void
     673           0 : AbstractFramePtr::setIsDebuggee()
     674             : {
     675           0 :     if (isInterpreterFrame())
     676           0 :         asInterpreterFrame()->setIsDebuggee();
     677           0 :     else if (isBaselineFrame())
     678           0 :         asBaselineFrame()->setIsDebuggee();
     679           0 :     else if (isWasmDebugFrame())
     680           0 :         asWasmDebugFrame()->setIsDebuggee();
     681             :     else
     682           0 :         asRematerializedFrame()->setIsDebuggee();
     683           0 : }
     684             : 
     685             : inline void
     686           0 : AbstractFramePtr::unsetIsDebuggee()
     687             : {
     688           0 :     if (isInterpreterFrame())
     689           0 :         asInterpreterFrame()->unsetIsDebuggee();
     690           0 :     else if (isBaselineFrame())
     691           0 :         asBaselineFrame()->unsetIsDebuggee();
     692           0 :     else if (isWasmDebugFrame())
     693           0 :         asWasmDebugFrame()->unsetIsDebuggee();
     694             :     else
     695           0 :         asRematerializedFrame()->unsetIsDebuggee();
     696           0 : }
     697             : 
     698             : inline bool
     699           0 : AbstractFramePtr::hasArgs() const
     700             : {
     701           0 :     return isFunctionFrame();
     702             : }
     703             : 
     704             : inline bool
     705       82307 : AbstractFramePtr::hasScript() const
     706             : {
     707       82307 :     return !isWasmDebugFrame();
     708             : }
     709             : 
     710             : inline JSScript*
     711      122734 : AbstractFramePtr::script() const
     712             : {
     713      122734 :     if (isInterpreterFrame())
     714      105510 :         return asInterpreterFrame()->script();
     715       17224 :     if (isBaselineFrame())
     716       17224 :         return asBaselineFrame()->script();
     717           0 :     return asRematerializedFrame()->script();
     718             : }
     719             : 
     720             : inline wasm::Instance*
     721           0 : AbstractFramePtr::wasmInstance() const
     722             : {
     723           0 :     return asWasmDebugFrame()->instance();
     724             : }
     725             : 
     726             : inline GlobalObject*
     727       12315 : AbstractFramePtr::global() const
     728             : {
     729       12315 :     if (isWasmDebugFrame())
     730           0 :         return &wasmInstance()->object()->global();
     731       12315 :     return &script()->global();
     732             : }
     733             : 
     734             : inline JSFunction*
     735       19200 : AbstractFramePtr::callee() const
     736             : {
     737       19200 :     if (isInterpreterFrame())
     738        9582 :         return &asInterpreterFrame()->callee();
     739        9618 :     if (isBaselineFrame())
     740        9618 :         return asBaselineFrame()->callee();
     741           0 :     return asRematerializedFrame()->callee();
     742             : }
     743             : 
     744             : inline Value
     745             : AbstractFramePtr::calleev() const
     746             : {
     747             :     if (isInterpreterFrame())
     748             :         return asInterpreterFrame()->calleev();
     749             :     if (isBaselineFrame())
     750             :         return asBaselineFrame()->calleev();
     751             :     return asRematerializedFrame()->calleev();
     752             : }
     753             : 
     754             : inline bool
     755       14141 : AbstractFramePtr::isFunctionFrame() const
     756             : {
     757       14141 :     if (isInterpreterFrame())
     758        7893 :         return asInterpreterFrame()->isFunctionFrame();
     759        6248 :     if (isBaselineFrame())
     760        6248 :         return asBaselineFrame()->isFunctionFrame();
     761           0 :     if (isWasmDebugFrame())
     762           0 :         return false;
     763           0 :     return asRematerializedFrame()->isFunctionFrame();
     764             : }
     765             : 
     766             : inline bool
     767             : AbstractFramePtr::isNonStrictDirectEvalFrame() const
     768             : {
     769             :     if (isInterpreterFrame())
     770             :         return asInterpreterFrame()->isNonStrictDirectEvalFrame();
     771             :     if (isBaselineFrame())
     772             :         return asBaselineFrame()->isNonStrictDirectEvalFrame();
     773             :     MOZ_ASSERT(isRematerializedFrame());
     774             :     return false;
     775             : }
     776             : 
     777             : inline bool
     778             : AbstractFramePtr::isStrictEvalFrame() const
     779             : {
     780             :     if (isInterpreterFrame())
     781             :         return asInterpreterFrame()->isStrictEvalFrame();
     782             :     if (isBaselineFrame())
     783             :         return asBaselineFrame()->isStrictEvalFrame();
     784             :     MOZ_ASSERT(isRematerializedFrame());
     785             :     return false;
     786             : }
     787             : 
     788             : inline Value*
     789         127 : AbstractFramePtr::argv() const
     790             : {
     791         127 :     if (isInterpreterFrame())
     792          77 :         return asInterpreterFrame()->argv();
     793          50 :     if (isBaselineFrame())
     794          50 :         return asBaselineFrame()->argv();
     795           0 :     return asRematerializedFrame()->argv();
     796             : }
     797             : 
     798             : inline bool
     799           0 : AbstractFramePtr::hasArgsObj() const
     800             : {
     801           0 :     if (isInterpreterFrame())
     802           0 :         return asInterpreterFrame()->hasArgsObj();
     803           0 :     if (isBaselineFrame())
     804           0 :         return asBaselineFrame()->hasArgsObj();
     805           0 :     return asRematerializedFrame()->hasArgsObj();
     806             : }
     807             : 
     808             : inline ArgumentsObject&
     809           0 : AbstractFramePtr::argsObj() const
     810             : {
     811           0 :     if (isInterpreterFrame())
     812           0 :         return asInterpreterFrame()->argsObj();
     813           0 :     if (isBaselineFrame())
     814           0 :         return asBaselineFrame()->argsObj();
     815           0 :     return asRematerializedFrame()->argsObj();
     816             : }
     817             : 
     818             : inline void
     819         127 : AbstractFramePtr::initArgsObj(ArgumentsObject& argsobj) const
     820             : {
     821         127 :     if (isInterpreterFrame()) {
     822          77 :         asInterpreterFrame()->initArgsObj(argsobj);
     823          77 :         return;
     824             :     }
     825          50 :     asBaselineFrame()->initArgsObj(argsobj);
     826             : }
     827             : 
     828             : inline bool
     829           0 : AbstractFramePtr::prevUpToDate() const
     830             : {
     831           0 :     if (isInterpreterFrame())
     832           0 :         return asInterpreterFrame()->prevUpToDate();
     833           0 :     if (isBaselineFrame())
     834           0 :         return asBaselineFrame()->prevUpToDate();
     835           0 :     if (isWasmDebugFrame())
     836           0 :         return asWasmDebugFrame()->prevUpToDate();
     837           0 :     return asRematerializedFrame()->prevUpToDate();
     838             : }
     839             : 
     840             : inline void
     841           0 : AbstractFramePtr::setPrevUpToDate() const
     842             : {
     843           0 :     if (isInterpreterFrame()) {
     844           0 :         asInterpreterFrame()->setPrevUpToDate();
     845           0 :         return;
     846             :     }
     847           0 :     if (isBaselineFrame()) {
     848           0 :         asBaselineFrame()->setPrevUpToDate();
     849           0 :         return;
     850             :     }
     851           0 :     if (isWasmDebugFrame()) {
     852           0 :         asWasmDebugFrame()->setPrevUpToDate();
     853           0 :         return;
     854             :     }
     855           0 :     asRematerializedFrame()->setPrevUpToDate();
     856             : }
     857             : 
     858             : inline void
     859           0 : AbstractFramePtr::unsetPrevUpToDate() const
     860             : {
     861           0 :     if (isInterpreterFrame()) {
     862           0 :         asInterpreterFrame()->unsetPrevUpToDate();
     863           0 :         return;
     864             :     }
     865           0 :     if (isBaselineFrame()) {
     866           0 :         asBaselineFrame()->unsetPrevUpToDate();
     867           0 :         return;
     868             :     }
     869           0 :     if (isWasmDebugFrame()) {
     870           0 :         asWasmDebugFrame()->unsetPrevUpToDate();
     871           0 :         return;
     872             :     }
     873           0 :     asRematerializedFrame()->unsetPrevUpToDate();
     874             : }
     875             : 
     876             : inline Value&
     877       11262 : AbstractFramePtr::thisArgument() const
     878             : {
     879       11262 :     if (isInterpreterFrame())
     880       11262 :         return asInterpreterFrame()->thisArgument();
     881           0 :     if (isBaselineFrame())
     882           0 :         return asBaselineFrame()->thisArgument();
     883           0 :     return asRematerializedFrame()->thisArgument();
     884             : }
     885             : 
     886             : inline Value
     887         136 : AbstractFramePtr::newTarget() const
     888             : {
     889         136 :     if (isInterpreterFrame())
     890          72 :         return asInterpreterFrame()->newTarget();
     891          64 :     if (isBaselineFrame())
     892          64 :         return asBaselineFrame()->newTarget();
     893           0 :     return asRematerializedFrame()->newTarget();
     894             : }
     895             : 
     896             : inline bool
     897           0 : AbstractFramePtr::debuggerNeedsCheckPrimitiveReturn() const
     898             : {
     899           0 :     if (isWasmDebugFrame())
     900           0 :         return false;
     901           0 :     return script()->isDerivedClassConstructor();
     902             : }
     903             : 
     904       36184 : ActivationEntryMonitor::~ActivationEntryMonitor()
     905             : {
     906       18092 :     if (entryMonitor_)
     907           0 :         entryMonitor_->Exit(cx_);
     908             : 
     909       18092 :     cx_->entryMonitor = entryMonitor_;
     910       18092 : }
     911             : 
     912       18100 : Activation::Activation(JSContext* cx, Kind kind)
     913             :   : cx_(cx),
     914       18100 :     compartment_(cx->compartment()),
     915             :     prev_(cx->activation_),
     916       18100 :     prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
     917             :     hideScriptedCallerCount_(0),
     918             :     frameCache_(cx),
     919             :     asyncStack_(cx, cx->asyncStackForNewActivations()),
     920             :     asyncCause_(cx->asyncCauseForNewActivations),
     921             :     asyncCallIsExplicit_(cx->asyncCallIsExplicit),
     922       54300 :     kind_(kind)
     923             : {
     924       18100 :     cx->asyncStackForNewActivations() = nullptr;
     925       18100 :     cx->asyncCauseForNewActivations = nullptr;
     926       18100 :     cx->asyncCallIsExplicit = false;
     927       18100 :     cx->activation_ = this;
     928       18100 : }
     929             : 
     930       36184 : Activation::~Activation()
     931             : {
     932       18092 :     MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
     933       18092 :     MOZ_ASSERT(cx_->activation_ == this);
     934       18092 :     MOZ_ASSERT(hideScriptedCallerCount_ == 0);
     935       18092 :     cx_->activation_ = prev_;
     936       18092 :     cx_->asyncCauseForNewActivations = asyncCause_;
     937       18092 :     cx_->asyncStackForNewActivations() = asyncStack_;
     938       18092 :     cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
     939       18092 : }
     940             : 
     941             : bool
     942       50617 : Activation::isProfiling() const
     943             : {
     944       50617 :     if (isInterpreter())
     945       24141 :         return asInterpreter()->isProfiling();
     946             : 
     947       26476 :     if (isJit())
     948       26476 :         return asJit()->isProfiling();
     949             : 
     950           0 :     MOZ_ASSERT(isWasm());
     951           0 :     return asWasm()->isProfiling();
     952             : }
     953             : 
     954             : Activation*
     955       17179 : Activation::mostRecentProfiling()
     956             : {
     957       17179 :     if (isProfiling())
     958        3457 :         return this;
     959       13722 :     return prevProfiling_;
     960             : }
     961             : 
     962             : inline LiveSavedFrameCache*
     963        4158 : Activation::getLiveSavedFrameCache(JSContext* cx) {
     964        4158 :     if (!frameCache_.get().initialized() && !frameCache_.get().init(cx))
     965           0 :         return nullptr;
     966        4158 :     return frameCache_.address();
     967             : }
     968             : 
     969       10427 : InterpreterActivation::InterpreterActivation(RunState& state, JSContext* cx,
     970       10427 :                                              InterpreterFrame* entryFrame)
     971             :   : Activation(cx, Interpreter),
     972             :     entryFrame_(entryFrame),
     973             :     opMask_(0)
     974             : #ifdef DEBUG
     975       10427 :   , oldFrameCount_(cx->interpreterStack().frameCount_)
     976             : #endif
     977             : {
     978       10427 :     regs_.prepareToRun(*entryFrame, state.script());
     979       10427 :     MOZ_ASSERT(regs_.pc == state.script()->code());
     980       10427 :     MOZ_ASSERT_IF(entryFrame_->isEvalFrame(), state.script()->isActiveEval());
     981       10427 : }
     982             : 
     983       20838 : InterpreterActivation::~InterpreterActivation()
     984             : {
     985             :     // Pop all inline frames.
     986       10419 :     while (regs_.fp() != entryFrame_)
     987           0 :         popInlineFrame(regs_.fp());
     988             : 
     989       10419 :     MOZ_ASSERT(oldFrameCount_ == cx_->interpreterStack().frameCount_);
     990       10419 :     MOZ_ASSERT_IF(oldFrameCount_ == 0, cx_->interpreterStack().allocator_.used() == 0);
     991             : 
     992       10419 :     if (entryFrame_)
     993       10419 :         cx_->interpreterStack().releaseFrame(entryFrame_);
     994       10419 : }
     995             : 
     996             : inline bool
     997        1674 : InterpreterActivation::pushInlineFrame(const CallArgs& args, HandleScript script,
     998             :                                        MaybeConstruct constructing)
     999             : {
    1000        1674 :     if (!cx_->interpreterStack().pushInlineFrame(cx_, regs_, args, script, constructing))
    1001           0 :         return false;
    1002        1674 :     MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment());
    1003        1674 :     return true;
    1004             : }
    1005             : 
    1006             : inline void
    1007        1869 : InterpreterActivation::popInlineFrame(InterpreterFrame* frame)
    1008             : {
    1009             :     (void)frame; // Quell compiler warning.
    1010        1869 :     MOZ_ASSERT(regs_.fp() == frame);
    1011        1869 :     MOZ_ASSERT(regs_.fp() != entryFrame_);
    1012             : 
    1013        1869 :     cx_->interpreterStack().popInlineFrame(regs_);
    1014        1869 : }
    1015             : 
    1016             : inline bool
    1017         198 : InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget,
    1018             :                                             HandleObject envChain)
    1019             : {
    1020         198 :     InterpreterStack& stack = cx_->interpreterStack();
    1021         198 :     if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, newTarget, envChain))
    1022           0 :         return false;
    1023             : 
    1024         198 :     MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
    1025         198 :     return true;
    1026             : }
    1027             : 
    1028             : inline bool
    1029        5675 : FrameIter::hasCachedSavedFrame() const
    1030             : {
    1031        5675 :     if (isWasm())
    1032           0 :         return false;
    1033             : 
    1034        5675 :     if (hasUsableAbstractFramePtr())
    1035        5675 :         return abstractFramePtr().hasCachedSavedFrame();
    1036             : 
    1037           0 :     MOZ_ASSERT(data_.jitFrames_.isIonScripted());
    1038             :     // SavedFrame caching is done at the physical frame granularity (rather than
    1039             :     // for each inlined frame) for ion. Therefore, it is impossible to have a
    1040             :     // cached SavedFrame if this frame is not a physical frame.
    1041           0 :     return isPhysicalIonFrame() && data_.jitFrames_.current()->hasCachedSavedFrame();
    1042             : }
    1043             : 
    1044             : inline void
    1045             : FrameIter::setHasCachedSavedFrame()
    1046             : {
    1047             :     MOZ_ASSERT(!isWasm());
    1048             : 
    1049             :     if (hasUsableAbstractFramePtr()) {
    1050             :         abstractFramePtr().setHasCachedSavedFrame();
    1051             :         return;
    1052             :     }
    1053             : 
    1054             :     MOZ_ASSERT(isPhysicalIonFrame());
    1055             :     data_.jitFrames_.current()->setHasCachedSavedFrame();
    1056             : }
    1057             : 
    1058             : } /* namespace js */
    1059             : 
    1060             : #endif /* vm_Stack_inl_h */

Generated by: LCOV version 1.13