LCOV - code coverage report
Current view: top level - js/src/vm - Runtime.h (source / functions) Hit Total Coverage
Test: output.info Lines: 164 275 59.6 %
Date: 2017-07-14 16:53:18 Functions: 77 172 44.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_Runtime_h
       8             : #define vm_Runtime_h
       9             : 
      10             : #include "mozilla/Atomics.h"
      11             : #include "mozilla/Attributes.h"
      12             : #include "mozilla/DoublyLinkedList.h"
      13             : #include "mozilla/LinkedList.h"
      14             : #include "mozilla/MemoryReporting.h"
      15             : #include "mozilla/PodOperations.h"
      16             : #include "mozilla/Scoped.h"
      17             : #include "mozilla/ThreadLocal.h"
      18             : #include "mozilla/Vector.h"
      19             : 
      20             : #include <setjmp.h>
      21             : 
      22             : #include "jsatom.h"
      23             : #include "jsscript.h"
      24             : 
      25             : #ifdef XP_DARWIN
      26             : # include "wasm/WasmSignalHandlers.h"
      27             : #endif
      28             : #include "builtin/AtomicsObject.h"
      29             : #include "builtin/Intl.h"
      30             : #include "builtin/Promise.h"
      31             : #include "ds/FixedSizeHash.h"
      32             : #include "frontend/NameCollections.h"
      33             : #include "gc/GCRuntime.h"
      34             : #include "gc/Tracer.h"
      35             : #include "gc/ZoneGroup.h"
      36             : #include "irregexp/RegExpStack.h"
      37             : #include "js/Debug.h"
      38             : #include "js/GCVector.h"
      39             : #include "js/HashTable.h"
      40             : #ifdef DEBUG
      41             : # include "js/Proxy.h" // For AutoEnterPolicy
      42             : #endif
      43             : #include "js/UniquePtr.h"
      44             : #include "js/Vector.h"
      45             : #include "threading/Thread.h"
      46             : #include "vm/Caches.h"
      47             : #include "vm/CodeCoverage.h"
      48             : #include "vm/CommonPropertyNames.h"
      49             : #include "vm/DateTime.h"
      50             : #include "vm/GeckoProfiler.h"
      51             : #include "vm/MallocProvider.h"
      52             : #include "vm/Scope.h"
      53             : #include "vm/SharedImmutableStringsCache.h"
      54             : #include "vm/Stack.h"
      55             : #include "vm/Stopwatch.h"
      56             : #include "vm/Symbol.h"
      57             : 
      58             : #ifdef _MSC_VER
      59             : #pragma warning(push)
      60             : #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
      61             : #endif
      62             : 
      63             : namespace js {
      64             : 
      65             : class AutoAssertNoContentJS;
      66             : class AutoKeepAtoms;
      67             : class EnterDebuggeeNoExecute;
      68             : #ifdef JS_TRACE_LOGGING
      69             : class TraceLoggerThread;
      70             : #endif
      71             : 
      72             : typedef Vector<UniquePtr<PromiseTask>, 0, SystemAllocPolicy> PromiseTaskPtrVector;
      73             : 
      74             : } // namespace js
      75             : 
      76             : struct DtoaState;
      77             : 
      78             : #ifdef JS_SIMULATOR_ARM64
      79             : namespace vixl {
      80             : class Simulator;
      81             : }
      82             : #endif
      83             : 
      84             : namespace js {
      85             : 
      86             : extern MOZ_COLD void
      87             : ReportOutOfMemory(JSContext* cx);
      88             : 
      89             : /* Different signature because the return type has MOZ_MUST_USE_TYPE. */
      90             : extern MOZ_COLD mozilla::GenericErrorResult<OOM&>
      91             : ReportOutOfMemoryResult(JSContext* cx);
      92             : 
      93             : extern MOZ_COLD void
      94             : ReportAllocationOverflow(JSContext* maybecx);
      95             : 
      96             : extern MOZ_COLD void
      97             : ReportOverRecursed(JSContext* cx);
      98             : 
      99             : class Activation;
     100             : class ActivationIterator;
     101             : class WasmActivation;
     102             : 
     103             : namespace jit {
     104             : class JitRuntime;
     105             : class JitActivation;
     106             : struct PcScriptCache;
     107             : struct AutoFlushICache;
     108             : class CompileRuntime;
     109             : 
     110             : #ifdef JS_SIMULATOR_ARM64
     111             : typedef vixl::Simulator Simulator;
     112             : #elif defined(JS_SIMULATOR)
     113             : class Simulator;
     114             : #endif
     115             : } // namespace jit
     116             : 
     117             : // JS Engine Threading
     118             : //
     119             : // Multiple threads may interact with a JS runtime. JS has run-to-completion
     120             : // semantics, which means that scripts cannot observe changes in behavior
     121             : // due to activities performed on other threads (there is an exception to this
     122             : // for shared array buffers and related APIs).
     123             : //
     124             : // The main way we ensure that run-to-completion semantics are preserved is
     125             : // by dividing content into zone groups. Pieces of web content will be in the
     126             : // the same zone group if they have the same tab/origin or can otherwise
     127             : // observe changes in each other via Window.opener and so forth. When a thread
     128             : // executes JS in a zone group, it acquires that group --- including exclusive
     129             : // access to most of the group's content --- and does not relinquish control of
     130             : // the zone group until the script finishes executing.
     131             : //
     132             : // Threads interacting with a runtime are divided into two categories:
     133             : //
     134             : // - Cooperating threads are capable of running JS. At most one cooperating
     135             : //   thread may be |active| at a time in a runtime, but they may yield control
     136             : //   to each other so that their execution is interleaved. As described above,
     137             : //   each thread owns the zone groups it is operating on so that this
     138             : //   interleaving does not cause observable changes in a script's behavior.
     139             : //
     140             : // - Helper threads do not run JS, and are controlled or triggered by activity
     141             : //   in the cooperating threads. Helper threads may have exclusive access to
     142             : //   zone groups created for them, for parsing and similar tasks, but their
     143             : //   activities do not cause observable changes in script behaviors. Activity
     144             : //   on helper threads may be referred to as happening 'off thread' or on a
     145             : //   background thread in some parts of the VM.
     146             : 
     147             : /*
     148             :  * A FreeOp can do one thing: free memory. For convenience, it has delete_
     149             :  * convenience methods that also call destructors.
     150             :  *
     151             :  * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
     152             :  * need to pass a JSContext to those hooks.
     153             :  */
     154             : class FreeOp : public JSFreeOp
     155             : {
     156             :     Vector<void*, 0, SystemAllocPolicy> freeLaterList;
     157             :     jit::JitPoisonRangeVector jitPoisonRanges;
     158             : 
     159             :   public:
     160           0 :     static FreeOp* get(JSFreeOp* fop) {
     161           0 :         return static_cast<FreeOp*>(fop);
     162             :     }
     163             : 
     164             :     explicit FreeOp(JSRuntime* maybeRuntime);
     165             :     ~FreeOp();
     166             : 
     167           0 :     bool onActiveCooperatingThread() const {
     168           0 :         return runtime_ != nullptr;
     169             :     }
     170             : 
     171           0 :     bool maybeOnHelperThread() const {
     172             :         // Sometimes background finalization happens on the active thread so
     173             :         // runtime_ being null doesn't always mean we are off thread.
     174           0 :         return !runtime_;
     175             :     }
     176             : 
     177             :     bool isDefaultFreeOp() const;
     178             : 
     179             :     inline void free_(void* p);
     180             :     inline void freeLater(void* p);
     181             : 
     182             :     inline bool appendJitPoisonRange(const jit::JitPoisonRange& range);
     183             : 
     184             :     template <class T>
     185         551 :     inline void delete_(T* p) {
     186         551 :         if (p) {
     187         551 :             p->~T();
     188         551 :             free_(p);
     189             :         }
     190         551 :     }
     191             : };
     192             : 
     193             : } /* namespace js */
     194             : 
     195             : namespace JS {
     196             : struct RuntimeSizes;
     197             : } // namespace JS
     198             : 
     199             : /* Various built-in or commonly-used names pinned on first context. */
     200             : struct JSAtomState
     201             : {
     202             : #define PROPERTYNAME_FIELD(idpart, id, text) js::ImmutablePropertyNamePtr id;
     203             :     FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
     204             : #undef PROPERTYNAME_FIELD
     205             : #define PROPERTYNAME_FIELD(name, code, init, clasp) js::ImmutablePropertyNamePtr name;
     206             :     JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
     207             : #undef PROPERTYNAME_FIELD
     208             : #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr name;
     209             :     JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
     210             : #undef PROPERTYNAME_FIELD
     211             : #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr Symbol_##name;
     212             :     JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
     213             : #undef PROPERTYNAME_FIELD
     214             : 
     215          13 :     js::ImmutablePropertyNamePtr* wellKnownSymbolNames() {
     216             : #define FIRST_PROPERTYNAME_FIELD(name) return &name;
     217          13 :     JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
     218             : #undef FIRST_PROPERTYNAME_FIELD
     219             :     }
     220             : 
     221           3 :     js::ImmutablePropertyNamePtr* wellKnownSymbolDescriptions() {
     222             : #define FIRST_PROPERTYNAME_FIELD(name) return &Symbol_ ##name;
     223           3 :     JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
     224             : #undef FIRST_PROPERTYNAME_FIELD
     225             :     }
     226             : };
     227             : 
     228             : namespace js {
     229             : 
     230             : /*
     231             :  * Storage for well-known symbols. It's a separate struct from the Runtime so
     232             :  * that it can be shared across multiple runtimes. As in JSAtomState, each
     233             :  * field is a smart pointer that's immutable once initialized.
     234             :  * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
     235             :  *
     236             :  * Well-known symbols are never GC'd. The description() of each well-known
     237             :  * symbol is a permanent atom.
     238             :  */
     239             : struct WellKnownSymbols
     240             : {
     241             : #define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
     242             :     JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
     243             : #undef DECLARE_SYMBOL
     244             : 
     245        7598 :     const ImmutableSymbolPtr& get(size_t u) const {
     246        7598 :         MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
     247        7598 :         const ImmutableSymbolPtr* symbols = reinterpret_cast<const ImmutableSymbolPtr*>(this);
     248        7598 :         return symbols[u];
     249             :     }
     250             : 
     251        3453 :     const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
     252        3453 :         return get(size_t(code));
     253             :     }
     254             : 
     255           3 :     WellKnownSymbols() {}
     256             :     WellKnownSymbols(const WellKnownSymbols&) = delete;
     257             :     WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
     258             : };
     259             : 
     260             : #define NAME_OFFSET(name)       offsetof(JSAtomState, name)
     261             : 
     262             : inline HandlePropertyName
     263     1190483 : AtomStateOffsetToName(const JSAtomState& atomState, size_t offset)
     264             : {
     265     1190483 :     return *reinterpret_cast<js::ImmutablePropertyNamePtr*>((char*)&atomState + offset);
     266             : }
     267             : 
     268             : // There are several coarse locks in the enum below. These may be either
     269             : // per-runtime or per-process. When acquiring more than one of these locks,
     270             : // the acquisition must be done in the order below to avoid deadlocks.
     271             : enum RuntimeLock {
     272             :     ExclusiveAccessLock,
     273             :     HelperThreadStateLock,
     274             :     GCLock
     275             : };
     276             : 
     277             : inline bool
     278         541 : CanUseExtraThreads()
     279             : {
     280             :     extern bool gCanUseExtraThreads;
     281         541 :     return gCanUseExtraThreads;
     282             : }
     283             : 
     284             : void DisableExtraThreads();
     285             : 
     286             : using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
     287             : 
     288             : class AutoLockForExclusiveAccess;
     289             : 
     290             : } // namespace js
     291             : 
     292             : struct JSRuntime : public js::MallocProvider<JSRuntime>
     293             : {
     294             :   private:
     295             :     friend class js::Activation;
     296             :     friend class js::ActivationIterator;
     297             :     friend class js::jit::JitActivation;
     298             :     friend class js::WasmActivation;
     299             :     friend class js::jit::CompileRuntime;
     300             : 
     301             :   public:
     302             :     /*
     303             :      * If non-null, another runtime guaranteed to outlive this one and whose
     304             :      * permanent data may be used by this one where possible.
     305             :      */
     306             :     JSRuntime* const parentRuntime;
     307             : 
     308             : #ifdef DEBUG
     309             :     /* The number of child runtimes that have this runtime as their parent. */
     310             :     mozilla::Atomic<size_t> childRuntimeCount;
     311             : 
     312             :     class AutoUpdateChildRuntimeCount
     313             :     {
     314             :         JSRuntime* parent_;
     315             : 
     316             :       public:
     317           4 :         explicit AutoUpdateChildRuntimeCount(JSRuntime* parent)
     318           4 :           : parent_(parent)
     319             :         {
     320           4 :             if (parent_)
     321           1 :                 parent_->childRuntimeCount++;
     322           4 :         }
     323             : 
     324           0 :         ~AutoUpdateChildRuntimeCount() {
     325           0 :             if (parent_)
     326           0 :                 parent_->childRuntimeCount--;
     327           0 :         }
     328             :     };
     329             : 
     330             :     AutoUpdateChildRuntimeCount updateChildRuntimeCount;
     331             : #endif
     332             : 
     333             :   private:
     334             : #ifdef DEBUG
     335             :     js::WriteOnceData<bool> initialized_;
     336             : #endif
     337             : 
     338             :     // The context for the thread which currently has exclusive access to most
     339             :     // contents of the runtime. When execution on the runtime is cooperatively
     340             :     // scheduled, this is the thread which is currently running.
     341             :     mozilla::Atomic<JSContext*, mozilla::ReleaseAcquire> activeContext_;
     342             : 
     343             :     // All contexts participating in cooperative scheduling. All threads other
     344             :     // than |activeContext_| are suspended.
     345             :     js::ActiveThreadData<js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>> cooperatingContexts_;
     346             : 
     347             :     // Count of AutoProhibitActiveContextChange instances on the active context.
     348             :     js::ActiveThreadData<size_t> activeContextChangeProhibited_;
     349             : 
     350             :     // Count of beginSingleThreadedExecution() calls that have occurred with no
     351             :     // matching endSingleThreadedExecution().
     352             :     js::ActiveThreadData<size_t> singleThreadedExecutionRequired_;
     353             : 
     354             :     // Whether some thread has called beginSingleThreadedExecution() and we are
     355             :     // in the associated callback (which may execute JS on other threads).
     356             :     js::ActiveThreadData<bool> startingSingleThreadedExecution_;
     357             : 
     358             :   public:
     359    49017676 :     JSContext* activeContext() const { return activeContext_; }
     360        1064 :     const void* addressOfActiveContext() { return &activeContext_; }
     361             : 
     362             :     void setActiveContext(JSContext* cx);
     363             :     void setNewbornActiveContext(JSContext* cx);
     364             :     void deleteActiveContext(JSContext* cx);
     365             : 
     366             :     inline JSContext* activeContextFromOwnThread();
     367             : 
     368          73 :     js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>& cooperatingContexts() {
     369          73 :         return cooperatingContexts_.ref();
     370             :     }
     371             : 
     372             :     class MOZ_RAII AutoProhibitActiveContextChange
     373             :     {
     374             :         JSRuntime* rt;
     375             : 
     376             :       public:
     377         632 :         explicit AutoProhibitActiveContextChange(JSRuntime* rt)
     378         632 :           : rt(rt)
     379             :         {
     380         632 :             rt->activeContextChangeProhibited_++;
     381         632 :         }
     382             : 
     383         632 :         ~AutoProhibitActiveContextChange()
     384         632 :         {
     385         632 :             rt->activeContextChangeProhibited_--;
     386         632 :         }
     387             :     };
     388             : 
     389          93 :     bool activeContextChangeProhibited() { return activeContextChangeProhibited_; }
     390           0 :     bool singleThreadedExecutionRequired() { return singleThreadedExecutionRequired_; }
     391             : 
     392             :     js::ActiveThreadData<JS::BeginSingleThreadedExecutionCallback> beginSingleThreadedExecutionCallback;
     393             :     js::ActiveThreadData<JS::EndSingleThreadedExecutionCallback> endSingleThreadedExecutionCallback;
     394             : 
     395             :     // Ensure there is only a single thread interacting with this runtime.
     396             :     // beginSingleThreadedExecution() returns false if some context has already
     397             :     // started forcing this runtime to be single threaded. Calls to these
     398             :     // functions must be balanced.
     399             :     bool beginSingleThreadedExecution(JSContext* cx);
     400             :     void endSingleThreadedExecution(JSContext* cx);
     401             : 
     402             :     /*
     403             :      * The profiler sampler generation after the latest sample.
     404             :      *
     405             :      * The lapCount indicates the number of largest number of 'laps'
     406             :      * (wrapping from high to low) that occurred when writing entries
     407             :      * into the sample buffer.  All JitcodeGlobalMap entries referenced
     408             :      * from a given sample are assigned the generation of the sample buffer
     409             :      * at the START of the run.  If multiple laps occur, then some entries
     410             :      * (towards the end) will be written out with the "wrong" generation.
     411             :      * The lapCount indicates the required fudge factor to use to compare
     412             :      * entry generations with the sample buffer generation.
     413             :      */
     414             :     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferGen_;
     415             :     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferLapCount_;
     416             : 
     417           0 :     uint32_t profilerSampleBufferGen() {
     418           0 :         return profilerSampleBufferGen_;
     419             :     }
     420           0 :     void resetProfilerSampleBufferGen() {
     421           0 :         profilerSampleBufferGen_ = 0;
     422           0 :     }
     423           0 :     void setProfilerSampleBufferGen(uint32_t gen) {
     424             :         // May be called from sampler thread or signal handler; use
     425             :         // compareExchange to make sure we have monotonic increase.
     426             :         for (;;) {
     427           0 :             uint32_t curGen = profilerSampleBufferGen_;
     428           0 :             if (curGen >= gen)
     429           0 :                 break;
     430             : 
     431           0 :             if (profilerSampleBufferGen_.compareExchange(curGen, gen))
     432           0 :                 break;
     433           0 :         }
     434           0 :     }
     435             : 
     436           0 :     uint32_t profilerSampleBufferLapCount() {
     437           0 :         MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
     438           0 :         return profilerSampleBufferLapCount_;
     439             :     }
     440           0 :     void resetProfilerSampleBufferLapCount() {
     441           0 :         profilerSampleBufferLapCount_ = 1;
     442           0 :     }
     443           0 :     void updateProfilerSampleBufferLapCount(uint32_t lapCount) {
     444           0 :         MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
     445             : 
     446             :         // May be called from sampler thread or signal handler; use
     447             :         // compareExchange to make sure we have monotonic increase.
     448             :         for (;;) {
     449           0 :             uint32_t curLapCount = profilerSampleBufferLapCount_;
     450           0 :             if (curLapCount >= lapCount)
     451           0 :                 break;
     452             : 
     453           0 :             if (profilerSampleBufferLapCount_.compareExchange(curLapCount, lapCount))
     454           0 :                 break;
     455           0 :         }
     456           0 :     }
     457             : 
     458             :     /* Call this to accumulate telemetry data. */
     459             :     js::ActiveThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
     460             :   public:
     461             :     // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
     462             :     // histogram. |key| provides an additional key to identify the histogram.
     463             :     // |sample| is the data to add to the histogram.
     464             :     void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
     465             : 
     466             :     void setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
     467             : 
     468             :   public:
     469             :     js::ActiveThreadData<JS::StartAsyncTaskCallback> startAsyncTaskCallback;
     470             :     js::UnprotectedData<JS::FinishAsyncTaskCallback> finishAsyncTaskCallback;
     471             :     js::ExclusiveData<js::PromiseTaskPtrVector> promiseTasksToDestroy;
     472             : 
     473             :     JSObject* getIncumbentGlobal(JSContext* cx);
     474             :     bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job, js::HandleObject promise,
     475             :                            js::HandleObject incumbentGlobal);
     476             :     void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
     477             :     void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
     478             : 
     479             :     /* Had an out-of-memory error which did not populate an exception. */
     480             :     mozilla::Atomic<bool> hadOutOfMemory;
     481             : 
     482             :     /*
     483             :      * Allow relazifying functions in compartments that are active. This is
     484             :      * only used by the relazifyFunctions() testing function.
     485             :      */
     486             :     js::ActiveThreadData<bool> allowRelazificationForTesting;
     487             : 
     488             :     /* Compartment destroy callback. */
     489             :     js::ActiveThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
     490             : 
     491             :     /* Compartment memory reporting callback. */
     492             :     js::ActiveThreadData<JSSizeOfIncludingThisCompartmentCallback> sizeOfIncludingThisCompartmentCallback;
     493             : 
     494             :     /* Call this to get the name of a compartment. */
     495             :     js::ActiveThreadData<JSCompartmentNameCallback> compartmentNameCallback;
     496             : 
     497             :     /* Callback for doing memory reporting on external strings. */
     498             :     js::ActiveThreadData<JSExternalStringSizeofCallback> externalStringSizeofCallback;
     499             : 
     500             :     js::ActiveThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
     501             : 
     502             :     js::ActiveThreadData<const JSSecurityCallbacks*> securityCallbacks;
     503             :     js::ActiveThreadData<const js::DOMCallbacks*> DOMcallbacks;
     504             :     js::ActiveThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
     505             :     js::ActiveThreadData<JSReadPrincipalsOp> readPrincipals;
     506             : 
     507             :     /* Optional warning reporter. */
     508             :     js::ActiveThreadData<JS::WarningReporter> warningReporter;
     509             : 
     510             :   private:
     511             :     /* Gecko profiling metadata */
     512             :     js::UnprotectedData<js::GeckoProfiler> geckoProfiler_;
     513             :   public:
     514       39217 :     js::GeckoProfiler& geckoProfiler() { return geckoProfiler_.ref(); }
     515             : 
     516             :     // Heap GC roots for PersistentRooted pointers.
     517             :     js::ActiveThreadData<mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
     518             :                                                  mozilla::LinkedList<JS::PersistentRooted<void*>>>> heapRoots;
     519             : 
     520             :     void tracePersistentRoots(JSTracer* trc);
     521             :     void finishPersistentRoots();
     522             : 
     523             :     void finishRoots();
     524             : 
     525             :   public:
     526             :     js::UnprotectedData<JS::BuildIdOp> buildIdOp;
     527             : 
     528             :     /* AsmJSCache callbacks are runtime-wide. */
     529             :     js::UnprotectedData<JS::AsmJSCacheOps> asmJSCacheOps;
     530             : 
     531             :   private:
     532             :     js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
     533             :   public:
     534           3 :     void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
     535       13432 :     const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
     536             : 
     537             :     js::ActiveThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
     538             :     js::ActiveThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
     539             : 
     540             :     js::ActiveThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
     541             : 
     542             :     js::ActiveThreadData<js::CTypesActivityCallback> ctypesActivityCallback;
     543             : 
     544             :   private:
     545             :     js::WriteOnceData<const js::Class*> windowProxyClass_;
     546             : 
     547             :   public:
     548       48822 :     const js::Class* maybeWindowProxyClass() const {
     549       48822 :         return windowProxyClass_;
     550             :     }
     551           3 :     void setWindowProxyClass(const js::Class* clasp) {
     552           3 :         windowProxyClass_ = clasp;
     553           3 :     }
     554             : 
     555             :   private:
     556             :     // List of non-ephemeron weak containers to sweep during beginSweepingSweepGroup.
     557             :     js::ActiveThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>> weakCaches_;
     558             :   public:
     559           0 :     mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() { return weakCaches_.ref(); }
     560           0 :     void registerWeakCache(JS::detail::WeakCacheBase* cachep) {
     561           0 :         weakCaches().insertBack(cachep);
     562           0 :     }
     563             : 
     564             :     template <typename T>
     565             :     struct GlobalObjectWatchersSiblingAccess {
     566           0 :       static T* GetNext(T* elm) {
     567           0 :         return elm->onNewGlobalObjectWatchersLink.mNext;
     568             :       }
     569           0 :       static void SetNext(T* elm, T* next) {
     570           0 :         elm->onNewGlobalObjectWatchersLink.mNext = next;
     571           0 :       }
     572           0 :       static T* GetPrev(T* elm) {
     573           0 :         return elm->onNewGlobalObjectWatchersLink.mPrev;
     574             :       }
     575           0 :       static void SetPrev(T* elm, T* prev) {
     576           0 :         elm->onNewGlobalObjectWatchersLink.mPrev = prev;
     577           0 :       }
     578             :     };
     579             : 
     580             :     using WatchersList =
     581             :         mozilla::DoublyLinkedList<js::Debugger,
     582             :                                   GlobalObjectWatchersSiblingAccess<js::Debugger>>;
     583             :   private:
     584             :     /*
     585             :      * List of all enabled Debuggers that have onNewGlobalObject handler
     586             :      * methods established.
     587             :      */
     588             :     js::ActiveThreadData<WatchersList> onNewGlobalObjectWatchers_;
     589             : 
     590             :   public:
     591         311 :     WatchersList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); }
     592             : 
     593             :   private:
     594             :     /*
     595             :      * Lock taken when using per-runtime or per-zone data that could otherwise
     596             :      * be accessed simultaneously by multiple threads.
     597             :      *
     598             :      * Locking this only occurs if there is actually a thread other than the
     599             :      * active thread which could access such data.
     600             :      */
     601             :     js::Mutex exclusiveAccessLock;
     602             : #ifdef DEBUG
     603             :     bool activeThreadHasExclusiveAccess;
     604             : #endif
     605             : 
     606             :     /* Number of zones which may be operated on by non-cooperating helper threads. */
     607             :     js::UnprotectedData<size_t> numHelperThreadZones;
     608             : 
     609             :     friend class js::AutoLockForExclusiveAccess;
     610             : 
     611             :   public:
     612             :     void setUsedByHelperThread(JS::Zone* zone);
     613             :     void clearUsedByHelperThread(JS::Zone* zone);
     614             : 
     615     3573865 :     bool hasHelperThreadZones() const {
     616     3573865 :         return numHelperThreadZones > 0;
     617             :     }
     618             : 
     619             : #ifdef DEBUG
     620     2381943 :     bool currentThreadHasExclusiveAccess() const {
     621     3472461 :         return (!hasHelperThreadZones() && activeThreadHasExclusiveAccess) ||
     622     3472503 :             exclusiveAccessLock.ownedByCurrentThread();
     623             :     }
     624             : #endif
     625             : 
     626             :     // How many compartments there are across all zones. This number includes
     627             :     // off thread context compartments, so it isn't necessarily equal to the
     628             :     // number of compartments visited by CompartmentsIter.
     629             :     js::ActiveThreadData<size_t> numCompartments;
     630             : 
     631             :     /* Locale-specific callbacks for string conversion. */
     632             :     js::ActiveThreadData<const JSLocaleCallbacks*> localeCallbacks;
     633             : 
     634             :     /* Default locale for Internationalization API */
     635             :     js::ActiveThreadData<char*> defaultLocale;
     636             : 
     637             :     /* Default JSVersion. */
     638             :     js::ActiveThreadData<JSVersion> defaultVersion_;
     639             : 
     640             :     /* If true, new scripts must be created with PC counter information. */
     641             :     js::ActiveThreadOrIonCompileData<bool> profilingScripts;
     642             : 
     643             :     /* Strong references on scripts held for PCCount profiling API. */
     644             :     js::ActiveThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*> scriptAndCountsVector;
     645             : 
     646             :   private:
     647             :     /* Code coverage output. */
     648             :     js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
     649             :   public:
     650       36910 :     js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
     651             : 
     652             :   private:
     653             :     js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
     654             : 
     655             :     /*
     656             :      * Self-hosting state cloned on demand into other compartments. Shared with the parent
     657             :      * runtime if there is one.
     658             :      */
     659             :     js::WriteOnceData<js::NativeObject*> selfHostingGlobal_;
     660             : 
     661             :     static js::GlobalObject*
     662             :     createSelfHostingGlobal(JSContext* cx);
     663             : 
     664             :     bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
     665             :                                     js::MutableHandleValue vp);
     666             :     JSFunction* getUnclonedSelfHostedFunction(JSContext* cx, js::HandlePropertyName name);
     667             : 
     668             :     js::jit::JitRuntime* createJitRuntime(JSContext* cx);
     669             : 
     670             :   public:
     671          13 :     js::jit::JitRuntime* getJitRuntime(JSContext* cx) {
     672          13 :         return jitRuntime_ ? jitRuntime_.ref() : createJitRuntime(cx);
     673             :     }
     674       40309 :     js::jit::JitRuntime* jitRuntime() const {
     675       40309 :         return jitRuntime_.ref();
     676             :     }
     677           7 :     bool hasJitRuntime() const {
     678           7 :         return !!jitRuntime_;
     679             :     }
     680             : 
     681             :   private:
     682             :     // Used to generate random keys for hash tables.
     683             :     mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
     684             :     mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
     685             : 
     686             :   public:
     687             :     mozilla::HashCodeScrambler randomHashCodeScrambler();
     688             :     mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
     689             : 
     690             :     //-------------------------------------------------------------------------
     691             :     // Self-hosting support
     692             :     //-------------------------------------------------------------------------
     693             : 
     694         312 :     bool hasInitializedSelfHosting() const {
     695         312 :         return selfHostingGlobal_;
     696             :     }
     697             : 
     698             :     bool initSelfHosting(JSContext* cx);
     699             :     void finishSelfHosting();
     700             :     void traceSelfHostingGlobal(JSTracer* trc);
     701       90487 :     bool isSelfHostingGlobal(JSObject* global) {
     702       90487 :         return global == selfHostingGlobal_;
     703             :     }
     704             :     bool isSelfHostingCompartment(JSCompartment* comp) const;
     705             :     bool isSelfHostingZone(const JS::Zone* zone) const;
     706             :     bool createLazySelfHostedFunctionClone(JSContext* cx, js::HandlePropertyName selfHostedName,
     707             :                                            js::HandleAtom name, unsigned nargs,
     708             :                                            js::HandleObject proto,
     709             :                                            js::NewObjectKind newKind,
     710             :                                            js::MutableHandleFunction fun);
     711             :     bool cloneSelfHostedFunctionScript(JSContext* cx, js::Handle<js::PropertyName*> name,
     712             :                                        js::Handle<JSFunction*> targetFun);
     713             :     bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
     714             :                               js::MutableHandleValue vp);
     715             :     void assertSelfHostedFunctionHasCanonicalName(JSContext* cx, js::HandlePropertyName name);
     716             : 
     717             :     //-------------------------------------------------------------------------
     718             :     // Locale information
     719             :     //-------------------------------------------------------------------------
     720             : 
     721             :     /*
     722             :      * Set the default locale for the ECMAScript Internationalization API
     723             :      * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
     724             :      * Note that the Internationalization API encourages clients to
     725             :      * specify their own locales.
     726             :      * The locale string remains owned by the caller.
     727             :      */
     728             :     bool setDefaultLocale(const char* locale);
     729             : 
     730             :     /* Reset the default locale to OS defaults. */
     731             :     void resetDefaultLocale();
     732             : 
     733             :     /* Gets current default locale. String remains owned by context. */
     734             :     const char* getDefaultLocale();
     735             : 
     736        3412 :     JSVersion defaultVersion() const { return defaultVersion_; }
     737             :     void setDefaultVersion(JSVersion v) { defaultVersion_ = v; }
     738             : 
     739             :     /* Garbage collector state, used by jsgc.c. */
     740             :     js::gc::GCRuntime   gc;
     741             : 
     742             :     /* Garbage collector state has been successfully initialized. */
     743             :     js::WriteOnceData<bool> gcInitialized;
     744             : 
     745         184 :     bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
     746             : 
     747             :     void lockGC() {
     748             :         gc.lockGC();
     749             :     }
     750             : 
     751             :     void unlockGC() {
     752             :         gc.unlockGC();
     753             :     }
     754             : 
     755             :     /* Well-known numbers. */
     756             :     const js::Value     NaNValue;
     757             :     const js::Value     negativeInfinityValue;
     758             :     const js::Value     positiveInfinityValue;
     759             : 
     760             :     js::WriteOnceData<js::PropertyName*> emptyString;
     761             : 
     762             :   private:
     763             :     js::WriteOnceData<js::FreeOp*> defaultFreeOp_;
     764             : 
     765             :   public:
     766      121212 :     js::FreeOp* defaultFreeOp() {
     767      121212 :         MOZ_ASSERT(defaultFreeOp_);
     768      121213 :         return defaultFreeOp_;
     769             :     }
     770             : 
     771             : #if !EXPOSE_INTL_API
     772             :     /* Number localization, used by jsnum.cpp. */
     773             :     js::WriteOnceData<const char*> thousandsSeparator;
     774             :     js::WriteOnceData<const char*> decimalSeparator;
     775             :     js::WriteOnceData<const char*> numGrouping;
     776             : #endif
     777             : 
     778             :   private:
     779             :     mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
     780             : 
     781             :   public:
     782             :     // If this particular JSRuntime has a SharedImmutableStringsCache, return a
     783             :     // pointer to it, otherwise return nullptr.
     784           1 :     js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
     785           1 :         return sharedImmutableStrings_.isSome() ? &*sharedImmutableStrings_ : nullptr;
     786             :     }
     787             : 
     788             :     // Get a reference to this JSRuntime's or its parent's
     789             :     // SharedImmutableStringsCache.
     790        1714 :     js::SharedImmutableStringsCache& sharedImmutableStrings() {
     791        1714 :         MOZ_ASSERT_IF(parentRuntime, !sharedImmutableStrings_);
     792        1714 :         MOZ_ASSERT_IF(!parentRuntime, sharedImmutableStrings_);
     793        1714 :         return parentRuntime ? parentRuntime->sharedImmutableStrings() : *sharedImmutableStrings_;
     794             :     }
     795             : 
     796             :   private:
     797             :     js::WriteOnceData<bool> beingDestroyed_;
     798             :   public:
     799           4 :     bool isBeingDestroyed() const {
     800           4 :         return beingDestroyed_;
     801             :     }
     802             : 
     803             :   private:
     804             :     bool allowContentJS_;
     805             :   public:
     806          68 :     bool allowContentJS() const {
     807          68 :         return allowContentJS_;
     808             :     }
     809             : 
     810             :     friend class js::AutoAssertNoContentJS;
     811             : 
     812             :   private:
     813             :     // Set of all atoms other than those in permanentAtoms and staticStrings.
     814             :     // Reading or writing this set requires the calling thread to use
     815             :     // AutoLockForExclusiveAccess.
     816             :     js::ExclusiveAccessLockOrGCTaskData<js::AtomSet*> atoms_;
     817             : 
     818             :     // Set of all atoms added while the main atoms table is being swept.
     819             :     js::ExclusiveAccessLockData<js::AtomSet*> atomsAddedWhileSweeping_;
     820             : 
     821             :     // Compartment and associated zone containing all atoms in the runtime, as
     822             :     // well as runtime wide IonCode stubs. Modifying the contents of this
     823             :     // compartment requires the calling thread to use AutoLockForExclusiveAccess.
     824             :     js::WriteOnceData<JSCompartment*> atomsCompartment_;
     825             : 
     826             :     // Set of all live symbols produced by Symbol.for(). All such symbols are
     827             :     // allocated in the atomsCompartment. Reading or writing the symbol
     828             :     // registry requires the calling thread to use AutoLockForExclusiveAccess.
     829             :     js::ExclusiveAccessLockOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
     830             : 
     831             :   public:
     832             :     bool initializeAtoms(JSContext* cx);
     833             :     void finishAtoms();
     834           2 :     bool atomsAreFinished() const { return !atoms_; }
     835             : 
     836           0 :     js::AtomSet* atomsForSweeping() {
     837           0 :         MOZ_ASSERT(JS::CurrentThreadIsHeapCollecting());
     838           0 :         return atoms_;
     839             :     }
     840             : 
     841       95256 :     js::AtomSet& atoms(js::AutoLockForExclusiveAccess& lock) {
     842       95256 :         MOZ_ASSERT(atoms_);
     843       95256 :         return *atoms_;
     844             :     }
     845      487368 :     js::AtomSet& unsafeAtoms() {
     846      487368 :         MOZ_ASSERT(atoms_);
     847      487368 :         return *atoms_;
     848             :     }
     849             : 
     850             :     bool createAtomsAddedWhileSweepingTable();
     851             :     void destroyAtomsAddedWhileSweepingTable();
     852       95256 :     js::AtomSet* atomsAddedWhileSweeping() {
     853       95256 :         return atomsAddedWhileSweeping_;
     854             :     }
     855             : 
     856       62684 :     JSCompartment* atomsCompartment(js::AutoLockForExclusiveAccess& lock) {
     857       62684 :         return atomsCompartment_;
     858             :     }
     859           0 :     JSCompartment* unsafeAtomsCompartment() {
     860           0 :         return atomsCompartment_;
     861             :     }
     862             : 
     863     1688878 :     bool isAtomsCompartment(JSCompartment* comp) {
     864     1688878 :         return comp == atomsCompartment_;
     865             :     }
     866             : 
     867           0 :     const JS::Zone* atomsZone(js::AutoLockForExclusiveAccess& lock) const {
     868           0 :         return gc.atomsZone;
     869             :     }
     870             : 
     871             :     // The atoms compartment is the only one in its zone.
     872     3643352 :     bool isAtomsZone(const JS::Zone* zone) const {
     873     3643352 :         return zone == gc.atomsZone;
     874             :     }
     875             : 
     876             :     bool activeGCInAtomsZone();
     877             : 
     878           0 :     js::SymbolRegistry& symbolRegistry(js::AutoLockForExclusiveAccess& lock) {
     879           0 :         return symbolRegistry_.ref();
     880             :     }
     881           0 :     js::SymbolRegistry& unsafeSymbolRegistry() {
     882           0 :         return symbolRegistry_.ref();
     883             :     }
     884             : 
     885             :     // Permanent atoms are fixed during initialization of the runtime and are
     886             :     // not modified or collected until the runtime is destroyed. These may be
     887             :     // shared with another, longer living runtime through |parentRuntime| and
     888             :     // can be freely accessed with no locking necessary.
     889             : 
     890             :     // Permanent atoms pre-allocated for general use.
     891             :     js::WriteOnceData<js::StaticStrings*> staticStrings;
     892             : 
     893             :     // Cached pointers to various permanent property names.
     894             :     js::WriteOnceData<JSAtomState*> commonNames;
     895             : 
     896             :     // All permanent atoms in the runtime, other than those in staticStrings.
     897             :     // Unlike |atoms_|, access to this does not require
     898             :     // AutoLockForExclusiveAccess because it is frozen and thus read-only.
     899             :     js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms;
     900             : 
     901             :     bool transformToPermanentAtoms(JSContext* cx);
     902             : 
     903             :     // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
     904             :     // these are shared with the parentRuntime, if any.
     905             :     js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
     906             : 
     907             :     /* Shared Intl data for this runtime. */
     908             :     js::ActiveThreadData<js::SharedIntlData> sharedIntlData;
     909             : 
     910             :     void traceSharedIntlData(JSTracer* trc);
     911             : 
     912             :     // Table of bytecode and other data that may be shared across scripts
     913             :     // within the runtime. This may be modified by threads using
     914             :     // AutoLockForExclusiveAccess.
     915             :   private:
     916             :     js::ExclusiveAccessLockData<js::ScriptDataTable> scriptDataTable_;
     917             :   public:
     918       29397 :     js::ScriptDataTable& scriptDataTable(js::AutoLockForExclusiveAccess& lock) {
     919       29397 :         return scriptDataTable_.ref();
     920             :     }
     921             : 
     922             :     js::WriteOnceData<bool> jitSupportsFloatingPoint;
     923             :     js::WriteOnceData<bool> jitSupportsUnalignedAccesses;
     924             :     js::WriteOnceData<bool> jitSupportsSimd;
     925             : 
     926             :   private:
     927             :     static mozilla::Atomic<size_t> liveRuntimesCount;
     928             : 
     929             :   public:
     930           3 :     static bool hasLiveRuntimes() {
     931           3 :         return liveRuntimesCount > 0;
     932             :     }
     933             : 
     934             :     explicit JSRuntime(JSRuntime* parentRuntime);
     935             :     ~JSRuntime();
     936             : 
     937             :     // destroyRuntime is used instead of a destructor, to ensure the downcast
     938             :     // to JSContext remains valid. The final GC triggered here depends on this.
     939             :     void destroyRuntime();
     940             : 
     941             :     bool init(JSContext* cx, uint32_t maxbytes, uint32_t maxNurseryBytes);
     942             : 
     943          12 :     JSRuntime* thisFromCtor() { return this; }
     944             : 
     945             :   public:
     946             :     /*
     947             :      * Call this after allocating memory held by GC things, to update memory
     948             :      * pressure counters or report the OOM error if necessary. If oomError and
     949             :      * cx is not null the function also reports OOM error.
     950             :      *
     951             :      * The function must be called outside the GC lock and in case of OOM error
     952             :      * the caller must ensure that no deadlock possible during OOM reporting.
     953             :      */
     954             :     void updateMallocCounter(size_t nbytes);
     955             :     void updateMallocCounter(JS::Zone* zone, size_t nbytes);
     956             : 
     957           0 :     void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
     958             : 
     959             :     /*
     960             :      * This should be called after system malloc/calloc/realloc returns nullptr
     961             :      * to try to recove some memory or to report an error.  For realloc, the
     962             :      * original pointer must be passed as reallocPtr.
     963             :      *
     964             :      * The function must be called outside the GC lock.
     965             :      */
     966             :     JS_FRIEND_API(void*) onOutOfMemory(js::AllocFunction allocator, size_t nbytes,
     967             :                                        void* reallocPtr = nullptr, JSContext* maybecx = nullptr);
     968             : 
     969             :     /*  onOutOfMemory but can call OnLargeAllocationFailure. */
     970             :     JS_FRIEND_API(void*) onOutOfMemoryCanGC(js::AllocFunction allocator, size_t nbytes,
     971             :                                             void* reallocPtr = nullptr);
     972             : 
     973             :     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* runtime);
     974             : 
     975             :   private:
     976             :     // Settings for how helper threads can be used.
     977             :     mozilla::Atomic<bool> offthreadIonCompilationEnabled_;
     978             :     mozilla::Atomic<bool> parallelParsingEnabled_;
     979             : 
     980             :     js::ActiveThreadData<bool> autoWritableJitCodeActive_;
     981             : 
     982             :   public:
     983             : 
     984             :     // Note: these values may be toggled dynamically (in response to about:config
     985             :     // prefs changing).
     986           3 :     void setOffthreadIonCompilationEnabled(bool value) {
     987           3 :         offthreadIonCompilationEnabled_ = value;
     988           3 :     }
     989         175 :     bool canUseOffthreadIonCompilation() const {
     990         175 :         return offthreadIonCompilationEnabled_;
     991             :     }
     992           3 :     void setParallelParsingEnabled(bool value) {
     993           3 :         parallelParsingEnabled_ = value;
     994           3 :     }
     995          32 :     bool canUseParallelParsing() const {
     996          32 :         return parallelParsingEnabled_;
     997             :     }
     998             : 
     999        8998 :     void toggleAutoWritableJitCodeActive(bool b) {
    1000        8998 :         MOZ_ASSERT(autoWritableJitCodeActive_ != b, "AutoWritableJitCode should not be nested.");
    1001        8998 :         autoWritableJitCodeActive_ = b;
    1002        8998 :     }
    1003             : 
    1004             :     /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
    1005             :     js::ActiveThreadData<JS::OutOfMemoryCallback> oomCallback;
    1006             :     js::ActiveThreadData<void*> oomCallbackData;
    1007             : 
    1008             :     /*
    1009             :      * These variations of malloc/calloc/realloc will call the
    1010             :      * large-allocation-failure callback on OOM and retry the allocation.
    1011             :      */
    1012             :     static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
    1013             : 
    1014             :     template <typename T>
    1015           0 :     T* pod_callocCanGC(size_t numElems) {
    1016           0 :         T* p = pod_calloc<T>(numElems);
    1017           0 :         if (MOZ_LIKELY(!!p))
    1018           0 :             return p;
    1019             :         size_t bytes;
    1020           0 :         if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(numElems, &bytes))) {
    1021           0 :             reportAllocationOverflow();
    1022           0 :             return nullptr;
    1023             :         }
    1024           0 :         return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Calloc, bytes));
    1025             :     }
    1026             : 
    1027             :     template <typename T>
    1028             :     T* pod_reallocCanGC(T* p, size_t oldSize, size_t newSize) {
    1029             :         T* p2 = pod_realloc<T>(p, oldSize, newSize);
    1030             :         if (MOZ_LIKELY(!!p2))
    1031             :             return p2;
    1032             :         size_t bytes;
    1033             :         if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(newSize, &bytes))) {
    1034             :             reportAllocationOverflow();
    1035             :             return nullptr;
    1036             :         }
    1037             :         return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Realloc, bytes, p));
    1038             :     }
    1039             : 
    1040             :     /*
    1041             :      * Debugger.Memory functions like takeCensus use this embedding-provided
    1042             :      * function to assess the size of malloc'd blocks of memory.
    1043             :      */
    1044             :     js::ActiveThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
    1045             : 
    1046             :     /* Last time at which an animation was played for this runtime. */
    1047             :     mozilla::Atomic<int64_t> lastAnimationTime;
    1048             : 
    1049             :   private:
    1050             :     js::ActiveThreadData<js::PerformanceMonitoring> performanceMonitoring_;
    1051             :   public:
    1052       37229 :     js::PerformanceMonitoring& performanceMonitoring() { return performanceMonitoring_.ref(); }
    1053             : 
    1054             :   private:
    1055             :     /* The stack format for the current runtime.  Only valid on non-child
    1056             :      * runtimes. */
    1057             :     mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
    1058             : 
    1059             :   public:
    1060           0 :     js::StackFormat stackFormat() const {
    1061           0 :         const JSRuntime* rt = this;
    1062           0 :         while (rt->parentRuntime) {
    1063           0 :             MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
    1064           0 :             rt = rt->parentRuntime;
    1065             :         }
    1066           0 :         MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
    1067           0 :         return rt->stackFormat_;
    1068             :     }
    1069           0 :     void setStackFormat(js::StackFormat format) {
    1070           0 :         MOZ_ASSERT(!parentRuntime);
    1071           0 :         MOZ_ASSERT(format != js::StackFormat::Default);
    1072           0 :         stackFormat_ = format;
    1073           0 :     }
    1074             : 
    1075             :     // For inherited heap state accessors.
    1076             :     friend class js::gc::AutoTraceSession;
    1077             :     friend class JS::AutoEnterCycleCollection;
    1078             : 
    1079             :   private:
    1080             :     js::ActiveThreadData<js::RuntimeCaches> caches_;
    1081             :   public:
    1082       41763 :     js::RuntimeCaches& caches() { return caches_.ref(); }
    1083             : 
    1084             :   private:
    1085             :     // When wasm is interrupted, the pc at which we should return if the
    1086             :     // interrupt hasn't stopped execution of the current running code. Since
    1087             :     // this is used only by the interrupt handler and the latter is not
    1088             :     // reentrant, this value can't be clobbered so there is at most one
    1089             :     // resume PC at a time.
    1090             :     js::ActiveThreadData<void*> wasmResumePC_;
    1091             : 
    1092             :     // To ensure a consistent state of fp/pc, the unwound pc might be
    1093             :     // different from the resumePC, especially at call boundaries.
    1094             :     js::ActiveThreadData<void*> wasmUnwindPC_;
    1095             : 
    1096             :   public:
    1097           0 :     void startWasmInterrupt(void* resumePC, void* unwindPC) {
    1098           0 :         MOZ_ASSERT(resumePC && unwindPC);
    1099           0 :         wasmResumePC_ = resumePC;
    1100           0 :         wasmUnwindPC_ = unwindPC;
    1101           0 :     }
    1102           0 :     void finishWasmInterrupt() {
    1103           0 :         MOZ_ASSERT(wasmResumePC_ && wasmUnwindPC_);
    1104           0 :         wasmResumePC_ = nullptr;
    1105           0 :         wasmUnwindPC_ = nullptr;
    1106           0 :     }
    1107           0 :     void* wasmResumePC() const {
    1108           0 :         return wasmResumePC_;
    1109             :     }
    1110           0 :     void* wasmUnwindPC() const {
    1111           0 :         return wasmUnwindPC_;
    1112             :     }
    1113             : };
    1114             : 
    1115             : namespace js {
    1116             : 
    1117             : /*
    1118             :  * Flags accompany script version data so that a) dynamically created scripts
    1119             :  * can inherit their caller's compile-time properties and b) scripts can be
    1120             :  * appropriately compared in the eval cache across global option changes. An
    1121             :  * example of the latter is enabling the top-level-anonymous-function-is-error
    1122             :  * option: subsequent evals of the same, previously-valid script text may have
    1123             :  * become invalid.
    1124             :  */
    1125             : namespace VersionFlags {
    1126             : static const unsigned MASK      = 0x0FFF; /* see JSVersion in jspubtd.h */
    1127             : } /* namespace VersionFlags */
    1128             : 
    1129             : static inline JSVersion
    1130        2137 : VersionNumber(JSVersion version)
    1131             : {
    1132        2137 :     return JSVersion(uint32_t(version) & VersionFlags::MASK);
    1133             : }
    1134             : 
    1135             : static inline JSVersion
    1136             : VersionExtractFlags(JSVersion version)
    1137             : {
    1138             :     return JSVersion(uint32_t(version) & ~VersionFlags::MASK);
    1139             : }
    1140             : 
    1141             : static inline void
    1142             : VersionCopyFlags(JSVersion* version, JSVersion from)
    1143             : {
    1144             :     *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
    1145             : }
    1146             : 
    1147             : static inline bool
    1148             : VersionHasFlags(JSVersion version)
    1149             : {
    1150             :     return !!VersionExtractFlags(version);
    1151             : }
    1152             : 
    1153             : static inline bool
    1154             : VersionIsKnown(JSVersion version)
    1155             : {
    1156             :     return VersionNumber(version) != JSVERSION_UNKNOWN;
    1157             : }
    1158             : 
    1159             : inline void
    1160         555 : FreeOp::free_(void* p)
    1161             : {
    1162         555 :     js_free(p);
    1163         555 : }
    1164             : 
    1165             : inline void
    1166           0 : FreeOp::freeLater(void* p)
    1167             : {
    1168             :     // FreeOps other than the defaultFreeOp() are constructed on the stack,
    1169             :     // and won't hold onto the pointers to free indefinitely.
    1170           0 :     MOZ_ASSERT(!isDefaultFreeOp());
    1171             : 
    1172           0 :     AutoEnterOOMUnsafeRegion oomUnsafe;
    1173           0 :     if (!freeLaterList.append(p))
    1174           0 :         oomUnsafe.crash("FreeOp::freeLater");
    1175           0 : }
    1176             : 
    1177             : inline bool
    1178           0 : FreeOp::appendJitPoisonRange(const jit::JitPoisonRange& range)
    1179             : {
    1180             :     // FreeOps other than the defaultFreeOp() are constructed on the stack,
    1181             :     // and won't hold onto the pointers to free indefinitely.
    1182           0 :     MOZ_ASSERT(!isDefaultFreeOp());
    1183             : 
    1184           0 :     return jitPoisonRanges.append(range);
    1185             : }
    1186             : 
    1187             : /*
    1188             :  * RAII class that takes the GC lock while it is live.
    1189             :  *
    1190             :  * Note that the lock may be temporarily released by use of AutoUnlockGC when
    1191             :  * passed a non-const reference to this class.
    1192             :  */
    1193             : class MOZ_RAII AutoLockGC
    1194             : {
    1195             :   public:
    1196        7212 :     explicit AutoLockGC(JSRuntime* rt
    1197             :                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    1198        7212 :       : runtime_(rt)
    1199             :     {
    1200        7212 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1201        7212 :         lock();
    1202        7212 :     }
    1203             : 
    1204       14424 :     ~AutoLockGC() {
    1205        7212 :         unlock();
    1206        7212 :     }
    1207             : 
    1208        7229 :     void lock() {
    1209        7229 :         MOZ_ASSERT(lockGuard_.isNothing());
    1210        7229 :         lockGuard_.emplace(runtime_->gc.lock);
    1211        7229 :     }
    1212             : 
    1213        7229 :     void unlock() {
    1214        7229 :         MOZ_ASSERT(lockGuard_.isSome());
    1215        7229 :         lockGuard_.reset();
    1216        7229 :     }
    1217             : 
    1218           0 :     js::LockGuard<js::Mutex>& guard() {
    1219           0 :         return lockGuard_.ref();
    1220             :     }
    1221             : 
    1222             :   private:
    1223             :     JSRuntime* runtime_;
    1224             :     mozilla::Maybe<js::LockGuard<js::Mutex>> lockGuard_;
    1225             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1226             : 
    1227             :     AutoLockGC(const AutoLockGC&) = delete;
    1228             :     AutoLockGC& operator=(const AutoLockGC&) = delete;
    1229             : };
    1230             : 
    1231             : class MOZ_RAII AutoUnlockGC
    1232             : {
    1233             :   public:
    1234          17 :     explicit AutoUnlockGC(AutoLockGC& lock
    1235             :                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    1236          17 :       : lock(lock)
    1237             :     {
    1238          17 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1239          17 :         lock.unlock();
    1240          17 :     }
    1241             : 
    1242          34 :     ~AutoUnlockGC() {
    1243          17 :         lock.lock();
    1244          17 :     }
    1245             : 
    1246             :   private:
    1247             :     AutoLockGC& lock;
    1248             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1249             : 
    1250             :     AutoUnlockGC(const AutoUnlockGC&) = delete;
    1251             :     AutoUnlockGC& operator=(const AutoUnlockGC&) = delete;
    1252             : };
    1253             : 
    1254             : /************************************************************************/
    1255             : 
    1256             : static MOZ_ALWAYS_INLINE void
    1257             : MakeRangeGCSafe(Value* vec, size_t len)
    1258             : {
    1259             :     mozilla::PodZero(vec, len);
    1260             : }
    1261             : 
    1262             : static MOZ_ALWAYS_INLINE void
    1263             : MakeRangeGCSafe(Value* beg, Value* end)
    1264             : {
    1265             :     mozilla::PodZero(beg, end - beg);
    1266             : }
    1267             : 
    1268             : static MOZ_ALWAYS_INLINE void
    1269             : MakeRangeGCSafe(jsid* beg, jsid* end)
    1270             : {
    1271             :     for (jsid* id = beg; id != end; ++id)
    1272             :         *id = INT_TO_JSID(0);
    1273             : }
    1274             : 
    1275             : static MOZ_ALWAYS_INLINE void
    1276             : MakeRangeGCSafe(jsid* vec, size_t len)
    1277             : {
    1278             :     MakeRangeGCSafe(vec, vec + len);
    1279             : }
    1280             : 
    1281             : static MOZ_ALWAYS_INLINE void
    1282             : MakeRangeGCSafe(Shape** beg, Shape** end)
    1283             : {
    1284             :     mozilla::PodZero(beg, end - beg);
    1285             : }
    1286             : 
    1287             : static MOZ_ALWAYS_INLINE void
    1288             : MakeRangeGCSafe(Shape** vec, size_t len)
    1289             : {
    1290             :     mozilla::PodZero(vec, len);
    1291             : }
    1292             : 
    1293             : static MOZ_ALWAYS_INLINE void
    1294       13157 : SetValueRangeToUndefined(Value* beg, Value* end)
    1295             : {
    1296       35838 :     for (Value* v = beg; v != end; ++v)
    1297       22681 :         v->setUndefined();
    1298       13157 : }
    1299             : 
    1300             : static MOZ_ALWAYS_INLINE void
    1301       13157 : SetValueRangeToUndefined(Value* vec, size_t len)
    1302             : {
    1303       13157 :     SetValueRangeToUndefined(vec, vec + len);
    1304       13157 : }
    1305             : 
    1306             : static MOZ_ALWAYS_INLINE void
    1307             : SetValueRangeToNull(Value* beg, Value* end)
    1308             : {
    1309             :     for (Value* v = beg; v != end; ++v)
    1310             :         v->setNull();
    1311             : }
    1312             : 
    1313             : static MOZ_ALWAYS_INLINE void
    1314             : SetValueRangeToNull(Value* vec, size_t len)
    1315             : {
    1316             :     SetValueRangeToNull(vec, vec + len);
    1317             : }
    1318             : 
    1319             : /*
    1320             :  * Allocation policy that uses JSRuntime::pod_malloc and friends, so that
    1321             :  * memory pressure is properly accounted for. This is suitable for
    1322             :  * long-lived objects owned by the JSRuntime.
    1323             :  *
    1324             :  * Since it doesn't hold a JSContext (those may not live long enough), it
    1325             :  * can't report out-of-memory conditions itself; the caller must check for
    1326             :  * OOM and take the appropriate action.
    1327             :  *
    1328             :  * FIXME bug 647103 - replace these *AllocPolicy names.
    1329             :  */
    1330             : class RuntimeAllocPolicy
    1331             : {
    1332             :     JSRuntime* const runtime;
    1333             : 
    1334             :   public:
    1335         744 :     MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime* rt) : runtime(rt) {}
    1336             : 
    1337             :     template <typename T>
    1338             :     T* maybe_pod_malloc(size_t numElems) {
    1339             :         return runtime->maybe_pod_malloc<T>(numElems);
    1340             :     }
    1341             : 
    1342             :     template <typename T>
    1343           7 :     T* maybe_pod_calloc(size_t numElems) {
    1344           7 :         return runtime->maybe_pod_calloc<T>(numElems);
    1345             :     }
    1346             : 
    1347             :     template <typename T>
    1348             :     T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
    1349             :         return runtime->maybe_pod_realloc<T>(p, oldSize, newSize);
    1350             :     }
    1351             : 
    1352             :     template <typename T>
    1353         958 :     T* pod_malloc(size_t numElems) {
    1354         958 :         return runtime->pod_malloc<T>(numElems);
    1355             :     }
    1356             : 
    1357             :     template <typename T>
    1358         403 :     T* pod_calloc(size_t numElems) {
    1359         403 :         return runtime->pod_calloc<T>(numElems);
    1360             :     }
    1361             : 
    1362             :     template <typename T>
    1363             :     T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
    1364             :         return runtime->pod_realloc<T>(p, oldSize, newSize);
    1365             :     }
    1366             : 
    1367         216 :     void free_(void* p) { js_free(p); }
    1368           0 :     void reportAllocOverflow() const {}
    1369             : 
    1370        2551 :     bool checkSimulatedOOM() const {
    1371        2551 :         return !js::oom::ShouldFailWithOOM();
    1372             :     }
    1373             : };
    1374             : 
    1375             : extern const JSSecurityCallbacks NullSecurityCallbacks;
    1376             : 
    1377             : inline Nursery&
    1378         850 : ZoneGroup::nursery()
    1379             : {
    1380         850 :     return runtime->gc.nursery();
    1381             : }
    1382             : 
    1383             : inline gc::StoreBuffer&
    1384         547 : ZoneGroup::storeBuffer()
    1385             : {
    1386         547 :     return runtime->gc.storeBuffer();
    1387             : }
    1388             : 
    1389             : // This callback is set by JS::SetProcessLargeAllocationFailureCallback
    1390             : // and may be null. See comment in jsapi.h.
    1391             : extern mozilla::Atomic<JS::LargeAllocationFailureCallback> OnLargeAllocationFailure;
    1392             : 
    1393             : } /* namespace js */
    1394             : 
    1395             : #ifdef _MSC_VER
    1396             : #pragma warning(pop)
    1397             : #endif
    1398             : 
    1399             : #endif /* vm_Runtime_h */

Generated by: LCOV version 1.13