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