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/. */
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"
22 #ifdef JS_HAS_INTL_API
23 # include "builtin/intl/SharedIntlData.h"
25 #include "frontend/ScriptIndex.h"
26 #include "gc/GCRuntime.h"
27 #include "js/AllocationRecording.h"
28 #include "js/BuildId.h" // JS::BuildIdOp
29 #include "js/Context.h"
30 #include "js/experimental/CTypes.h" // JS::CTypesActivityCallback
31 #include "js/friend/StackLimits.h" // js::ReportOverRecursed
32 #include "js/friend/UsageStatistics.h" // JSAccumulateTelemetryDataCallback
33 #include "js/GCVector.h"
34 #include "js/HashTable.h"
35 #include "js/Initialization.h"
36 #include "js/MemoryCallbacks.h"
37 #include "js/Modules.h" // JS::Module{DynamicImport,Metadata,Resolve}Hook
38 #include "js/ScriptPrivate.h"
39 #include "js/shadow/Zone.h"
40 #include "js/ShadowRealmCallbacks.h"
42 #include "js/StreamConsumer.h"
43 #include "js/Symbol.h"
44 #include "js/UniquePtr.h"
45 #include "js/Utility.h"
46 #include "js/WaitCallbacks.h"
47 #include "js/Warnings.h" // JS::WarningReporter
49 #include "vm/Caches.h" // js::RuntimeCaches
50 #include "vm/CodeCoverage.h"
51 #include "vm/GeckoProfiler.h"
52 #include "vm/JSScript.h"
53 #include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseRuntimeState
54 #include "vm/SharedScriptDataTableHolder.h" // js::SharedScriptDataTableHolder
56 #include "wasm/WasmTypeDecls.h"
60 struct JSErrorInterceptor
;
61 struct JSWrapObjectCallbacks
;
65 class AutoAssertNoContentJS
;
67 class EnterDebuggeeNoExecute
;
68 class FrontendContext
;
75 struct JSLocaleCallbacks
;
77 #ifdef JS_SIMULATOR_ARM64
85 extern MOZ_COLD
void ReportOutOfMemory(JSContext
* cx
);
86 extern MOZ_COLD
void ReportAllocationOverflow(JSContext
* maybecx
);
87 extern MOZ_COLD
void ReportAllocationOverflow(FrontendContext
* fc
);
88 extern MOZ_COLD
void ReportOversizedAllocation(JSContext
* cx
,
89 const unsigned errorNumber
);
92 class ActivationIterator
;
100 class CompileRuntime
;
102 #ifdef JS_SIMULATOR_ARM64
103 typedef vixl::Simulator Simulator
;
104 #elif defined(JS_SIMULATOR)
110 struct CompilationInput
;
111 struct CompilationStencil
;
112 } // namespace frontend
114 // [SMDOC] JS Engine Threading
116 // Threads interacting with a runtime are divided into two categories:
118 // - The main thread is capable of running JS. There's at most one main thread
121 // - Helper threads do not run JS, and are controlled or triggered by activity
122 // on the main thread (or main threads, since all runtimes in a process share
123 // helper threads). Helper threads may have exclusive access to zones created
124 // for them, for parsing and similar tasks, but their activities do not cause
125 // observable changes in script behaviors. Activity on helper threads may be
126 // referred to as happening 'off thread' or on a background thread in some
138 * Storage for well-known symbols. It's a separate struct from the Runtime so
139 * that it can be shared across multiple runtimes. As in JSAtomState, each
140 * field is a smart pointer that's immutable once initialized.
141 * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
143 * Well-known symbols are never GC'd. The description() of each well-known
144 * symbol is a permanent atom.
146 struct WellKnownSymbols
{
147 #define DECLARE_SYMBOL(name) ImmutableTenuredPtr<JS::Symbol*> name;
148 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL
)
149 #undef DECLARE_SYMBOL
151 const ImmutableTenuredPtr
<JS::Symbol
*>& get(size_t u
) const {
152 MOZ_ASSERT(u
< JS::WellKnownSymbolLimit
);
153 const ImmutableTenuredPtr
<JS::Symbol
*>* symbols
=
154 reinterpret_cast<const ImmutableTenuredPtr
<JS::Symbol
*>*>(this);
158 const ImmutableTenuredPtr
<JS::Symbol
*>& get(JS::SymbolCode code
) const {
159 return get(size_t(code
));
162 WellKnownSymbols() = default;
163 WellKnownSymbols(const WellKnownSymbols
&) = delete;
164 WellKnownSymbols
& operator=(const WellKnownSymbols
&) = delete;
167 // There are several coarse locks in the enum below. These may be either
168 // per-runtime or per-process. When acquiring more than one of these locks,
169 // the acquisition must be done in the order below to avoid deadlocks.
170 enum RuntimeLock
{ HelperThreadStateLock
, GCLock
};
172 inline bool CanUseExtraThreads() {
173 extern bool gCanUseExtraThreads
;
174 return gCanUseExtraThreads
;
177 void DisableExtraThreads();
179 using ScriptAndCountsVector
= GCVector
<ScriptAndCounts
, 0, SystemAllocPolicy
>;
181 class AutoLockScriptData
;
183 // Self-hosted lazy functions do not maintain a BaseScript as we can clone from
184 // the copy in the self-hosting zone. To allow these functions to be called by
185 // the JITs, we need a minimal script object. There is one instance per runtime.
186 struct SelfHostedLazyScript
{
187 SelfHostedLazyScript() = default;
189 // Pointer to interpreter trampoline. This field is stored at same location as
190 // in BaseScript::jitCodeRaw_.
191 uint8_t* jitCodeRaw_
= nullptr;
193 // Warm-up count of zero. This field is stored at the same offset as
194 // BaseScript::warmUpData_.
195 ScriptWarmUpData warmUpData_
= {};
197 static constexpr size_t offsetOfJitCodeRaw() {
198 return offsetof(SelfHostedLazyScript
, jitCodeRaw_
);
200 static constexpr size_t offsetOfWarmUpData() {
201 return offsetof(SelfHostedLazyScript
, warmUpData_
);
205 // An interface for reporting telemetry from within SpiderMonkey. Reporting data
206 // to this interface will forward it to the embedding if a telemetry callback
207 // was registered. It is the embedding's responsibility to store and/or combine
208 // repeated samples for each metric.
214 explicit Metrics(JSRuntime
* rt
) : rt_(rt
) {}
216 // Records a TimeDuration metric. These are converted to integers when being
217 // recorded so choose an appropriate scale. In the future these will be Glean
218 // Timing Distribution metrics.
219 struct TimeDuration_S
{
220 using SourceType
= mozilla::TimeDuration
;
221 static uint32_t convert(SourceType td
) { return uint32_t(td
.ToSeconds()); }
223 struct TimeDuration_MS
{
224 using SourceType
= mozilla::TimeDuration
;
225 static uint32_t convert(SourceType td
) {
226 return uint32_t(td
.ToMilliseconds());
229 struct TimeDuration_US
{
230 using SourceType
= mozilla::TimeDuration
;
231 static uint32_t convert(SourceType td
) {
232 return uint32_t(td
.ToMicroseconds());
236 // Record a metric in bytes. In the future these will be Glean Memory
237 // Distribution metrics.
238 struct MemoryDistribution
{
239 using SourceType
= size_t;
240 static uint32_t convert(SourceType sz
) {
241 return static_cast<uint32_t>(std::min(sz
, size_t(UINT32_MAX
)));
245 // Record a metric for a quanity of items. This doesn't currently have a Glean
246 // analogue and we avoid using MemoryDistribution directly to avoid confusion
248 using QuantityDistribution
= MemoryDistribution
;
250 // Record the distribution of boolean values. In the future this will be a
251 // Glean Rate metric.
253 using SourceType
= bool;
254 static uint32_t convert(SourceType sample
) {
255 return static_cast<uint32_t>(sample
);
259 // Record the distribution of an enumeration value. This records integer
260 // values so take care not to redefine the value of enum values. In the
261 // future, these should become Glean Labeled Counter metrics.
263 using SourceType
= unsigned int;
264 static uint32_t convert(SourceType sample
) {
265 MOZ_ASSERT(sample
<= 100);
266 return static_cast<uint32_t>(sample
);
270 // Record a percentage distribution in the range 0 to 100. This takes a double
271 // and converts it to an integer. In the future, this will be a Glean Custom
272 // Distribution unless they add a better match.
274 using SourceType
= double;
275 static uint32_t convert(SourceType sample
) {
276 MOZ_ASSERT(sample
>= 0.0 && sample
<= 100.0);
277 return static_cast<uint32_t>(sample
);
281 // Record an unsigned integer.
283 using SourceType
= uint32_t;
284 static uint32_t convert(SourceType sample
) { return sample
; }
287 inline void addTelemetry(JSMetric id
, uint32_t sample
);
289 #define DECLARE_METRIC_HELPER(NAME, TY) \
290 void NAME(TY::SourceType sample) { \
291 addTelemetry(JSMetric::NAME, TY::convert(sample)); \
293 FOR_EACH_JS_METRIC(DECLARE_METRIC_HELPER
)
294 #undef DECLARE_METRIC_HELPER
301 friend class js::Activation
;
302 friend class js::ActivationIterator
;
303 friend class js::jit::JitActivation
;
304 friend class js::jit::CompileRuntime
;
306 /* Space for interpreter frames. */
307 js::MainThreadData
<js::InterpreterStack
> interpreterStack_
;
309 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
310 /* Space for portable baseline interpreter frames. */
311 js::MainThreadData
<js::PortableBaselineStack
> portableBaselineStack_
;
315 js::InterpreterStack
& interpreterStack() { return interpreterStack_
.ref(); }
316 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
317 js::PortableBaselineStack
& portableBaselineStack() {
318 return portableBaselineStack_
.ref();
323 * If non-null, another runtime guaranteed to outlive this one and whose
324 * permanent data may be used by this one where possible.
326 JSRuntime
* const parentRuntime
;
328 bool isMainRuntime() const { return !parentRuntime
; }
331 /* The number of child runtimes that have this runtime as their parent. */
332 mozilla::Atomic
<size_t> childRuntimeCount
;
334 class AutoUpdateChildRuntimeCount
{
338 explicit AutoUpdateChildRuntimeCount(JSRuntime
* parent
) : parent_(parent
) {
340 parent_
->childRuntimeCount
++;
344 ~AutoUpdateChildRuntimeCount() {
346 parent_
->childRuntimeCount
--;
351 AutoUpdateChildRuntimeCount updateChildRuntimeCount
;
356 js::WriteOnceData
<bool> initialized_
;
359 // The JSContext* for the runtime's main thread. Immutable after this is set
360 // in JSRuntime::init.
361 JSContext
* mainContext_
;
364 JSContext
* mainContextFromAnyThread() const { return mainContext_
; }
365 const void* addressOfMainContext() { return &mainContext_
; }
366 js::Fprinter parserWatcherFile
;
368 inline JSContext
* mainContextFromOwnThread();
370 js::Metrics
metrics() { return js::Metrics(this); }
373 * The start of the range stored in the profiler sample buffer, as measured
374 * after the most recent sample.
375 * All JitcodeGlobalTable entries referenced from a given sample are
376 * assigned the buffer position of the START of the sample. The buffer
377 * entries that reference the JitcodeGlobalTable entries will only ever be
378 * read from the buffer while the entire sample is still inside the buffer;
379 * if some buffer entries at the start of the sample have left the buffer,
380 * the entire sample will be considered inaccessible.
381 * This means that, once profilerSampleBufferRangeStart_ advances beyond
382 * the sample position that's stored on a JitcodeGlobalTable entry, the
383 * buffer entries that reference this JitcodeGlobalTable entry will be
384 * considered inaccessible, and those JitcodeGlobalTable entry can be
387 mozilla::Atomic
<uint64_t, mozilla::ReleaseAcquire
>
388 profilerSampleBufferRangeStart_
;
390 mozilla::Maybe
<uint64_t> profilerSampleBufferRangeStart() {
391 if (beingDestroyed_
|| !geckoProfiler().enabled()) {
392 return mozilla::Nothing();
394 uint64_t rangeStart
= profilerSampleBufferRangeStart_
;
395 return mozilla::Some(rangeStart
);
397 void setProfilerSampleBufferRangeStart(uint64_t rangeStart
) {
398 profilerSampleBufferRangeStart_
= rangeStart
;
401 /* Call this to accumulate telemetry data. May be called from any thread; the
402 * embedder is responsible for locking. */
403 JSAccumulateTelemetryDataCallback telemetryCallback
;
405 /* Call this to accumulate use counter data. */
406 js::MainThreadData
<JSSetUseCounterCallback
> useCounterCallback
;
409 // Accumulates data for Firefox telemetry.
410 void addTelemetry(JSMetric id
, uint32_t sample
);
412 void setTelemetryCallback(JSRuntime
* rt
,
413 JSAccumulateTelemetryDataCallback callback
);
415 // Sets the use counter for a specific feature, measuring the presence or
416 // absence of usage of a feature on a specific web page and document which
417 // the passed JSObject belongs to.
418 void setUseCounter(JSObject
* obj
, JSUseCounter counter
);
420 void setUseCounterCallback(JSRuntime
* rt
, JSSetUseCounterCallback callback
);
423 js::UnprotectedData
<js::OffThreadPromiseRuntimeState
> offThreadPromiseState
;
424 js::UnprotectedData
<JS::ConsumeStreamCallback
> consumeStreamCallback
;
425 js::UnprotectedData
<JS::ReportStreamErrorCallback
> reportStreamErrorCallback
;
427 js::GlobalObject
* getIncumbentGlobal(JSContext
* cx
);
428 bool enqueuePromiseJob(JSContext
* cx
, js::HandleFunction job
,
429 js::HandleObject promise
,
430 js::Handle
<js::GlobalObject
*> incumbentGlobal
);
431 void addUnhandledRejectedPromise(JSContext
* cx
, js::HandleObject promise
);
432 void removeUnhandledRejectedPromise(JSContext
* cx
, js::HandleObject promise
);
434 /* Had an out-of-memory error which did not populate an exception. */
435 mozilla::Atomic
<bool, mozilla::SequentiallyConsistent
> hadOutOfMemory
;
438 * Allow relazifying functions in compartments that are active. This is
439 * only used by the relazifyFunctions() testing function.
441 js::MainThreadData
<bool> allowRelazificationForTesting
;
443 /* Zone destroy callback. */
444 js::MainThreadData
<JSDestroyZoneCallback
> destroyZoneCallback
;
446 /* Compartment destroy callback. */
447 js::MainThreadData
<JSDestroyCompartmentCallback
> destroyCompartmentCallback
;
449 /* Compartment memory reporting callback. */
450 js::MainThreadData
<JSSizeOfIncludingThisCompartmentCallback
>
451 sizeOfIncludingThisCompartmentCallback
;
453 /* Callback for creating ubi::Nodes representing DOM node objects. Set by
454 * JS::ubi::SetConstructUbiNodeForDOMObjectCallback. Refer to
455 * js/public/UbiNode.h.
457 void (*constructUbiNodeForDOMObjectCallback
)(void*, JSObject
*) = nullptr;
459 /* Realm destroy callback. */
460 js::MainThreadData
<JS::DestroyRealmCallback
> destroyRealmCallback
;
462 /* Call this to get the name of a realm. */
463 js::MainThreadData
<JS::RealmNameCallback
> realmNameCallback
;
465 js::MainThreadData
<mozilla::UniquePtr
<js::SourceHook
>> sourceHook
;
467 js::MainThreadData
<const JSSecurityCallbacks
*> securityCallbacks
;
468 js::MainThreadData
<const js::DOMCallbacks
*> DOMcallbacks
;
469 js::MainThreadData
<JSDestroyPrincipalsOp
> destroyPrincipals
;
470 js::MainThreadData
<JSReadPrincipalsOp
> readPrincipals
;
472 js::MainThreadData
<JS::EnsureCanAddPrivateElementOp
> canAddPrivateElement
;
474 /* Optional warning reporter. */
475 js::MainThreadData
<JS::WarningReporter
> warningReporter
;
477 // Lazy self-hosted functions use a shared SelfHostedLazyScript instance
478 // instead instead of a BaseScript. This contains the minimal pointers to
479 // trampolines for the scripts to support direct jitCodeRaw calls.
480 js::UnprotectedData
<js::SelfHostedLazyScript
> selfHostedLazyScript
;
483 // The self-hosted JS code is compiled as a Stencil which is then attached to
484 // the Runtime. This is used to instantiate functions into realms on demand.
485 js::WriteOnceData
<js::frontend::CompilationInput
*> selfHostStencilInput_
;
486 js::WriteOnceData
<js::frontend::CompilationStencil
*> selfHostStencil_
;
489 // The self-hosted stencil is immutable once attached to the runtime, so
490 // worker runtimes directly use the stencil on the parent runtime.
491 js::frontend::CompilationInput
& selfHostStencilInput() {
492 MOZ_ASSERT(hasSelfHostStencil());
493 return *selfHostStencilInput_
.ref();
495 js::frontend::CompilationStencil
& selfHostStencil() {
496 MOZ_ASSERT(hasSelfHostStencil());
497 return *selfHostStencil_
.ref();
499 bool hasSelfHostStencil() const { return bool(selfHostStencil_
.ref()); }
501 // A mapping from the name of self-hosted function to a ScriptIndex range of
502 // the function and inner-functions within the self-hosted stencil.
504 JS::GCHashMap
<js::PreBarriered
<JSAtom
*>, js::frontend::ScriptIndexRange
,
505 js::DefaultHasher
<JSAtom
*>, js::SystemAllocPolicy
>>
509 /* Gecko profiling metadata */
510 js::UnprotectedData
<js::GeckoProfilerRuntime
> geckoProfiler_
;
513 js::GeckoProfilerRuntime
& geckoProfiler() { return geckoProfiler_
.ref(); }
515 // Heap GC roots for PersistentRooted pointers.
517 mozilla::EnumeratedArray
<JS::RootKind
, JS::RootKind::Limit
,
518 mozilla::LinkedList
<js::PersistentRootedBase
>>>
521 void tracePersistentRoots(JSTracer
* trc
);
522 void finishPersistentRoots();
527 js::UnprotectedData
<const JSPrincipals
*> trustedPrincipals_
;
530 void setTrustedPrincipals(const JSPrincipals
* p
) { trustedPrincipals_
= p
; }
531 const JSPrincipals
* trustedPrincipals() const { return trustedPrincipals_
; }
533 js::MainThreadData
<const JSWrapObjectCallbacks
*> wrapObjectCallbacks
;
534 js::MainThreadData
<js::PreserveWrapperCallback
> preserveWrapperCallback
;
535 js::MainThreadData
<js::HasReleasedWrapperCallback
> hasReleasedWrapperCallback
;
537 js::MainThreadData
<js::ScriptEnvironmentPreparer
*> scriptEnvironmentPreparer
;
539 js::MainThreadData
<JS::CTypesActivityCallback
> ctypesActivityCallback
;
542 js::WriteOnceData
<const JSClass
*> windowProxyClass_
;
545 const JSClass
* maybeWindowProxyClass() const { return windowProxyClass_
; }
546 void setWindowProxyClass(const JSClass
* clasp
) { windowProxyClass_
= clasp
; }
549 // List of non-ephemeron weak containers to sweep during
550 // beginSweepingSweepGroup.
551 js::MainThreadData
<mozilla::LinkedList
<JS::detail::WeakCacheBase
>>
555 mozilla::LinkedList
<JS::detail::WeakCacheBase
>& weakCaches() {
556 return weakCaches_
.ref();
558 void registerWeakCache(JS::detail::WeakCacheBase
* cachep
) {
559 weakCaches().insertBack(cachep
);
562 template <typename T
>
563 struct GlobalObjectWatchersLinkAccess
{
564 static mozilla::DoublyLinkedListElement
<T
>& Get(T
* aThis
) {
565 return aThis
->onNewGlobalObjectWatchersLink
;
569 template <typename T
>
570 struct GarbageCollectionWatchersLinkAccess
{
571 static mozilla::DoublyLinkedListElement
<T
>& Get(T
* aThis
) {
572 return aThis
->onGarbageCollectionWatchersLink
;
576 using OnNewGlobalWatchersList
=
577 mozilla::DoublyLinkedList
<js::Debugger
,
578 GlobalObjectWatchersLinkAccess
<js::Debugger
>>;
579 using OnGarbageCollectionWatchersList
= mozilla::DoublyLinkedList
<
580 js::Debugger
, GarbageCollectionWatchersLinkAccess
<js::Debugger
>>;
584 * List of all enabled Debuggers that have onNewGlobalObject handler
585 * methods established.
587 js::MainThreadData
<OnNewGlobalWatchersList
> onNewGlobalObjectWatchers_
;
590 * List of all enabled Debuggers that have onGarbageCollection handler
591 * methods established.
593 js::MainThreadData
<OnGarbageCollectionWatchersList
>
594 onGarbageCollectionWatchers_
;
597 OnNewGlobalWatchersList
& onNewGlobalObjectWatchers() {
598 return onNewGlobalObjectWatchers_
.ref();
601 OnGarbageCollectionWatchersList
& onGarbageCollectionWatchers() {
602 return onGarbageCollectionWatchers_
.ref();
606 /* Linked list of all Debugger objects in the runtime. */
607 js::MainThreadData
<mozilla::LinkedList
<js::Debugger
>> debuggerList_
;
610 mozilla::LinkedList
<js::Debugger
>& debuggerList() {
611 return debuggerList_
.ref();
615 JS::HeapState
heapState() const { return gc
.heapState(); }
617 // How many realms there are across all zones. This number includes
618 // off-thread context realms, so it isn't necessarily equal to the
619 // number of realms visited by RealmsIter.
620 js::MainThreadData
<size_t> numRealms
;
622 // The Gecko Profiler may want to sample the allocations happening across the
623 // browser. This callback can be registered to record the allocation.
624 js::MainThreadData
<JS::RecordAllocationsCallback
> recordAllocationCallback
;
625 js::MainThreadData
<double> allocationSamplingProbability
;
628 // Number of debuggee realms in the runtime.
629 js::MainThreadData
<size_t> numDebuggeeRealms_
;
631 // Number of debuggee realms in the runtime observing code coverage.
632 js::MainThreadData
<size_t> numDebuggeeRealmsObservingCoverage_
;
635 void incrementNumDebuggeeRealms();
636 void decrementNumDebuggeeRealms();
638 size_t numDebuggeeRealms() const { return numDebuggeeRealms_
; }
640 void incrementNumDebuggeeRealmsObservingCoverage();
641 void decrementNumDebuggeeRealmsObservingCoverage();
643 void startRecordingAllocations(double probability
,
644 JS::RecordAllocationsCallback callback
);
645 void stopRecordingAllocations();
646 void ensureRealmIsRecordingAllocations(JS::Handle
<js::GlobalObject
*> global
);
648 /* Locale-specific callbacks for string conversion. */
649 js::MainThreadData
<const JSLocaleCallbacks
*> localeCallbacks
;
651 /* Default locale for Internationalization API */
652 js::MainThreadData
<js::UniqueChars
> defaultLocale
;
654 /* If true, new scripts must be created with PC counter information. */
655 js::MainThreadOrIonCompileData
<bool> profilingScripts
;
657 /* Strong references on scripts held for PCCount profiling API. */
658 js::MainThreadData
<JS::PersistentRooted
<js::ScriptAndCountsVector
>*>
659 scriptAndCountsVector
;
661 using RootedPlainObjVec
= JS::PersistentRooted
<
662 JS::GCVector
<js::PlainObject
*, 0, js::SystemAllocPolicy
>>;
663 js::MainThreadData
<js::UniquePtr
<RootedPlainObjVec
>> watchtowerTestingLog
;
666 /* Code coverage output. */
667 js::UnprotectedData
<js::coverage::LCovRuntime
> lcovOutput_
;
670 js::coverage::LCovRuntime
& lcovOutput() { return lcovOutput_
.ref(); }
673 js::UnprotectedData
<js::jit::JitRuntime
*> jitRuntime_
;
676 mozilla::Maybe
<js::frontend::ScriptIndexRange
> getSelfHostedScriptIndexRange(
677 js::PropertyName
* name
);
679 [[nodiscard
]] bool createJitRuntime(JSContext
* cx
);
680 js::jit::JitRuntime
* jitRuntime() const { return jitRuntime_
.ref(); }
681 bool hasJitRuntime() const { return !!jitRuntime_
; }
684 // Used to generate random keys for hash tables.
685 mozilla::Maybe
<mozilla::non_crypto::XorShift128PlusRNG
> randomKeyGenerator_
;
686 mozilla::non_crypto::XorShift128PlusRNG
& randomKeyGenerator();
688 // Used to generate random hash codes for symbols.
689 mozilla::Maybe
<mozilla::non_crypto::XorShift128PlusRNG
>
690 randomHashCodeGenerator_
;
693 mozilla::HashCodeScrambler
randomHashCodeScrambler();
694 mozilla::non_crypto::XorShift128PlusRNG
forkRandomKeyGenerator();
696 js::HashNumber
randomHashCode();
698 //-------------------------------------------------------------------------
699 // Self-hosting support
700 //-------------------------------------------------------------------------
702 bool hasInitializedSelfHosting() const { return hasSelfHostStencil(); }
704 bool initSelfHostingStencil(JSContext
* cx
, JS::SelfHostedCache xdrCache
,
705 JS::SelfHostedWriter xdrWriter
);
706 bool initSelfHostingFromStencil(JSContext
* cx
);
707 void finishSelfHosting();
708 void traceSelfHostingStencil(JSTracer
* trc
);
709 js::GeneratorKind
getSelfHostedFunctionGeneratorKind(js::PropertyName
* name
);
710 bool delazifySelfHostedFunction(JSContext
* cx
,
711 js::Handle
<js::PropertyName
*> name
,
712 js::Handle
<JSFunction
*> targetFun
);
713 bool getSelfHostedValue(JSContext
* cx
, js::Handle
<js::PropertyName
*> name
,
714 js::MutableHandleValue vp
);
715 void assertSelfHostedFunctionHasCanonicalName(
716 JS::Handle
<js::PropertyName
*> name
);
719 void setSelfHostingStencil(
720 JS::MutableHandle
<js::UniquePtr
<js::frontend::CompilationInput
>> input
,
721 RefPtr
<js::frontend::CompilationStencil
>&& stencil
);
723 //-------------------------------------------------------------------------
724 // Locale information
725 //-------------------------------------------------------------------------
729 * Set the default locale for the ECMAScript Internationalization API
730 * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
731 * Note that the Internationalization API encourages clients to
732 * specify their own locales.
733 * The locale string remains owned by the caller.
735 bool setDefaultLocale(const char* locale
);
737 /* Reset the default locale to OS defaults. */
738 void resetDefaultLocale();
740 /* Gets current default locale. String remains owned by context. */
741 const char* getDefaultLocale();
743 /* Garbage collector state. */
744 js::gc::GCRuntime gc
;
746 /* Garbage collector state has been successfully initialized. */
748 bool hasZealMode(js::gc::ZealMode mode
) { return gc
.hasZealMode(mode
); }
750 void lockGC() { gc
.lockGC(); }
752 void unlockGC() { gc
.unlockGC(); }
754 js::WriteOnceData
<js::PropertyName
*> emptyString
;
757 JS::GCContext
* gcContext() { return &gc
.mainThreadContext
.ref(); }
760 /* Number localization, used by jsnum.cpp. */
761 js::WriteOnceData
<const char*> thousandsSeparator
;
762 js::WriteOnceData
<const char*> decimalSeparator
;
763 js::WriteOnceData
<const char*> numGrouping
;
767 js::WriteOnceData
<bool> beingDestroyed_
;
770 bool isBeingDestroyed() const { return beingDestroyed_
; }
773 bool allowContentJS_
;
776 bool allowContentJS() const { return allowContentJS_
; }
778 friend class js::AutoAssertNoContentJS
;
781 // Table of all atoms other than those in permanentAtoms and staticStrings.
782 js::WriteOnceData
<js::AtomsTable
*> atoms_
;
784 // Set of all live symbols produced by Symbol.for(). All such symbols are
785 // allocated in the atoms zone. Reading or writing the symbol registry
786 // can only be done from the main thread.
787 js::MainThreadOrGCTaskData
<js::SymbolRegistry
> symbolRegistry_
;
789 js::WriteOnceData
<js::FrozenAtomSet
*> permanentAtoms_
;
792 bool initializeAtoms(JSContext
* cx
);
794 bool atomsAreFinished() const { return !atoms_
; }
796 js::AtomsTable
* atomsForSweeping() {
797 MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
801 js::AtomsTable
& atoms() {
806 JS::Zone
* atomsZone() {
807 MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(this));
808 return unsafeAtomsZone();
810 JS::Zone
* unsafeAtomsZone() { return gc
.atomsZone(); }
813 bool isAtomsZone(const JS::Zone
* zone
) const {
814 return JS::shadow::Zone::from(zone
)->isAtomsZone();
818 bool activeGCInAtomsZone();
820 js::SymbolRegistry
& symbolRegistry() { return symbolRegistry_
.ref(); }
822 // Permanent atoms are fixed during initialization of the runtime and are
823 // not modified or collected until the runtime is destroyed. These may be
824 // shared with another, longer living runtime through |parentRuntime| and
825 // can be freely accessed with no locking necessary.
827 // Permanent atoms pre-allocated for general use.
828 js::WriteOnceData
<js::StaticStrings
*> staticStrings
;
830 // Cached pointers to various permanent property names.
831 js::WriteOnceData
<JSAtomState
*> commonNames
;
833 // All permanent atoms in the runtime, other than those in staticStrings.
834 // Access to this does not require a lock because it is frozen and thus
836 const js::FrozenAtomSet
* permanentAtoms() const {
837 MOZ_ASSERT(permanentAtomsPopulated());
838 return permanentAtoms_
.ref();
841 // The permanent atoms table is populated during initialization.
842 bool permanentAtomsPopulated() const { return permanentAtoms_
; }
844 // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
845 // these are shared with the parentRuntime, if any.
846 js::WriteOnceData
<js::WellKnownSymbols
*> wellKnownSymbols
;
848 #ifdef JS_HAS_INTL_API
849 /* Shared Intl data for this runtime. */
850 js::MainThreadData
<js::intl::SharedIntlData
> sharedIntlData
;
852 void traceSharedIntlData(JSTracer
* trc
);
856 js::SharedScriptDataTableHolder scriptDataTableHolder_
;
859 // Returns the runtime's local script data table holder.
860 js::SharedScriptDataTableHolder
& scriptDataTableHolder();
863 static mozilla::Atomic
<size_t> liveRuntimesCount
;
866 static bool hasLiveRuntimes() { return liveRuntimesCount
> 0; }
867 static bool hasSingleLiveRuntime() { return liveRuntimesCount
== 1; }
869 explicit JSRuntime(JSRuntime
* parentRuntime
);
872 // destroyRuntime is used instead of a destructor, to ensure the downcast
873 // to JSContext remains valid. The final GC triggered here depends on this.
874 void destroyRuntime();
876 bool init(JSContext
* cx
, uint32_t maxbytes
);
878 JSRuntime
* thisFromCtor() { return this; }
881 // Number of live SharedArrayBuffer objects, including those in Wasm shared
882 // memories. uint64_t to avoid any risk of overflow.
883 js::MainThreadData
<uint64_t> liveSABs
;
887 MOZ_RELEASE_ASSERT(liveSABs
!= UINT64_MAX
);
892 MOZ_RELEASE_ASSERT(liveSABs
> 0);
896 bool hasLiveSABs() const { return liveSABs
> 0; }
899 js::MainThreadData
<JS::BeforeWaitCallback
> beforeWaitCallback
;
900 js::MainThreadData
<JS::AfterWaitCallback
> afterWaitCallback
;
903 void reportAllocationOverflow() {
904 js::ReportAllocationOverflow(static_cast<JSContext
*>(nullptr));
908 * This should be called after system malloc/calloc/realloc returns nullptr
909 * to try to recove some memory or to report an error. For realloc, the
910 * original pointer must be passed as reallocPtr.
912 * The function must be called outside the GC lock.
914 JS_PUBLIC_API
void* onOutOfMemory(js::AllocFunction allocator
,
915 arena_id_t arena
, size_t nbytes
,
916 void* reallocPtr
= nullptr,
917 JSContext
* maybecx
= nullptr);
919 /* onOutOfMemory but can call OnLargeAllocationFailure. */
920 JS_PUBLIC_API
void* onOutOfMemoryCanGC(js::AllocFunction allocator
,
921 arena_id_t arena
, size_t nbytes
,
922 void* reallocPtr
= nullptr);
924 static const unsigned LARGE_ALLOCATION
= 25 * 1024 * 1024;
926 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
,
927 JS::RuntimeSizes
* rtSizes
);
930 // Settings for how helper threads can be used.
931 mozilla::Atomic
<bool, mozilla::SequentiallyConsistent
>
932 offthreadIonCompilationEnabled_
;
933 mozilla::Atomic
<bool, mozilla::SequentiallyConsistent
>
934 parallelParsingEnabled_
;
936 js::MainThreadData
<bool> autoWritableJitCodeActive_
;
939 // Note: these values may be toggled dynamically (in response to about:config
941 void setOffthreadIonCompilationEnabled(bool value
) {
942 offthreadIonCompilationEnabled_
= value
;
944 bool canUseOffthreadIonCompilation() const {
945 return offthreadIonCompilationEnabled_
;
947 void setParallelParsingEnabled(bool value
) {
948 parallelParsingEnabled_
= value
;
950 bool canUseParallelParsing() const { return parallelParsingEnabled_
; }
952 void toggleAutoWritableJitCodeActive(bool b
) {
953 MOZ_ASSERT(autoWritableJitCodeActive_
!= b
,
954 "AutoWritableJitCode should not be nested.");
955 autoWritableJitCodeActive_
= b
;
958 /* See comment for JS::SetOutOfMemoryCallback in js/MemoryCallbacks.h. */
959 js::MainThreadData
<JS::OutOfMemoryCallback
> oomCallback
;
960 js::MainThreadData
<void*> oomCallbackData
;
963 * Debugger.Memory functions like takeCensus use this embedding-provided
964 * function to assess the size of malloc'd blocks of memory.
966 js::MainThreadData
<mozilla::MallocSizeOf
> debuggerMallocSizeOf
;
968 /* Last time at which an animation was played for this runtime. */
969 js::MainThreadData
<mozilla::TimeStamp
> lastAnimationTime
;
972 /* The stack format for the current runtime. Only valid on non-child
974 mozilla::Atomic
<js::StackFormat
, mozilla::ReleaseAcquire
> stackFormat_
;
977 js::StackFormat
stackFormat() const {
978 const JSRuntime
* rt
= this;
979 while (rt
->parentRuntime
) {
980 MOZ_ASSERT(rt
->stackFormat_
== js::StackFormat::Default
);
981 rt
= rt
->parentRuntime
;
983 MOZ_ASSERT(rt
->stackFormat_
!= js::StackFormat::Default
);
984 return rt
->stackFormat_
;
986 void setStackFormat(js::StackFormat format
) {
987 MOZ_ASSERT(!parentRuntime
);
988 MOZ_ASSERT(format
!= js::StackFormat::Default
);
989 stackFormat_
= format
;
993 // Warning: no data should be accessed in these caches from another thread,
994 // but Ion needs to be able to access addresses inside here, which should be
995 // safe, as the actual cache lookups will be performed on the main thread
996 // through jitted code.
997 js::MainThreadOrIonCompileData
<js::RuntimeCaches
> caches_
;
1000 js::RuntimeCaches
& caches() { return caches_
.ref(); }
1002 // List of all the live wasm::Instances in the runtime. Equal to the union
1003 // of all instances registered in all JS::Realms. Accessed from watchdog
1004 // threads for purposes of wasm::InterruptRunningCode().
1005 js::ExclusiveData
<js::wasm::InstanceVector
> wasmInstances
;
1007 // A counter used when recording the order in which modules had their
1008 // AsyncEvaluation field set to true. This is used to order queued
1009 // evaluations. This is reset when the last module that was async evaluating
1012 // See https://tc39.es/ecma262/#sec-async-module-execution-fulfilled step 10
1014 js::MainThreadData
<uint32_t> moduleAsyncEvaluatingPostOrder
;
1016 // The implementation-defined abstract operation HostResolveImportedModule.
1017 js::MainThreadData
<JS::ModuleResolveHook
> moduleResolveHook
;
1019 // A hook that implements the abstract operations
1020 // HostGetImportMetaProperties and HostFinalizeImportMeta.
1021 js::MainThreadData
<JS::ModuleMetadataHook
> moduleMetadataHook
;
1023 // A hook that implements the abstract operation
1024 // HostImportModuleDynamically. This is also used to enable/disable dynamic
1025 // module import and can accessed by off-thread parsing.
1026 mozilla::Atomic
<JS::ModuleDynamicImportHook
> moduleDynamicImportHook
;
1028 // The supported module import assertions.
1029 // https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions
1030 js::MainThreadData
<JS::ImportAssertionVector
> supportedImportAssertions
;
1032 // Hooks called when script private references are created and destroyed.
1033 js::MainThreadData
<JS::ScriptPrivateReferenceHook
> scriptPrivateAddRefHook
;
1034 js::MainThreadData
<JS::ScriptPrivateReferenceHook
> scriptPrivateReleaseHook
;
1036 void addRefScriptPrivate(const JS::Value
& value
) {
1037 if (!value
.isUndefined() && scriptPrivateAddRefHook
) {
1038 scriptPrivateAddRefHook(value
);
1042 void releaseScriptPrivate(const JS::Value
& value
) {
1043 if (!value
.isUndefined() && scriptPrivateReleaseHook
) {
1044 scriptPrivateReleaseHook(value
);
1049 #if defined(NIGHTLY_BUILD)
1050 // Support for informing the embedding of any error thrown.
1051 // This mechanism is designed to let the embedding
1052 // log/report/fail in case certain errors are thrown
1053 // (e.g. SyntaxError, ReferenceError or TypeError
1054 // in critical code).
1055 struct ErrorInterceptionSupport
{
1056 ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {}
1058 // true if the error interceptor is currently executing,
1059 // false otherwise. Used to avoid infinite loops.
1062 // if non-null, any call to `setPendingException`
1063 // in this runtime will trigger the call to `interceptor`
1064 JSErrorInterceptor
* interceptor
;
1066 ErrorInterceptionSupport errorInterception
;
1067 #endif // defined(NIGHTLY_BUILD)
1070 JS::GlobalInitializeCallback
getShadowRealmInitializeGlobalCallback() {
1071 return shadowRealmInitializeGlobalCallback
;
1074 JS::GlobalCreationCallback
getShadowRealmGlobalCreationCallback() {
1075 return shadowRealmGlobalCreationCallback
;
1078 js::MainThreadData
<JS::GlobalInitializeCallback
>
1079 shadowRealmInitializeGlobalCallback
;
1081 js::MainThreadData
<JS::GlobalCreationCallback
>
1082 shadowRealmGlobalCreationCallback
;
1087 void Metrics::addTelemetry(JSMetric id
, uint32_t sample
) {
1088 rt_
->addTelemetry(id
, sample
);
1091 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(Value
* vec
, size_t len
) {
1092 // Don't PodZero here because JS::Value is non-trivial.
1093 for (size_t i
= 0; i
< len
; i
++) {
1094 vec
[i
].setDouble(+0.0);
1098 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(Value
* beg
, Value
* end
) {
1099 MakeRangeGCSafe(beg
, end
- beg
);
1102 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(jsid
* beg
, jsid
* end
) {
1103 std::fill(beg
, end
, PropertyKey::Int(0));
1106 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(jsid
* vec
, size_t len
) {
1107 MakeRangeGCSafe(vec
, vec
+ len
);
1110 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(Shape
** beg
, Shape
** end
) {
1111 std::fill(beg
, end
, nullptr);
1114 static MOZ_ALWAYS_INLINE
void MakeRangeGCSafe(Shape
** vec
, size_t len
) {
1115 MakeRangeGCSafe(vec
, vec
+ len
);
1118 static MOZ_ALWAYS_INLINE
void SetValueRangeToUndefined(Value
* beg
, Value
* end
) {
1119 for (Value
* v
= beg
; v
!= end
; ++v
) {
1124 static MOZ_ALWAYS_INLINE
void SetValueRangeToUndefined(Value
* vec
, size_t len
) {
1125 SetValueRangeToUndefined(vec
, vec
+ len
);
1128 static MOZ_ALWAYS_INLINE
void SetValueRangeToNull(Value
* beg
, Value
* end
) {
1129 for (Value
* v
= beg
; v
!= end
; ++v
) {
1134 static MOZ_ALWAYS_INLINE
void SetValueRangeToNull(Value
* vec
, size_t len
) {
1135 SetValueRangeToNull(vec
, vec
+ len
);
1138 extern const JSSecurityCallbacks NullSecurityCallbacks
;
1140 // This callback is set by JS::SetProcessLargeAllocationFailureCallback
1141 // and may be null. See comment in jsapi.h.
1142 extern mozilla::Atomic
<JS::LargeAllocationFailureCallback
>
1143 OnLargeAllocationFailure
;
1145 // This callback is set by JS::SetBuildIdOp and may be null. See comment in
1147 extern mozilla::Atomic
<JS::BuildIdOp
> GetBuildId
;
1149 extern JS::FilenameValidationCallback gFilenameValidationCallback
;
1151 } /* namespace js */
1153 #endif /* vm_Runtime_h */