LCOV - code coverage report
Current view: top level - js/src - jscntxtinlines.h (source / functions) Hit Total Coverage
Test: output.info Lines: 242 276 87.7 %
Date: 2017-07-14 16:53:18 Functions: 102 140 72.9 %
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 jscntxtinlines_h
       8             : #define jscntxtinlines_h
       9             : 
      10             : #include "jscntxt.h"
      11             : #include "jscompartment.h"
      12             : 
      13             : #include "jsiter.h"
      14             : 
      15             : #include "builtin/Object.h"
      16             : #include "jit/JitFrames.h"
      17             : #include "proxy/Proxy.h"
      18             : #include "vm/HelperThreads.h"
      19             : #include "vm/Interpreter.h"
      20             : #include "vm/Symbol.h"
      21             : 
      22             : namespace js {
      23             : 
      24             : class CompartmentChecker
      25             : {
      26             :     JSCompartment* compartment;
      27             : 
      28             :   public:
      29      551089 :     explicit CompartmentChecker(JSContext* cx)
      30      551089 :       : compartment(cx->compartment())
      31             :     {
      32      551089 :     }
      33             : 
      34             :     /*
      35             :      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      36             :      * compartment mismatches.
      37             :      */
      38           0 :     static void fail(JSCompartment* c1, JSCompartment* c2) {
      39           0 :         printf("*** Compartment mismatch %p vs. %p\n", (void*) c1, (void*) c2);
      40           0 :         MOZ_CRASH();
      41             :     }
      42             : 
      43           0 :     static void fail(JS::Zone* z1, JS::Zone* z2) {
      44           0 :         printf("*** Zone mismatch %p vs. %p\n", (void*) z1, (void*) z2);
      45           0 :         MOZ_CRASH();
      46             :     }
      47             : 
      48             :     /* Note: should only be used when neither c1 nor c2 may be the atoms compartment. */
      49             :     static void check(JSCompartment* c1, JSCompartment* c2) {
      50             :         MOZ_ASSERT(!c1->runtimeFromAnyThread()->isAtomsCompartment(c1));
      51             :         MOZ_ASSERT(!c2->runtimeFromAnyThread()->isAtomsCompartment(c2));
      52             :         if (c1 != c2)
      53             :             fail(c1, c2);
      54             :     }
      55             : 
      56      474240 :     void check(JSCompartment* c) {
      57      474240 :         if (c && !compartment->runtimeFromAnyThread()->isAtomsCompartment(c)) {
      58      469464 :             if (!compartment)
      59           0 :                 compartment = c;
      60      469464 :             else if (c != compartment)
      61           0 :                 fail(compartment, c);
      62             :         }
      63      474240 :     }
      64             : 
      65       14063 :     void checkZone(JS::Zone* z) {
      66       14063 :         if (compartment && z != compartment->zone())
      67           0 :             fail(compartment->zone(), z);
      68       14063 :     }
      69             : 
      70      469582 :     void check(JSObject* obj) {
      71      469582 :         if (obj) {
      72      436067 :             MOZ_ASSERT(JS::ObjectIsNotGray(obj));
      73      436068 :             MOZ_ASSERT(!js::gc::IsAboutToBeFinalizedUnbarriered(&obj));
      74      436070 :             check(obj->compartment());
      75             :         }
      76      469585 :     }
      77             : 
      78             :     template<typename T>
      79        4200 :     void check(const Rooted<T>& rooted) {
      80        4200 :         check(rooted.get());
      81        4200 :     }
      82             : 
      83             :     template<typename T>
      84      343932 :     void check(Handle<T> handle) {
      85      343932 :         check(handle.get());
      86      343932 :     }
      87             : 
      88             :     template<typename T>
      89       80897 :     void check(MutableHandle<T> handle) {
      90       80897 :         check(handle.get());
      91       80898 :     }
      92             : 
      93             :     template <typename T>
      94      163383 :     void checkAtom(T* thing) {
      95             :         static_assert(mozilla::IsSame<T, JSAtom>::value ||
      96             :                       mozilla::IsSame<T, JS::Symbol>::value,
      97             :                       "Should only be called with JSAtom* or JS::Symbol* argument");
      98             : 
      99             : #ifdef DEBUG
     100             :         // Atoms which move across zone boundaries need to be marked in the new
     101             :         // zone, see JS_MarkCrossZoneId.
     102      163383 :         if (compartment) {
     103      163383 :             JSRuntime* rt = compartment->runtimeFromAnyThread();
     104      163383 :             MOZ_ASSERT(rt->gc.atomMarking.atomIsMarked(compartment->zone(), thing));
     105             :         }
     106             : #endif
     107      163383 :     }
     108             : 
     109       61336 :     void check(JSString* str) {
     110       61336 :         MOZ_ASSERT(JS::CellIsNotGray(str));
     111       61336 :         if (str->isAtom()) {
     112       47273 :             checkAtom(&str->asAtom());
     113             :         } else {
     114       14063 :             checkZone(str->zone());
     115             :         }
     116       61336 :     }
     117             : 
     118         620 :     void check(JS::Symbol* symbol) {
     119         620 :         checkAtom(symbol);
     120         620 :     }
     121             : 
     122      447318 :     void check(const js::Value& v) {
     123      447318 :         if (v.isObject())
     124      271885 :             check(&v.toObject());
     125      175436 :         else if (v.isString())
     126       53990 :             check(v.toString());
     127      121446 :         else if (v.isSymbol())
     128         620 :             check(v.toSymbol());
     129      447322 :     }
     130             : 
     131             :     // Check the contents of any container class that supports the C++
     132             :     // iteration protocol, eg GCVector<jsid>.
     133             :     template <typename Container>
     134             :     typename mozilla::EnableIf<
     135             :         mozilla::IsSame<
     136             :             decltype(((Container*)nullptr)->begin()),
     137             :             decltype(((Container*)nullptr)->end())
     138             :         >::value
     139             :     >::Type
     140          19 :     check(const Container& container) {
     141          19 :         for (auto i : container)
     142           0 :             check(i);
     143          19 :     }
     144             : 
     145             :     void check(const ValueArray& arr) {
     146             :         for (size_t i = 0; i < arr.length; i++)
     147             :             check(arr.array[i]);
     148             :     }
     149             : 
     150         272 :     void check(const JSValueArray& arr) {
     151         816 :         for (size_t i = 0; i < arr.length; i++)
     152         544 :             check(arr.array[i]);
     153         272 :     }
     154             : 
     155        1937 :     void check(const JS::HandleValueArray& arr) {
     156        4083 :         for (size_t i = 0; i < arr.length(); i++)
     157        2146 :             check(arr[i]);
     158        1937 :     }
     159             : 
     160       32451 :     void check(const CallArgs& args) {
     161      139770 :         for (Value* p = args.base(); p != args.end(); ++p)
     162      107319 :             check(*p);
     163       32451 :     }
     164             : 
     165      118833 :     void check(jsid id) {
     166      118833 :         if (JSID_IS_ATOM(id))
     167      112188 :             checkAtom(JSID_TO_ATOM(id));
     168        6645 :         else if (JSID_IS_SYMBOL(id))
     169        3265 :             checkAtom(JSID_TO_SYMBOL(id));
     170             :         else
     171        3380 :             MOZ_ASSERT(!JSID_IS_GCTHING(id));
     172      118833 :     }
     173             : 
     174       13164 :     void check(JSScript* script) {
     175       13164 :         MOZ_ASSERT(JS::CellIsNotGray(script));
     176       13164 :         if (script)
     177       13164 :             check(script->compartment());
     178       13164 :     }
     179             : 
     180             :     void check(InterpreterFrame* fp);
     181             :     void check(AbstractFramePtr frame);
     182             :     void check(SavedStacks* stacks);
     183             : 
     184         316 :     void check(Handle<PropertyDescriptor> desc) {
     185         316 :         check(desc.object());
     186         316 :         if (desc.hasGetterObject())
     187         131 :             check(desc.getterObject());
     188         316 :         if (desc.hasSetterObject())
     189          67 :             check(desc.setterObject());
     190         316 :         check(desc.value());
     191         316 :     }
     192             : 
     193       12543 :     void check(TypeSet::Type type) {
     194       12543 :         check(type.maybeCompartment());
     195       12543 :     }
     196             : };
     197             : 
     198             : /*
     199             :  * Don't perform these checks when called from a finalizer. The checking
     200             :  * depends on other objects not having been swept yet.
     201             :  */
     202             : #define START_ASSERT_SAME_COMPARTMENT()                                 \
     203             :     if (cx->heapState != JS::HeapState::Idle)                           \
     204             :         return;                                                         \
     205             :     CompartmentChecker c(cx)
     206             : 
     207             : template <class T1> inline void
     208        2261 : releaseAssertSameCompartment(JSContext* cx, const T1& t1)
     209             : {
     210        2261 :     START_ASSERT_SAME_COMPARTMENT();
     211        2261 :     c.check(t1);
     212             : }
     213             : 
     214             : template <class T1> inline void
     215      250572 : assertSameCompartment(JSContext* cx, const T1& t1)
     216             : {
     217             : #ifdef JS_CRASH_DIAGNOSTICS
     218      250572 :     START_ASSERT_SAME_COMPARTMENT();
     219      250572 :     c.check(t1);
     220             : #endif
     221             : }
     222             : 
     223             : template <class T1> inline void
     224      193882 : assertSameCompartmentDebugOnly(JSContext* cx, const T1& t1)
     225             : {
     226             : #if defined(DEBUG) && defined(JS_CRASH_DIAGNOSTICS)
     227      193882 :     START_ASSERT_SAME_COMPARTMENT();
     228      193882 :     c.check(t1);
     229             : #endif
     230             : }
     231             : 
     232             : template <class T1, class T2> inline void
     233       57477 : assertSameCompartment(JSContext* cx, const T1& t1, const T2& t2)
     234             : {
     235             : #ifdef JS_CRASH_DIAGNOSTICS
     236       57477 :     START_ASSERT_SAME_COMPARTMENT();
     237       57477 :     c.check(t1);
     238       57477 :     c.check(t2);
     239             : #endif
     240             : }
     241             : 
     242             : template <class T1, class T2, class T3> inline void
     243       23494 : assertSameCompartment(JSContext* cx, const T1& t1, const T2& t2, const T3& t3)
     244             : {
     245             : #ifdef JS_CRASH_DIAGNOSTICS
     246       23494 :     START_ASSERT_SAME_COMPARTMENT();
     247       23494 :     c.check(t1);
     248       23494 :     c.check(t2);
     249       23494 :     c.check(t3);
     250             : #endif
     251             : }
     252             : 
     253             : template <class T1, class T2, class T3, class T4> inline void
     254           0 : assertSameCompartment(JSContext* cx,
     255             :                       const T1& t1, const T2& t2, const T3& t3, const T4& t4)
     256             : {
     257             : #ifdef JS_CRASH_DIAGNOSTICS
     258           0 :     START_ASSERT_SAME_COMPARTMENT();
     259           0 :     c.check(t1);
     260           0 :     c.check(t2);
     261           0 :     c.check(t3);
     262           0 :     c.check(t4);
     263             : #endif
     264             : }
     265             : 
     266             : template <class T1, class T2, class T3, class T4, class T5> inline void
     267       23351 : assertSameCompartment(JSContext* cx,
     268             :                       const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
     269             : {
     270             : #ifdef JS_CRASH_DIAGNOSTICS
     271       23351 :     START_ASSERT_SAME_COMPARTMENT();
     272       23351 :     c.check(t1);
     273       23351 :     c.check(t2);
     274       23351 :     c.check(t3);
     275       23351 :     c.check(t4);
     276       23351 :     c.check(t5);
     277             : #endif
     278             : }
     279             : 
     280             : #undef START_ASSERT_SAME_COMPARTMENT
     281             : 
     282             : STATIC_PRECONDITION_ASSUME(ubound(args.argv_) >= argc)
     283             : MOZ_ALWAYS_INLINE bool
     284       32451 : CallJSNative(JSContext* cx, Native native, const CallArgs& args)
     285             : {
     286       32451 :     if (!CheckRecursionLimit(cx))
     287           0 :         return false;
     288             : 
     289             : #ifdef DEBUG
     290       32451 :     bool alreadyThrowing = cx->isExceptionPending();
     291             : #endif
     292       32451 :     assertSameCompartment(cx, args);
     293       32451 :     bool ok = native(cx, args.length(), args.base());
     294       32444 :     if (ok) {
     295       32265 :         assertSameCompartment(cx, args.rval());
     296       32266 :         MOZ_ASSERT_IF(!alreadyThrowing, !cx->isExceptionPending());
     297             :     }
     298       32445 :     return ok;
     299             : }
     300             : 
     301             : STATIC_PRECONDITION_ASSUME(ubound(args.argv_) >= argc)
     302             : MOZ_ALWAYS_INLINE bool
     303           0 : CallNativeImpl(JSContext* cx, NativeImpl impl, const CallArgs& args)
     304             : {
     305             : #ifdef DEBUG
     306           0 :     bool alreadyThrowing = cx->isExceptionPending();
     307             : #endif
     308           0 :     assertSameCompartment(cx, args);
     309           0 :     bool ok = impl(cx, args);
     310           0 :     if (ok) {
     311           0 :         assertSameCompartment(cx, args.rval());
     312           0 :         MOZ_ASSERT_IF(!alreadyThrowing, !cx->isExceptionPending());
     313             :     }
     314           0 :     return ok;
     315             : }
     316             : 
     317             : STATIC_PRECONDITION(ubound(args.argv_) >= argc)
     318             : MOZ_ALWAYS_INLINE bool
     319         749 : CallJSNativeConstructor(JSContext* cx, Native native, const CallArgs& args)
     320             : {
     321             : #ifdef DEBUG
     322        1498 :     RootedObject callee(cx, &args.callee());
     323             : #endif
     324             : 
     325         749 :     MOZ_ASSERT(args.thisv().isMagic());
     326         749 :     if (!CallJSNative(cx, native, args))
     327          11 :         return false;
     328             : 
     329             :     /*
     330             :      * Native constructors must return non-primitive values on success.
     331             :      * Although it is legal, if a constructor returns the callee, there is a
     332             :      * 99.9999% chance it is a bug. If any valid code actually wants the
     333             :      * constructor to return the callee, the assertion can be removed or
     334             :      * (another) conjunct can be added to the antecedent.
     335             :      *
     336             :      * Exceptions:
     337             :      *
     338             :      * - Proxies are exceptions to both rules: they can return primitives and
     339             :      *   they allow content to return the callee.
     340             :      *
     341             :      * - CallOrConstructBoundFunction is an exception as well because we might
     342             :      *   have used bind on a proxy function.
     343             :      *
     344             :      * - new Iterator(x) is user-hookable; it returns x.__iterator__() which
     345             :      *   could be any object.
     346             :      *
     347             :      * - (new Object(Object)) returns the callee.
     348             :      */
     349         738 :     MOZ_ASSERT_IF(native != js::proxy_Construct &&
     350             :                   native != js::IteratorConstructor &&
     351             :                   (!callee->is<JSFunction>() || callee->as<JSFunction>().native() != obj_construct),
     352             :                   args.rval().isObject() && callee != &args.rval().toObject());
     353             : 
     354         738 :     return true;
     355             : }
     356             : 
     357             : MOZ_ALWAYS_INLINE bool
     358         738 : CallJSGetterOp(JSContext* cx, GetterOp op, HandleObject obj, HandleId id,
     359             :                MutableHandleValue vp)
     360             : {
     361         738 :     if (!CheckRecursionLimit(cx))
     362           0 :         return false;
     363             : 
     364         738 :     assertSameCompartment(cx, obj, id, vp);
     365         738 :     bool ok = op(cx, obj, id, vp);
     366         738 :     if (ok)
     367         738 :         assertSameCompartment(cx, vp);
     368         738 :     return ok;
     369             : }
     370             : 
     371             : MOZ_ALWAYS_INLINE bool
     372          72 : CallJSSetterOp(JSContext* cx, SetterOp op, HandleObject obj, HandleId id, MutableHandleValue vp,
     373             :                ObjectOpResult& result)
     374             : {
     375          72 :     if (!CheckRecursionLimit(cx))
     376           0 :         return false;
     377             : 
     378          72 :     assertSameCompartment(cx, obj, id, vp);
     379          72 :     return op(cx, obj, id, vp, result);
     380             : }
     381             : 
     382             : inline bool
     383       13614 : CallJSAddPropertyOp(JSContext* cx, JSAddPropertyOp op, HandleObject obj, HandleId id,
     384             :                     HandleValue v)
     385             : {
     386       13614 :     if (!CheckRecursionLimit(cx))
     387           0 :         return false;
     388             : 
     389       13614 :     assertSameCompartment(cx, obj, id, v);
     390       13614 :     return op(cx, obj, id, v);
     391             : }
     392             : 
     393             : inline bool
     394         477 : CallJSDeletePropertyOp(JSContext* cx, JSDeletePropertyOp op, HandleObject receiver, HandleId id,
     395             :                        ObjectOpResult& result)
     396             : {
     397         477 :     if (!CheckRecursionLimit(cx))
     398           0 :         return false;
     399             : 
     400         477 :     assertSameCompartment(cx, receiver, id);
     401         477 :     if (op)
     402          17 :         return op(cx, receiver, id, result);
     403         460 :     return result.succeed();
     404             : }
     405             : 
     406             : MOZ_ALWAYS_INLINE bool
     407       18615 : CheckForInterrupt(JSContext* cx)
     408             : {
     409       18615 :     MOZ_ASSERT(!cx->isExceptionPending());
     410             :     // Add an inline fast-path since we have to check for interrupts in some hot
     411             :     // C++ loops of library builtins.
     412       18615 :     if (MOZ_UNLIKELY(cx->hasPendingInterrupt()))
     413          15 :         return cx->handleInterrupt();
     414       18600 :     return true;
     415             : }
     416             : 
     417             : }  /* namespace js */
     418             : 
     419             : inline js::LifoAlloc&
     420       84887 : JSContext::typeLifoAlloc()
     421             : {
     422       84887 :     return zone()->types.typeLifoAlloc();
     423             : }
     424             : 
     425             : inline js::Nursery&
     426      212230 : JSContext::nursery()
     427             : {
     428      212230 :     return runtime()->gc.nursery();
     429             : }
     430             : 
     431             : inline void
     432           0 : JSContext::minorGC(JS::gcreason::Reason reason)
     433             : {
     434           0 :     runtime()->gc.minorGC(reason);
     435           0 : }
     436             : 
     437             : inline void
     438        4142 : JSContext::setPendingException(const js::Value& v)
     439             : {
     440             :     // overRecursed_ is set after the fact by ReportOverRecursed.
     441        4142 :     this->overRecursed_ = false;
     442        4142 :     this->throwing = true;
     443        4142 :     this->unwrappedException() = v;
     444             :     // We don't use assertSameCompartment here to allow
     445             :     // js::SetPendingExceptionCrossContext to work.
     446        4142 :     MOZ_ASSERT_IF(v.isObject(), v.toObject().compartment() == compartment());
     447        4142 : }
     448             : 
     449             : inline bool
     450         797 : JSContext::runningWithTrustedPrincipals()
     451             : {
     452         797 :     return !compartment() || compartment()->principals() == runtime()->trustedPrincipals();
     453             : }
     454             : 
     455             : inline void
     456       83424 : JSContext::enterNonAtomsCompartment(JSCompartment* c)
     457             : {
     458       83424 :     enterCompartmentDepth_++;
     459             : 
     460       83424 :     MOZ_ASSERT(!c->zone()->isAtomsZone());
     461       83424 :     enterZoneGroup(c->zone()->group());
     462             : 
     463       83424 :     c->enter();
     464       83424 :     setCompartment(c, nullptr);
     465       83424 : }
     466             : 
     467             : inline void
     468       62625 : JSContext::enterAtomsCompartment(JSCompartment* c,
     469             :                                  const js::AutoLockForExclusiveAccess& lock)
     470             : {
     471       62625 :     enterCompartmentDepth_++;
     472             : 
     473       62625 :     MOZ_ASSERT(c->zone()->isAtomsZone());
     474             : 
     475       62625 :     c->enter();
     476       62625 :     setCompartment(c, &lock);
     477       62625 : }
     478             : 
     479             : template <typename T>
     480             : inline void
     481       70309 : JSContext::enterCompartmentOf(const T& target)
     482             : {
     483       70309 :     MOZ_ASSERT(JS::CellIsNotGray(target));
     484       70309 :     enterNonAtomsCompartment(target->compartment());
     485       70309 : }
     486             : 
     487             : inline void
     488        1656 : JSContext::enterNullCompartment()
     489             : {
     490        1656 :     enterCompartmentDepth_++;
     491        1656 :     setCompartment(nullptr);
     492        1656 : }
     493             : 
     494             : inline void
     495      147691 : JSContext::leaveCompartment(
     496             :     JSCompartment* oldCompartment,
     497             :     const js::AutoLockForExclusiveAccess* maybeLock /* = nullptr */)
     498             : {
     499      147691 :     MOZ_ASSERT(hasEnteredCompartment());
     500      147692 :     enterCompartmentDepth_--;
     501             : 
     502             :     // Only call leave() after we've setCompartment()-ed away from the current
     503             :     // compartment.
     504      147693 :     JSCompartment* startingCompartment = compartment_;
     505      147693 :     setCompartment(oldCompartment, maybeLock);
     506      147694 :     if (startingCompartment) {
     507      146038 :         startingCompartment->leave();
     508      146038 :         if (!startingCompartment->zone()->isAtomsZone())
     509       83413 :             leaveZoneGroup(startingCompartment->zone()->group());
     510             :     }
     511      147694 : }
     512             : 
     513             : inline void
     514      295387 : JSContext::setCompartment(JSCompartment* comp,
     515             :                           const js::AutoLockForExclusiveAccess* maybeLock /* = nullptr */)
     516             : {
     517             :     // Only one thread can be in the atoms compartment at a time.
     518      295387 :     MOZ_ASSERT_IF(runtime_->isAtomsCompartment(comp), maybeLock != nullptr);
     519      295387 :     MOZ_ASSERT_IF(runtime_->isAtomsCompartment(comp) || runtime_->isAtomsCompartment(compartment_),
     520             :                   runtime_->currentThreadHasExclusiveAccess());
     521             : 
     522             :     // Make sure that the atoms compartment has its own zone.
     523      295393 :     MOZ_ASSERT_IF(comp && !runtime_->isAtomsCompartment(comp),
     524             :                   !comp->zone()->isAtomsZone());
     525             : 
     526             :     // Both the current and the new compartment should be properly marked as
     527             :     // entered at this point.
     528      295394 :     MOZ_ASSERT_IF(compartment_, compartment_->hasBeenEntered());
     529      295394 :     MOZ_ASSERT_IF(comp, comp->hasBeenEntered());
     530             : 
     531             :     // This context must have exclusive access to the zone's group.
     532      295394 :     MOZ_ASSERT_IF(comp && !comp->zone()->isAtomsZone(),
     533             :                   comp->zone()->group()->ownedByCurrentThread());
     534             : 
     535      295394 :     compartment_ = comp;
     536      295394 :     zone_ = comp ? comp->zone() : nullptr;
     537      295394 :     arenas_ = zone_ ? &zone_->arenas : nullptr;
     538      295398 : }
     539             : 
     540             : inline void
     541       83424 : JSContext::enterZoneGroup(js::ZoneGroup* group)
     542             : {
     543       83424 :     MOZ_ASSERT(this == js::TlsContext.get());
     544       83424 :     group->enter(this);
     545       83424 : }
     546             : 
     547             : inline void
     548       83413 : JSContext::leaveZoneGroup(js::ZoneGroup* group)
     549             : {
     550       83413 :     MOZ_ASSERT(this == js::TlsContext.get());
     551       83413 :     group->leave();
     552       83413 : }
     553             : 
     554             : inline JSScript*
     555       35902 : JSContext::currentScript(jsbytecode** ppc,
     556             :                          MaybeAllowCrossCompartment allowCrossCompartment) const
     557             : {
     558       35902 :     if (ppc)
     559        6936 :         *ppc = nullptr;
     560             : 
     561       35902 :     js::Activation* act = activation();
     562       35902 :     while (act && act->isJit() && !act->asJit()->isActive())
     563           0 :         act = act->prev();
     564             : 
     565       35902 :     if (!act)
     566        4508 :         return nullptr;
     567             : 
     568       31394 :     MOZ_ASSERT(act->cx() == this);
     569             : 
     570       31394 :     if (!allowCrossCompartment && act->compartment() != compartment())
     571        1333 :         return nullptr;
     572             : 
     573       30061 :     if (act->isJit()) {
     574        4072 :         JSScript* script = nullptr;
     575        4072 :         js::jit::GetPcScript(const_cast<JSContext*>(this), &script, ppc);
     576        4072 :         MOZ_ASSERT(allowCrossCompartment || script->compartment() == compartment());
     577        4072 :         return script;
     578             :     }
     579             : 
     580       25989 :     if (act->isWasm())
     581           0 :         return nullptr;
     582             : 
     583       25989 :     MOZ_ASSERT(act->isInterpreter());
     584             : 
     585       25989 :     js::InterpreterFrame* fp = act->asInterpreter()->current();
     586       25989 :     MOZ_ASSERT(!fp->runningInJit());
     587             : 
     588       25989 :     JSScript* script = fp->script();
     589       25989 :     MOZ_ASSERT(allowCrossCompartment || script->compartment() == compartment());
     590             : 
     591       25989 :     if (ppc) {
     592        4634 :         *ppc = act->asInterpreter()->regs().pc;
     593        4634 :         MOZ_ASSERT(script->containsPC(*ppc));
     594             :     }
     595             : 
     596       25989 :     return script;
     597             : }
     598             : 
     599             : inline js::RuntimeCaches&
     600       41731 : JSContext::caches()
     601             : {
     602       41731 :     return runtime()->caches();
     603             : }
     604             : 
     605             : #endif /* jscntxtinlines_h */

Generated by: LCOV version 1.13