Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / js / src / vm / Runtime.h
blob934a534185a8cf39f6b1ba680ad129faa3528d65
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/. */
7 #ifndef vm_Runtime_h
8 #define vm_Runtime_h
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/MemoryReporting.h"
17 #include "mozilla/TimeStamp.h"
18 #include "mozilla/XorShift128PlusRNG.h"
20 #include <algorithm>
21 #include <utility>
23 #ifdef JS_HAS_INTL_API
24 # include "builtin/intl/SharedIntlData.h"
25 #endif
26 #include "frontend/ScriptIndex.h"
27 #include "gc/GCRuntime.h"
28 #include "js/AllocationRecording.h"
29 #include "js/BuildId.h" // JS::BuildIdOp
30 #include "js/Context.h"
31 #include "js/experimental/CTypes.h" // JS::CTypesActivityCallback
32 #include "js/friend/StackLimits.h" // js::ReportOverRecursed
33 #include "js/friend/UsageStatistics.h" // JSAccumulateTelemetryDataCallback
34 #include "js/GCVector.h"
35 #include "js/HashTable.h"
36 #include "js/Initialization.h"
37 #include "js/MemoryCallbacks.h"
38 #include "js/Modules.h" // JS::Module{DynamicImport,Metadata,Resolve}Hook
39 #include "js/ScriptPrivate.h"
40 #include "js/shadow/Zone.h"
41 #include "js/ShadowRealmCallbacks.h"
42 #include "js/Stack.h"
43 #include "js/StreamConsumer.h"
44 #include "js/Symbol.h"
45 #include "js/UniquePtr.h"
46 #include "js/Utility.h"
47 #include "js/WaitCallbacks.h"
48 #include "js/Warnings.h" // JS::WarningReporter
49 #include "js/Zone.h"
50 #include "vm/Caches.h" // js::RuntimeCaches
51 #include "vm/CodeCoverage.h"
52 #include "vm/GeckoProfiler.h"
53 #include "vm/InvalidatingFuse.h"
54 #include "vm/JSScript.h"
55 #include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseRuntimeState
56 #include "vm/SharedScriptDataTableHolder.h" // js::SharedScriptDataTableHolder
57 #include "vm/Stack.h"
58 #include "wasm/WasmTypeDecls.h"
60 struct JSAtomState;
61 struct JSClass;
62 struct JSErrorInterceptor;
63 struct JSWrapObjectCallbacks;
65 namespace js {
67 class AutoAssertNoContentJS;
68 class Debugger;
69 class EnterDebuggeeNoExecute;
70 class FrontendContext;
71 class PlainObject;
72 class StaticStrings;
74 } // namespace js
76 struct DtoaState;
77 struct JSLocaleCallbacks;
79 #ifdef JS_SIMULATOR_ARM64
80 namespace vixl {
81 class Simulator;
83 #endif
85 namespace js {
87 extern MOZ_COLD void ReportOutOfMemory(JSContext* cx);
88 extern MOZ_COLD void ReportAllocationOverflow(JSContext* maybecx);
89 extern MOZ_COLD void ReportAllocationOverflow(FrontendContext* fc);
90 extern MOZ_COLD void ReportOversizedAllocation(JSContext* cx,
91 const unsigned errorNumber);
93 class Activation;
94 class ActivationIterator;
95 class Shape;
96 class SourceHook;
98 namespace jit {
99 class JitRuntime;
100 class JitActivation;
101 struct PcScriptCache;
102 class CompileRuntime;
104 #ifdef JS_SIMULATOR_ARM64
105 typedef vixl::Simulator Simulator;
106 #elif defined(JS_SIMULATOR)
107 class Simulator;
108 #endif
109 } // namespace jit
111 namespace frontend {
112 struct CompilationInput;
113 struct CompilationStencil;
114 } // namespace frontend
116 // [SMDOC] JS Engine Threading
118 // Threads interacting with a runtime are divided into two categories:
120 // - The main thread is capable of running JS. There's at most one main thread
121 // per runtime.
123 // - Helper threads do not run JS, and are controlled or triggered by activity
124 // on the main thread (or main threads, since all runtimes in a process share
125 // helper threads). Helper threads may have exclusive access to zones created
126 // for them, for parsing and similar tasks, but their activities do not cause
127 // observable changes in script behaviors. Activity on helper threads may be
128 // referred to as happening 'off thread' or on a background thread in some
129 // parts of the VM.
131 } /* namespace js */
133 namespace JS {
134 struct RuntimeSizes;
135 } // namespace JS
137 namespace js {
140 * Storage for well-known symbols. It's a separate struct from the Runtime so
141 * that it can be shared across multiple runtimes. As in JSAtomState, each
142 * field is a smart pointer that's immutable once initialized.
143 * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
145 * Well-known symbols are never GC'd. The description() of each well-known
146 * symbol is a permanent atom.
148 struct WellKnownSymbols {
149 #define DECLARE_SYMBOL(name) ImmutableTenuredPtr<JS::Symbol*> name;
150 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
151 #undef DECLARE_SYMBOL
153 const ImmutableTenuredPtr<JS::Symbol*>& get(size_t u) const {
154 MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
155 const ImmutableTenuredPtr<JS::Symbol*>* symbols =
156 reinterpret_cast<const ImmutableTenuredPtr<JS::Symbol*>*>(this);
157 return symbols[u];
160 const ImmutableTenuredPtr<JS::Symbol*>& get(JS::SymbolCode code) const {
161 return get(size_t(code));
164 WellKnownSymbols() = default;
165 WellKnownSymbols(const WellKnownSymbols&) = delete;
166 WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
169 // There are several coarse locks in the enum below. These may be either
170 // per-runtime or per-process. When acquiring more than one of these locks,
171 // the acquisition must be done in the order below to avoid deadlocks.
172 enum RuntimeLock { HelperThreadStateLock, GCLock };
174 inline bool CanUseExtraThreads() {
175 extern bool gCanUseExtraThreads;
176 return gCanUseExtraThreads;
179 void DisableExtraThreads();
181 using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
183 class AutoLockScriptData;
185 // Self-hosted lazy functions do not maintain a BaseScript as we can clone from
186 // the copy in the self-hosting zone. To allow these functions to be called by
187 // the JITs, we need a minimal script object. There is one instance per runtime.
188 struct SelfHostedLazyScript {
189 SelfHostedLazyScript() = default;
191 // Pointer to interpreter trampoline. This field is stored at same location as
192 // in BaseScript::jitCodeRaw_.
193 uint8_t* jitCodeRaw_ = nullptr;
195 // Warm-up count of zero. This field is stored at the same offset as
196 // BaseScript::warmUpData_.
197 ScriptWarmUpData warmUpData_ = {};
199 static constexpr size_t offsetOfJitCodeRaw() {
200 return offsetof(SelfHostedLazyScript, jitCodeRaw_);
202 static constexpr size_t offsetOfWarmUpData() {
203 return offsetof(SelfHostedLazyScript, warmUpData_);
207 // An interface for reporting telemetry from within SpiderMonkey. Reporting data
208 // to this interface will forward it to the embedding if a telemetry callback
209 // was registered. It is the embedding's responsibility to store and/or combine
210 // repeated samples for each metric.
211 class Metrics {
212 private:
213 JSRuntime* rt_;
215 public:
216 explicit Metrics(JSRuntime* rt) : rt_(rt) {}
218 // Records a TimeDuration metric. These are converted to integers when being
219 // recorded so choose an appropriate scale. In the future these will be Glean
220 // Timing Distribution metrics.
221 struct TimeDuration_S {
222 using SourceType = mozilla::TimeDuration;
223 static uint32_t convert(SourceType td) { return uint32_t(td.ToSeconds()); }
225 struct TimeDuration_MS {
226 using SourceType = mozilla::TimeDuration;
227 static uint32_t convert(SourceType td) {
228 return uint32_t(td.ToMilliseconds());
231 struct TimeDuration_US {
232 using SourceType = mozilla::TimeDuration;
233 static uint32_t convert(SourceType td) {
234 return uint32_t(td.ToMicroseconds());
238 // Record a metric in bytes. In the future these will be Glean Memory
239 // Distribution metrics.
240 struct MemoryDistribution {
241 using SourceType = size_t;
242 static uint32_t convert(SourceType sz) {
243 return static_cast<uint32_t>(std::min(sz, size_t(UINT32_MAX)));
247 // Record a metric for a quanity of items. This doesn't currently have a Glean
248 // analogue and we avoid using MemoryDistribution directly to avoid confusion
249 // about units.
250 using QuantityDistribution = MemoryDistribution;
252 // Record the distribution of boolean values. In the future this will be a
253 // Glean Rate metric.
254 struct Boolean {
255 using SourceType = bool;
256 static uint32_t convert(SourceType sample) {
257 return static_cast<uint32_t>(sample);
261 // Record the distribution of an enumeration value. This records integer
262 // values so take care not to redefine the value of enum values. In the
263 // future, these should become Glean Labeled Counter metrics.
264 struct Enumeration {
265 using SourceType = unsigned int;
266 static uint32_t convert(SourceType sample) {
267 MOZ_ASSERT(sample <= 100);
268 return static_cast<uint32_t>(sample);
272 // Record a percentage distribution in the range 0 to 100. This takes a double
273 // and converts it to an integer. In the future, this will be a Glean Custom
274 // Distribution unless they add a better match.
275 struct Percentage {
276 using SourceType = double;
277 static uint32_t convert(SourceType sample) {
278 MOZ_ASSERT(sample >= 0.0 && sample <= 100.0);
279 return static_cast<uint32_t>(sample);
283 // Record an unsigned integer.
284 struct Integer {
285 using SourceType = uint32_t;
286 static uint32_t convert(SourceType sample) { return sample; }
289 inline void addTelemetry(JSMetric id, uint32_t sample);
291 #define DECLARE_METRIC_HELPER(NAME, TY) \
292 void NAME(TY::SourceType sample) { \
293 addTelemetry(JSMetric::NAME, TY::convert(sample)); \
295 FOR_EACH_JS_METRIC(DECLARE_METRIC_HELPER)
296 #undef DECLARE_METRIC_HELPER
299 class HasSeenObjectEmulateUndefinedFuse : public js::InvalidatingRuntimeFuse {
300 virtual const char* name() override {
301 return "HasSeenObjectEmulateUndefinedFuse";
303 virtual bool checkInvariant(JSContext* cx) override {
304 // Without traversing the GC heap I don't think it's possible to assert
305 // this invariant directly.
306 return true;
310 } // namespace js
312 struct JSRuntime {
313 private:
314 friend class js::Activation;
315 friend class js::ActivationIterator;
316 friend class js::jit::JitActivation;
317 friend class js::jit::CompileRuntime;
319 /* Space for interpreter frames. */
320 js::MainThreadData<js::InterpreterStack> interpreterStack_;
322 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
323 /* Space for portable baseline interpreter frames. */
324 js::MainThreadData<js::PortableBaselineStack> portableBaselineStack_;
325 #endif
327 public:
328 js::InterpreterStack& interpreterStack() { return interpreterStack_.ref(); }
329 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
330 js::PortableBaselineStack& portableBaselineStack() {
331 return portableBaselineStack_.ref();
333 #endif
336 * If non-null, another runtime guaranteed to outlive this one and whose
337 * permanent data may be used by this one where possible.
339 JSRuntime* const parentRuntime;
341 bool isMainRuntime() const { return !parentRuntime; }
343 #ifdef DEBUG
344 /* The number of child runtimes that have this runtime as their parent. */
345 mozilla::Atomic<size_t> childRuntimeCount;
347 class AutoUpdateChildRuntimeCount {
348 JSRuntime* parent_;
350 public:
351 explicit AutoUpdateChildRuntimeCount(JSRuntime* parent) : parent_(parent) {
352 if (parent_) {
353 parent_->childRuntimeCount++;
357 ~AutoUpdateChildRuntimeCount() {
358 if (parent_) {
359 parent_->childRuntimeCount--;
364 AutoUpdateChildRuntimeCount updateChildRuntimeCount;
365 #endif
367 private:
368 #ifdef DEBUG
369 js::WriteOnceData<bool> initialized_;
370 #endif
372 // The JSContext* for the runtime's main thread. Immutable after this is set
373 // in JSRuntime::init.
374 JSContext* mainContext_;
376 public:
377 JSContext* mainContextFromAnyThread() const { return mainContext_; }
378 const void* addressOfMainContext() { return &mainContext_; }
379 js::Fprinter parserWatcherFile;
381 inline JSContext* mainContextFromOwnThread();
383 js::Metrics metrics() { return js::Metrics(this); }
386 * The start of the range stored in the profiler sample buffer, as measured
387 * after the most recent sample.
388 * All JitcodeGlobalTable entries referenced from a given sample are
389 * assigned the buffer position of the START of the sample. The buffer
390 * entries that reference the JitcodeGlobalTable entries will only ever be
391 * read from the buffer while the entire sample is still inside the buffer;
392 * if some buffer entries at the start of the sample have left the buffer,
393 * the entire sample will be considered inaccessible.
394 * This means that, once profilerSampleBufferRangeStart_ advances beyond
395 * the sample position that's stored on a JitcodeGlobalTable entry, the
396 * buffer entries that reference this JitcodeGlobalTable entry will be
397 * considered inaccessible, and those JitcodeGlobalTable entry can be
398 * disposed of.
400 mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire>
401 profilerSampleBufferRangeStart_;
403 mozilla::Maybe<uint64_t> profilerSampleBufferRangeStart() {
404 if (beingDestroyed_ || !geckoProfiler().enabled()) {
405 return mozilla::Nothing();
407 uint64_t rangeStart = profilerSampleBufferRangeStart_;
408 return mozilla::Some(rangeStart);
410 void setProfilerSampleBufferRangeStart(uint64_t rangeStart) {
411 profilerSampleBufferRangeStart_ = rangeStart;
414 /* Call this to accumulate telemetry data. May be called from any thread; the
415 * embedder is responsible for locking. */
416 JSAccumulateTelemetryDataCallback telemetryCallback;
418 /* Call this to accumulate use counter data. */
419 js::MainThreadData<JSSetUseCounterCallback> useCounterCallback;
421 public:
422 // Accumulates data for Firefox telemetry.
423 void addTelemetry(JSMetric id, uint32_t sample);
425 void setTelemetryCallback(JSRuntime* rt,
426 JSAccumulateTelemetryDataCallback callback);
428 // Sets the use counter for a specific feature, measuring the presence or
429 // absence of usage of a feature on a specific web page and document which
430 // the passed JSObject belongs to.
431 void setUseCounter(JSObject* obj, JSUseCounter counter);
433 void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
435 public:
436 js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;
437 js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback;
438 js::UnprotectedData<JS::ReportStreamErrorCallback> reportStreamErrorCallback;
440 js::GlobalObject* getIncumbentGlobal(JSContext* cx);
441 bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job,
442 js::HandleObject promise,
443 js::Handle<js::GlobalObject*> incumbentGlobal);
444 void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
445 void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
447 /* Had an out-of-memory error which did not populate an exception. */
448 mozilla::Atomic<bool, mozilla::SequentiallyConsistent> hadOutOfMemory;
451 * Allow relazifying functions in compartments that are active. This is
452 * only used by the relazifyFunctions() testing function.
454 js::MainThreadData<bool> allowRelazificationForTesting;
456 /* Zone destroy callback. */
457 js::MainThreadData<JSDestroyZoneCallback> destroyZoneCallback;
459 /* Compartment destroy callback. */
460 js::MainThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
462 /* Compartment memory reporting callback. */
463 js::MainThreadData<JSSizeOfIncludingThisCompartmentCallback>
464 sizeOfIncludingThisCompartmentCallback;
466 /* Callback for creating ubi::Nodes representing DOM node objects. Set by
467 * JS::ubi::SetConstructUbiNodeForDOMObjectCallback. Refer to
468 * js/public/UbiNode.h.
470 void (*constructUbiNodeForDOMObjectCallback)(void*, JSObject*) = nullptr;
472 /* Realm destroy callback. */
473 js::MainThreadData<JS::DestroyRealmCallback> destroyRealmCallback;
475 /* Call this to get the name of a realm. */
476 js::MainThreadData<JS::RealmNameCallback> realmNameCallback;
478 js::MainThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
480 js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks;
481 js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks;
482 js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
483 js::MainThreadData<JSReadPrincipalsOp> readPrincipals;
485 js::MainThreadData<JS::EnsureCanAddPrivateElementOp> canAddPrivateElement;
487 /* Optional warning reporter. */
488 js::MainThreadData<JS::WarningReporter> warningReporter;
490 // Lazy self-hosted functions use a shared SelfHostedLazyScript instance
491 // instead instead of a BaseScript. This contains the minimal pointers to
492 // trampolines for the scripts to support direct jitCodeRaw calls.
493 js::UnprotectedData<js::SelfHostedLazyScript> selfHostedLazyScript;
495 private:
496 // The self-hosted JS code is compiled as a Stencil which is then attached to
497 // the Runtime. This is used to instantiate functions into realms on demand.
498 js::WriteOnceData<js::frontend::CompilationInput*> selfHostStencilInput_;
499 js::WriteOnceData<js::frontend::CompilationStencil*> selfHostStencil_;
501 public:
502 // The self-hosted stencil is immutable once attached to the runtime, so
503 // worker runtimes directly use the stencil on the parent runtime.
504 js::frontend::CompilationInput& selfHostStencilInput() {
505 MOZ_ASSERT(hasSelfHostStencil());
506 return *selfHostStencilInput_.ref();
508 js::frontend::CompilationStencil& selfHostStencil() {
509 MOZ_ASSERT(hasSelfHostStencil());
510 return *selfHostStencil_.ref();
512 bool hasSelfHostStencil() const { return bool(selfHostStencil_.ref()); }
514 // A mapping from the name of self-hosted function to a ScriptIndex range of
515 // the function and inner-functions within the self-hosted stencil.
516 js::MainThreadData<
517 JS::GCHashMap<js::PreBarriered<JSAtom*>, js::frontend::ScriptIndexRange,
518 js::DefaultHasher<JSAtom*>, js::SystemAllocPolicy>>
519 selfHostScriptMap;
521 private:
522 /* Gecko profiling metadata */
523 js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_;
525 public:
526 js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
528 // Heap GC roots for PersistentRooted pointers.
529 js::MainThreadData<
530 mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
531 mozilla::LinkedList<js::PersistentRootedBase>>>
532 heapRoots;
534 void tracePersistentRoots(JSTracer* trc);
535 void finishPersistentRoots();
537 void finishRoots();
539 private:
540 js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
542 public:
543 void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
544 const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
546 js::MainThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
547 js::MainThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
548 js::MainThreadData<js::HasReleasedWrapperCallback> hasReleasedWrapperCallback;
550 js::MainThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
552 js::MainThreadData<JS::CTypesActivityCallback> ctypesActivityCallback;
554 private:
555 js::WriteOnceData<const JSClass*> windowProxyClass_;
557 public:
558 const JSClass* maybeWindowProxyClass() const { return windowProxyClass_; }
559 void setWindowProxyClass(const JSClass* clasp) { windowProxyClass_ = clasp; }
561 private:
562 // List of non-ephemeron weak containers to sweep during
563 // beginSweepingSweepGroup.
564 js::MainThreadData<mozilla::LinkedList<js::gc::WeakCacheBase>> weakCaches_;
566 public:
567 mozilla::LinkedList<js::gc::WeakCacheBase>& weakCaches() {
568 return weakCaches_.ref();
570 void registerWeakCache(js::gc::WeakCacheBase* cachep) {
571 weakCaches().insertBack(cachep);
574 template <typename T>
575 struct GlobalObjectWatchersLinkAccess {
576 static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
577 return aThis->onNewGlobalObjectWatchersLink;
581 template <typename T>
582 struct GarbageCollectionWatchersLinkAccess {
583 static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
584 return aThis->onGarbageCollectionWatchersLink;
588 using OnNewGlobalWatchersList =
589 mozilla::DoublyLinkedList<js::Debugger,
590 GlobalObjectWatchersLinkAccess<js::Debugger>>;
591 using OnGarbageCollectionWatchersList = mozilla::DoublyLinkedList<
592 js::Debugger, GarbageCollectionWatchersLinkAccess<js::Debugger>>;
594 private:
596 * List of all enabled Debuggers that have onNewGlobalObject handler
597 * methods established.
599 js::MainThreadData<OnNewGlobalWatchersList> onNewGlobalObjectWatchers_;
602 * List of all enabled Debuggers that have onGarbageCollection handler
603 * methods established.
605 js::MainThreadData<OnGarbageCollectionWatchersList>
606 onGarbageCollectionWatchers_;
608 public:
609 OnNewGlobalWatchersList& onNewGlobalObjectWatchers() {
610 return onNewGlobalObjectWatchers_.ref();
613 OnGarbageCollectionWatchersList& onGarbageCollectionWatchers() {
614 return onGarbageCollectionWatchers_.ref();
617 private:
618 /* Linked list of all Debugger objects in the runtime. */
619 js::MainThreadData<mozilla::LinkedList<js::Debugger>> debuggerList_;
621 public:
622 mozilla::LinkedList<js::Debugger>& debuggerList() {
623 return debuggerList_.ref();
626 public:
627 JS::HeapState heapState() const { return gc.heapState(); }
629 // How many realms there are across all zones. This number includes
630 // off-thread context realms, so it isn't necessarily equal to the
631 // number of realms visited by RealmsIter.
632 js::MainThreadData<size_t> numRealms;
634 // The Gecko Profiler may want to sample the allocations happening across the
635 // browser. This callback can be registered to record the allocation.
636 js::MainThreadData<JS::RecordAllocationsCallback> recordAllocationCallback;
637 js::MainThreadData<double> allocationSamplingProbability;
639 private:
640 // Number of debuggee realms in the runtime.
641 js::MainThreadData<size_t> numDebuggeeRealms_;
643 // Number of debuggee realms in the runtime observing code coverage.
644 js::MainThreadData<size_t> numDebuggeeRealmsObservingCoverage_;
646 public:
647 void incrementNumDebuggeeRealms();
648 void decrementNumDebuggeeRealms();
650 size_t numDebuggeeRealms() const { return numDebuggeeRealms_; }
652 void incrementNumDebuggeeRealmsObservingCoverage();
653 void decrementNumDebuggeeRealmsObservingCoverage();
655 void startRecordingAllocations(double probability,
656 JS::RecordAllocationsCallback callback);
657 void stopRecordingAllocations();
658 void ensureRealmIsRecordingAllocations(JS::Handle<js::GlobalObject*> global);
660 /* Locale-specific callbacks for string conversion. */
661 js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks;
663 /* Default locale for Internationalization API */
664 js::MainThreadData<js::UniqueChars> defaultLocale;
666 /* If true, new scripts must be created with PC counter information. */
667 js::MainThreadOrIonCompileData<bool> profilingScripts;
669 /* Strong references on scripts held for PCCount profiling API. */
670 js::MainThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*>
671 scriptAndCountsVector;
673 using RootedPlainObjVec = JS::PersistentRooted<
674 JS::GCVector<js::PlainObject*, 0, js::SystemAllocPolicy>>;
675 js::MainThreadData<js::UniquePtr<RootedPlainObjVec>> watchtowerTestingLog;
677 private:
678 /* Code coverage output. */
679 js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
681 /* Functions to call, together with data, when the runtime is being torn down.
683 js::MainThreadData<mozilla::Vector<std::pair<void (*)(void*), void*>, 4>>
684 cleanupClosures;
686 public:
687 js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
689 /* Register a cleanup function to be called during runtime shutdown. Do not
690 * depend on the ordering of cleanup calls. */
691 bool atExit(void (*function)(void*), void* data) {
692 return cleanupClosures.ref().append(std::pair(function, data));
695 private:
696 js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
698 public:
699 mozilla::Maybe<js::frontend::ScriptIndexRange> getSelfHostedScriptIndexRange(
700 js::PropertyName* name);
702 [[nodiscard]] bool createJitRuntime(JSContext* cx);
703 js::jit::JitRuntime* jitRuntime() const { return jitRuntime_.ref(); }
704 bool hasJitRuntime() const { return !!jitRuntime_; }
706 private:
707 // Used to generate random keys for hash tables.
708 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
709 mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
711 // Used to generate random hash codes for symbols.
712 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG>
713 randomHashCodeGenerator_;
715 public:
716 mozilla::HashCodeScrambler randomHashCodeScrambler();
717 mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
719 js::HashNumber randomHashCode();
721 //-------------------------------------------------------------------------
722 // Self-hosting support
723 //-------------------------------------------------------------------------
725 bool hasInitializedSelfHosting() const { return hasSelfHostStencil(); }
727 bool initSelfHostingStencil(JSContext* cx, JS::SelfHostedCache xdrCache,
728 JS::SelfHostedWriter xdrWriter);
729 bool initSelfHostingFromStencil(JSContext* cx);
730 void finishSelfHosting();
731 void traceSelfHostingStencil(JSTracer* trc);
732 js::GeneratorKind getSelfHostedFunctionGeneratorKind(js::PropertyName* name);
733 bool delazifySelfHostedFunction(JSContext* cx,
734 js::Handle<js::PropertyName*> name,
735 js::Handle<JSFunction*> targetFun);
736 bool getSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
737 js::MutableHandleValue vp);
738 void assertSelfHostedFunctionHasCanonicalName(
739 JS::Handle<js::PropertyName*> name);
741 private:
742 void setSelfHostingStencil(
743 JS::MutableHandle<js::UniquePtr<js::frontend::CompilationInput>> input,
744 RefPtr<js::frontend::CompilationStencil>&& stencil);
746 //-------------------------------------------------------------------------
747 // Locale information
748 //-------------------------------------------------------------------------
750 public:
752 * Set the default locale for the ECMAScript Internationalization API
753 * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
754 * Note that the Internationalization API encourages clients to
755 * specify their own locales.
756 * The locale string remains owned by the caller.
758 bool setDefaultLocale(const char* locale);
760 /* Reset the default locale to OS defaults. */
761 void resetDefaultLocale();
763 /* Gets current default locale. String remains owned by context. */
764 const char* getDefaultLocale();
766 /* Garbage collector state. */
767 js::gc::GCRuntime gc;
769 /* Garbage collector state has been successfully initialized. */
771 bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
773 void lockGC() { gc.lockGC(); }
775 void unlockGC() { gc.unlockGC(); }
777 js::WriteOnceData<js::PropertyName*> emptyString;
779 public:
780 JS::GCContext* gcContext() { return &gc.mainThreadContext.ref(); }
782 #if !JS_HAS_INTL_API
783 /* Number localization, used by jsnum.cpp. */
784 js::WriteOnceData<const char*> thousandsSeparator;
785 js::WriteOnceData<const char*> decimalSeparator;
786 js::WriteOnceData<const char*> numGrouping;
787 #endif
789 private:
790 js::WriteOnceData<bool> beingDestroyed_;
792 public:
793 bool isBeingDestroyed() const { return beingDestroyed_; }
795 private:
796 bool allowContentJS_;
798 public:
799 bool allowContentJS() const { return allowContentJS_; }
801 friend class js::AutoAssertNoContentJS;
803 private:
804 // Table of all atoms other than those in permanentAtoms and staticStrings.
805 js::WriteOnceData<js::AtomsTable*> atoms_;
807 // Set of all live symbols produced by Symbol.for(). All such symbols are
808 // allocated in the atoms zone. Reading or writing the symbol registry
809 // can only be done from the main thread.
810 js::MainThreadOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
812 js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms_;
814 public:
815 bool initializeAtoms(JSContext* cx);
816 void finishAtoms();
817 bool atomsAreFinished() const { return !atoms_; }
819 js::AtomsTable* atomsForSweeping() {
820 MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
821 return atoms_;
824 js::AtomsTable& atoms() {
825 MOZ_ASSERT(atoms_);
826 return *atoms_;
829 JS::Zone* atomsZone() {
830 MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(this));
831 return unsafeAtomsZone();
833 JS::Zone* unsafeAtomsZone() { return gc.atomsZone(); }
835 #ifdef DEBUG
836 bool isAtomsZone(const JS::Zone* zone) const {
837 return JS::shadow::Zone::from(zone)->isAtomsZone();
839 #endif
841 bool activeGCInAtomsZone();
843 js::SymbolRegistry& symbolRegistry() { return symbolRegistry_.ref(); }
845 // Permanent atoms are fixed during initialization of the runtime and are
846 // not modified or collected until the runtime is destroyed. These may be
847 // shared with another, longer living runtime through |parentRuntime| and
848 // can be freely accessed with no locking necessary.
850 // Permanent atoms pre-allocated for general use.
851 js::WriteOnceData<js::StaticStrings*> staticStrings;
853 // Cached pointers to various permanent property names.
854 js::WriteOnceData<JSAtomState*> commonNames;
856 // All permanent atoms in the runtime, other than those in staticStrings.
857 // Access to this does not require a lock because it is frozen and thus
858 // read-only.
859 const js::FrozenAtomSet* permanentAtoms() const {
860 MOZ_ASSERT(permanentAtomsPopulated());
861 return permanentAtoms_.ref();
864 // The permanent atoms table is populated during initialization.
865 bool permanentAtomsPopulated() const { return permanentAtoms_; }
867 // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
868 // these are shared with the parentRuntime, if any.
869 js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
871 #ifdef JS_HAS_INTL_API
872 /* Shared Intl data for this runtime. */
873 js::MainThreadData<js::intl::SharedIntlData> sharedIntlData;
875 void traceSharedIntlData(JSTracer* trc);
876 #endif
878 private:
879 js::SharedScriptDataTableHolder scriptDataTableHolder_;
881 public:
882 // Returns the runtime's local script data table holder.
883 js::SharedScriptDataTableHolder& scriptDataTableHolder();
885 private:
886 static mozilla::Atomic<size_t> liveRuntimesCount;
888 public:
889 static bool hasLiveRuntimes() { return liveRuntimesCount > 0; }
890 static bool hasSingleLiveRuntime() { return liveRuntimesCount == 1; }
892 explicit JSRuntime(JSRuntime* parentRuntime);
893 ~JSRuntime();
895 // destroyRuntime is used instead of a destructor, to ensure the downcast
896 // to JSContext remains valid. The final GC triggered here depends on this.
897 void destroyRuntime();
899 bool init(JSContext* cx, uint32_t maxbytes);
901 JSRuntime* thisFromCtor() { return this; }
903 private:
904 // Number of live SharedArrayBuffer objects, including those in Wasm shared
905 // memories. uint64_t to avoid any risk of overflow.
906 js::MainThreadData<uint64_t> liveSABs;
908 public:
909 void incSABCount() {
910 MOZ_RELEASE_ASSERT(liveSABs != UINT64_MAX);
911 liveSABs++;
914 void decSABCount() {
915 MOZ_RELEASE_ASSERT(liveSABs > 0);
916 liveSABs--;
919 bool hasLiveSABs() const { return liveSABs > 0; }
921 public:
922 js::MainThreadData<JS::BeforeWaitCallback> beforeWaitCallback;
923 js::MainThreadData<JS::AfterWaitCallback> afterWaitCallback;
925 public:
926 void reportAllocationOverflow() {
927 js::ReportAllocationOverflow(static_cast<JSContext*>(nullptr));
931 * This should be called after system malloc/calloc/realloc returns nullptr
932 * to try to recove some memory or to report an error. For realloc, the
933 * original pointer must be passed as reallocPtr.
935 * The function must be called outside the GC lock.
937 JS_PUBLIC_API void* onOutOfMemory(js::AllocFunction allocator,
938 arena_id_t arena, size_t nbytes,
939 void* reallocPtr = nullptr,
940 JSContext* maybecx = nullptr);
942 /* onOutOfMemory but can call OnLargeAllocationFailure. */
943 JS_PUBLIC_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
944 arena_id_t arena, size_t nbytes,
945 void* reallocPtr = nullptr);
947 static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
949 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
950 JS::RuntimeSizes* rtSizes);
952 private:
953 // Settings for how helper threads can be used.
954 mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
955 offthreadIonCompilationEnabled_;
956 mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
957 parallelParsingEnabled_;
959 js::MainThreadData<bool> autoWritableJitCodeActive_;
961 public:
962 // Note: these values may be toggled dynamically (in response to about:config
963 // prefs changing).
964 void setOffthreadIonCompilationEnabled(bool value) {
965 offthreadIonCompilationEnabled_ = value;
967 bool canUseOffthreadIonCompilation() const {
968 return offthreadIonCompilationEnabled_;
970 void setParallelParsingEnabled(bool value) {
971 parallelParsingEnabled_ = value;
973 bool canUseParallelParsing() const { return parallelParsingEnabled_; }
975 void toggleAutoWritableJitCodeActive(bool b) {
976 MOZ_ASSERT(autoWritableJitCodeActive_ != b,
977 "AutoWritableJitCode should not be nested.");
978 autoWritableJitCodeActive_ = b;
981 /* See comment for JS::SetOutOfMemoryCallback in js/MemoryCallbacks.h. */
982 js::MainThreadData<JS::OutOfMemoryCallback> oomCallback;
983 js::MainThreadData<void*> oomCallbackData;
986 * Debugger.Memory functions like takeCensus use this embedding-provided
987 * function to assess the size of malloc'd blocks of memory.
989 js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
991 /* Last time at which an animation was played for this runtime. */
992 js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
994 private:
995 /* The stack format for the current runtime. Only valid on non-child
996 * runtimes. */
997 mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
999 public:
1000 js::StackFormat stackFormat() const {
1001 const JSRuntime* rt = this;
1002 while (rt->parentRuntime) {
1003 MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
1004 rt = rt->parentRuntime;
1006 MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
1007 return rt->stackFormat_;
1009 void setStackFormat(js::StackFormat format) {
1010 MOZ_ASSERT(!parentRuntime);
1011 MOZ_ASSERT(format != js::StackFormat::Default);
1012 stackFormat_ = format;
1015 private:
1016 // Warning: no data should be accessed in these caches from another thread,
1017 // but Ion needs to be able to access addresses inside here, which should be
1018 // safe, as the actual cache lookups will be performed on the main thread
1019 // through jitted code.
1020 js::MainThreadOrIonCompileData<js::RuntimeCaches> caches_;
1022 public:
1023 js::RuntimeCaches& caches() { return caches_.ref(); }
1025 // List of all the live wasm::Instances in the runtime. Equal to the union
1026 // of all instances registered in all JS::Realms. Accessed from watchdog
1027 // threads for purposes of wasm::InterruptRunningCode().
1028 js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
1030 // A counter used when recording the order in which modules had their
1031 // AsyncEvaluation field set to true. This is used to order queued
1032 // evaluations. This is reset when the last module that was async evaluating
1033 // is finished.
1035 // See https://tc39.es/ecma262/#sec-async-module-execution-fulfilled step 10
1036 // for use.
1037 js::MainThreadData<uint32_t> moduleAsyncEvaluatingPostOrder;
1039 // The implementation-defined abstract operation HostResolveImportedModule.
1040 js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
1042 // A hook that implements the abstract operations
1043 // HostGetImportMetaProperties and HostFinalizeImportMeta.
1044 js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
1046 // A hook that implements the abstract operation
1047 // HostImportModuleDynamically. This is also used to enable/disable dynamic
1048 // module import and can accessed by off-thread parsing.
1049 mozilla::Atomic<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
1051 // Hooks called when script private references are created and destroyed.
1052 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook;
1053 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook;
1055 void addRefScriptPrivate(const JS::Value& value) {
1056 if (!value.isUndefined() && scriptPrivateAddRefHook) {
1057 scriptPrivateAddRefHook(value);
1061 void releaseScriptPrivate(const JS::Value& value) {
1062 if (!value.isUndefined() && scriptPrivateReleaseHook) {
1063 scriptPrivateReleaseHook(value);
1067 public:
1068 #if defined(NIGHTLY_BUILD)
1069 // Support for informing the embedding of any error thrown.
1070 // This mechanism is designed to let the embedding
1071 // log/report/fail in case certain errors are thrown
1072 // (e.g. SyntaxError, ReferenceError or TypeError
1073 // in critical code).
1074 struct ErrorInterceptionSupport {
1075 ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {}
1077 // true if the error interceptor is currently executing,
1078 // false otherwise. Used to avoid infinite loops.
1079 bool isExecuting;
1081 // if non-null, any call to `setPendingException`
1082 // in this runtime will trigger the call to `interceptor`
1083 JSErrorInterceptor* interceptor;
1085 ErrorInterceptionSupport errorInterception;
1086 #endif // defined(NIGHTLY_BUILD)
1088 public:
1089 JS::GlobalInitializeCallback getShadowRealmInitializeGlobalCallback() {
1090 return shadowRealmInitializeGlobalCallback;
1093 JS::GlobalCreationCallback getShadowRealmGlobalCreationCallback() {
1094 return shadowRealmGlobalCreationCallback;
1097 js::MainThreadData<JS::GlobalInitializeCallback>
1098 shadowRealmInitializeGlobalCallback;
1100 js::MainThreadData<JS::GlobalCreationCallback>
1101 shadowRealmGlobalCreationCallback;
1103 js::MainThreadData<js::HasSeenObjectEmulateUndefinedFuse>
1104 hasSeenObjectEmulateUndefinedFuse;
1107 namespace js {
1109 void Metrics::addTelemetry(JSMetric id, uint32_t sample) {
1110 rt_->addTelemetry(id, sample);
1113 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* vec, size_t len) {
1114 // Don't PodZero here because JS::Value is non-trivial.
1115 for (size_t i = 0; i < len; i++) {
1116 vec[i].setDouble(+0.0);
1120 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* beg, Value* end) {
1121 MakeRangeGCSafe(beg, end - beg);
1124 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* beg, jsid* end) {
1125 std::fill(beg, end, PropertyKey::Int(0));
1128 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* vec, size_t len) {
1129 MakeRangeGCSafe(vec, vec + len);
1132 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** beg, Shape** end) {
1133 std::fill(beg, end, nullptr);
1136 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** vec, size_t len) {
1137 MakeRangeGCSafe(vec, vec + len);
1140 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* beg, Value* end) {
1141 for (Value* v = beg; v != end; ++v) {
1142 v->setUndefined();
1146 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* vec, size_t len) {
1147 SetValueRangeToUndefined(vec, vec + len);
1150 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* beg, Value* end) {
1151 for (Value* v = beg; v != end; ++v) {
1152 v->setNull();
1156 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* vec, size_t len) {
1157 SetValueRangeToNull(vec, vec + len);
1160 extern const JSSecurityCallbacks NullSecurityCallbacks;
1162 // This callback is set by JS::SetProcessLargeAllocationFailureCallback
1163 // and may be null. See comment in jsapi.h.
1164 extern mozilla::Atomic<JS::LargeAllocationFailureCallback>
1165 OnLargeAllocationFailure;
1167 // This callback is set by JS::SetBuildIdOp and may be null. See comment in
1168 // jsapi.h.
1169 extern mozilla::Atomic<JS::BuildIdOp> GetBuildId;
1171 extern JS::FilenameValidationCallback gFilenameValidationCallback;
1173 } /* namespace js */
1175 #endif /* vm_Runtime_h */