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/Atomics.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/DoublyLinkedList.h"
13 #include "mozilla/LinkedList.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/MaybeOneOf.h"
16 #include "mozilla/MemoryReporting.h"
17 #include "mozilla/ThreadLocal.h"
18 #include "mozilla/TimeStamp.h"
19 #include "mozilla/Vector.h"
20
21 #include <algorithm>
22 #include <setjmp.h>
23
24 #include "jsapi.h"
25
26 #include "builtin/AtomicsObject.h"
27 #ifdef JS_HAS_INTL_API
28 # include "builtin/intl/SharedIntlData.h"
29 #endif
30 #include "frontend/BinASTRuntimeSupport.h"
31 #include "frontend/NameCollections.h"
32 #include "gc/GCRuntime.h"
33 #include "gc/Tracer.h"
34 #ifndef ENABLE_NEW_REGEXP
35 # include "irregexp/RegExpStack.h"
36 #endif
37 #include "js/AllocationRecording.h"
38 #include "js/BuildId.h" // JS::BuildIdOp
39 #include "js/CompilationAndEvaluation.h"
40 #include "js/Debug.h"
41 #include "js/experimental/SourceHook.h" // js::SourceHook
42 #include "js/GCVector.h"
43 #include "js/HashTable.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"
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/JSScript.h"
61 #include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseRuntimeState
62 #include "vm/Scope.h"
63 #include "vm/SharedImmutableStringsCache.h"
64 #include "vm/Stack.h"
65 #include "vm/SymbolType.h"
66 #include "wasm/WasmTypes.h"
67
68 namespace js {
69
70 class AutoAssertNoContentJS;
71 class AutoKeepAtoms;
72 class EnterDebuggeeNoExecute;
73 #ifdef JS_TRACE_LOGGING
74 class TraceLoggerThread;
75 #endif
76
77 } // namespace js
78
79 struct DtoaState;
80 struct JSLocaleCallbacks;
81
82 #ifdef JS_SIMULATOR_ARM64
83 namespace vixl {
84 class Simulator;
85 }
86 #endif
87
88 namespace js {
89
90 extern MOZ_COLD void ReportOutOfMemory(JSContext* cx);
91
92 /* Different signature because the return type has MOZ_MUST_USE_TYPE. */
93 extern MOZ_COLD mozilla::GenericErrorResult<OOM&> ReportOutOfMemoryResult(
94 JSContext* cx);
95
96 extern MOZ_COLD void ReportAllocationOverflow(JSContext* maybecx);
97
98 extern MOZ_COLD void ReportOverRecursed(JSContext* cx);
99
100 class Activation;
101 class ActivationIterator;
102
103 namespace jit {
104 class JitRuntime;
105 class JitActivation;
106 struct PcScriptCache;
107 class CompileRuntime;
108
109 #ifdef JS_SIMULATOR_ARM64
110 typedef vixl::Simulator Simulator;
111 #elif defined(JS_SIMULATOR)
112 class Simulator;
113 #endif
114 } // namespace jit
115
116 // [SMDOC] JS Engine Threading
117 //
118 // Threads interacting with a runtime are divided into two categories:
119 //
120 // - The main thread is capable of running JS. There's at most one main thread
121 // per runtime.
122 //
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.
130
131 } /* namespace js */
132
133 namespace JS {
134 struct RuntimeSizes;
135 } // namespace JS
136
137 /* Various built-in or commonly-used names pinned on first context. */
138 struct JSAtomState {
139 #define PROPERTYNAME_FIELD(idpart, id, text) js::ImmutablePropertyNamePtr id;
140 FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
141 #undef PROPERTYNAME_FIELD
142 #define PROPERTYNAME_FIELD(name, clasp) js::ImmutablePropertyNamePtr name;
JS_FOR_EACH_PROTOTYPEJSAtomState143 JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
144 #undef PROPERTYNAME_FIELD
145 #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr name;
146 JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
147 #undef PROPERTYNAME_FIELD
148 #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr Symbol_##name;
149 JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
150 #undef PROPERTYNAME_FIELD
151
152 js::ImmutablePropertyNamePtr* wellKnownSymbolNames() {
153 #define FIRST_PROPERTYNAME_FIELD(name) return &name;
154 JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
155 #undef FIRST_PROPERTYNAME_FIELD
156 }
157
wellKnownSymbolDescriptionsJSAtomState158 js::ImmutablePropertyNamePtr* wellKnownSymbolDescriptions() {
159 #define FIRST_PROPERTYNAME_FIELD(name) return &Symbol_##name;
160 JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
161 #undef FIRST_PROPERTYNAME_FIELD
162 }
163 };
164
165 namespace js {
166
167 /*
168 * Storage for well-known symbols. It's a separate struct from the Runtime so
169 * that it can be shared across multiple runtimes. As in JSAtomState, each
170 * field is a smart pointer that's immutable once initialized.
171 * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
172 *
173 * Well-known symbols are never GC'd. The description() of each well-known
174 * symbol is a permanent atom.
175 */
176 struct WellKnownSymbols {
177 #define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
JS_FOR_EACH_WELL_KNOWN_SYMBOLWellKnownSymbols178 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
179 #undef DECLARE_SYMBOL
180
181 const ImmutableSymbolPtr& get(size_t u) const {
182 MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
183 const ImmutableSymbolPtr* symbols =
184 reinterpret_cast<const ImmutableSymbolPtr*>(this);
185 return symbols[u];
186 }
187
getWellKnownSymbols188 const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
189 return get(size_t(code));
190 }
191
192 WellKnownSymbols() = default;
193 WellKnownSymbols(const WellKnownSymbols&) = delete;
194 WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
195 };
196
197 #define NAME_OFFSET(name) offsetof(JSAtomState, name)
198
AtomStateOffsetToName(const JSAtomState & atomState,size_t offset)199 inline HandlePropertyName AtomStateOffsetToName(const JSAtomState& atomState,
200 size_t offset) {
201 return *reinterpret_cast<js::ImmutablePropertyNamePtr*>((char*)&atomState +
202 offset);
203 }
204
205 // There are several coarse locks in the enum below. These may be either
206 // per-runtime or per-process. When acquiring more than one of these locks,
207 // the acquisition must be done in the order below to avoid deadlocks.
208 enum RuntimeLock { HelperThreadStateLock, GCLock };
209
CanUseExtraThreads()210 inline bool CanUseExtraThreads() {
211 extern bool gCanUseExtraThreads;
212 return gCanUseExtraThreads;
213 }
214
215 void DisableExtraThreads();
216
217 using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
218
219 class AutoLockScriptData;
220
221 // Self-hosted lazy functions do not maintain a BaseScript as we can clone from
222 // the copy in the self-hosting zone. To allow these functions to be called by
223 // the JITs, we need a minimal script object. There is one instance per runtime.
224 struct SelfHostedLazyScript {
225 SelfHostedLazyScript() = default;
226
227 // Pointer to interpreter trampoline. This field is stored at same location as
228 // in BaseScript::jitCodeRaw_.
229 uint8_t* jitCodeRaw_ = nullptr;
230
offsetOfJitCodeRawSelfHostedLazyScript231 static constexpr size_t offsetOfJitCodeRaw() {
232 return offsetof(SelfHostedLazyScript, jitCodeRaw_);
233 }
234 };
235
236 } // namespace js
237
238 struct JSRuntime {
239 private:
240 friend class js::Activation;
241 friend class js::ActivationIterator;
242 friend class js::jit::JitActivation;
243 friend class js::jit::CompileRuntime;
244
245 /* Space for interpreter frames. */
246 js::MainThreadData<js::InterpreterStack> interpreterStack_;
247
248 public:
interpreterStackJSRuntime249 js::InterpreterStack& interpreterStack() { return interpreterStack_.ref(); }
250
251 /*
252 * If non-null, another runtime guaranteed to outlive this one and whose
253 * permanent data may be used by this one where possible.
254 */
255 JSRuntime* const parentRuntime;
256
257 #ifdef DEBUG
258 /* The number of child runtimes that have this runtime as their parent. */
259 mozilla::Atomic<size_t> childRuntimeCount;
260
261 class AutoUpdateChildRuntimeCount {
262 JSRuntime* parent_;
263
264 public:
AutoUpdateChildRuntimeCountJSRuntime265 explicit AutoUpdateChildRuntimeCount(JSRuntime* parent) : parent_(parent) {
266 if (parent_) {
267 parent_->childRuntimeCount++;
268 }
269 }
270
~AutoUpdateChildRuntimeCountJSRuntime271 ~AutoUpdateChildRuntimeCount() {
272 if (parent_) {
273 parent_->childRuntimeCount--;
274 }
275 }
276 };
277
278 AutoUpdateChildRuntimeCount updateChildRuntimeCount;
279 #endif
280
281 private:
282 #ifdef DEBUG
283 js::WriteOnceData<bool> initialized_;
284 #endif
285
286 // The JSContext* for the runtime's main thread. Immutable after this is set
287 // in JSRuntime::init.
288 JSContext* mainContext_;
289
290 public:
mainContextFromAnyThreadJSRuntime291 JSContext* mainContextFromAnyThread() const { return mainContext_; }
addressOfMainContextJSRuntime292 const void* addressOfMainContext() { return &mainContext_; }
293 js::Fprinter parserWatcherFile;
294
295 inline JSContext* mainContextFromOwnThread();
296
297 /*
298 * The start of the range stored in the profiler sample buffer, as measured
299 * after the most recent sample.
300 * All JitcodeGlobalTable entries referenced from a given sample are
301 * assigned the buffer position of the START of the sample. The buffer
302 * entries that reference the JitcodeGlobalTable entries will only ever be
303 * read from the buffer while the entire sample is still inside the buffer;
304 * if some buffer entries at the start of the sample have left the buffer,
305 * the entire sample will be considered inaccessible.
306 * This means that, once profilerSampleBufferRangeStart_ advances beyond
307 * the sample position that's stored on a JitcodeGlobalTable entry, the
308 * buffer entries that reference this JitcodeGlobalTable entry will be
309 * considered inaccessible, and those JitcodeGlobalTable entry can be
310 * disposed of.
311 */
312 mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire>
313 profilerSampleBufferRangeStart_;
314
profilerSampleBufferRangeStartJSRuntime315 mozilla::Maybe<uint64_t> profilerSampleBufferRangeStart() {
316 if (beingDestroyed_ || !geckoProfiler().enabled()) {
317 return mozilla::Nothing();
318 }
319 uint64_t rangeStart = profilerSampleBufferRangeStart_;
320 return mozilla::Some(rangeStart);
321 }
setProfilerSampleBufferRangeStartJSRuntime322 void setProfilerSampleBufferRangeStart(uint64_t rangeStart) {
323 profilerSampleBufferRangeStart_ = rangeStart;
324 }
325
326 /* Call this to accumulate telemetry data. */
327 js::MainThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
328
329 /* Call this to accumulate use counter data. */
330 js::MainThreadData<JSSetUseCounterCallback> useCounterCallback;
331
332 js::MainThreadData<JSGetElementCallback> getElementCallback;
333
334 public:
335 // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
336 // histogram. |key| provides an additional key to identify the histogram.
337 // |sample| is the data to add to the histogram.
338 void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
339
340 void setTelemetryCallback(JSRuntime* rt,
341 JSAccumulateTelemetryDataCallback callback);
342
343 void setElementCallback(JSRuntime* rt, JSGetElementCallback callback);
344
345 // Sets the use counter for a specific feature, measuring the presence or
346 // absence of usage of a feature on a specific web page and document which
347 // the passed JSObject belongs to.
348 void setUseCounter(JSObject* obj, JSUseCounter counter);
349
350 void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
351
352 public:
353 js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;
354 js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback;
355 js::UnprotectedData<JS::ReportStreamErrorCallback> reportStreamErrorCallback;
356
357 js::GlobalObject* getIncumbentGlobal(JSContext* cx);
358 bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job,
359 js::HandleObject promise,
360 js::Handle<js::GlobalObject*> incumbentGlobal);
361 void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
362 void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
363
364 /* Had an out-of-memory error which did not populate an exception. */
365 mozilla::Atomic<bool, mozilla::SequentiallyConsistent> hadOutOfMemory;
366
367 /*
368 * Allow relazifying functions in compartments that are active. This is
369 * only used by the relazifyFunctions() testing function.
370 */
371 js::MainThreadData<bool> allowRelazificationForTesting;
372
373 /* Zone destroy callback. */
374 js::MainThreadData<JSDestroyZoneCallback> destroyZoneCallback;
375
376 /* Compartment destroy callback. */
377 js::MainThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
378
379 /* Compartment memory reporting callback. */
380 js::MainThreadData<JSSizeOfIncludingThisCompartmentCallback>
381 sizeOfIncludingThisCompartmentCallback;
382
383 /* Callback for creating ubi::Nodes representing DOM node objects. Set by
384 * JS::ubi::SetConstructUbiNodeForDOMObjectCallback. Refer to
385 * js/public/UbiNode.h.
386 */
387 void (*constructUbiNodeForDOMObjectCallback)(void*, JSObject*) = nullptr;
388
389 /* Realm destroy callback. */
390 js::MainThreadData<JS::DestroyRealmCallback> destroyRealmCallback;
391
392 /* Call this to get the name of a realm. */
393 js::MainThreadData<JS::RealmNameCallback> realmNameCallback;
394
395 js::MainThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
396
397 js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks;
398 js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks;
399 js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
400 js::MainThreadData<JSReadPrincipalsOp> readPrincipals;
401
402 /* Optional warning reporter. */
403 js::MainThreadData<JS::WarningReporter> warningReporter;
404
405 // Lazy self-hosted functions use a shared SelfHostedLazyScript instance
406 // instead instead of a BaseScript. This contains the minimal pointers to
407 // trampolines for the scripts to support direct jitCodeRaw calls.
408 js::UnprotectedData<js::SelfHostedLazyScript> selfHostedLazyScript;
409
410 private:
411 /* Gecko profiling metadata */
412 js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_;
413
414 public:
geckoProfilerJSRuntime415 js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
416
417 // Heap GC roots for PersistentRooted pointers.
418 js::MainThreadData<mozilla::EnumeratedArray<
419 JS::RootKind, JS::RootKind::Limit,
420 mozilla::LinkedList<JS::PersistentRooted<void*>>>>
421 heapRoots;
422
423 void tracePersistentRoots(JSTracer* trc);
424 void finishPersistentRoots();
425
426 void finishRoots();
427
428 private:
429 js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
430
431 public:
setTrustedPrincipalsJSRuntime432 void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
trustedPrincipalsJSRuntime433 const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
434
435 js::MainThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
436 js::MainThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
437
438 js::MainThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
439
440 js::MainThreadData<js::CTypesActivityCallback> ctypesActivityCallback;
441
442 private:
443 js::WriteOnceData<const JSClass*> windowProxyClass_;
444
445 public:
maybeWindowProxyClassJSRuntime446 const JSClass* maybeWindowProxyClass() const { return windowProxyClass_; }
setWindowProxyClassJSRuntime447 void setWindowProxyClass(const JSClass* clasp) { windowProxyClass_ = clasp; }
448
449 private:
450 // List of non-ephemeron weak containers to sweep during
451 // beginSweepingSweepGroup.
452 js::MainThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>>
453 weakCaches_;
454
455 public:
weakCachesJSRuntime456 mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() {
457 return weakCaches_.ref();
458 }
registerWeakCacheJSRuntime459 void registerWeakCache(JS::detail::WeakCacheBase* cachep) {
460 weakCaches().insertBack(cachep);
461 }
462
463 template <typename T>
464 struct GlobalObjectWatchersLinkAccess {
GetJSRuntime::GlobalObjectWatchersLinkAccess465 static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
466 return aThis->onNewGlobalObjectWatchersLink;
467 }
468 };
469
470 using WatchersList =
471 mozilla::DoublyLinkedList<js::Debugger,
472 GlobalObjectWatchersLinkAccess<js::Debugger>>;
473
474 private:
475 /*
476 * List of all enabled Debuggers that have onNewGlobalObject handler
477 * methods established.
478 */
479 js::MainThreadData<WatchersList> onNewGlobalObjectWatchers_;
480
481 public:
onNewGlobalObjectWatchersJSRuntime482 WatchersList& onNewGlobalObjectWatchers() {
483 return onNewGlobalObjectWatchers_.ref();
484 }
485
486 private:
487 /* Linked list of all Debugger objects in the runtime. */
488 js::MainThreadData<mozilla::LinkedList<js::Debugger>> debuggerList_;
489
490 public:
debuggerListJSRuntime491 mozilla::LinkedList<js::Debugger>& debuggerList() {
492 return debuggerList_.ref();
493 }
494
495 private:
496 /*
497 * Lock used to protect the script data table, which can be used by
498 * off-thread parsing.
499 *
500 * Locking this only occurs if there is actually a thread other than the
501 * main thread which could access this.
502 */
503 js::Mutex scriptDataLock;
504 #ifdef DEBUG
505 bool activeThreadHasScriptDataAccess;
506 #endif
507
508 // Number of zones which may be operated on by helper threads.
509 mozilla::Atomic<size_t, mozilla::SequentiallyConsistent>
510 numActiveHelperThreadZones;
511
512 friend class js::AutoLockScriptData;
513
514 public:
515 void setUsedByHelperThread(JS::Zone* zone);
516 void clearUsedByHelperThread(JS::Zone* zone);
517
hasHelperThreadZonesJSRuntime518 bool hasHelperThreadZones() const { return numActiveHelperThreadZones > 0; }
519
520 #ifdef DEBUG
currentThreadHasScriptDataAccessJSRuntime521 bool currentThreadHasScriptDataAccess() const {
522 if (!hasHelperThreadZones()) {
523 return js::CurrentThreadCanAccessRuntime(this) &&
524 activeThreadHasScriptDataAccess;
525 }
526
527 return scriptDataLock.ownedByCurrentThread();
528 }
529
currentThreadHasAtomsTableAccessJSRuntime530 bool currentThreadHasAtomsTableAccess() const {
531 return js::CurrentThreadCanAccessRuntime(this) &&
532 atoms_->mainThreadHasAllLocks();
533 }
534 #endif
535
heapStateJSRuntime536 JS::HeapState heapState() const { return gc.heapState(); }
537
538 // How many realms there are across all zones. This number includes
539 // off-thread context realms, so it isn't necessarily equal to the
540 // number of realms visited by RealmsIter.
541 js::MainThreadData<size_t> numRealms;
542
543 // The Gecko Profiler may want to sample the allocations happening across the
544 // browser. This callback can be registered to record the allocation.
545 js::MainThreadData<JS::RecordAllocationsCallback> recordAllocationCallback;
546 js::MainThreadData<double> allocationSamplingProbability;
547
548 private:
549 // Number of debuggee realms in the runtime.
550 js::MainThreadData<size_t> numDebuggeeRealms_;
551
552 // Number of debuggee realms in the runtime observing code coverage.
553 js::MainThreadData<size_t> numDebuggeeRealmsObservingCoverage_;
554
555 public:
556 void incrementNumDebuggeeRealms();
557 void decrementNumDebuggeeRealms();
558
numDebuggeeRealmsJSRuntime559 size_t numDebuggeeRealms() const { return numDebuggeeRealms_; }
560
561 void incrementNumDebuggeeRealmsObservingCoverage();
562 void decrementNumDebuggeeRealmsObservingCoverage();
563
564 void startRecordingAllocations(double probability,
565 JS::RecordAllocationsCallback callback);
566 void stopRecordingAllocations();
567 void ensureRealmIsRecordingAllocations(JS::Handle<js::GlobalObject*> global);
568
569 /* Locale-specific callbacks for string conversion. */
570 js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks;
571
572 /* Default locale for Internationalization API */
573 js::MainThreadData<js::UniqueChars> defaultLocale;
574
575 /* If true, new scripts must be created with PC counter information. */
576 js::MainThreadOrIonCompileData<bool> profilingScripts;
577
578 /* Strong references on scripts held for PCCount profiling API. */
579 js::MainThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*>
580 scriptAndCountsVector;
581
582 private:
583 /* Code coverage output. */
584 js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
585
586 public:
lcovOutputJSRuntime587 js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
588
589 private:
590 js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
591
592 /*
593 * Self-hosting state cloned on demand into other compartments. Shared with
594 * the parent runtime if there is one.
595 */
596 js::WriteOnceData<js::NativeObject*> selfHostingGlobal_;
597
598 static js::GlobalObject* createSelfHostingGlobal(JSContext* cx);
599
600 public:
601 bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
602 js::MutableHandleValue vp);
603 JSFunction* getUnclonedSelfHostedFunction(JSContext* cx,
604 js::HandlePropertyName name);
605
606 MOZ_MUST_USE bool createJitRuntime(JSContext* cx);
jitRuntimeJSRuntime607 js::jit::JitRuntime* jitRuntime() const { return jitRuntime_.ref(); }
hasJitRuntimeJSRuntime608 bool hasJitRuntime() const { return !!jitRuntime_; }
609
610 private:
611 // Used to generate random keys for hash tables.
612 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
613 mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
614
615 // Used to generate random hash codes for symbols.
616 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG>
617 randomHashCodeGenerator_;
618
619 public:
620 mozilla::HashCodeScrambler randomHashCodeScrambler();
621 mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
622
623 js::HashNumber randomHashCode();
624
625 //-------------------------------------------------------------------------
626 // Self-hosting support
627 //-------------------------------------------------------------------------
628
hasInitializedSelfHostingJSRuntime629 bool hasInitializedSelfHosting() const { return selfHostingGlobal_; }
630
631 bool initSelfHosting(JSContext* cx);
632 void finishSelfHosting();
633 void traceSelfHostingGlobal(JSTracer* trc);
isSelfHostingGlobalJSRuntime634 bool isSelfHostingGlobal(JSObject* global) {
635 return global == selfHostingGlobal_;
636 }
637 bool createLazySelfHostedFunctionClone(JSContext* cx,
638 js::HandlePropertyName selfHostedName,
639 js::HandleAtom name, unsigned nargs,
640 js::HandleObject proto,
641 js::NewObjectKind newKind,
642 js::MutableHandleFunction fun);
643 bool cloneSelfHostedFunctionScript(JSContext* cx,
644 js::Handle<js::PropertyName*> name,
645 js::Handle<JSFunction*> targetFun);
646 bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
647 js::MutableHandleValue vp);
648 void assertSelfHostedFunctionHasCanonicalName(JSContext* cx,
649 js::HandlePropertyName name);
650 #if DEBUG
isSelfHostingZoneJSRuntime651 bool isSelfHostingZone(const JS::Zone* zone) const {
652 return selfHostingGlobal_ && selfHostingGlobal_->zone() == zone;
653 }
654 #endif
655
656 //-------------------------------------------------------------------------
657 // Locale information
658 //-------------------------------------------------------------------------
659
660 /*
661 * Set the default locale for the ECMAScript Internationalization API
662 * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
663 * Note that the Internationalization API encourages clients to
664 * specify their own locales.
665 * The locale string remains owned by the caller.
666 */
667 bool setDefaultLocale(const char* locale);
668
669 /* Reset the default locale to OS defaults. */
670 void resetDefaultLocale();
671
672 /* Gets current default locale. String remains owned by context. */
673 const char* getDefaultLocale();
674
675 /* Garbage collector state. */
676 js::gc::GCRuntime gc;
677
678 /* Garbage collector state has been successfully initialized. */
679 js::WriteOnceData<bool> gcInitialized;
680
hasZealModeJSRuntime681 bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
682
lockGCJSRuntime683 void lockGC() { gc.lockGC(); }
684
unlockGCJSRuntime685 void unlockGC() { gc.unlockGC(); }
686
687 js::WriteOnceData<js::PropertyName*> emptyString;
688
689 private:
690 js::MainThreadOrGCTaskData<JSFreeOp*> defaultFreeOp_;
691
692 public:
defaultFreeOpJSRuntime693 JSFreeOp* defaultFreeOp() {
694 MOZ_ASSERT(defaultFreeOp_);
695 return defaultFreeOp_;
696 }
697
698 #if !JS_HAS_INTL_API
699 /* Number localization, used by jsnum.cpp. */
700 js::WriteOnceData<const char*> thousandsSeparator;
701 js::WriteOnceData<const char*> decimalSeparator;
702 js::WriteOnceData<const char*> numGrouping;
703 #endif
704
705 private:
706 mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
707
708 public:
709 // If this particular JSRuntime has a SharedImmutableStringsCache, return a
710 // pointer to it, otherwise return nullptr.
maybeThisRuntimeSharedImmutableStringsJSRuntime711 js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
712 return sharedImmutableStrings_.isSome() ? &*sharedImmutableStrings_
713 : nullptr;
714 }
715
716 // Get a reference to this JSRuntime's or its parent's
717 // SharedImmutableStringsCache.
sharedImmutableStringsJSRuntime718 js::SharedImmutableStringsCache& sharedImmutableStrings() {
719 MOZ_ASSERT_IF(parentRuntime, !sharedImmutableStrings_);
720 MOZ_ASSERT_IF(!parentRuntime, sharedImmutableStrings_);
721 return parentRuntime ? parentRuntime->sharedImmutableStrings()
722 : *sharedImmutableStrings_;
723 }
724
725 private:
726 js::WriteOnceData<bool> beingDestroyed_;
727
728 public:
isBeingDestroyedJSRuntime729 bool isBeingDestroyed() const { return beingDestroyed_; }
730
731 private:
732 bool allowContentJS_;
733
734 public:
allowContentJSJSRuntime735 bool allowContentJS() const { return allowContentJS_; }
736
737 friend class js::AutoAssertNoContentJS;
738
739 private:
740 // Table of all atoms other than those in permanentAtoms and staticStrings.
741 js::WriteOnceData<js::AtomsTable*> atoms_;
742
743 // Set of all live symbols produced by Symbol.for(). All such symbols are
744 // allocated in the atoms zone. Reading or writing the symbol registry
745 // can only be done from the main thread.
746 js::MainThreadOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
747
748 js::WriteOnceData<js::AtomSet*> permanentAtomsDuringInit_;
749 js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms_;
750
751 public:
752 bool initializeAtoms(JSContext* cx);
753 void finishAtoms();
atomsAreFinishedJSRuntime754 bool atomsAreFinished() const {
755 return !atoms_ && !permanentAtomsDuringInit_;
756 }
757
atomsForSweepingJSRuntime758 js::AtomsTable* atomsForSweeping() {
759 MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
760 return atoms_;
761 }
762
atomsJSRuntime763 js::AtomsTable& atoms() {
764 MOZ_ASSERT(atoms_);
765 return *atoms_;
766 }
767
atomsZoneJSRuntime768 const JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) const {
769 return gc.atomsZone;
770 }
atomsZoneJSRuntime771 JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) {
772 return gc.atomsZone;
773 }
unsafeAtomsZoneJSRuntime774 JS::Zone* unsafeAtomsZone() { return gc.atomsZone; }
775
776 #ifdef DEBUG
isAtomsZoneJSRuntime777 bool isAtomsZone(const JS::Zone* zone) const { return zone == gc.atomsZone; }
778 #endif
779
780 bool activeGCInAtomsZone();
781
symbolRegistryJSRuntime782 js::SymbolRegistry& symbolRegistry() { return symbolRegistry_.ref(); }
783
784 // Permanent atoms are fixed during initialization of the runtime and are
785 // not modified or collected until the runtime is destroyed. These may be
786 // shared with another, longer living runtime through |parentRuntime| and
787 // can be freely accessed with no locking necessary.
788
789 // Permanent atoms pre-allocated for general use.
790 js::WriteOnceData<js::StaticStrings*> staticStrings;
791
792 // Cached pointers to various permanent property names.
793 js::WriteOnceData<JSAtomState*> commonNames;
794
795 // All permanent atoms in the runtime, other than those in staticStrings.
796 // Access to this does not require a lock because it is frozen and thus
797 // read-only.
permanentAtomsJSRuntime798 const js::FrozenAtomSet* permanentAtoms() const {
799 MOZ_ASSERT(permanentAtomsPopulated());
800 return permanentAtoms_.ref();
801 }
802
803 // The permanent atoms table is populated during initialization.
permanentAtomsPopulatedJSRuntime804 bool permanentAtomsPopulated() const { return permanentAtoms_; }
805
806 // For internal use, return the permanent atoms table while it is being
807 // populated.
permanentAtomsDuringInitJSRuntime808 js::AtomSet* permanentAtomsDuringInit() const {
809 MOZ_ASSERT(!permanentAtoms_);
810 return permanentAtomsDuringInit_.ref();
811 }
812
813 bool initMainAtomsTables(JSContext* cx);
814 void tracePermanentAtoms(JSTracer* trc);
815
816 // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
817 // these are shared with the parentRuntime, if any.
818 js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
819
820 #ifdef JS_HAS_INTL_API
821 /* Shared Intl data for this runtime. */
822 js::MainThreadData<js::intl::SharedIntlData> sharedIntlData;
823
824 void traceSharedIntlData(JSTracer* trc);
825 #endif
826
827 // Table of bytecode and other data that may be shared across scripts
828 // within the runtime. This may be modified by threads using
829 // AutoLockScriptData.
830 private:
831 js::ScriptDataLockData<js::RuntimeScriptDataTable> scriptDataTable_;
832
833 public:
scriptDataTableJSRuntime834 js::RuntimeScriptDataTable& scriptDataTable(
835 const js::AutoLockScriptData& lock) {
836 return scriptDataTable_.ref();
837 }
838
839 private:
840 static mozilla::Atomic<size_t> liveRuntimesCount;
841
842 public:
hasLiveRuntimesJSRuntime843 static bool hasLiveRuntimes() { return liveRuntimesCount > 0; }
844
845 explicit JSRuntime(JSRuntime* parentRuntime);
846 ~JSRuntime();
847
848 // destroyRuntime is used instead of a destructor, to ensure the downcast
849 // to JSContext remains valid. The final GC triggered here depends on this.
850 void destroyRuntime();
851
852 bool init(JSContext* cx, uint32_t maxbytes);
853
thisFromCtorJSRuntime854 JSRuntime* thisFromCtor() { return this; }
855
856 private:
857 // Number of live SharedArrayBuffer objects, including those in Wasm shared
858 // memories. uint64_t to avoid any risk of overflow.
859 js::MainThreadData<uint64_t> liveSABs;
860
861 public:
incSABCountJSRuntime862 void incSABCount() {
863 MOZ_RELEASE_ASSERT(liveSABs != UINT64_MAX);
864 liveSABs++;
865 }
866
decSABCountJSRuntime867 void decSABCount() {
868 MOZ_RELEASE_ASSERT(liveSABs > 0);
869 liveSABs--;
870 }
871
hasLiveSABsJSRuntime872 bool hasLiveSABs() const { return liveSABs > 0; }
873
874 public:
875 js::MainThreadData<JS::BeforeWaitCallback> beforeWaitCallback;
876 js::MainThreadData<JS::AfterWaitCallback> afterWaitCallback;
877
878 public:
reportAllocationOverflowJSRuntime879 void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
880
881 /*
882 * This should be called after system malloc/calloc/realloc returns nullptr
883 * to try to recove some memory or to report an error. For realloc, the
884 * original pointer must be passed as reallocPtr.
885 *
886 * The function must be called outside the GC lock.
887 */
888 JS_FRIEND_API void* onOutOfMemory(js::AllocFunction allocator,
889 arena_id_t arena, size_t nbytes,
890 void* reallocPtr = nullptr,
891 JSContext* maybecx = nullptr);
892
893 /* onOutOfMemory but can call OnLargeAllocationFailure. */
894 JS_FRIEND_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
895 arena_id_t arena, size_t nbytes,
896 void* reallocPtr = nullptr);
897
898 static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
899
900 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
901 JS::RuntimeSizes* rtSizes);
902
903 private:
904 // Settings for how helper threads can be used.
905 mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
906 offthreadIonCompilationEnabled_;
907 mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
908 parallelParsingEnabled_;
909
910 #ifdef DEBUG
911 mozilla::Atomic<uint32_t> offThreadParsesRunning_;
912 mozilla::Atomic<bool> offThreadParsingBlocked_;
913 #endif
914
915 js::MainThreadData<bool> autoWritableJitCodeActive_;
916
917 public:
918 // Note: these values may be toggled dynamically (in response to about:config
919 // prefs changing).
setOffthreadIonCompilationEnabledJSRuntime920 void setOffthreadIonCompilationEnabled(bool value) {
921 offthreadIonCompilationEnabled_ = value;
922 }
canUseOffthreadIonCompilationJSRuntime923 bool canUseOffthreadIonCompilation() const {
924 return offthreadIonCompilationEnabled_;
925 }
setParallelParsingEnabledJSRuntime926 void setParallelParsingEnabled(bool value) {
927 parallelParsingEnabled_ = value;
928 }
canUseParallelParsingJSRuntime929 bool canUseParallelParsing() const { return parallelParsingEnabled_; }
930
931 #ifdef DEBUG
932
incOffThreadParsesRunningJSRuntime933 void incOffThreadParsesRunning() {
934 MOZ_ASSERT(!isOffThreadParsingBlocked());
935 offThreadParsesRunning_++;
936 }
937
decOffThreadParsesRunningJSRuntime938 void decOffThreadParsesRunning() {
939 MOZ_ASSERT(isOffThreadParseRunning());
940 offThreadParsesRunning_--;
941 }
942
isOffThreadParseRunningJSRuntime943 bool isOffThreadParseRunning() const { return offThreadParsesRunning_; }
944
isOffThreadParsingBlockedJSRuntime945 bool isOffThreadParsingBlocked() const { return offThreadParsingBlocked_; }
setOffThreadParsingBlockedJSRuntime946 void setOffThreadParsingBlocked(bool blocked) {
947 MOZ_ASSERT(offThreadParsingBlocked_ != blocked);
948 MOZ_ASSERT(!isOffThreadParseRunning());
949 offThreadParsingBlocked_ = blocked;
950 }
951
952 #endif
953
toggleAutoWritableJitCodeActiveJSRuntime954 void toggleAutoWritableJitCodeActive(bool b) {
955 MOZ_ASSERT(autoWritableJitCodeActive_ != b,
956 "AutoWritableJitCode should not be nested.");
957 autoWritableJitCodeActive_ = b;
958 }
959
960 /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
961 js::MainThreadData<JS::OutOfMemoryCallback> oomCallback;
962 js::MainThreadData<void*> oomCallbackData;
963
964 /*
965 * Debugger.Memory functions like takeCensus use this embedding-provided
966 * function to assess the size of malloc'd blocks of memory.
967 */
968 js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
969
970 /* Last time at which an animation was played for this runtime. */
971 js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
972
973 private:
974 /* The stack format for the current runtime. Only valid on non-child
975 * runtimes. */
976 mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
977
978 public:
stackFormatJSRuntime979 js::StackFormat stackFormat() const {
980 const JSRuntime* rt = this;
981 while (rt->parentRuntime) {
982 MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
983 rt = rt->parentRuntime;
984 }
985 MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
986 return rt->stackFormat_;
987 }
setStackFormatJSRuntime988 void setStackFormat(js::StackFormat format) {
989 MOZ_ASSERT(!parentRuntime);
990 MOZ_ASSERT(format != js::StackFormat::Default);
991 stackFormat_ = format;
992 }
993
994 private:
995 js::MainThreadData<js::RuntimeCaches> caches_;
996
997 public:
cachesJSRuntime998 js::RuntimeCaches& caches() { return caches_.ref(); }
999
1000 // List of all the live wasm::Instances in the runtime. Equal to the union
1001 // of all instances registered in all JS::Realms. Accessed from watchdog
1002 // threads for purposes of wasm::InterruptRunningCode().
1003 js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
1004
1005 // The implementation-defined abstract operation HostResolveImportedModule.
1006 js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
1007
1008 // A hook that implements the abstract operations
1009 // HostGetImportMetaProperties and HostFinalizeImportMeta.
1010 js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
1011
1012 // A hook that implements the abstract operation
1013 // HostImportModuleDynamically. This is also used to enable/disable dynamic
1014 // module import and can accessed by off-thread parsing.
1015 mozilla::Atomic<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
1016
1017 // Hooks called when script private references are created and destroyed.
1018 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook;
1019 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook;
1020
addRefScriptPrivateJSRuntime1021 void addRefScriptPrivate(const JS::Value& value) {
1022 if (!value.isUndefined() && scriptPrivateAddRefHook) {
1023 scriptPrivateAddRefHook(value);
1024 }
1025 }
1026
releaseScriptPrivateJSRuntime1027 void releaseScriptPrivate(const JS::Value& value) {
1028 if (!value.isUndefined() && scriptPrivateReleaseHook) {
1029 scriptPrivateReleaseHook(value);
1030 }
1031 }
1032
1033 public:
1034 #if defined(JS_BUILD_BINAST)
binastJSRuntime1035 js::BinaryASTSupport& binast() { return binast_; }
1036
1037 private:
1038 js::BinaryASTSupport binast_;
1039 #endif // defined(JS_BUILD_BINAST)
1040
1041 public:
1042 #if defined(NIGHTLY_BUILD)
1043 // Support for informing the embedding of any error thrown.
1044 // This mechanism is designed to let the embedding
1045 // log/report/fail in case certain errors are thrown
1046 // (e.g. SyntaxError, ReferenceError or TypeError
1047 // in critical code).
1048 struct ErrorInterceptionSupport {
ErrorInterceptionSupportJSRuntime::ErrorInterceptionSupport1049 ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {}
1050
1051 // true if the error interceptor is currently executing,
1052 // false otherwise. Used to avoid infinite loops.
1053 bool isExecuting;
1054
1055 // if non-null, any call to `setPendingException`
1056 // in this runtime will trigger the call to `interceptor`
1057 JSErrorInterceptor* interceptor;
1058 };
1059 ErrorInterceptionSupport errorInterception;
1060 #endif // defined(NIGHTLY_BUILD)
1061 };
1062
1063 namespace js {
1064
MakeRangeGCSafe(Value * vec,size_t len)1065 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* vec, size_t len) {
1066 // Don't PodZero here because JS::Value is non-trivial.
1067 for (size_t i = 0; i < len; i++) {
1068 vec[i].setDouble(+0.0);
1069 }
1070 }
1071
MakeRangeGCSafe(Value * beg,Value * end)1072 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* beg, Value* end) {
1073 MakeRangeGCSafe(beg, end - beg);
1074 }
1075
MakeRangeGCSafe(jsid * beg,jsid * end)1076 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* beg, jsid* end) {
1077 std::fill(beg, end, INT_TO_JSID(0));
1078 }
1079
MakeRangeGCSafe(jsid * vec,size_t len)1080 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* vec, size_t len) {
1081 MakeRangeGCSafe(vec, vec + len);
1082 }
1083
MakeRangeGCSafe(Shape ** beg,Shape ** end)1084 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** beg, Shape** end) {
1085 std::fill(beg, end, nullptr);
1086 }
1087
MakeRangeGCSafe(Shape ** vec,size_t len)1088 static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** vec, size_t len) {
1089 MakeRangeGCSafe(vec, vec + len);
1090 }
1091
SetValueRangeToUndefined(Value * beg,Value * end)1092 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* beg, Value* end) {
1093 for (Value* v = beg; v != end; ++v) {
1094 v->setUndefined();
1095 }
1096 }
1097
SetValueRangeToUndefined(Value * vec,size_t len)1098 static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* vec, size_t len) {
1099 SetValueRangeToUndefined(vec, vec + len);
1100 }
1101
SetValueRangeToNull(Value * beg,Value * end)1102 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* beg, Value* end) {
1103 for (Value* v = beg; v != end; ++v) {
1104 v->setNull();
1105 }
1106 }
1107
SetValueRangeToNull(Value * vec,size_t len)1108 static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* vec, size_t len) {
1109 SetValueRangeToNull(vec, vec + len);
1110 }
1111
1112 extern const JSSecurityCallbacks NullSecurityCallbacks;
1113
1114 // This callback is set by JS::SetProcessLargeAllocationFailureCallback
1115 // and may be null. See comment in jsapi.h.
1116 extern mozilla::Atomic<JS::LargeAllocationFailureCallback>
1117 OnLargeAllocationFailure;
1118
1119 // This callback is set by JS::SetBuildIdOp and may be null. See comment in
1120 // jsapi.h.
1121 extern mozilla::Atomic<JS::BuildIdOp> GetBuildId;
1122
1123 extern JS::FilenameValidationCallback gFilenameValidationCallback;
1124
1125 // This callback is set by js::SetHelperThreadTaskCallback and may be null.
1126 // See comment in jsapi.h.
1127 extern void (*HelperThreadTaskCallback)(js::UniquePtr<js::RunnableTask>);
1128
1129 } /* namespace js */
1130
1131 #endif /* vm_Runtime_h */
1132