LCOV - code coverage report
Current view: top level - js/src/vm - JSContext.h (source / functions) Hit Total Coverage
Test: output.info Lines: 117 215 54.4 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
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             : /* JS execution context. */
       8             : 
       9             : #ifndef vm_JSContext_h
      10             : #define vm_JSContext_h
      11             : 
      12             : #include "mozilla/MemoryReporting.h"
      13             : 
      14             : #include "js/CharacterEncoding.h"
      15             : #include "js/GCVector.h"
      16             : #include "js/Result.h"
      17             : #include "js/Utility.h"
      18             : #include "js/Vector.h"
      19             : #include "threading/ProtectedData.h"
      20             : #include "vm/ErrorReporting.h"
      21             : #include "vm/MallocProvider.h"
      22             : #include "vm/Runtime.h"
      23             : 
      24             : struct DtoaState;
      25             : 
      26             : namespace js {
      27             : 
      28             : class AutoAtomsZone;
      29             : class AutoRealm;
      30             : 
      31             : namespace jit {
      32             : class JitContext;
      33             : class DebugModeOSRVolatileJitFrameIter;
      34             : } // namespace jit
      35             : 
      36             : namespace gc {
      37             : class AutoSuppressNurseryCellAlloc;
      38             : }
      39             : 
      40             : typedef HashSet<Shape*> ShapeSet;
      41             : 
      42             : /* Detects cycles when traversing an object graph. */
      43             : class MOZ_RAII AutoCycleDetector
      44             : {
      45             :   public:
      46             :     using Vector = GCVector<JSObject*, 8>;
      47             : 
      48             :     AutoCycleDetector(JSContext* cx, HandleObject objArg
      49             :                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
      50           0 :       : cx(cx), obj(cx, objArg), cyclic(true)
      51             :     {
      52           0 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
      53             :     }
      54             : 
      55             :     ~AutoCycleDetector();
      56             : 
      57             :     bool init();
      58             : 
      59             :     bool foundCycle() { return cyclic; }
      60             : 
      61             :   private:
      62             :     JSContext* cx;
      63             :     RootedObject obj;
      64             :     bool cyclic;
      65             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
      66             : };
      67             : 
      68             : struct AutoResolving;
      69             : 
      70             : struct HelperThread;
      71             : 
      72             : using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>;
      73             : 
      74             : class AutoLockForExclusiveAccess;
      75             : class AutoLockScriptData;
      76             : 
      77             : void ReportOverRecursed(JSContext* cx, unsigned errorNumber);
      78             : 
      79             : /* Thread Local Storage slot for storing the context for a thread. */
      80             : extern MOZ_THREAD_LOCAL(JSContext*) TlsContext;
      81             : 
      82             : enum class ContextKind
      83             : {
      84             :     // Context for the main thread of a JSRuntime.
      85             :     MainThread,
      86             : 
      87             :     // Context for a helper thread.
      88             :     HelperThread
      89             : };
      90             : 
      91             : #ifdef DEBUG
      92             : bool
      93             : CurrentThreadIsParseThread();
      94             : #endif
      95             : 
      96             : enum class InterruptReason : uint32_t
      97             : {
      98             :     GC = 1 << 0,
      99             :     AttachIonCompilations = 1 << 1,
     100             :     CallbackUrgent = 1 << 2,
     101             :     CallbackCanWait = 1 << 3,
     102             : };
     103             : 
     104             : } /* namespace js */
     105             : 
     106             : /*
     107             :  * A JSContext encapsulates the thread local state used when using the JS
     108             :  * runtime.
     109             :  */
     110             : struct JSContext : public JS::RootingContext,
     111             :                    public js::MallocProvider<JSContext>
     112             : {
     113             :     JSContext(JSRuntime* runtime, const JS::ContextOptions& options);
     114             :     ~JSContext();
     115             : 
     116             :     bool init(js::ContextKind kind);
     117             : 
     118             :   private:
     119             :     js::UnprotectedData<JSRuntime*> runtime_;
     120             :     js::WriteOnceData<js::ContextKind> kind_;
     121             : 
     122             :     // The thread on which this context is running if this is not the main thread.
     123             :     js::ThreadData<js::HelperThread*> helperThread_;
     124             : 
     125             :     friend class js::gc::AutoSuppressNurseryCellAlloc;
     126             :     js::ThreadData<size_t> nurserySuppressions_;
     127             : 
     128             :     js::ThreadData<JS::ContextOptions> options_;
     129             : 
     130             :     js::ThreadData<js::gc::ArenaLists*> arenas_;
     131             : 
     132             :   public:
     133             :     // This is used by helper threads to change the runtime their context is
     134             :     // currently operating on.
     135             :     void setRuntime(JSRuntime* rt);
     136             : 
     137           0 :     bool isMainThreadContext() const { return kind_ == js::ContextKind::MainThread; }
     138             : 
     139           0 :     inline js::gc::ArenaLists* arenas() const { return arenas_; }
     140             : 
     141             :     template <typename T>
     142             :     bool isInsideCurrentZone(T thing) const {
     143           0 :         return thing->zoneFromAnyThread() == zone_;
     144             :     }
     145             : 
     146             :     template <typename T>
     147             :     inline bool isInsideCurrentCompartment(T thing) const {
     148           0 :         return thing->compartment() == compartment();
     149             :     }
     150             : 
     151           0 :     void* onOutOfMemory(js::AllocFunction allocFunc, size_t nbytes, void* reallocPtr = nullptr) {
     152           0 :         if (helperThread()) {
     153           0 :             addPendingOutOfMemory();
     154           0 :             return nullptr;
     155             :         }
     156           0 :         return runtime_->onOutOfMemory(allocFunc, nbytes, reallocPtr, this);
     157             :     }
     158             : 
     159             :     /* Clear the pending exception (if any) due to OOM. */
     160             :     void recoverFromOutOfMemory();
     161             : 
     162             :     void updateMallocCounter(size_t nbytes);
     163             : 
     164             :     void reportAllocationOverflow() {
     165           0 :         js::ReportAllocationOverflow(this);
     166             :     }
     167             : 
     168             :     // Accessors for immutable runtime data.
     169           0 :     JSAtomState& names() { return *runtime_->commonNames; }
     170           0 :     js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }
     171             :     js::SharedImmutableStringsCache& sharedImmutableStrings() {
     172             :         return runtime_->sharedImmutableStrings();
     173             :     }
     174           0 :     bool isPermanentAtomsInitialized() { return !!runtime_->permanentAtoms; }
     175           0 :     js::FrozenAtomSet& permanentAtoms() { return *runtime_->permanentAtoms; }
     176           0 :     js::WellKnownSymbols& wellKnownSymbols() { return *runtime_->wellKnownSymbols; }
     177           0 :     JS::BuildIdOp buildIdOp() { return runtime_->buildIdOp; }
     178           0 :     const JS::AsmJSCacheOps& asmJSCacheOps() { return runtime_->asmJSCacheOps; }
     179           0 :     js::PropertyName* emptyString() { return runtime_->emptyString; }
     180           0 :     js::FreeOp* defaultFreeOp() { return runtime_->defaultFreeOp(); }
     181           0 :     void* stackLimitAddress(JS::StackKind kind) { return &nativeStackLimit[kind]; }
     182             :     void* stackLimitAddressForJitCode(JS::StackKind kind);
     183           0 :     uintptr_t stackLimit(JS::StackKind kind) { return nativeStackLimit[kind]; }
     184             :     uintptr_t stackLimitForJitCode(JS::StackKind kind);
     185             :     size_t gcSystemPageSize() { return js::gc::SystemPageSize(); }
     186           0 :     bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
     187           0 :     bool jitSupportsUnalignedAccesses() const { return runtime_->jitSupportsUnalignedAccesses; }
     188           0 :     bool jitSupportsSimd() const { return runtime_->jitSupportsSimd; }
     189           0 :     bool lcovEnabled() const { return runtime_->lcovOutput().isEnabled(); }
     190             : 
     191             :     /*
     192             :      * "Entering" a realm changes cx->realm (which changes cx->global). Note
     193             :      * that this does not push an Activation so it's possible for the caller's
     194             :      * realm to be != cx->realm(). This is not a problem since, in general, most
     195             :      * places in the VM cannot know that they were called from script (e.g.,
     196             :      * they may have been called through the JSAPI via JS_CallFunction) and thus
     197             :      * cannot expect there is a scripted caller.
     198             :      *
     199             :      * Realms should be entered/left in a LIFO fasion. To enter a realm, code
     200             :      * should prefer using AutoRealm over JS::EnterRealm/JS::LeaveRealm.
     201             :      *
     202             :      * Also note that the JIT can enter (same-compartment) realms without going
     203             :      * through these methods - it will update cx->realm_ directly.
     204             :      */
     205             :   private:
     206             :     inline void setRealm(JS::Realm* realm);
     207             :     inline void enterRealm(JS::Realm* realm);
     208             :     inline void enterAtomsZone(const js::AutoLockForExclusiveAccess& lock);
     209             : 
     210             :     friend class js::AutoAtomsZone;
     211             :     friend class js::AutoRealm;
     212             : 
     213             :   public:
     214             :     template <typename T>
     215             :     inline void enterRealmOf(const T& target);
     216             :     inline void enterNullRealm();
     217             : 
     218             :     inline void leaveRealm(JS::Realm* oldRealm);
     219             :     inline void leaveAtomsZone(JS::Realm* oldRealm,
     220             :                                const js::AutoLockForExclusiveAccess& lock);
     221             : 
     222             :     void setHelperThread(js::HelperThread* helperThread);
     223     3876739 :     js::HelperThread* helperThread() const { return helperThread_; }
     224             : 
     225             :     bool isNurseryAllocSuppressed() const {
     226      675634 :         return nurserySuppressions_;
     227             :     }
     228             : 
     229             :     // Threads may freely access any data in their realm, compartment and zone.
     230             :     JS::Compartment* compartment() const {
     231     2856417 :         return realm_ ? JS::GetCompartmentForRealm(realm_) : nullptr;
     232             :     }
     233             : 
     234             :     JS::Realm* realm() const {
     235     8390240 :         return realm_;
     236             :     }
     237             : 
     238             : #ifdef DEBUG
     239             :     bool inAtomsZone() const;
     240             : #endif
     241             : 
     242           0 :     JS::Zone* zone() const {
     243     3511112 :         MOZ_ASSERT_IF(!realm() && zone_, inAtomsZone());
     244     3511112 :         MOZ_ASSERT_IF(realm(), js::GetRealmZone(realm()) == zone_);
     245     3511278 :         return zoneRaw();
     246             :     }
     247             : 
     248             :     // For use when the context's zone is being read by another thread and the
     249             :     // compartment and zone pointers might not be in sync.
     250             :     JS::Zone* zoneRaw() const {
     251     3511278 :         return zone_;
     252             :     }
     253             : 
     254             :     // For JIT use.
     255             :     static size_t offsetOfZone() {
     256             :         return offsetof(JSContext, zone_);
     257             :     }
     258             : 
     259             :     // Zone local methods that can be used freely.
     260             :     inline js::LifoAlloc& typeLifoAlloc();
     261             : 
     262             :     // Current global. This is only safe to use within the scope of the
     263             :     // AutoRealm from which it's called.
     264             :     inline js::Handle<js::GlobalObject*> global() const;
     265             : 
     266             :     // Methods to access runtime data that must be protected by locks.
     267             :     js::AtomSet& atoms(js::AutoLockForExclusiveAccess& lock) {
     268             :         return runtime_->atoms(lock);
     269             :     }
     270             :     const JS::Zone* atomsZone(js::AutoLockForExclusiveAccess& lock) {
     271          72 :         return runtime_->atomsZone(lock);
     272             :     }
     273             :     js::SymbolRegistry& symbolRegistry(js::AutoLockForExclusiveAccess& lock) {
     274           0 :         return runtime_->symbolRegistry(lock);
     275             :     }
     276             :     js::ScriptDataTable& scriptDataTable(js::AutoLockScriptData& lock) {
     277       79098 :         return runtime_->scriptDataTable(lock);
     278             :     }
     279             : 
     280             :     // Methods to access other runtime data that checks locking internally.
     281             :     js::gc::AtomMarkingRuntime& atomMarking() {
     282      405272 :         return runtime_->gc.atomMarking;
     283             :     }
     284      102704 :     void markAtom(JSAtom* atom) {
     285      102704 :         atomMarking().markAtom(this, atom);
     286           0 :     }
     287          24 :     void markAtom(JS::Symbol* symbol) {
     288          24 :         atomMarking().markAtom(this, symbol);
     289           0 :     }
     290       31266 :     void markId(jsid id) {
     291       31266 :         atomMarking().markId(this, id);
     292           0 :     }
     293        2011 :     void markAtomValue(const js::Value& value) {
     294        2011 :         atomMarking().markAtomValue(this, value);
     295        2011 :     }
     296             : 
     297             :     // Methods specific to any HelperThread for the context.
     298             :     bool addPendingCompileError(js::CompileError** err);
     299             :     void addPendingOverRecursed();
     300             :     void addPendingOutOfMemory();
     301             : 
     302           0 :     JSRuntime* runtime() { return runtime_; }
     303           0 :     const JSRuntime* runtime() const { return runtime_; }
     304             : 
     305             :     static size_t offsetOfRealm() {
     306             :         return offsetof(JSContext, realm_);
     307             :     }
     308             : 
     309             :     friend class JS::AutoSaveExceptionState;
     310             :     friend class js::jit::DebugModeOSRVolatileJitFrameIter;
     311             :     friend void js::ReportOverRecursed(JSContext*, unsigned errorNumber);
     312             : 
     313             :   private:
     314             :     static JS::Error reportedError;
     315             :     static JS::OOM reportedOOM;
     316             : 
     317             :   public:
     318             :     inline JS::Result<> boolToResult(bool ok);
     319             : 
     320             :     /**
     321             :      * Intentionally awkward signpost method that is stationed on the
     322             :      * boundary between Result-using and non-Result-using code.
     323             :      */
     324             :     template <typename V, typename E>
     325             :     bool resultToBool(const JS::Result<V, E>& result) {
     326           0 :         return result.isOk();
     327             :     }
     328             : 
     329             :     template <typename V, typename E>
     330             :     V* resultToPtr(const JS::Result<V*, E>& result) {
     331             :         return result.isOk() ? result.unwrap() : nullptr;
     332             :     }
     333             : 
     334             :     mozilla::GenericErrorResult<JS::OOM&> alreadyReportedOOM();
     335             :     mozilla::GenericErrorResult<JS::Error&> alreadyReportedError();
     336             : 
     337             :     /*
     338             :      * Points to the most recent JitActivation pushed on the thread.
     339             :      * See JitActivation constructor in vm/Stack.cpp
     340             :      */
     341             :     js::ThreadData<js::jit::JitActivation*> jitActivation;
     342             : 
     343             :     // Information about the heap allocated backtrack stack used by RegExp JIT code.
     344             :     js::ThreadData<js::irregexp::RegExpStack> regexpStack;
     345             : 
     346             :     /*
     347             :      * Points to the most recent activation running on the thread.
     348             :      * See Activation comment in vm/Stack.h.
     349             :      */
     350             :     js::ThreadData<js::Activation*> activation_;
     351             : 
     352             :     /*
     353             :      * Points to the most recent profiling activation running on the
     354             :      * thread.
     355             :      */
     356             :     js::Activation* volatile profilingActivation_;
     357             : 
     358             :   public:
     359             :     js::Activation* activation() const {
     360      175590 :         return activation_;
     361             :     }
     362             :     static size_t offsetOfActivation() {
     363             :         return offsetof(JSContext, activation_);
     364             :     }
     365             : 
     366             :     js::Activation* profilingActivation() const {
     367           0 :         return profilingActivation_;
     368             :     }
     369             :     static size_t offsetOfProfilingActivation() {
     370             :         return offsetof(JSContext, profilingActivation_);
     371             :     }
     372             : 
     373             :     static size_t offsetOfJitActivation() {
     374             :         return offsetof(JSContext, jitActivation);
     375             :     }
     376             : 
     377             : #ifdef DEBUG
     378             :     static size_t offsetOfInUnsafeCallWithABI() {
     379             :         return offsetof(JSContext, inUnsafeCallWithABI);
     380             :     }
     381             : #endif
     382             : 
     383             :   private:
     384             :     /* Space for interpreter frames. */
     385             :     js::ThreadData<js::InterpreterStack> interpreterStack_;
     386             : 
     387             :   public:
     388             :     js::InterpreterStack& interpreterStack() {
     389       44266 :         return interpreterStack_.ref();
     390             :     }
     391             : 
     392             :     /* Base address of the native stack for the current thread. */
     393             :     const uintptr_t     nativeStackBase;
     394             : 
     395             :     /* The native stack size limit that runtime should not exceed. */
     396             :     js::ThreadData<size_t> nativeStackQuota[JS::StackKindCount];
     397             : 
     398             :   public:
     399             :     /* If non-null, report JavaScript entry points to this monitor. */
     400             :     js::ThreadData<JS::dbg::AutoEntryMonitor*> entryMonitor;
     401             : 
     402             :     /*
     403             :      * Stack of debuggers that currently disallow debuggee execution.
     404             :      *
     405             :      * When we check for NX we are inside the debuggee compartment, and thus a
     406             :      * stack of Debuggers that have prevented execution need to be tracked to
     407             :      * enter the correct Debugger compartment to report the error.
     408             :      */
     409             :     js::ThreadData<js::EnterDebuggeeNoExecute*> noExecuteDebuggerTop;
     410             : 
     411             :     js::ThreadData<js::ActivityCallback> activityCallback;
     412             :     js::ThreadData<void*>                activityCallbackArg;
     413             :     void triggerActivityCallback(bool active);
     414             : 
     415             :     /* The request depth for this thread. */
     416             :     js::ThreadData<unsigned> requestDepth;
     417             : 
     418             : #ifdef DEBUG
     419             :     js::ThreadData<unsigned> checkRequestDepth;
     420             :     js::ThreadData<uint32_t> inUnsafeCallWithABI;
     421             :     js::ThreadData<bool> hasAutoUnsafeCallWithABI;
     422             : #endif
     423             : 
     424             : #ifdef JS_SIMULATOR
     425             :   private:
     426             :     js::ThreadData<js::jit::Simulator*> simulator_;
     427             :   public:
     428             :     js::jit::Simulator* simulator() const;
     429             :     uintptr_t* addressOfSimulatorStackLimit();
     430             : #endif
     431             : 
     432             : #ifdef JS_TRACE_LOGGING
     433             :     js::ThreadData<js::TraceLoggerThread*> traceLogger;
     434             : #endif
     435             : 
     436             :   private:
     437             :     /* Pointer to the current AutoFlushICache. */
     438             :     js::ThreadData<js::jit::AutoFlushICache*> autoFlushICache_;
     439             :   public:
     440             : 
     441             :     js::jit::AutoFlushICache* autoFlushICache() const;
     442             :     void setAutoFlushICache(js::jit::AutoFlushICache* afc);
     443             : 
     444             :     // State used by util/DoubleToString.cpp.
     445             :     js::ThreadData<DtoaState*> dtoaState;
     446             : 
     447             :     /*
     448             :      * When this flag is non-zero, any attempt to GC will be skipped. It is used
     449             :      * to suppress GC when reporting an OOM (see ReportOutOfMemory) and in
     450             :      * debugging facilities that cannot tolerate a GC and would rather OOM
     451             :      * immediately, such as utilities exposed to GDB. Setting this flag is
     452             :      * extremely dangerous and should only be used when in an OOM situation or
     453             :      * in non-exposed debugging facilities.
     454             :      */
     455             :     js::ThreadData<int32_t> suppressGC;
     456             : 
     457             : #ifdef DEBUG
     458             :     // Whether this thread is actively Ion compiling.
     459             :     js::ThreadData<bool> ionCompiling;
     460             : 
     461             :     // Whether this thread is actively Ion compiling in a context where a minor
     462             :     // GC could happen simultaneously. If this is true, this thread cannot use
     463             :     // any pointers into the nursery.
     464             :     js::ThreadData<bool> ionCompilingSafeForMinorGC;
     465             : 
     466             :     // Whether this thread is currently performing GC.  This thread could be the
     467             :     // main thread or a helper thread while the main thread is running the
     468             :     // collector.
     469             :     js::ThreadData<bool> performingGC;
     470             : 
     471             :     // Whether this thread is currently sweeping GC things.  This thread could
     472             :     // be the main thread or a helper thread while the main thread is running
     473             :     // the mutator.  This is used to assert that destruction of GCPtr only
     474             :     // happens when we are sweeping.
     475             :     js::ThreadData<bool> gcSweeping;
     476             : 
     477             :     // Whether this thread is performing work in the background for a runtime's
     478             :     // GCHelperState.
     479             :     js::ThreadData<bool> gcHelperStateThread;
     480             : 
     481             :     // Whether this thread is currently manipulating possibly-gray GC things.
     482             :     js::ThreadData<size_t> isTouchingGrayThings;
     483             : 
     484             :     js::ThreadData<size_t> noGCOrAllocationCheck;
     485             :     js::ThreadData<size_t> noNurseryAllocationCheck;
     486             : 
     487             :     /*
     488             :      * If this is 0, all cross-compartment proxies must be registered in the
     489             :      * wrapper map. This checking must be disabled temporarily while creating
     490             :      * new wrappers. When non-zero, this records the recursion depth of wrapper
     491             :      * creation.
     492             :      */
     493             :     js::ThreadData<uintptr_t> disableStrictProxyCheckingCount;
     494             : 
     495             :     bool isAllocAllowed() { return noGCOrAllocationCheck == 0; }
     496             :     void disallowAlloc() { ++noGCOrAllocationCheck; }
     497             :     void allowAlloc() {
     498      868877 :         MOZ_ASSERT(!isAllocAllowed());
     499             :         --noGCOrAllocationCheck;
     500             :     }
     501             : 
     502             :     bool isNurseryAllocAllowed() { return noNurseryAllocationCheck == 0; }
     503             :     void disallowNurseryAlloc() { ++noNurseryAllocationCheck; }
     504             :     void allowNurseryAlloc() {
     505      208022 :         MOZ_ASSERT(!isNurseryAllocAllowed());
     506           0 :         --noNurseryAllocationCheck;
     507           0 :     }
     508           0 : 
     509           0 :     bool isStrictProxyCheckingEnabled() { return disableStrictProxyCheckingCount == 0; }
     510           0 :     void disableStrictProxyChecking() { ++disableStrictProxyCheckingCount; }
     511             :     void enableStrictProxyChecking() {
     512        1876 :         MOZ_ASSERT(disableStrictProxyCheckingCount > 0);
     513           0 :         --disableStrictProxyCheckingCount;
     514       57681 :     }
     515      115362 : #endif
     516      115362 : 
     517       57681 : #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     518             :     // We are currently running a simulated OOM test.
     519             :     js::ThreadData<bool> runningOOMTest;
     520             : #endif
     521             : 
     522             :     // True if we should assert that
     523             :     //     !comp->validAccessPtr || *comp->validAccessPtr
     524             :     // is true for every |comp| that we run JS code in.
     525             :     js::ThreadData<unsigned> enableAccessValidation;
     526             : 
     527             :     /*
     528             :      * Some regions of code are hard for the static rooting hazard analysis to
     529             :      * understand. In those cases, we trade the static analysis for a dynamic
     530             :      * analysis. When this is non-zero, we should assert if we trigger, or
     531             :      * might trigger, a GC.
     532             :      */
     533             :     js::ThreadData<int> inUnsafeRegion;
     534             : 
     535             :     // Count of AutoDisableGenerationalGC instances on the thread's stack.
     536             :     js::ThreadData<unsigned> generationalDisabled;
     537             : 
     538             :     // Some code cannot tolerate compacting GC so it can be disabled temporarily
     539             :     // with AutoDisableCompactingGC which uses this counter.
     540             :     js::ThreadData<unsigned> compactingDisabledCount;
     541             : 
     542             :     bool canCollectAtoms() const {
     543             :         return !runtime()->hasHelperThreadZones();
     544             :     }
     545           0 : 
     546           0 :   private:
     547             :     // Pools used for recycling name maps and vectors when parsing and
     548             :     // emitting bytecode. Purged on GC when there are no active script
     549             :     // compilations.
     550             :     js::ThreadData<js::frontend::NameCollectionPool> frontendCollectionPool_;
     551             :   public:
     552             : 
     553             :     js::frontend::NameCollectionPool& frontendCollectionPool() {
     554             :         return frontendCollectionPool_.ref();
     555             :     }
     556             : 
     557      209748 :     void verifyIsSafeToGC() {
     558             :         MOZ_DIAGNOSTIC_ASSERT(!inUnsafeRegion,
     559             :                               "[AutoAssertNoGC] possible GC in GC-unsafe region");
     560      297320 :     }
     561      594636 : 
     562             :     /* Whether sampling should be enabled or not. */
     563      297316 :   private:
     564             :     mozilla::Atomic<bool, mozilla::SequentiallyConsistent> suppressProfilerSampling;
     565             : 
     566             :   public:
     567             :     bool isProfilerSamplingEnabled() const {
     568             :         return !suppressProfilerSampling;
     569             :     }
     570             :     void disableProfilerSampling() {
     571           0 :         suppressProfilerSampling = true;
     572             :     }
     573             :     void enableProfilerSampling() {
     574        1704 :         suppressProfilerSampling = false;
     575             :     }
     576             : 
     577        1704 : #if defined(XP_DARWIN)
     578             :     js::wasm::MachExceptionHandler wasmMachExceptionHandler;
     579             : #endif
     580             : 
     581             :     /* Temporary arena pool used while compiling and decompiling. */
     582             :     static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
     583             :   private:
     584             :     js::ThreadData<js::LifoAlloc> tempLifoAlloc_;
     585             :   public:
     586             :     js::LifoAlloc& tempLifoAlloc() { return tempLifoAlloc_.ref(); }
     587             :     const js::LifoAlloc& tempLifoAlloc() const { return tempLifoAlloc_.ref(); }
     588             : 
     589           0 :     js::ThreadData<uint32_t> debuggerMutations;
     590           0 : 
     591             :     // Cache for jit::GetPcScript().
     592             :     js::ThreadData<js::jit::PcScriptCache*> ionPcScriptCache;
     593             : 
     594             :   private:
     595             :     /* Exception state -- the exception member is a GC root by definition. */
     596             :     js::ThreadData<bool> throwing;            /* is there a pending exception? */
     597             :     js::ThreadData<JS::PersistentRooted<JS::Value>> unwrappedException_; /* most-recently-thrown exception */
     598             : 
     599             :     JS::Value& unwrappedException() {
     600             :         if (!unwrappedException_.ref().initialized())
     601             :             unwrappedException_.ref().init(this);
     602        3659 :         return unwrappedException_.ref().get();
     603           0 :     }
     604           3 : 
     605        3659 :     // True if the exception currently being thrown is by result of
     606             :     // ReportOverRecursed. See Debugger::slowPathOnExceptionUnwind.
     607             :     js::ThreadData<bool> overRecursed_;
     608             : 
     609             :     // True if propagating a forced return from an interrupt handler during
     610             :     // debug mode.
     611             :     js::ThreadData<bool> propagatingForcedReturn_;
     612             : 
     613             :     // A stack of live iterators that need to be updated in case of debug mode
     614             :     // OSR.
     615             :     js::ThreadData<js::jit::DebugModeOSRVolatileJitFrameIter*>
     616             :         liveVolatileJitFrameIter_;
     617             : 
     618             :   public:
     619             :     js::ThreadData<int32_t> reportGranularity;  /* see vm/Probes.h */
     620             : 
     621             :     js::ThreadData<js::AutoResolving*> resolvingList;
     622             : 
     623             : #ifdef DEBUG
     624             :     js::ThreadData<js::AutoEnterPolicy*> enteredPolicy;
     625             : #endif
     626             : 
     627             :     /* True if generating an error, to prevent runaway recursion. */
     628             :     js::ThreadData<bool> generatingError;
     629             : 
     630             :   private:
     631             :     /* State for object and array toSource conversion. */
     632             :     js::ThreadData<js::AutoCycleDetector::Vector> cycleDetectorVector_;
     633             : 
     634             :   public:
     635             :     js::AutoCycleDetector::Vector& cycleDetectorVector() {
     636             :         return cycleDetectorVector_.ref();
     637             :     }
     638             :     const js::AutoCycleDetector::Vector& cycleDetectorVector() const {
     639        2568 :         return cycleDetectorVector_.ref();
     640             :     }
     641             : 
     642           0 :     /* Client opaque pointer. */
     643             :     js::UnprotectedData<void*> data;
     644             : 
     645             :     void initJitStackLimit();
     646             :     void resetJitStackLimit();
     647             : 
     648             :   public:
     649             :     JS::ContextOptions& options() {
     650             :         return options_.ref();
     651             :     }
     652             : 
     653      199471 :     bool runtimeMatches(JSRuntime* rt) const {
     654             :         return runtime_ == rt;
     655             :     }
     656             : 
     657             :     // Number of JS_BeginRequest calls without the corresponding JS_EndRequest.
     658             :     js::ThreadData<unsigned> outstandingRequests;
     659             : 
     660             :     js::ThreadData<bool> jitIsBroken;
     661             : 
     662             :     void updateJITEnabled();
     663             : 
     664             :   private:
     665             :     /*
     666             :      * Youngest frame of a saved stack that will be picked up as an async stack
     667             :      * by any new Activation, and is nullptr when no async stack should be used.
     668             :      *
     669             :      * The JS::AutoSetAsyncStackForNewCalls class can be used to set this.
     670             :      *
     671             :      * New activations will reset this to nullptr on construction after getting
     672             :      * the current value, and will restore the previous value on destruction.
     673             :      */
     674             :     js::ThreadData<JS::PersistentRooted<js::SavedFrame*>> asyncStackForNewActivations_;
     675             :   public:
     676             : 
     677             :     js::SavedFrame*& asyncStackForNewActivations() {
     678             :         if (!asyncStackForNewActivations_.ref().initialized())
     679             :             asyncStackForNewActivations_.ref().init(this);
     680       83547 :         return asyncStackForNewActivations_.ref().get();
     681      167093 :     }
     682           4 : 
     683       83546 :     /*
     684             :      * Value of asyncCause to be attached to asyncStackForNewActivations.
     685             :      */
     686             :     js::ThreadData<const char*> asyncCauseForNewActivations;
     687             : 
     688             :     /*
     689             :      * True if the async call was explicitly requested, e.g. via
     690             :      * callFunctionWithAsyncStack.
     691             :      */
     692             :     js::ThreadData<bool> asyncCallIsExplicit;
     693             : 
     694             :     bool currentlyRunningInInterpreter() const {
     695             :         return activation()->isInterpreter();
     696             :     }
     697             :     bool currentlyRunningInJit() const {
     698             :         return activation()->isJit();
     699             :     }
     700             :     js::InterpreterFrame* interpreterFrame() const {
     701          29 :         return activation()->asInterpreter()->current();
     702             :     }
     703       15001 :     js::InterpreterRegs& interpreterRegs() const {
     704       30002 :         return activation()->asInterpreter()->regs();
     705             :     }
     706             : 
     707           0 :     /*
     708             :      * Get the topmost script and optional pc on the stack. By default, this
     709             :      * function only returns a JSScript in the current compartment, returning
     710             :      * nullptr if the current script is in a different compartment. This
     711             :      * behavior can be overridden by passing ALLOW_CROSS_COMPARTMENT.
     712             :      */
     713             :     enum MaybeAllowCrossCompartment {
     714             :         DONT_ALLOW_CROSS_COMPARTMENT = false,
     715             :         ALLOW_CROSS_COMPARTMENT = true
     716             :     };
     717             :     inline JSScript* currentScript(jsbytecode** pc = nullptr,
     718             :                                    MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const;
     719             : 
     720             :     inline js::Nursery& nursery();
     721             :     inline void minorGC(JS::gcreason::Reason reason);
     722             : 
     723             :   public:
     724             :     bool isExceptionPending() const {
     725             :         return throwing;
     726             :     }
     727             : 
     728      998118 :     MOZ_MUST_USE
     729             :     bool getPendingException(JS::MutableHandleValue rval);
     730             : 
     731             :     bool isThrowingOutOfMemory();
     732             :     bool isThrowingDebuggeeWouldRun();
     733             :     bool isClosingGenerator();
     734             : 
     735             :     void setPendingException(const js::Value& v);
     736             : 
     737             :     void clearPendingException() {
     738             :         throwing = false;
     739             :         overRecursed_ = false;
     740         588 :         unwrappedException().setUndefined();
     741        1176 :     }
     742        1176 : 
     743        1176 :     bool isThrowingOverRecursed() const { return throwing && overRecursed_; }
     744         588 :     bool isPropagatingForcedReturn() const { return propagatingForcedReturn_; }
     745             :     void setPropagatingForcedReturn() { propagatingForcedReturn_ = true; }
     746          22 :     void clearPropagatingForcedReturn() { propagatingForcedReturn_ = false; }
     747         186 : 
     748           0 :     /*
     749           0 :      * See JS_SetTrustedPrincipals in jsapi.h.
     750             :      * Note: !cx->compartment is treated as trusted.
     751             :      */
     752             :     inline bool runningWithTrustedPrincipals();
     753             : 
     754             :     JS_FRIEND_API(size_t) sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     755             : 
     756             :     void trace(JSTracer* trc);
     757             : 
     758             :     inline js::RuntimeCaches& caches();
     759             : 
     760             :   private:
     761             :     /*
     762             :      * The allocation code calls the function to indicate either OOM failure
     763             :      * when p is null or that a memory pressure counter has reached some
     764             :      * threshold when p is not null. The function takes the pointer and not
     765             :      * a boolean flag to minimize the amount of code in its inlined callers.
     766             :      */
     767             :     JS_FRIEND_API(void) checkMallocGCPressure(void* p);
     768             : 
     769             :   public:
     770             :     using InterruptCallbackVector = js::Vector<JSInterruptCallback, 2, js::SystemAllocPolicy>;
     771             : 
     772             :   private:
     773             :     js::ThreadData<InterruptCallbackVector> interruptCallbacks_;
     774             :   public:
     775             :     InterruptCallbackVector& interruptCallbacks() { return interruptCallbacks_.ref(); }
     776             : 
     777             :     js::ThreadData<bool> interruptCallbackDisabled;
     778           4 : 
     779             :     // Bitfield storing InterruptReason values.
     780             :     mozilla::Atomic<uint32_t, mozilla::Relaxed> interruptBits_;
     781             : 
     782             :     // Any thread can call requestInterrupt() to request that this thread
     783             :     // stop running. To stop this thread, requestInterrupt sets two fields:
     784             :     // interruptBits_ (a bitset of InterruptReasons) and jitStackLimit_ (set to
     785             :     // UINTPTR_MAX). The JS engine must continually poll one of these fields
     786             :     // and call handleInterrupt if either field has the interrupt value.
     787             :     //
     788             :     // The point of setting jitStackLimit_ to UINTPTR_MAX is that JIT code
     789             :     // already needs to guard on jitStackLimit_ in every function prologue to
     790             :     // avoid stack overflow, so we avoid a second branch on interruptBits_ by
     791             :     // setting jitStackLimit_ to a value that is guaranteed to fail the guard.)
     792             :     //
     793             :     // Note that the writes to interruptBits_ and jitStackLimit_ use a Relaxed
     794             :     // Atomic so, while the writes are guaranteed to eventually be visible to
     795             :     // this thread, it can happen in any order. handleInterrupt calls the
     796             :     // interrupt callback if either is set, so it really doesn't matter as long
     797             :     // as the JS engine is continually polling at least one field. In corner
     798             :     // cases, this relaxed ordering could lead to an interrupt handler being
     799             :     // called twice in succession after a single requestInterrupt call, but
     800             :     // that's fine.
     801             :     void requestInterrupt(js::InterruptReason reason);
     802             :     bool handleInterrupt();
     803             : 
     804             :     MOZ_ALWAYS_INLINE bool hasAnyPendingInterrupt() const {
     805             :         static_assert(sizeof(interruptBits_) == sizeof(uint32_t), "Assumed by JIT callers");
     806             :         return interruptBits_ != 0;
     807             :     }
     808             :     bool hasPendingInterrupt(js::InterruptReason reason) const {
     809      699724 :         return interruptBits_ & uint32_t(reason);
     810             :     }
     811             : 
     812         200 :   public:
     813             :     void* addressOfInterruptBits() {
     814             :         return &interruptBits_;
     815             :     }
     816             :     void* addressOfJitStackLimit() {
     817         981 :         return &jitStackLimit;
     818             :     }
     819             :     void* addressOfJitStackLimitNoInterrupt() {
     820         858 :         return &jitStackLimitNoInterrupt;
     821             :     }
     822             : 
     823         149 :     /* Futex state, used by Atomics.wait() and Atomics.wake() on the Atomics object */
     824             :     js::FutexThread fx;
     825             : 
     826             :     // Buffer for OSR from baseline to Ion. To avoid holding on to this for
     827             :     // too long, it's also freed in EnterBaseline (after returning from JIT code).
     828             :     js::ThreadData<uint8_t*> osrTempData_;
     829             : 
     830             :     uint8_t* allocateOsrTempData(size_t size);
     831             :     void freeOsrTempData();
     832             : 
     833             :     // In certain cases, we want to optimize certain opcodes to typed instructions,
     834             :     // to avoid carrying an extra register to feed into an unbox. Unfortunately,
     835             :     // that's not always possible. For example, a GetPropertyCacheT could return a
     836             :     // typed double, but if it takes its out-of-line path, it could return an
     837             :     // object, and trigger invalidation. The invalidation bailout will consider the
     838             :     // return value to be a double, and create a garbage Value.
     839             :     //
     840             :     // To allow the GetPropertyCacheT optimization, we allow the ability for
     841             :     // GetPropertyCache to override the return value at the top of the stack - the
     842             :     // value that will be temporarily corrupt. This special override value is set
     843             :     // only in callVM() targets that are about to return *and* have invalidated
     844             :     // their callee.
     845             :     js::ThreadData<js::Value> ionReturnOverride_;
     846             : 
     847             :     bool hasIonReturnOverride() const {
     848             :         return !ionReturnOverride_.ref().isMagic(JS_ARG_POISON);
     849             :     }
     850       15720 :     js::Value takeIonReturnOverride() {
     851       15720 :         js::Value v = ionReturnOverride_;
     852             :         ionReturnOverride_ = js::MagicValue(JS_ARG_POISON);
     853           0 :         return v;
     854           0 :     }
     855           0 :     void setIonReturnOverride(const js::Value& v) {
     856           0 :         MOZ_ASSERT(!hasIonReturnOverride());
     857             :         MOZ_ASSERT(!v.isMagic());
     858           0 :         ionReturnOverride_ = v;
     859           0 :     }
     860           0 : 
     861           0 :     mozilla::Atomic<uintptr_t, mozilla::Relaxed> jitStackLimit;
     862           0 : 
     863             :     // Like jitStackLimit, but not reset to trigger interrupts.
     864             :     js::ThreadData<uintptr_t> jitStackLimitNoInterrupt;
     865             : 
     866             :     // Promise callbacks.
     867             :     js::ThreadData<JSGetIncumbentGlobalCallback> getIncumbentGlobalCallback;
     868             :     js::ThreadData<JSEnqueuePromiseJobCallback> enqueuePromiseJobCallback;
     869             :     js::ThreadData<void*> enqueuePromiseJobCallbackData;
     870             : 
     871             :     // Queue of pending jobs as described in ES2016 section 8.4.
     872             :     // Only used if internal job queue handling was activated using
     873             :     // `js::UseInternalJobQueues`.
     874             :     js::ThreadData<JS::PersistentRooted<js::JobQueue>*> jobQueue;
     875             :     js::ThreadData<bool> drainingJobQueue;
     876             :     js::ThreadData<bool> stopDrainingJobQueue;
     877             : 
     878             :     js::ThreadData<JSPromiseRejectionTrackerCallback> promiseRejectionTrackerCallback;
     879             :     js::ThreadData<void*> promiseRejectionTrackerCallbackData;
     880             : 
     881             :     JSObject* getIncumbentGlobal(JSContext* cx);
     882             :     bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job, js::HandleObject promise,
     883             :                            js::HandleObject incumbentGlobal);
     884             :     void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
     885             :     void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
     886             : }; /* struct JSContext */
     887             : 
     888             : inline JS::Result<>
     889             : JSContext::boolToResult(bool ok)
     890             : {
     891             :     if (MOZ_LIKELY(ok)) {
     892             :         MOZ_ASSERT(!isExceptionPending());
     893             :         MOZ_ASSERT(!isPropagatingForcedReturn());
     894             :         return JS::Ok();
     895             :     }
     896             :     return JS::Result<>(reportedError);
     897             : }
     898             : 
     899             : inline JSContext*
     900             : JSRuntime::mainContextFromOwnThread()
     901             : {
     902             :     MOZ_ASSERT(mainContextFromAnyThread() == js::TlsContext.get());
     903         114 :     return mainContextFromAnyThread();
     904             : }
     905         228 : 
     906         114 : namespace js {
     907             : 
     908             : struct MOZ_RAII AutoResolving {
     909             :   public:
     910             :     enum Kind {
     911             :         LOOKUP,
     912             :         WATCH
     913             :     };
     914             : 
     915             :     AutoResolving(JSContext* cx, HandleObject obj, HandleId id, Kind kind = LOOKUP
     916             :                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     917             :       : context(cx), object(obj), id(id), kind(kind), link(cx->resolvingList)
     918       18040 :     {
     919             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     920       54120 :         MOZ_ASSERT(obj);
     921             :         cx->resolvingList = this;
     922       36080 :     }
     923       18040 : 
     924       36080 :     ~AutoResolving() {
     925       18040 :         MOZ_ASSERT(context->resolvingList == this);
     926             :         context->resolvingList = link;
     927       36079 :     }
     928       36079 : 
     929           0 :     bool alreadyStarted() const {
     930       18039 :         return link && alreadyStartedSlow();
     931             :     }
     932             : 
     933       18040 :   private:
     934             :     bool alreadyStartedSlow() const;
     935             : 
     936             :     JSContext*          const context;
     937             :     HandleObject        object;
     938             :     HandleId            id;
     939             :     Kind                const kind;
     940             :     AutoResolving*      const link;
     941             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     942             : };
     943             : 
     944             : /*
     945             :  * Create and destroy functions for JSContext, which is manually allocated
     946             :  * and exclusively owned.
     947             :  */
     948             : extern JSContext*
     949             : NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime);
     950             : 
     951             : extern void
     952             : DestroyContext(JSContext* cx);
     953             : 
     954             : enum ErrorArgumentsType {
     955             :     ArgumentsAreUnicode,
     956             :     ArgumentsAreASCII,
     957             :     ArgumentsAreLatin1,
     958             :     ArgumentsAreUTF8
     959             : };
     960             : 
     961             : /**
     962             :  * Report an exception, using printf-style APIs to generate the error
     963             :  * message.
     964             :  */
     965             : #ifdef va_start
     966             : extern bool
     967             : ReportErrorVA(JSContext* cx, unsigned flags, const char* format,
     968             :               ErrorArgumentsType argumentsType, va_list ap) MOZ_FORMAT_PRINTF(3, 0);
     969             : 
     970             : extern bool
     971             : ReportErrorNumberVA(JSContext* cx, unsigned flags, JSErrorCallback callback,
     972             :                     void* userRef, const unsigned errorNumber,
     973             :                     ErrorArgumentsType argumentsType, va_list ap);
     974             : 
     975             : extern bool
     976             : ReportErrorNumberUCArray(JSContext* cx, unsigned flags, JSErrorCallback callback,
     977             :                          void* userRef, const unsigned errorNumber,
     978             :                          const char16_t** args);
     979             : #endif
     980             : 
     981             : extern bool
     982             : ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
     983             :                        void* userRef, const unsigned errorNumber,
     984             :                        const char16_t** messageArgs,
     985             :                        ErrorArgumentsType argumentsType,
     986             :                        JSErrorReport* reportp, va_list ap);
     987             : 
     988             : extern bool
     989             : ExpandErrorArgumentsVA(JSContext* cx, JSErrorCallback callback,
     990             :                        void* userRef, const unsigned errorNumber,
     991             :                        const char16_t** messageArgs,
     992             :                        ErrorArgumentsType argumentsType,
     993             :                        JSErrorNotes::Note* notep, va_list ap);
     994             : 
     995             : /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
     996             : extern void
     997             : ReportUsageErrorASCII(JSContext* cx, HandleObject callee, const char* msg);
     998             : 
     999             : /*
    1000             :  * Prints a full report and returns true if the given report is non-nullptr
    1001             :  * and the report doesn't have the JSREPORT_WARNING flag set or reportWarnings
    1002             :  * is true.
    1003             :  * Returns false otherwise.
    1004             :  */
    1005             : extern bool
    1006             : PrintError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
    1007             :            JSErrorReport* report, bool reportWarnings);
    1008             : 
    1009             : extern void
    1010             : ReportIsNotDefined(JSContext* cx, HandlePropertyName name);
    1011             : 
    1012             : extern void
    1013             : ReportIsNotDefined(JSContext* cx, HandleId id);
    1014             : 
    1015             : /*
    1016             :  * Report an attempt to access the property of a null or undefined value (v).
    1017             :  */
    1018             : extern void
    1019             : ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v);
    1020             : 
    1021             : extern void
    1022             : ReportMissingArg(JSContext* cx, js::HandleValue v, unsigned arg);
    1023             : 
    1024             : /*
    1025             :  * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
    1026             :  * the first argument for the error message. If the error message has less
    1027             :  * then 3 arguments, use null for arg1 or arg2.
    1028             :  */
    1029             : extern bool
    1030             : ReportValueErrorFlags(JSContext* cx, unsigned flags, const unsigned errorNumber,
    1031             :                       int spindex, HandleValue v, HandleString fallback,
    1032             :                       const char* arg1, const char* arg2);
    1033             : 
    1034             : inline void
    1035             : ReportValueError(JSContext* cx, const unsigned errorNumber, int spindex, HandleValue v,
    1036             :                  HandleString fallback, const char* arg1 = nullptr, const char* arg2 = nullptr)
    1037             : {
    1038             :     ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, spindex, v, fallback, arg1, arg2);
    1039             : }
    1040             : 
    1041             : JSObject*
    1042             : CreateErrorNotesArray(JSContext* cx, JSErrorReport* report);
    1043             : 
    1044             : } /* namespace js */
    1045             : 
    1046             : extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
    1047             : 
    1048             : namespace js {
    1049             : 
    1050             : /************************************************************************/
    1051             : 
    1052             : /* AutoArrayRooter roots an external array of Values. */
    1053             : class MOZ_RAII AutoArrayRooter : private JS::AutoGCRooter
    1054             : {
    1055             :   public:
    1056             :     AutoArrayRooter(JSContext* cx, size_t len, Value* vec
    1057             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    1058             :       : JS::AutoGCRooter(cx, JS::AutoGCRooter::Tag::Array), array_(vec), length_(len)
    1059             :     {
    1060             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1061       20326 :     }
    1062             : 
    1063             :     Value* begin() {
    1064             :         return array_;
    1065             :     }
    1066       60978 : 
    1067             :     size_t length() {
    1068       40652 :         return length_;
    1069             :     }
    1070             : 
    1071             :     friend void JS::AutoGCRooter::trace(JSTracer* trc);
    1072             : 
    1073             :   private:
    1074             :     Value* array_;
    1075             :     size_t length_;
    1076             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1077             : };
    1078             : 
    1079             : class AutoAssertNoException
    1080             : {
    1081             : #ifdef DEBUG
    1082             :     JSContext* cx;
    1083             :     bool hadException;
    1084             : #endif
    1085             : 
    1086             :   public:
    1087             :     explicit AutoAssertNoException(JSContext* cx)
    1088             : #ifdef DEBUG
    1089             :       : cx(cx),
    1090             :         hadException(cx->isExceptionPending())
    1091             : #endif
    1092             :     {
    1093             :     }
    1094             : 
    1095             :     ~AutoAssertNoException()
    1096             :     {
    1097       63140 :         MOZ_ASSERT_IF(!hadException, !cx->isExceptionPending());
    1098      126280 :     }
    1099             : };
    1100             : 
    1101             : class MOZ_RAII AutoLockForExclusiveAccess
    1102             : {
    1103       63140 :     JSRuntime* runtime;
    1104       63140 : 
    1105      126280 :     void init(JSRuntime* rt) {
    1106       63140 :         MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt) || CurrentThreadIsParseThread());
    1107             :         runtime = rt;
    1108             :         if (runtime->hasHelperThreadZones()) {
    1109             :             runtime->exclusiveAccessLock.lock();
    1110             :         } else {
    1111             :             MOZ_ASSERT(!runtime->activeThreadHasExclusiveAccess);
    1112             : #ifdef DEBUG
    1113       66669 :             runtime->activeThreadHasExclusiveAccess = true;
    1114       66669 : #endif
    1115       66669 :         }
    1116      133338 :     }
    1117        5928 : 
    1118             :   public:
    1119       60741 :     explicit AutoLockForExclusiveAccess(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
    1120             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1121       60741 :         init(cx->runtime());
    1122             :     }
    1123             :     explicit AutoLockForExclusiveAccess(JSRuntime* rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
    1124           0 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1125             :         init(rt);
    1126             :     }
    1127      133320 :     ~AutoLockForExclusiveAccess() {
    1128      133320 :         if (runtime->hasHelperThreadZones()) {
    1129           0 :             runtime->exclusiveAccessLock.unlock();
    1130             :         } else {
    1131           0 :             MOZ_ASSERT(runtime->activeThreadHasExclusiveAccess);
    1132           0 : #ifdef DEBUG
    1133           9 :             runtime->activeThreadHasExclusiveAccess = false;
    1134             : #endif
    1135      133338 :         }
    1136      133338 :     }
    1137        5928 : 
    1138             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1139           0 : };
    1140             : 
    1141           0 : class MOZ_RAII AutoLockScriptData
    1142             : {
    1143             :     JSRuntime* runtime;
    1144       66669 : 
    1145             :   public:
    1146             :     explicit AutoLockScriptData(JSRuntime* rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
    1147             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1148             :         MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt) || CurrentThreadIsParseThread());
    1149             :         runtime = rt;
    1150             :         if (runtime->hasHelperThreadZones()) {
    1151             :             runtime->scriptDataLock.lock();
    1152             :         } else {
    1153             :             MOZ_ASSERT(!runtime->activeThreadHasScriptDataAccess);
    1154           0 : #ifdef DEBUG
    1155           0 :             runtime->activeThreadHasScriptDataAccess = true;
    1156       13491 : #endif
    1157           0 :         }
    1158           0 :     }
    1159           0 :     ~AutoLockScriptData() {
    1160             :         if (runtime->hasHelperThreadZones()) {
    1161           0 :             runtime->scriptDataLock.unlock();
    1162             :         } else {
    1163           0 :             MOZ_ASSERT(runtime->activeThreadHasScriptDataAccess);
    1164             : #ifdef DEBUG
    1165             :             runtime->activeThreadHasScriptDataAccess = false;
    1166       13491 : #endif
    1167           0 :         }
    1168       26982 :     }
    1169        1954 : 
    1170             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1171       11537 : };
    1172             : 
    1173       11537 : class MOZ_RAII AutoKeepAtoms
    1174             : {
    1175             :     JSContext* cx;
    1176       13491 :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1177             : 
    1178             :   public:
    1179             :     explicit inline AutoKeepAtoms(JSContext* cx
    1180             :                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
    1181             :     inline ~AutoKeepAtoms();
    1182             : };
    1183             : 
    1184             : // Debugging RAII class which marks the current thread as performing an Ion
    1185             : // compilation, for use by CurrentThreadCan{Read,Write}CompilationData
    1186             : class MOZ_RAII AutoEnterIonCompilation
    1187             : {
    1188             :   public:
    1189             :     explicit AutoEnterIonCompilation(bool safeForMinorGC
    1190             :                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
    1191             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1192             : 
    1193             : #ifdef DEBUG
    1194             :         JSContext* cx = TlsContext.get();
    1195             :         MOZ_ASSERT(!cx->ionCompiling);
    1196             :         MOZ_ASSERT(!cx->ionCompilingSafeForMinorGC);
    1197           0 :         cx->ionCompiling = true;
    1198         100 :         cx->ionCompilingSafeForMinorGC = safeForMinorGC;
    1199           0 : #endif
    1200             :     }
    1201             : 
    1202           0 :     ~AutoEnterIonCompilation() {
    1203         100 : #ifdef DEBUG
    1204         100 :         JSContext* cx = TlsContext.get();
    1205         100 :         MOZ_ASSERT(cx->ionCompiling);
    1206         100 :         cx->ionCompiling = false;
    1207             :         cx->ionCompilingSafeForMinorGC = false;
    1208          50 : #endif
    1209             :     }
    1210         100 : 
    1211             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1212          50 : };
    1213         100 : 
    1214         100 : // Should be used in functions called directly from JIT code (with
    1215           0 : // masm.callWithABI) to assert invariants in debug builds.
    1216             : class MOZ_RAII AutoUnsafeCallWithABI
    1217           0 : {
    1218             : #ifdef DEBUG
    1219             :     JSContext* cx_;
    1220             :     bool nested_;
    1221             : #endif
    1222             :     JS::AutoCheckCannotGC nogc;
    1223             : 
    1224             :   public:
    1225             : #ifdef DEBUG
    1226             :     AutoUnsafeCallWithABI();
    1227             :     ~AutoUnsafeCallWithABI();
    1228             : #endif
    1229             : };
    1230             : 
    1231             : namespace gc {
    1232             : 
    1233             : // In debug builds, set/unset the performing GC flag for the current thread.
    1234             : struct MOZ_RAII AutoSetThreadIsPerformingGC
    1235             : {
    1236             : #ifdef DEBUG
    1237             :     AutoSetThreadIsPerformingGC()
    1238             :       : cx(TlsContext.get())
    1239             :     {
    1240             :         MOZ_ASSERT(!cx->performingGC);
    1241             :         cx->performingGC = true;
    1242             :     }
    1243             : 
    1244             :     ~AutoSetThreadIsPerformingGC() {
    1245           0 :         MOZ_ASSERT(cx->performingGC);
    1246           0 :         cx->performingGC = false;
    1247             :     }
    1248           0 : 
    1249          50 :   private:
    1250           0 :     JSContext* cx;
    1251             : #else
    1252           0 :     AutoSetThreadIsPerformingGC() {}
    1253           0 : #endif
    1254           0 : };
    1255           0 : 
    1256             : // In debug builds, set/unset the GC sweeping flag for the current thread.
    1257             : struct MOZ_RAII AutoSetThreadIsSweeping
    1258             : {
    1259             : #ifdef DEBUG
    1260             :     AutoSetThreadIsSweeping()
    1261             :       : cx(TlsContext.get())
    1262             :     {
    1263             :         MOZ_ASSERT(!cx->gcSweeping);
    1264             :         cx->gcSweeping = true;
    1265             :     }
    1266             : 
    1267             :     ~AutoSetThreadIsSweeping() {
    1268           0 :         MOZ_ASSERT(cx->gcSweeping);
    1269           0 :         cx->gcSweeping = false;
    1270             :     }
    1271           0 : 
    1272           0 :   private:
    1273           0 :     JSContext* cx;
    1274             : #else
    1275           0 :     AutoSetThreadIsSweeping() {}
    1276           0 : #endif
    1277           0 : };
    1278           0 : 
    1279             : } // namespace gc
    1280             : 
    1281             : } /* namespace js */
    1282             : 
    1283             : #endif /* vm_JSContext_h */

Generated by: LCOV version 1.13-14-ga5dd952