1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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/Assertions.h"  // MOZ_ASSERT
11 #include "mozilla/Atomics.h"
12 #include "mozilla/Attributes.h"
13 #include "mozilla/DoublyLinkedList.h"
14 #include "mozilla/LinkedList.h"
15 #include "mozilla/Maybe.h"
16 #include "mozilla/MaybeOneOf.h"
17 #include "mozilla/MemoryReporting.h"
18 #include "mozilla/ThreadLocal.h"
19 #include "mozilla/TimeStamp.h"
20 #include "mozilla/Vector.h"
21 #include "mozilla/XorShift128PlusRNG.h"
22 
23 #include <algorithm>
24 
25 #include "jsapi.h"
26 
27 #include "builtin/AtomicsObject.h"
28 #ifdef JS_HAS_INTL_API
29 #  include "builtin/intl/SharedIntlData.h"
30 #endif
31 #include "frontend/NameCollections.h"
32 #include "gc/GCRuntime.h"
33 #include "gc/Tracer.h"
34 #include "js/AllocationRecording.h"
35 #include "js/BuildId.h"  // JS::BuildIdOp
36 #include "js/Debug.h"
37 #include "js/experimental/CTypes.h"      // JS::CTypesActivityCallback
38 #include "js/experimental/SourceHook.h"  // js::SourceHook
39 #include "js/friend/StackLimits.h"       // js::ReportOverRecursed
40 #include "js/friend/UsageStatistics.h"   // JSAccumulateTelemetryDataCallback
41 #include "js/GCVector.h"
42 #include "js/HashTable.h"
43 #include "js/Initialization.h"
44 #include "js/Modules.h"  // JS::Module{DynamicImport,Metadata,Resolve}Hook
45 #ifdef DEBUG
46 #  include "js/Proxy.h"  // For AutoEnterPolicy
47 #endif
48 #include "js/Stream.h"  // JS::AbortSignalIsAborted
49 #include "js/Symbol.h"
50 #include "js/UniquePtr.h"
51 #include "js/Utility.h"
52 #include "js/Vector.h"
53 #include "js/Warnings.h"  // JS::WarningReporter
54 #include "threading/Thread.h"
55 #include "vm/Caches.h"
56 #include "vm/CodeCoverage.h"
57 #include "vm/CommonPropertyNames.h"
58 #include "vm/GeckoProfiler.h"
59 #include "vm/JSAtom.h"
60 #include "vm/JSAtomState.h"
61 #include "vm/JSScript.h"
62 #include "vm/OffThreadPromiseRuntimeState.h"  // js::OffThreadPromiseRuntimeState
63 #include "vm/Scope.h"
64 #include "vm/SharedImmutableStringsCache.h"
65 #include "vm/SharedStencil.h"  // js::SharedImmutableScriptDataTable
66 #include "vm/Stack.h"
67 #include "vm/SymbolType.h"
68 #include "wasm/WasmTypes.h"
69 
70 struct JSClass;
71 
72 namespace js {
73 
74 class AutoAssertNoContentJS;
75 class EnterDebuggeeNoExecute;
76 #ifdef JS_TRACE_LOGGING
77 class TraceLoggerThread;
78 #endif
79 
80 }  // namespace js
81 
82 struct DtoaState;
83 struct JSLocaleCallbacks;
84 
85 #ifdef JS_SIMULATOR_ARM64
86 namespace vixl {
87 class Simulator;
88 }
89 #endif
90 
91 namespace js {
92 
93 extern MOZ_COLD void ReportOutOfMemory(JSContext* cx);
94 
95 /* Different signature because the return type has [[nodiscard]]_TYPE. */
96 extern MOZ_COLD mozilla::GenericErrorResult<OOM> ReportOutOfMemoryResult(
97     JSContext* cx);
98 
99 extern MOZ_COLD void ReportAllocationOverflow(JSContext* maybecx);
100 
101 class Activation;
102 class ActivationIterator;
103 
104 namespace jit {
105 class JitRuntime;
106 class JitActivation;
107 struct PcScriptCache;
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 namespace frontend {
118 class WellKnownParserAtoms;
119 }  // namespace frontend
120 
121 // [SMDOC] JS Engine Threading
122 //
123 // Threads interacting with a runtime are divided into two categories:
124 //
125 // - The main thread is capable of running JS. There's at most one main thread
126 //   per runtime.
127 //
128 // - Helper threads do not run JS, and are controlled or triggered by activity
129 //   on the main thread (or main threads, since all runtimes in a process share
130 //   helper threads). Helper threads may have exclusive access to zones created
131 //   for them, for parsing and similar tasks, but their activities do not cause
132 //   observable changes in script behaviors. Activity on helper threads may be
133 //   referred to as happening 'off thread' or on a background thread in some
134 //   parts of the VM.
135 
136 } /* namespace js */
137 
138 namespace JS {
139 struct RuntimeSizes;
140 }  // namespace JS
141 
142 namespace js {
143 
144 /*
145  * Storage for well-known symbols. It's a separate struct from the Runtime so
146  * that it can be shared across multiple runtimes. As in JSAtomState, each
147  * field is a smart pointer that's immutable once initialized.
148  * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
149  *
150  * Well-known symbols are never GC'd. The description() of each well-known
151  * symbol is a permanent atom.
152  */
153 struct WellKnownSymbols {
154 #define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
JS_FOR_EACH_WELL_KNOWN_SYMBOLWellKnownSymbols155   JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
156 #undef DECLARE_SYMBOL
157 
158   const ImmutableSymbolPtr& get(size_t u) const {
159     MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
160     const ImmutableSymbolPtr* symbols =
161         reinterpret_cast<const ImmutableSymbolPtr*>(this);
162     return symbols[u];
163   }
164 
getWellKnownSymbols165   const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
166     return get(size_t(code));
167   }
168 
169   WellKnownSymbols() = default;
170   WellKnownSymbols(const WellKnownSymbols&) = delete;
171   WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
172 };
173 
174 // There are several coarse locks in the enum below. These may be either
175 // per-runtime or per-process. When acquiring more than one of these locks,
176 // the acquisition must be done in the order below to avoid deadlocks.
177 enum RuntimeLock { HelperThreadStateLock, GCLock };
178 
CanUseExtraThreads()179 inline bool CanUseExtraThreads() {
180   extern bool gCanUseExtraThreads;
181   return gCanUseExtraThreads;
182 }
183 
184 void DisableExtraThreads();
185 
186 using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
187 
188 class AutoLockScriptData;
189 
190 // Self-hosted lazy functions do not maintain a BaseScript as we can clone from
191 // the copy in the self-hosting zone. To allow these functions to be called by
192 // the JITs, we need a minimal script object. There is one instance per runtime.
193 struct SelfHostedLazyScript {
194   SelfHostedLazyScript() = default;
195 
196   // Pointer to interpreter trampoline. This field is stored at same location as
197   // in BaseScript::jitCodeRaw_.
198   uint8_t* jitCodeRaw_ = nullptr;
199 
200   // Warm-up count of zero. This field is stored at the same offset as
201   // BaseScript::warmUpData_.
202   ScriptWarmUpData warmUpData_ = {};
203 
offsetOfJitCodeRawSelfHostedLazyScript204   static constexpr size_t offsetOfJitCodeRaw() {
205     return offsetof(SelfHostedLazyScript, jitCodeRaw_);
206   }
offsetOfWarmUpDataSelfHostedLazyScript207   static constexpr size_t offsetOfWarmUpData() {
208     return offsetof(SelfHostedLazyScript, warmUpData_);
209   }
210 };
211 
212 }  // namespace js
213 
214 struct JSTelemetrySender;
215 
216 struct JSRuntime {
217  private:
218   friend class js::Activation;
219   friend class js::ActivationIterator;
220   friend class js::jit::JitActivation;
221   friend class js::jit::CompileRuntime;
222 
223   /* Space for interpreter frames. */
224   js::MainThreadData<js::InterpreterStack> interpreterStack_;
225 
226  public:
interpreterStackJSRuntime227   js::InterpreterStack& interpreterStack() { return interpreterStack_.ref(); }
228 
229   /*
230    * If non-null, another runtime guaranteed to outlive this one and whose
231    * permanent data may be used by this one where possible.
232    */
233   JSRuntime* const parentRuntime;
234 
isMainRuntimeJSRuntime235   bool isMainRuntime() const { return !parentRuntime; }
236 
237 #ifdef DEBUG
238   /* The number of child runtimes that have this runtime as their parent. */
239   mozilla::Atomic<size_t> childRuntimeCount;
240 
241   class AutoUpdateChildRuntimeCount {
242     JSRuntime* parent_;
243 
244    public:
AutoUpdateChildRuntimeCountJSRuntime245     explicit AutoUpdateChildRuntimeCount(JSRuntime* parent) : parent_(parent) {
246       if (parent_) {
247         parent_->childRuntimeCount++;
248       }
249     }
250 
~AutoUpdateChildRuntimeCountJSRuntime251     ~AutoUpdateChildRuntimeCount() {
252       if (parent_) {
253         parent_->childRuntimeCount--;
254       }
255     }
256   };
257 
258   AutoUpdateChildRuntimeCount updateChildRuntimeCount;
259 #endif
260 
261  private:
262 #ifdef DEBUG
263   js::WriteOnceData<bool> initialized_;
264 #endif
265 
266   // The JSContext* for the runtime's main thread. Immutable after this is set
267   // in JSRuntime::init.
268   JSContext* mainContext_;
269 
270  public:
mainContextFromAnyThreadJSRuntime271   JSContext* mainContextFromAnyThread() const { return mainContext_; }
addressOfMainContextJSRuntime272   const void* addressOfMainContext() { return &mainContext_; }
273   js::Fprinter parserWatcherFile;
274 
275   inline JSContext* mainContextFromOwnThread();
276 
277   /*
278    * The start of the range stored in the profiler sample buffer, as measured
279    * after the most recent sample.
280    * All JitcodeGlobalTable entries referenced from a given sample are
281    * assigned the buffer position of the START of the sample. The buffer
282    * entries that reference the JitcodeGlobalTable entries will only ever be
283    * read from the buffer while the entire sample is still inside the buffer;
284    * if some buffer entries at the start of the sample have left the buffer,
285    * the entire sample will be considered inaccessible.
286    * This means that, once profilerSampleBufferRangeStart_ advances beyond
287    * the sample position that's stored on a JitcodeGlobalTable entry, the
288    * buffer entries that reference this JitcodeGlobalTable entry will be
289    * considered inaccessible, and those JitcodeGlobalTable entry can be
290    * disposed of.
291    */
292   mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire>
293       profilerSampleBufferRangeStart_;
294 
profilerSampleBufferRangeStartJSRuntime295   mozilla::Maybe<uint64_t> profilerSampleBufferRangeStart() {
296     if (beingDestroyed_ || !geckoProfiler().enabled()) {
297       return mozilla::Nothing();
298     }
299     uint64_t rangeStart = profilerSampleBufferRangeStart_;
300     return mozilla::Some(rangeStart);
301   }
setProfilerSampleBufferRangeStartJSRuntime302   void setProfilerSampleBufferRangeStart(uint64_t rangeStart) {
303     profilerSampleBufferRangeStart_ = rangeStart;
304   }
305 
306   /* Call this to accumulate telemetry data. May be called from any thread; the
307    * embedder is responsible for locking. */
308   JSAccumulateTelemetryDataCallback telemetryCallback;
309 
310   /* Call this to accumulate use counter data. */
311   js::MainThreadData<JSSetUseCounterCallback> useCounterCallback;
312 
313   js::MainThreadData<JSSourceElementCallback> sourceElementCallback;
314 
315  public:
316   // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
317   // histogram. |key| provides an additional key to identify the histogram.
318   // |sample| is the data to add to the histogram.
319   void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
320 
321   JSTelemetrySender getTelemetrySender() const;
322 
323   void setTelemetryCallback(JSRuntime* rt,
324                             JSAccumulateTelemetryDataCallback callback);
325 
326   void setSourceElementCallback(JSRuntime* rt,
327                                 JSSourceElementCallback callback);
328 
329   // Sets the use counter for a specific feature, measuring the presence or
330   // absence of usage of a feature on a specific web page and document which
331   // the passed JSObject belongs to.
332   void setUseCounter(JSObject* obj, JSUseCounter counter);
333 
334   void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
335 
336  public:
337   js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;
338   js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback;
339   js::UnprotectedData<JS::ReportStreamErrorCallback> reportStreamErrorCallback;
340 
341   js::GlobalObject* getIncumbentGlobal(JSContext* cx);
342   bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job,
343                          js::HandleObject promise,
344                          js::Handle<js::GlobalObject*> incumbentGlobal);
345   void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
346   void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
347 
348   /* Had an out-of-memory error which did not populate an exception. */
349   mozilla::Atomic<bool, mozilla::SequentiallyConsistent> hadOutOfMemory;
350 
351   /*
352    * Allow relazifying functions in compartments that are active. This is
353    * only used by the relazifyFunctions() testing function.
354    */
355   js::MainThreadData<bool> allowRelazificationForTesting;
356 
357   /* Zone destroy callback. */
358   js::MainThreadData<JSDestroyZoneCallback> destroyZoneCallback;
359 
360   /* Compartment destroy callback. */
361   js::MainThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
362 
363   /* Compartment memory reporting callback. */
364   js::MainThreadData<JSSizeOfIncludingThisCompartmentCallback>
365       sizeOfIncludingThisCompartmentCallback;
366 
367   /* Callback for creating ubi::Nodes representing DOM node objects. Set by
368    * JS::ubi::SetConstructUbiNodeForDOMObjectCallback. Refer to
369    * js/public/UbiNode.h.
370    */
371   void (*constructUbiNodeForDOMObjectCallback)(void*, JSObject*) = nullptr;
372 
373   /* Realm destroy callback. */
374   js::MainThreadData<JS::DestroyRealmCallback> destroyRealmCallback;
375 
376   /* Call this to get the name of a realm. */
377   js::MainThreadData<JS::RealmNameCallback> realmNameCallback;
378 
379   js::MainThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
380 
381   js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks;
382   js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks;
383   js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
384   js::MainThreadData<JSReadPrincipalsOp> readPrincipals;
385 
386   /* Optional warning reporter. */
387   js::MainThreadData<JS::WarningReporter> warningReporter;
388 
389   // Lazy self-hosted functions use a shared SelfHostedLazyScript instance
390   // instead instead of a BaseScript. This contains the minimal pointers to
391   // trampolines for the scripts to support direct jitCodeRaw calls.
392   js::UnprotectedData<js::SelfHostedLazyScript> selfHostedLazyScript;
393 
394  private:
395   /* Gecko profiling metadata */
396   js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_;
397 
398  public:
geckoProfilerJSRuntime399   js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
400 
401   // Heap GC roots for PersistentRooted pointers.
402   js::MainThreadData<mozilla::EnumeratedArray<
403       JS::RootKind, JS::RootKind::Limit,
404       mozilla::LinkedList<JS::PersistentRooted<JS::detail::RootListEntry*>>>>
405       heapRoots;
406 
407   void tracePersistentRoots(JSTracer* trc);
408   void finishPersistentRoots();
409 
410   void finishRoots();
411 
412  private:
413   js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
414 
415  public:
setTrustedPrincipalsJSRuntime416   void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
trustedPrincipalsJSRuntime417   const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
418 
419   js::MainThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
420   js::MainThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
421   js::MainThreadData<js::HasReleasedWrapperCallback> hasReleasedWrapperCallback;
422 
423   js::MainThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
424 
425   js::MainThreadData<JS::CTypesActivityCallback> ctypesActivityCallback;
426 
427  private:
428   js::WriteOnceData<const JSClass*> windowProxyClass_;
429 
430  public:
maybeWindowProxyClassJSRuntime431   const JSClass* maybeWindowProxyClass() const { return windowProxyClass_; }
setWindowProxyClassJSRuntime432   void setWindowProxyClass(const JSClass* clasp) { windowProxyClass_ = clasp; }
433 
434  private:
435   js::WriteOnceData<const JSClass*> abortSignalClass_;
436   js::WriteOnceData<JS::AbortSignalIsAborted> abortSignalIsAborted_;
437 
438  public:
initPipeToHandlingJSRuntime439   void initPipeToHandling(const JSClass* abortSignalClass,
440                           JS::AbortSignalIsAborted isAborted) {
441     MOZ_ASSERT(abortSignalClass != nullptr,
442                "doesn't make sense for an embedder to provide a null class "
443                "when specifying pipeTo handling");
444     MOZ_ASSERT(isAborted != nullptr, "must pass a valid function pointer");
445 
446     abortSignalClass_ = abortSignalClass;
447     abortSignalIsAborted_ = isAborted;
448   }
449 
maybeAbortSignalClassJSRuntime450   const JSClass* maybeAbortSignalClass() const { return abortSignalClass_; }
451 
abortSignalIsAbortedJSRuntime452   bool abortSignalIsAborted(JSObject* obj) {
453     MOZ_ASSERT(abortSignalIsAborted_ != nullptr,
454                "must call initPipeToHandling first");
455     return abortSignalIsAborted_(obj);
456   }
457 
458  private:
459   // List of non-ephemeron weak containers to sweep during
460   // beginSweepingSweepGroup.
461   js::MainThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>>
462       weakCaches_;
463 
464  public:
weakCachesJSRuntime465   mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() {
466     return weakCaches_.ref();
467   }
registerWeakCacheJSRuntime468   void registerWeakCache(JS::detail::WeakCacheBase* cachep) {
469     weakCaches().insertBack(cachep);
470   }
471 
472   template <typename T>
473   struct GlobalObjectWatchersLinkAccess {
GetJSRuntime::GlobalObjectWatchersLinkAccess474     static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
475       return aThis->onNewGlobalObjectWatchersLink;
476     }
477   };
478 
479   template <typename T>
480   struct GarbageCollectionWatchersLinkAccess {
GetJSRuntime::GarbageCollectionWatchersLinkAccess481     static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
482       return aThis->onGarbageCollectionWatchersLink;
483     }
484   };
485 
486   using OnNewGlobalWatchersList =
487       mozilla::DoublyLinkedList<js::Debugger,
488                                 GlobalObjectWatchersLinkAccess<js::Debugger>>;
489   using OnGarbageCollectionWatchersList = mozilla::DoublyLinkedList<
490       js::Debugger, GarbageCollectionWatchersLinkAccess<js::Debugger>>;
491 
492  private:
493   /*
494    * List of all enabled Debuggers that have onNewGlobalObject handler
495    * methods established.
496    */
497   js::MainThreadData<OnNewGlobalWatchersList> onNewGlobalObjectWatchers_;
498 
499   /*
500    * List of all enabled Debuggers that have onGarbageCollection handler
501    * methods established.
502    */
503   js::MainThreadData<OnGarbageCollectionWatchersList>
504       onGarbageCollectionWatchers_;
505 
506  public:
onNewGlobalObjectWatchersJSRuntime507   OnNewGlobalWatchersList& onNewGlobalObjectWatchers() {
508     return onNewGlobalObjectWatchers_.ref();
509   }
510 
onGarbageCollectionWatchersJSRuntime511   OnGarbageCollectionWatchersList& onGarbageCollectionWatchers() {
512     return onGarbageCollectionWatchers_.ref();
513   }
514 
515  private:
516   /* Linked list of all Debugger objects in the runtime. */
517   js::MainThreadData<mozilla::LinkedList<js::Debugger>> debuggerList_;
518 
519  public:
debuggerListJSRuntime520   mozilla::LinkedList<js::Debugger>& debuggerList() {
521     return debuggerList_.ref();
522   }
523 
524  private:
525   /*
526    * Lock used to protect the script data table, which can be used by
527    * off-thread parsing.
528    *
529    * Locking this only occurs if there is actually a thread other than the
530    * main thread which could access this.
531    */
532   js::Mutex scriptDataLock;
533 #ifdef DEBUG
534   bool activeThreadHasScriptDataAccess;
535 #endif
536 
537   // Number of off-thread ParseTasks that are using this runtime. This is only
538   // updated on main-thread. If this is non-zero we must use `scriptDataLock` to
539   // protect access to the bytecode table;
540   mozilla::Atomic<size_t, mozilla::SequentiallyConsistent> numParseTasks;
541 
542   // Number of zones which may be operated on by helper threads.
543   mozilla::Atomic<size_t, mozilla::SequentiallyConsistent>
544       numActiveHelperThreadZones;
545 
546   friend class js::AutoLockScriptData;
547 
548  public:
549   void setUsedByHelperThread(JS::Zone* zone);
550   void clearUsedByHelperThread(JS::Zone* zone);
551 
hasParseTasksJSRuntime552   bool hasParseTasks() const { return numParseTasks > 0; }
hasHelperThreadZonesJSRuntime553   bool hasHelperThreadZones() const { return numActiveHelperThreadZones > 0; }
554 
addParseTaskRefJSRuntime555   void addParseTaskRef() { numParseTasks++; }
decParseTaskRefJSRuntime556   void decParseTaskRef() { numParseTasks--; }
557 
558 #ifdef DEBUG
assertCurrentThreadHasScriptDataAccessJSRuntime559   void assertCurrentThreadHasScriptDataAccess() const {
560     if (!hasParseTasks()) {
561       MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(this) &&
562                  activeThreadHasScriptDataAccess);
563       return;
564     }
565 
566     scriptDataLock.assertOwnedByCurrentThread();
567   }
568 
currentThreadHasAtomsTableAccessJSRuntime569   bool currentThreadHasAtomsTableAccess() const {
570     return js::CurrentThreadCanAccessRuntime(this) &&
571            atoms_->mainThreadHasAllLocks();
572   }
573 #endif
574 
heapStateJSRuntime575   JS::HeapState heapState() const { return gc.heapState(); }
576 
577   // How many realms there are across all zones. This number includes
578   // off-thread context realms, so it isn't necessarily equal to the
579   // number of realms visited by RealmsIter.
580   js::MainThreadData<size_t> numRealms;
581 
582   // The Gecko Profiler may want to sample the allocations happening across the
583   // browser. This callback can be registered to record the allocation.
584   js::MainThreadData<JS::RecordAllocationsCallback> recordAllocationCallback;
585   js::MainThreadData<double> allocationSamplingProbability;
586 
587  private:
588   // Number of debuggee realms in the runtime.
589   js::MainThreadData<size_t> numDebuggeeRealms_;
590 
591   // Number of debuggee realms in the runtime observing code coverage.
592   js::MainThreadData<size_t> numDebuggeeRealmsObservingCoverage_;
593 
594  public:
595   void incrementNumDebuggeeRealms();
596   void decrementNumDebuggeeRealms();
597 
numDebuggeeRealmsJSRuntime598   size_t numDebuggeeRealms() const { return numDebuggeeRealms_; }
599 
600   void incrementNumDebuggeeRealmsObservingCoverage();
601   void decrementNumDebuggeeRealmsObservingCoverage();
602 
603   void startRecordingAllocations(double probability,
604                                  JS::RecordAllocationsCallback callback);
605   void stopRecordingAllocations();
606   void ensureRealmIsRecordingAllocations(JS::Handle<js::GlobalObject*> global);
607 
608   /* Locale-specific callbacks for string conversion. */
609   js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks;
610 
611   /* Default locale for Internationalization API */
612   js::MainThreadData<js::UniqueChars> defaultLocale;
613 
614   /* If true, new scripts must be created with PC counter information. */
615   js::MainThreadOrIonCompileData<bool> profilingScripts;
616 
617   /* Strong references on scripts held for PCCount profiling API. */
618   js::MainThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*>
619       scriptAndCountsVector;
620 
621  private:
622   /* Code coverage output. */
623   js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
624 
625  public:
lcovOutputJSRuntime626   js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
627 
628  private:
629   js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
630 
631   /*
632    * Self-hosting state cloned on demand into other compartments. Shared with
633    * the parent runtime if there is one.
634    */
635   js::WriteOnceData<js::NativeObject*> selfHostingGlobal_;
636 
637   static js::GlobalObject* createSelfHostingGlobal(JSContext* cx);
638 
639  public:
640   void getUnclonedSelfHostedValue(js::PropertyName* name, JS::Value* vp);
641   JSFunction* getUnclonedSelfHostedFunction(js::PropertyName* name);
642 
643   [[nodiscard]] bool createJitRuntime(JSContext* cx);
jitRuntimeJSRuntime644   js::jit::JitRuntime* jitRuntime() const { return jitRuntime_.ref(); }
hasJitRuntimeJSRuntime645   bool hasJitRuntime() const { return !!jitRuntime_; }
646 
647  private:
648   // Used to generate random keys for hash tables.
649   mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
650   mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
651 
652   // Used to generate random hash codes for symbols.
653   mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG>
654       randomHashCodeGenerator_;
655 
656  public:
657   mozilla::HashCodeScrambler randomHashCodeScrambler();
658   mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
659 
660   js::HashNumber randomHashCode();
661 
662   //-------------------------------------------------------------------------
663   // Self-hosting support
664   //-------------------------------------------------------------------------
665 
hasInitializedSelfHostingJSRuntime666   bool hasInitializedSelfHosting() const { return selfHostingGlobal_; }
667 
668   bool initSelfHosting(JSContext* cx, JS::SelfHostedCache xdrCache = nullptr,
669                        JS::SelfHostedWriter xdrWriter = nullptr);
670   void finishSelfHosting();
671   void traceSelfHostingGlobal(JSTracer* trc);
isSelfHostingGlobalJSRuntime672   bool isSelfHostingGlobal(JSObject* global) {
673     return global == selfHostingGlobal_;
674   }
675   js::GeneratorKind getSelfHostedFunctionGeneratorKind(JSAtom* name);
676   bool createLazySelfHostedFunctionClone(JSContext* cx,
677                                          js::HandlePropertyName selfHostedName,
678                                          js::HandleAtom name, unsigned nargs,
679                                          js::NewObjectKind newKind,
680                                          js::MutableHandleFunction fun);
681   bool cloneSelfHostedFunctionScript(JSContext* cx,
682                                      js::Handle<js::PropertyName*> name,
683                                      js::Handle<JSFunction*> targetFun);
684   bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
685                             js::MutableHandleValue vp);
686   void assertSelfHostedFunctionHasCanonicalName(JSContext* cx,
687                                                 js::HandlePropertyName name);
688 #if DEBUG
isSelfHostingZoneJSRuntime689   bool isSelfHostingZone(const JS::Zone* zone) const {
690     return selfHostingGlobal_ && selfHostingGlobal_->zone() == zone;
691   }
692 #endif
693 
694   //-------------------------------------------------------------------------
695   // Locale information
696   //-------------------------------------------------------------------------
697 
698   /*
699    * Set the default locale for the ECMAScript Internationalization API
700    * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
701    * Note that the Internationalization API encourages clients to
702    * specify their own locales.
703    * The locale string remains owned by the caller.
704    */
705   bool setDefaultLocale(const char* locale);
706 
707   /* Reset the default locale to OS defaults. */
708   void resetDefaultLocale();
709 
710   /* Gets current default locale. String remains owned by context. */
711   const char* getDefaultLocale();
712 
713   /* Garbage collector state. */
714   js::gc::GCRuntime gc;
715 
716   /* Garbage collector state has been successfully initialized. */
717   js::WriteOnceData<bool> gcInitialized;
718 
hasZealModeJSRuntime719   bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
720 
lockGCJSRuntime721   void lockGC() { gc.lockGC(); }
722 
unlockGCJSRuntime723   void unlockGC() { gc.unlockGC(); }
724 
725   js::WriteOnceData<js::PropertyName*> emptyString;
726 
727  private:
728   js::MainThreadOrGCTaskData<JSFreeOp*> defaultFreeOp_;
729 
730  public:
defaultFreeOpJSRuntime731   JSFreeOp* defaultFreeOp() {
732     MOZ_ASSERT(defaultFreeOp_);
733     return defaultFreeOp_;
734   }
735 
736 #if !JS_HAS_INTL_API
737   /* Number localization, used by jsnum.cpp. */
738   js::WriteOnceData<const char*> thousandsSeparator;
739   js::WriteOnceData<const char*> decimalSeparator;
740   js::WriteOnceData<const char*> numGrouping;
741 #endif
742 
743  private:
744   mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
745 
746  public:
747   // If this particular JSRuntime has a SharedImmutableStringsCache, return a
748   // pointer to it, otherwise return nullptr.
maybeThisRuntimeSharedImmutableStringsJSRuntime749   js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
750     return sharedImmutableStrings_.isSome() ? &*sharedImmutableStrings_
751                                             : nullptr;
752   }
753 
754   // Get a reference to this JSRuntime's or its parent's
755   // SharedImmutableStringsCache.
sharedImmutableStringsJSRuntime756   js::SharedImmutableStringsCache& sharedImmutableStrings() {
757     MOZ_ASSERT_IF(parentRuntime, !sharedImmutableStrings_);
758     MOZ_ASSERT_IF(!parentRuntime, sharedImmutableStrings_);
759     return parentRuntime ? parentRuntime->sharedImmutableStrings()
760                          : *sharedImmutableStrings_;
761   }
762 
763  private:
764   js::WriteOnceData<bool> beingDestroyed_;
765 
766  public:
isBeingDestroyedJSRuntime767   bool isBeingDestroyed() const { return beingDestroyed_; }
768 
769  private:
770   bool allowContentJS_;
771 
772  public:
allowContentJSJSRuntime773   bool allowContentJS() const { return allowContentJS_; }
774 
775   friend class js::AutoAssertNoContentJS;
776 
777  private:
778   // Table of all atoms other than those in permanentAtoms and staticStrings.
779   js::WriteOnceData<js::AtomsTable*> atoms_;
780 
781   // Set of all live symbols produced by Symbol.for(). All such symbols are
782   // allocated in the atoms zone. Reading or writing the symbol registry
783   // can only be done from the main thread.
784   js::MainThreadOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
785 
786   js::WriteOnceData<js::AtomSet*> permanentAtomsDuringInit_;
787   js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms_;
788 
789  public:
790   bool initializeAtoms(JSContext* cx);
791   bool initializeParserAtoms(JSContext* cx);
792   void finishAtoms();
793   void finishParserAtoms();
atomsAreFinishedJSRuntime794   bool atomsAreFinished() const {
795     return !atoms_ && !permanentAtomsDuringInit_;
796   }
797 
atomsForSweepingJSRuntime798   js::AtomsTable* atomsForSweeping() {
799     MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
800     return atoms_;
801   }
802 
atomsJSRuntime803   js::AtomsTable& atoms() {
804     MOZ_ASSERT(atoms_);
805     return *atoms_;
806   }
807 
atomsZoneJSRuntime808   const JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) const {
809     return gc.atomsZone;
810   }
atomsZoneJSRuntime811   JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) {
812     return gc.atomsZone;
813   }
unsafeAtomsZoneJSRuntime814   JS::Zone* unsafeAtomsZone() { return gc.atomsZone; }
815 
816 #ifdef DEBUG
isAtomsZoneJSRuntime817   bool isAtomsZone(const JS::Zone* zone) const { return zone == gc.atomsZone; }
818 #endif
819 
820   bool activeGCInAtomsZone();
821 
symbolRegistryJSRuntime822   js::SymbolRegistry& symbolRegistry() { return symbolRegistry_.ref(); }
823 
824   // Permanent atoms are fixed during initialization of the runtime and are
825   // not modified or collected until the runtime is destroyed. These may be
826   // shared with another, longer living runtime through |parentRuntime| and
827   // can be freely accessed with no locking necessary.
828 
829   // Permanent atoms pre-allocated for general use.
830   js::WriteOnceData<js::StaticStrings*> staticStrings;
831 
832   // Cached pointers to various permanent property names.
833   js::WriteOnceData<JSAtomState*> commonNames;
834   js::WriteOnceData<js::frontend::WellKnownParserAtoms*> commonParserNames;
835 
836   // All permanent atoms in the runtime, other than those in staticStrings.
837   // Access to this does not require a lock because it is frozen and thus
838   // read-only.
permanentAtomsJSRuntime839   const js::FrozenAtomSet* permanentAtoms() const {
840     MOZ_ASSERT(permanentAtomsPopulated());
841     return permanentAtoms_.ref();
842   }
843 
844   // The permanent atoms table is populated during initialization.
permanentAtomsPopulatedJSRuntime845   bool permanentAtomsPopulated() const { return permanentAtoms_; }
846 
847   // For internal use, return the permanent atoms table while it is being
848   // populated.
permanentAtomsDuringInitJSRuntime849   js::AtomSet* permanentAtomsDuringInit() const {
850     MOZ_ASSERT(!permanentAtoms_);
851     return permanentAtomsDuringInit_.ref();
852   }
853 
854   bool initMainAtomsTables(JSContext* cx);
855   void tracePermanentAtoms(JSTracer* trc);
856 
857   // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
858   // these are shared with the parentRuntime, if any.
859   js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
860 
861 #ifdef JS_HAS_INTL_API
862   /* Shared Intl data for this runtime. */
863   js::MainThreadData<js::intl::SharedIntlData> sharedIntlData;
864 
865   void traceSharedIntlData(JSTracer* trc);
866 #endif
867 
868   // Table of bytecode and other data that may be shared across scripts
869   // within the runtime. This may be modified by threads using
870   // AutoLockScriptData.
871  private:
872   js::ScriptDataLockData<js::SharedImmutableScriptDataTable> scriptDataTable_;
873 
874  public:
scriptDataTableJSRuntime875   js::SharedImmutableScriptDataTable& scriptDataTable(
876       const js::AutoLockScriptData& lock) {
877     return scriptDataTable_.ref();
878   }
879 
880  private:
881   static mozilla::Atomic<size_t> liveRuntimesCount;
882 
883  public:
hasLiveRuntimesJSRuntime884   static bool hasLiveRuntimes() { return liveRuntimesCount > 0; }
885 
886   explicit JSRuntime(JSRuntime* parentRuntime);
887   ~JSRuntime();
888 
889   // destroyRuntime is used instead of a destructor, to ensure the downcast
890   // to JSContext remains valid. The final GC triggered here depends on this.
891   void destroyRuntime();
892 
893   bool init(JSContext* cx, uint32_t maxbytes);
894 
thisFromCtorJSRuntime895   JSRuntime* thisFromCtor() { return this; }
896 
897  private:
898   // Number of live SharedArrayBuffer objects, including those in Wasm shared
899   // memories.  uint64_t to avoid any risk of overflow.
900   js::MainThreadData<uint64_t> liveSABs;
901 
902  public:
incSABCountJSRuntime903   void incSABCount() {
904     MOZ_RELEASE_ASSERT(liveSABs != UINT64_MAX);
905     liveSABs++;
906   }
907 
decSABCountJSRuntime908   void decSABCount() {
909     MOZ_RELEASE_ASSERT(liveSABs > 0);
910     liveSABs--;
911   }
912 
hasLiveSABsJSRuntime913   bool hasLiveSABs() const { return liveSABs > 0; }
914 
915  public:
916   js::MainThreadData<JS::BeforeWaitCallback> beforeWaitCallback;
917   js::MainThreadData<JS::AfterWaitCallback> afterWaitCallback;
918 
919  public:
reportAllocationOverflowJSRuntime920   void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
921 
922   /*
923    * This should be called after system malloc/calloc/realloc returns nullptr
924    * to try to recove some memory or to report an error.  For realloc, the
925    * original pointer must be passed as reallocPtr.
926    *
927    * The function must be called outside the GC lock.
928    */
929   JS_PUBLIC_API void* onOutOfMemory(js::AllocFunction allocator,
930                                     arena_id_t arena, size_t nbytes,
931                                     void* reallocPtr = nullptr,
932                                     JSContext* maybecx = nullptr);
933 
934   /*  onOutOfMemory but can call OnLargeAllocationFailure. */
935   JS_PUBLIC_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
936                                          arena_id_t arena, size_t nbytes,
937                                          void* reallocPtr = nullptr);
938 
939   static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
940 
941   void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
942                               JS::RuntimeSizes* rtSizes);
943 
944  private:
945   // Settings for how helper threads can be used.
946   mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
947       offthreadIonCompilationEnabled_;
948   mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
949       parallelParsingEnabled_;
950 
951 #ifdef DEBUG
952   mozilla::Atomic<uint32_t> offThreadParsesRunning_;
953   mozilla::Atomic<bool> offThreadParsingBlocked_;
954 #endif
955 
956   js::MainThreadData<bool> autoWritableJitCodeActive_;
957 
958  public:
959   // Note: these values may be toggled dynamically (in response to about:config
960   // prefs changing).
setOffthreadIonCompilationEnabledJSRuntime961   void setOffthreadIonCompilationEnabled(bool value) {
962     offthreadIonCompilationEnabled_ = value;
963   }
canUseOffthreadIonCompilationJSRuntime964   bool canUseOffthreadIonCompilation() const {
965     return offthreadIonCompilationEnabled_;
966   }
setParallelParsingEnabledJSRuntime967   void setParallelParsingEnabled(bool value) {
968     parallelParsingEnabled_ = value;
969   }
canUseParallelParsingJSRuntime970   bool canUseParallelParsing() const { return parallelParsingEnabled_; }
971 
972 #ifdef DEBUG
973 
incOffThreadParsesRunningJSRuntime974   void incOffThreadParsesRunning() {
975     MOZ_ASSERT(!isOffThreadParsingBlocked());
976     offThreadParsesRunning_++;
977   }
978 
decOffThreadParsesRunningJSRuntime979   void decOffThreadParsesRunning() {
980     MOZ_ASSERT(isOffThreadParseRunning());
981     offThreadParsesRunning_--;
982   }
983 
isOffThreadParseRunningJSRuntime984   bool isOffThreadParseRunning() const { return offThreadParsesRunning_; }
985 
isOffThreadParsingBlockedJSRuntime986   bool isOffThreadParsingBlocked() const { return offThreadParsingBlocked_; }
setOffThreadParsingBlockedJSRuntime987   void setOffThreadParsingBlocked(bool blocked) {
988     MOZ_ASSERT(offThreadParsingBlocked_ != blocked);
989     MOZ_ASSERT(!isOffThreadParseRunning());
990     offThreadParsingBlocked_ = blocked;
991   }
992 
993 #endif
994 
toggleAutoWritableJitCodeActiveJSRuntime995   void toggleAutoWritableJitCodeActive(bool b) {
996     MOZ_ASSERT(autoWritableJitCodeActive_ != b,
997                "AutoWritableJitCode should not be nested.");
998     autoWritableJitCodeActive_ = b;
999   }
1000 
1001   /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
1002   js::MainThreadData<JS::OutOfMemoryCallback> oomCallback;
1003   js::MainThreadData<void*> oomCallbackData;
1004 
1005   /*
1006    * Debugger.Memory functions like takeCensus use this embedding-provided
1007    * function to assess the size of malloc'd blocks of memory.
1008    */
1009   js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
1010 
1011   /* Last time at which an animation was played for this runtime. */
1012   js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
1013 
1014  private:
1015   /* The stack format for the current runtime.  Only valid on non-child
1016    * runtimes. */
1017   mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
1018 
1019  public:
stackFormatJSRuntime1020   js::StackFormat stackFormat() const {
1021     const JSRuntime* rt = this;
1022     while (rt->parentRuntime) {
1023       MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
1024       rt = rt->parentRuntime;
1025     }
1026     MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
1027     return rt->stackFormat_;
1028   }
setStackFormatJSRuntime1029   void setStackFormat(js::StackFormat format) {
1030     MOZ_ASSERT(!parentRuntime);
1031     MOZ_ASSERT(format != js::StackFormat::Default);
1032     stackFormat_ = format;
1033   }
1034 
1035  private:
1036   js::MainThreadData<js::RuntimeCaches> caches_;
1037 
1038  public:
cachesJSRuntime1039   js::RuntimeCaches& caches() { return caches_.ref(); }
1040 
1041   // List of all the live wasm::Instances in the runtime. Equal to the union
1042   // of all instances registered in all JS::Realms. Accessed from watchdog
1043   // threads for purposes of wasm::InterruptRunningCode().
1044   js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
1045 
1046   // The implementation-defined abstract operation HostResolveImportedModule.
1047   js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
1048 
1049   // A hook that implements the abstract operations
1050   // HostGetImportMetaProperties and HostFinalizeImportMeta.
1051   js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
1052 
1053   // A hook that implements the abstract operation
1054   // HostImportModuleDynamically. This is also used to enable/disable dynamic
1055   // module import and can accessed by off-thread parsing.
1056   mozilla::Atomic<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
1057 
1058   // Hooks called when script private references are created and destroyed.
1059   js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook;
1060   js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook;
1061 
addRefScriptPrivateJSRuntime1062   void addRefScriptPrivate(const JS::Value& value) {
1063     if (!value.isUndefined() && scriptPrivateAddRefHook) {
1064       scriptPrivateAddRefHook(value);
1065     }
1066   }
1067 
releaseScriptPrivateJSRuntime1068   void releaseScriptPrivate(const JS::Value& value) {
1069     if (!value.isUndefined() && scriptPrivateReleaseHook) {
1070       scriptPrivateReleaseHook(value);
1071     }
1072   }
1073 
1074  public:
1075 #if defined(NIGHTLY_BUILD)
1076   // Support for informing the embedding of any error thrown.
1077   // This mechanism is designed to let the embedding
1078   // log/report/fail in case certain errors are thrown
1079   // (e.g. SyntaxError, ReferenceError or TypeError
1080   // in critical code).
1081   struct ErrorInterceptionSupport {
ErrorInterceptionSupportJSRuntime::ErrorInterceptionSupport1082     ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {}
1083 
1084     // true if the error interceptor is currently executing,
1085     // false otherwise. Used to avoid infinite loops.
1086     bool isExecuting;
1087 
1088     // if non-null, any call to `setPendingException`
1089     // in this runtime will trigger the call to `interceptor`
1090     JSErrorInterceptor* interceptor;
1091   };
1092   ErrorInterceptionSupport errorInterception;
1093 #endif  // defined(NIGHTLY_BUILD)
1094 };
1095 
1096 // Context for sending telemetry to the embedder from any thread, main or
1097 // helper.  Obtain a |JSTelemetrySender| by calling |getTelemetrySender()| on
1098 // the |JSRuntime|.
1099 struct JSTelemetrySender {
1100  private:
1101   friend struct JSRuntime;
1102 
1103   JSAccumulateTelemetryDataCallback callback_;
1104 
JSTelemetrySenderJSTelemetrySender1105   explicit JSTelemetrySender(JSAccumulateTelemetryDataCallback callback)
1106       : callback_(callback) {}
1107 
1108  public:
JSTelemetrySenderJSTelemetrySender1109   JSTelemetrySender() : callback_(nullptr) {}
1110   JSTelemetrySender(const JSTelemetrySender& other) = default;
JSTelemetrySenderJSTelemetrySender1111   explicit JSTelemetrySender(JSRuntime* runtime)
1112       : JSTelemetrySender(runtime->getTelemetrySender()) {}
1113 
1114   // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
1115   // histogram. |key| provides an additional key to identify the histogram.
1116   // |sample| is the data to add to the histogram.
1117   void addTelemetry(int id, uint32_t sample, const char* key = nullptr) {
1118     if (callback_) {
1119       callback_(id, sample, key);
1120     }
1121   }
1122 };
1123 
1124 namespace js {
1125 
MakeRangeGCSafe(Value * vec,size_t len)1126 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* vec, size_t len) {
1127   // Don't PodZero here because JS::Value is non-trivial.
1128   for (size_t i = 0; i < len; i++) {
1129     vec[i].setDouble(+0.0);
1130   }
1131 }
1132 
MakeRangeGCSafe(Value * beg,Value * end)1133 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* beg, Value* end) {
1134   MakeRangeGCSafe(beg, end - beg);
1135 }
1136 
MakeRangeGCSafe(jsid * beg,jsid * end)1137 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* beg, jsid* end) {
1138   std::fill(beg, end, INT_TO_JSID(0));
1139 }
1140 
MakeRangeGCSafe(jsid * vec,size_t len)1141 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* vec, size_t len) {
1142   MakeRangeGCSafe(vec, vec + len);
1143 }
1144 
MakeRangeGCSafe(Shape ** beg,Shape ** end)1145 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** beg, Shape** end) {
1146   std::fill(beg, end, nullptr);
1147 }
1148 
MakeRangeGCSafe(Shape ** vec,size_t len)1149 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** vec, size_t len) {
1150   MakeRangeGCSafe(vec, vec + len);
1151 }
1152 
SetValueRangeToUndefined(Value * beg,Value * end)1153 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* beg, Value* end) {
1154   for (Value* v = beg; v != end; ++v) {
1155     v->setUndefined();
1156   }
1157 }
1158 
SetValueRangeToUndefined(Value * vec,size_t len)1159 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* vec, size_t len) {
1160   SetValueRangeToUndefined(vec, vec + len);
1161 }
1162 
SetValueRangeToNull(Value * beg,Value * end)1163 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* beg, Value* end) {
1164   for (Value* v = beg; v != end; ++v) {
1165     v->setNull();
1166   }
1167 }
1168 
SetValueRangeToNull(Value * vec,size_t len)1169 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* vec, size_t len) {
1170   SetValueRangeToNull(vec, vec + len);
1171 }
1172 
1173 extern const JSSecurityCallbacks NullSecurityCallbacks;
1174 
1175 // This callback is set by JS::SetProcessLargeAllocationFailureCallback
1176 // and may be null. See comment in jsapi.h.
1177 extern mozilla::Atomic<JS::LargeAllocationFailureCallback>
1178     OnLargeAllocationFailure;
1179 
1180 // This callback is set by JS::SetBuildIdOp and may be null. See comment in
1181 // jsapi.h.
1182 extern mozilla::Atomic<JS::BuildIdOp> GetBuildId;
1183 
1184 extern JS::FilenameValidationCallback gFilenameValidationCallback;
1185 
1186 } /* namespace js */
1187 
1188 #endif /* vm_Runtime_h */
1189