LCOV - code coverage report
Current view: top level - js/src - jscntxt.h (source / functions) Hit Total Coverage
Test: output.info Lines: 219 281 77.9 %
Date: 2017-07-14 16:53:18 Functions: 87 117 74.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13