Runtime.h (41103B)
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/MemoryReporting.h" 17 #include "mozilla/TimeStamp.h" 18 #include "mozilla/XorShift128PlusRNG.h" 19 20 #include <algorithm> 21 #include <utility> 22 23 #ifdef JS_HAS_INTL_API 24 # include "builtin/intl/SharedIntlData.h" 25 #endif 26 #include "frontend/ScriptIndex.h" 27 #include "gc/GCRuntime.h" 28 #include "js/AllocationRecording.h" 29 #include "js/BuildId.h" // JS::BuildIdOp 30 #include "js/Context.h" 31 #include "js/DOMEventDispatch.h" 32 #include "js/experimental/CTypes.h" // JS::CTypesActivityCallback 33 #include "js/friend/StackLimits.h" // js::ReportOverRecursed 34 #include "js/friend/UsageStatistics.h" // JSAccumulateTelemetryDataCallback 35 #include "js/GCVector.h" 36 #include "js/HashTable.h" 37 #include "js/Initialization.h" 38 #include "js/MemoryCallbacks.h" 39 #include "js/Modules.h" // JS::Module{DynamicImport,Metadata,Resolve}Hook 40 #include "js/ScriptPrivate.h" 41 #include "js/shadow/Zone.h" 42 #include "js/ShadowRealmCallbacks.h" 43 #include "js/Stack.h" 44 #include "js/StreamConsumer.h" 45 #include "js/Symbol.h" 46 #include "js/UniquePtr.h" 47 #include "js/Utility.h" 48 #include "js/WaitCallbacks.h" 49 #include "js/Warnings.h" // JS::WarningReporter 50 #include "js/Zone.h" 51 #include "vm/Caches.h" // js::RuntimeCaches 52 #include "vm/CodeCoverage.h" 53 #include "vm/GeckoProfiler.h" 54 #include "vm/InvalidatingFuse.h" 55 #include "vm/JSScript.h" 56 #include "vm/Logging.h" 57 #include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseRuntimeState 58 #include "vm/RuntimeFuses.h" 59 #include "vm/SharedScriptDataTableHolder.h" // js::SharedScriptDataTableHolder 60 #include "vm/Stack.h" 61 #include "wasm/WasmTypeDecls.h" 62 63 struct JSAtomState; 64 struct JSClass; 65 struct JSErrorInterceptor; 66 struct JSWrapObjectCallbacks; 67 68 namespace js { 69 70 class AutoAssertNoContentJS; 71 class Debugger; 72 class EnterDebuggeeNoExecute; 73 class FrontendContext; 74 class PlainObject; 75 class StaticStrings; 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 extern MOZ_COLD void ReportAllocationOverflow(JSContext* maybecx); 92 extern MOZ_COLD void ReportAllocationOverflow(FrontendContext* fc); 93 extern MOZ_COLD void ReportOversizedAllocation(JSContext* cx, 94 const unsigned errorNumber); 95 96 class Activation; 97 class ActivationIterator; 98 class Shape; 99 class SourceHook; 100 101 namespace jit { 102 class JitRuntime; 103 class JitActivation; 104 struct PcScriptCache; 105 class CompileRuntime; 106 107 #ifdef JS_SIMULATOR_ARM64 108 using vixl::Simulator; 109 #elif defined(JS_SIMULATOR) 110 class Simulator; 111 #endif 112 } // namespace jit 113 114 namespace frontend { 115 struct CompilationInput; 116 struct CompilationStencil; 117 } // namespace frontend 118 119 // [SMDOC] JS Engine Threading 120 // 121 // Threads interacting with a runtime are divided into two categories: 122 // 123 // - The main thread is capable of running JS. There's at most one main thread 124 // per runtime. 125 // 126 // - Helper threads do not run JS, and are controlled or triggered by activity 127 // on the main thread (or main threads, since all runtimes in a process share 128 // helper threads). Helper threads may have exclusive access to zones created 129 // for them, for parsing and similar tasks, but their activities do not cause 130 // observable changes in script behaviors. Activity on helper threads may be 131 // referred to as happening 'off thread' or on a background thread in some 132 // parts of the VM. 133 134 } /* namespace js */ 135 136 namespace JS { 137 struct RuntimeSizes; 138 } // namespace JS 139 140 namespace js { 141 142 /* 143 * Storage for well-known symbols. It's a separate struct from the Runtime so 144 * that it can be shared across multiple runtimes. As in JSAtomState, each 145 * field is a smart pointer that's immutable once initialized. 146 * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>. 147 * 148 * Well-known symbols are never GC'd. The description() of each well-known 149 * symbol is a permanent atom. 150 */ 151 struct WellKnownSymbols { 152 #define DECLARE_SYMBOL(name) ImmutableTenuredPtr<JS::Symbol*> name; 153 JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL) 154 #undef DECLARE_SYMBOL 155 156 const ImmutableTenuredPtr<JS::Symbol*>& get(size_t u) const { 157 MOZ_ASSERT(u < JS::WellKnownSymbolLimit); 158 const ImmutableTenuredPtr<JS::Symbol*>* symbols = 159 reinterpret_cast<const ImmutableTenuredPtr<JS::Symbol*>*>(this); 160 return symbols[u]; 161 } 162 163 const ImmutableTenuredPtr<JS::Symbol*>& get(JS::SymbolCode code) const { 164 return get(size_t(code)); 165 } 166 167 WellKnownSymbols() = default; 168 WellKnownSymbols(const WellKnownSymbols&) = delete; 169 WellKnownSymbols& operator=(const WellKnownSymbols&) = delete; 170 }; 171 172 // There are several coarse locks in the enum below. These may be either 173 // per-runtime or per-process. When acquiring more than one of these locks, 174 // the acquisition must be done in the order below to avoid deadlocks. 175 enum RuntimeLock { HelperThreadStateLock, GCLock }; 176 177 inline bool CanUseExtraThreads() { 178 extern bool gCanUseExtraThreads; 179 return gCanUseExtraThreads; 180 } 181 182 void DisableExtraThreads(); 183 184 using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>; 185 186 class AutoLockScriptData; 187 188 // Self-hosted lazy functions do not maintain a BaseScript as we can clone from 189 // the copy in the self-hosting zone. To allow these functions to be called by 190 // the JITs, we need a minimal script object. There is one instance per runtime. 191 struct SelfHostedLazyScript { 192 SelfHostedLazyScript() = default; 193 194 // Pointer to interpreter trampoline. This field is stored at same location as 195 // in BaseScript::jitCodeRaw_. 196 uint8_t* jitCodeRaw_ = nullptr; 197 198 // Warm-up count of zero. This field is stored at the same offset as 199 // BaseScript::warmUpData_. 200 ScriptWarmUpData warmUpData_ = {}; 201 202 static constexpr size_t offsetOfJitCodeRaw() { 203 return offsetof(SelfHostedLazyScript, jitCodeRaw_); 204 } 205 static constexpr size_t offsetOfWarmUpData() { 206 return offsetof(SelfHostedLazyScript, warmUpData_); 207 } 208 }; 209 210 // An interface for reporting telemetry from within SpiderMonkey. Reporting data 211 // to this interface will forward it to the embedding if a telemetry callback 212 // was registered. It is the embedding's responsibility to store and/or combine 213 // repeated samples for each metric. 214 class Metrics { 215 private: 216 JSRuntime* rt_; 217 218 public: 219 explicit Metrics(JSRuntime* rt) : rt_(rt) {} 220 221 // Records a TimeDuration metric. These are converted to integers when being 222 // recorded so choose an appropriate scale. In the future these will be Glean 223 // Timing Distribution metrics. 224 struct TimeDuration_S { 225 using SourceType = mozilla::TimeDuration; 226 static uint32_t convert(SourceType td) { return uint32_t(td.ToSeconds()); } 227 }; 228 struct TimeDuration_MS { 229 using SourceType = mozilla::TimeDuration; 230 static uint32_t convert(SourceType td) { 231 return uint32_t(td.ToMilliseconds()); 232 } 233 }; 234 struct TimeDuration_US { 235 using SourceType = mozilla::TimeDuration; 236 static uint32_t convert(SourceType td) { 237 return uint32_t(td.ToMicroseconds()); 238 } 239 }; 240 241 // Record a metric in bytes. In the future these will be Glean Memory 242 // Distribution metrics. 243 struct MemoryDistribution { 244 using SourceType = size_t; 245 static uint32_t convert(SourceType sz) { 246 return static_cast<uint32_t>(std::min(sz, size_t(UINT32_MAX))); 247 } 248 }; 249 250 // Record a metric for a quanity of items. This doesn't currently have a Glean 251 // analogue and we avoid using MemoryDistribution directly to avoid confusion 252 // about units. 253 using QuantityDistribution = MemoryDistribution; 254 255 // Record the distribution of boolean values. In the future this will be a 256 // Glean Rate metric. 257 struct Boolean { 258 using SourceType = bool; 259 static uint32_t convert(SourceType sample) { 260 return static_cast<uint32_t>(sample); 261 } 262 }; 263 264 // Record the distribution of an enumeration value. This records integer 265 // values so take care not to redefine the value of enum values. In the 266 // future, these should become Glean Labeled Counter metrics. 267 struct Enumeration { 268 using SourceType = unsigned int; 269 static uint32_t convert(SourceType sample) { 270 MOZ_ASSERT(sample <= 100); 271 return static_cast<uint32_t>(sample); 272 } 273 }; 274 275 // Record a percentage distribution in the range 0 to 100. This takes a double 276 // and converts it to an integer. In the future, this will be a Glean Custom 277 // Distribution unless they add a better match. 278 struct Percentage { 279 using SourceType = double; 280 static uint32_t convert(SourceType sample) { 281 MOZ_ASSERT(sample >= 0.0 && sample <= 100.0); 282 return static_cast<uint32_t>(sample); 283 } 284 }; 285 286 // Record an unsigned integer. 287 struct Integer { 288 using SourceType = uint32_t; 289 static uint32_t convert(SourceType sample) { return sample; } 290 }; 291 292 inline void addTelemetry(JSMetric id, uint32_t sample); 293 294 #define DECLARE_METRIC_HELPER(NAME, TY) \ 295 void NAME(TY::SourceType sample) { \ 296 addTelemetry(JSMetric::NAME, TY::convert(sample)); \ 297 } 298 FOR_EACH_JS_METRIC(DECLARE_METRIC_HELPER) 299 #undef DECLARE_METRIC_HELPER 300 }; 301 302 } // namespace js 303 304 struct JSRuntime { 305 private: 306 friend class js::Activation; 307 friend class js::ActivationIterator; 308 friend class js::jit::JitActivation; 309 friend class js::jit::CompileRuntime; 310 311 /* Space for interpreter frames. */ 312 js::MainThreadData<js::InterpreterStack> interpreterStack_; 313 314 #ifdef ENABLE_PORTABLE_BASELINE_INTERP 315 /* Space for portable baseline interpreter frames. */ 316 js::MainThreadData<js::PortableBaselineStack> portableBaselineStack_; 317 #endif 318 319 public: 320 js::InterpreterStack& interpreterStack() { return interpreterStack_.ref(); } 321 #ifdef ENABLE_PORTABLE_BASELINE_INTERP 322 js::PortableBaselineStack& portableBaselineStack() { 323 return portableBaselineStack_.ref(); 324 } 325 #endif 326 327 /* 328 * If non-null, another runtime guaranteed to outlive this one and whose 329 * permanent data may be used by this one where possible. 330 */ 331 JSRuntime* const parentRuntime; 332 333 bool isMainRuntime() const { return !parentRuntime; } 334 335 #ifdef DEBUG 336 /* The number of child runtimes that have this runtime as their parent. */ 337 mozilla::Atomic<size_t> childRuntimeCount; 338 339 class AutoUpdateChildRuntimeCount { 340 JSRuntime* parent_; 341 342 public: 343 explicit AutoUpdateChildRuntimeCount(JSRuntime* parent) : parent_(parent) { 344 if (parent_) { 345 parent_->childRuntimeCount++; 346 } 347 } 348 349 ~AutoUpdateChildRuntimeCount() { 350 if (parent_) { 351 parent_->childRuntimeCount--; 352 } 353 } 354 }; 355 356 AutoUpdateChildRuntimeCount updateChildRuntimeCount; 357 #endif 358 359 private: 360 #ifdef DEBUG 361 js::WriteOnceData<bool> initialized_; 362 #endif 363 364 // The JSContext* for the runtime's main thread. Immutable after this is set 365 // in JSRuntime::init. 366 JSContext* mainContext_; 367 368 public: 369 JSContext* mainContextFromAnyThread() const { return mainContext_; } 370 const void* addressOfMainContext() { return &mainContext_; } 371 js::Fprinter parserWatcherFile; 372 373 inline JSContext* mainContextFromOwnThread(); 374 375 js::Metrics metrics() { return js::Metrics(this); } 376 377 /* 378 * The start of the range stored in the profiler sample buffer, as measured 379 * after the most recent sample. 380 * All JitcodeGlobalTable entries referenced from a given sample are 381 * assigned the buffer position of the START of the sample. The buffer 382 * entries that reference the JitcodeGlobalTable entries will only ever be 383 * read from the buffer while the entire sample is still inside the buffer; 384 * if some buffer entries at the start of the sample have left the buffer, 385 * the entire sample will be considered inaccessible. 386 * This means that, once profilerSampleBufferRangeStart_ advances beyond 387 * the sample position that's stored on a JitcodeGlobalTable entry, the 388 * buffer entries that reference this JitcodeGlobalTable entry will be 389 * considered inaccessible, and those JitcodeGlobalTable entry can be 390 * disposed of. 391 */ 392 mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire> 393 profilerSampleBufferRangeStart_; 394 395 mozilla::Maybe<uint64_t> profilerSampleBufferRangeStart() { 396 if (beingDestroyed_ || !geckoProfiler().enabled()) { 397 return mozilla::Nothing(); 398 } 399 uint64_t rangeStart = profilerSampleBufferRangeStart_; 400 return mozilla::Some(rangeStart); 401 } 402 void setProfilerSampleBufferRangeStart(uint64_t rangeStart) { 403 profilerSampleBufferRangeStart_ = rangeStart; 404 } 405 406 /* Call this to accumulate telemetry data. May be called from any thread; the 407 * embedder is responsible for locking. */ 408 JSAccumulateTelemetryDataCallback telemetryCallback; 409 410 /* Call this to accumulate use counter data. */ 411 js::MainThreadData<JSSetUseCounterCallback> useCounterCallback; 412 413 public: 414 // Accumulates data for Firefox telemetry. 415 void addTelemetry(JSMetric id, uint32_t sample); 416 417 void setTelemetryCallback(JSRuntime* rt, 418 JSAccumulateTelemetryDataCallback callback); 419 420 // Sets the use counter for a specific feature, measuring the presence or 421 // absence of usage of a feature on a specific web page and document which 422 // the passed JSObject belongs to. 423 void setUseCounter(JSObject* obj, JSUseCounter counter); 424 425 void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback); 426 427 public: 428 js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState; 429 js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback; 430 js::UnprotectedData<JS::ReportStreamErrorCallback> reportStreamErrorCallback; 431 432 bool getHostDefinedData(JSContext* cx, 433 JS::MutableHandle<JSObject*> data) const; 434 435 bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job, 436 js::HandleObject promise, 437 js::HandleObject hostDefinedData); 438 void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise); 439 void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise); 440 441 /* Had an out-of-memory error which did not populate an exception. */ 442 mozilla::Atomic<bool, mozilla::SequentiallyConsistent> hadOutOfMemory; 443 444 /* 445 * Allow relazifying functions in compartments that are active. This is 446 * only used by the relazifyFunctions() testing function. 447 */ 448 js::MainThreadData<bool> allowRelazificationForTesting; 449 450 /* Zone destroy callback. */ 451 js::MainThreadData<JSDestroyZoneCallback> destroyZoneCallback; 452 453 /* Compartment destroy callback. */ 454 js::MainThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback; 455 456 /* Compartment memory reporting callback. */ 457 js::MainThreadData<JSSizeOfIncludingThisCompartmentCallback> 458 sizeOfIncludingThisCompartmentCallback; 459 460 /* DOM event dispatch callback for testing. */ 461 js::MainThreadData<JS::DispatchDOMEventCallback> dispatchDOMEventCallback; 462 463 /* Callback for creating ubi::Nodes representing DOM node objects. Set by 464 * JS::ubi::SetConstructUbiNodeForDOMObjectCallback. Refer to 465 * js/public/UbiNode.h. 466 */ 467 void (*constructUbiNodeForDOMObjectCallback)(void*, JSObject*) = nullptr; 468 469 /* Realm destroy callback. */ 470 js::MainThreadData<JS::DestroyRealmCallback> destroyRealmCallback; 471 472 /* Call this to get the name of a realm. */ 473 js::MainThreadData<JS::RealmNameCallback> realmNameCallback; 474 475 js::MainThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook; 476 477 js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks; 478 js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks; 479 js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals; 480 js::MainThreadData<JSReadPrincipalsOp> readPrincipals; 481 482 js::MainThreadData<JS::EnsureCanAddPrivateElementOp> canAddPrivateElement; 483 484 /* Optional warning reporter. */ 485 js::MainThreadData<JS::WarningReporter> warningReporter; 486 487 // Lazy self-hosted functions use a shared SelfHostedLazyScript instance 488 // instead instead of a BaseScript. This contains the minimal pointers to 489 // trampolines for the scripts to support direct jitCodeRaw calls. 490 js::UnprotectedData<js::SelfHostedLazyScript> selfHostedLazyScript; 491 492 private: 493 // The self-hosted JS code is compiled as a Stencil which is then attached to 494 // the Runtime. This is used to instantiate functions into realms on demand. 495 js::WriteOnceData<js::frontend::CompilationInput*> selfHostStencilInput_; 496 js::WriteOnceData<js::frontend::CompilationStencil*> selfHostStencil_; 497 498 public: 499 // The self-hosted stencil is immutable once attached to the runtime, so 500 // worker runtimes directly use the stencil on the parent runtime. 501 js::frontend::CompilationInput& selfHostStencilInput() { 502 MOZ_ASSERT(hasSelfHostStencil()); 503 return *selfHostStencilInput_.ref(); 504 } 505 js::frontend::CompilationStencil& selfHostStencil() { 506 MOZ_ASSERT(hasSelfHostStencil()); 507 return *selfHostStencil_.ref(); 508 } 509 bool hasSelfHostStencil() const { return bool(selfHostStencil_.ref()); } 510 511 // A mapping from the name of self-hosted function to a ScriptIndex range of 512 // the function and inner-functions within the self-hosted stencil. 513 js::MainThreadData< 514 JS::GCHashMap<js::PreBarriered<JSAtom*>, js::frontend::ScriptIndexRange, 515 js::DefaultHasher<JSAtom*>, js::SystemAllocPolicy>> 516 selfHostScriptMap; 517 518 struct JitCacheKey { 519 JitCacheKey(JSAtom* name, bool isDebuggee) 520 : name(name), isDebuggee(isDebuggee) {} 521 522 js::PreBarriered<JSAtom*> name; 523 bool isDebuggee; 524 525 void trace(JSTracer* trc) { 526 TraceNullableEdge(trc, &name, "JitCacheKey::name"); 527 } 528 }; 529 530 struct JitCacheKeyHasher : public js::DefaultHasher<JitCacheKey> { 531 using PreBarrieredAtomHasher = DefaultHasher<js::PreBarriered<JSAtom*>>; 532 533 static js::HashNumber hash(const Lookup& key) { 534 return mozilla::HashGeneric(key.name->hash(), key.isDebuggee); 535 } 536 537 static bool match(const JitCacheKey& key, const Lookup& lookup) { 538 return PreBarrieredAtomHasher::match(key.name, lookup.name) && 539 key.isDebuggee == lookup.isDebuggee; 540 } 541 }; 542 543 // A cache for a self-hosted function's JitCode (managed through a 544 // BaselineScript) keyed by script name and debuggee status. 545 js::MainThreadData<js::GCHashMap<JitCacheKey, js::jit::BaselineScript*, 546 JitCacheKeyHasher, js::SystemAllocPolicy>> 547 selfHostJitCache; 548 549 void clearSelfHostedJitCache(); 550 551 private: 552 /* Gecko profiling metadata */ 553 js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_; 554 555 public: 556 js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); } 557 558 // Heap GC roots for PersistentRooted pointers. 559 js::MainThreadData<mozilla::EnumeratedArray< 560 JS::RootKind, mozilla::LinkedList<js::PersistentRootedBase>, 561 size_t(JS::RootKind::Limit)>> 562 heapRoots; 563 564 void tracePersistentRoots(JSTracer* trc); 565 void finishPersistentRoots(); 566 567 void finishRoots(); 568 569 private: 570 js::UnprotectedData<const JSPrincipals*> trustedPrincipals_; 571 572 public: 573 void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; } 574 const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; } 575 576 void commitPendingWrapperPreservations(); 577 void commitPendingWrapperPreservations(JS::Zone* zone); 578 579 js::MainThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks; 580 js::MainThreadData<js::PreserveWrapperCallback> preserveWrapperCallback; 581 js::MainThreadData<js::HasReleasedWrapperCallback> hasReleasedWrapperCallback; 582 583 js::MainThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer; 584 585 js::MainThreadData<JS::CTypesActivityCallback> ctypesActivityCallback; 586 587 private: 588 // Script sources to compress off-thread. Only accessed by the main thread or 589 // off-thread GC sweeping (GCRuntime::sweepCompressionTasks). 590 using PendingCompressions = 591 js::Vector<js::PendingSourceCompressionEntry, 4, js::SystemAllocPolicy>; 592 js::MainThreadOrGCTaskData<PendingCompressions> pendingCompressions_; 593 594 public: 595 [[nodiscard]] bool addPendingCompressionEntry(js::ScriptSource* source) { 596 return pendingCompressions().emplaceBack(this, source); 597 } 598 PendingCompressions& pendingCompressions() { 599 return pendingCompressions_.ref(); 600 } 601 602 private: 603 js::WriteOnceData<const JSClass*> windowProxyClass_; 604 605 public: 606 const JSClass* maybeWindowProxyClass() const { return windowProxyClass_; } 607 void setWindowProxyClass(const JSClass* clasp) { windowProxyClass_ = clasp; } 608 609 private: 610 // List of non-ephemeron weak containers to sweep during 611 // beginSweepingSweepGroup. 612 js::MainThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>> 613 weakCaches_; 614 615 public: 616 mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() { 617 return weakCaches_.ref(); 618 } 619 void registerWeakCache(JS::detail::WeakCacheBase* cachep) { 620 weakCaches().insertBack(cachep); 621 } 622 623 template <typename T> 624 struct GlobalObjectWatchersLinkAccess { 625 static const mozilla::DoublyLinkedListElement<T>& Get(const T* aThis) { 626 return aThis->onNewGlobalObjectWatchersLink; 627 } 628 static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) { 629 return aThis->onNewGlobalObjectWatchersLink; 630 } 631 }; 632 633 template <typename T> 634 struct GarbageCollectionWatchersLinkAccess { 635 static const mozilla::DoublyLinkedListElement<T>& Get(const T* aThis) { 636 return aThis->onGarbageCollectionWatchersLink; 637 } 638 static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) { 639 return aThis->onGarbageCollectionWatchersLink; 640 } 641 }; 642 643 using OnNewGlobalWatchersList = 644 mozilla::DoublyLinkedList<js::Debugger, 645 GlobalObjectWatchersLinkAccess<js::Debugger>>; 646 using OnGarbageCollectionWatchersList = mozilla::DoublyLinkedList< 647 js::Debugger, GarbageCollectionWatchersLinkAccess<js::Debugger>>; 648 649 private: 650 /* 651 * List of all enabled Debuggers that have onNewGlobalObject handler 652 * methods established. 653 */ 654 js::MainThreadData<OnNewGlobalWatchersList> onNewGlobalObjectWatchers_; 655 656 /* 657 * List of all enabled Debuggers that have onGarbageCollection handler 658 * methods established. 659 */ 660 js::MainThreadData<OnGarbageCollectionWatchersList> 661 onGarbageCollectionWatchers_; 662 663 public: 664 OnNewGlobalWatchersList& onNewGlobalObjectWatchers() { 665 return onNewGlobalObjectWatchers_.ref(); 666 } 667 668 OnGarbageCollectionWatchersList& onGarbageCollectionWatchers() { 669 return onGarbageCollectionWatchers_.ref(); 670 } 671 672 private: 673 /* Linked list of all Debugger objects in the runtime. */ 674 js::MainThreadData<mozilla::LinkedList<js::Debugger>> debuggerList_; 675 676 public: 677 mozilla::LinkedList<js::Debugger>& debuggerList() { 678 return debuggerList_.ref(); 679 } 680 681 public: 682 JS::HeapState heapState() const { return gc.heapState(); } 683 684 // How many realms there are across all zones. This number includes 685 // off-thread context realms, so it isn't necessarily equal to the 686 // number of realms visited by RealmsIter. 687 js::MainThreadData<size_t> numRealms; 688 689 // The Gecko Profiler may want to sample the allocations happening across the 690 // browser. This callback can be registered to record the allocation. 691 js::MainThreadData<JS::RecordAllocationsCallback> recordAllocationCallback; 692 js::MainThreadData<double> allocationSamplingProbability; 693 694 private: 695 // Number of debuggee realms in the runtime. 696 js::MainThreadData<size_t> numDebuggeeRealms_; 697 698 // Number of debuggee realms in the runtime observing code coverage. 699 js::MainThreadData<size_t> numDebuggeeRealmsObservingCoverage_; 700 701 public: 702 void incrementNumDebuggeeRealms(); 703 void decrementNumDebuggeeRealms(); 704 705 size_t numDebuggeeRealms() const { return numDebuggeeRealms_; } 706 707 void incrementNumDebuggeeRealmsObservingCoverage(); 708 void decrementNumDebuggeeRealmsObservingCoverage(); 709 710 void startRecordingAllocations(double probability, 711 JS::RecordAllocationsCallback callback); 712 void stopRecordingAllocations(); 713 void ensureRealmIsRecordingAllocations(JS::Handle<js::GlobalObject*> global); 714 715 /* Locale-specific callbacks for string conversion. */ 716 js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks; 717 718 /* Default locale for Internationalization API */ 719 js::MainThreadData<js::UniqueChars> defaultLocale; 720 721 /* If true, new scripts must be created with PC counter information. */ 722 js::MainThreadOrIonCompileData<bool> profilingScripts; 723 724 /* Strong references on scripts held for PCCount profiling API. */ 725 js::MainThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*> 726 scriptAndCountsVector; 727 728 using RootedPlainObjVec = JS::PersistentRooted< 729 JS::GCVector<js::PlainObject*, 0, js::SystemAllocPolicy>>; 730 js::MainThreadData<js::UniquePtr<RootedPlainObjVec>> watchtowerTestingLog; 731 732 private: 733 /* Code coverage output. */ 734 js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_; 735 736 /* Functions to call, together with data, when the runtime is being torn down. 737 */ 738 js::MainThreadData<mozilla::Vector<std::pair<void (*)(void*), void*>, 4>> 739 cleanupClosures; 740 741 public: 742 js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); } 743 744 /* Register a cleanup function to be called during runtime shutdown. Do not 745 * depend on the ordering of cleanup calls. */ 746 bool atExit(void (*function)(void*), void* data) { 747 return cleanupClosures.ref().append(std::pair(function, data)); 748 } 749 750 private: 751 js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_; 752 753 public: 754 mozilla::Maybe<js::frontend::ScriptIndexRange> getSelfHostedScriptIndexRange( 755 js::PropertyName* name); 756 757 [[nodiscard]] bool createJitRuntime(JSContext* cx); 758 js::jit::JitRuntime* jitRuntime() const { return jitRuntime_.ref(); } 759 bool hasJitRuntime() const { return !!jitRuntime_; } 760 static constexpr size_t offsetOfJitRuntime() { 761 return offsetof(JSRuntime, jitRuntime_) + 762 js::UnprotectedData<js::jit::JitRuntime*>::offsetOfValue(); 763 } 764 765 private: 766 // Used to generate random keys for hash tables. 767 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_; 768 mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator(); 769 770 // Used to generate random hash codes for symbols. 771 mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> 772 randomHashCodeGenerator_; 773 774 public: 775 mozilla::HashCodeScrambler randomHashCodeScrambler(); 776 mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator(); 777 778 js::HashNumber randomHashCode(); 779 780 //------------------------------------------------------------------------- 781 // Self-hosting support 782 //------------------------------------------------------------------------- 783 784 bool hasInitializedSelfHosting() const { return hasSelfHostStencil(); } 785 786 bool initSelfHostingStencil(JSContext* cx, JS::SelfHostedCache xdrCache, 787 JS::SelfHostedWriter xdrWriter); 788 bool initSelfHostingFromStencil(JSContext* cx); 789 void finishSelfHosting(); 790 void traceSelfHostingStencil(JSTracer* trc); 791 js::GeneratorKind getSelfHostedFunctionGeneratorKind(js::PropertyName* name); 792 bool delazifySelfHostedFunction(JSContext* cx, 793 js::Handle<js::PropertyName*> name, 794 js::Handle<JSFunction*> targetFun); 795 bool getSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name, 796 js::MutableHandleValue vp); 797 void assertSelfHostedFunctionHasCanonicalName( 798 JS::Handle<js::PropertyName*> name); 799 800 private: 801 void setSelfHostingStencil( 802 JS::MutableHandle<js::UniquePtr<js::frontend::CompilationInput>> input, 803 RefPtr<js::frontend::CompilationStencil>&& stencil); 804 805 //------------------------------------------------------------------------- 806 // Locale information 807 //------------------------------------------------------------------------- 808 809 public: 810 /* 811 * Set the default locale for the ECMAScript Internationalization API 812 * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat). 813 * Note that the Internationalization API encourages clients to 814 * specify their own locales. 815 * The locale string remains owned by the caller. 816 */ 817 bool setDefaultLocale(const char* locale); 818 819 /* Reset the default locale to OS defaults. */ 820 void resetDefaultLocale(); 821 822 /* Gets current default locale. String remains owned by runtime. */ 823 const char* getDefaultLocale(); 824 825 /* 826 * Gets current default locale or nullptr if not initialized. 827 * String remains owned by runtime. 828 */ 829 const char* getDefaultLocaleIfInitialized() const { 830 return defaultLocale.ref().get(); 831 } 832 833 /* Garbage collector state. */ 834 js::gc::GCRuntime gc; 835 836 /* Garbage collector state has been successfully initialized. */ 837 838 bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); } 839 840 void lockGC() { gc.lockGC(); } 841 842 void unlockGC() { gc.unlockGC(); } 843 844 js::WriteOnceData<js::PropertyName*> emptyString; 845 846 public: 847 JS::GCContext* gcContext() { return &gc.mainThreadContext.ref(); } 848 849 #if !JS_HAS_INTL_API 850 /* Number localization, used by jsnum.cpp. */ 851 js::WriteOnceData<const char*> thousandsSeparator; 852 js::WriteOnceData<const char*> decimalSeparator; 853 js::WriteOnceData<const char*> numGrouping; 854 #endif 855 856 private: 857 js::WriteOnceData<bool> beingDestroyed_; 858 859 public: 860 bool isBeingDestroyed() const { return beingDestroyed_; } 861 862 private: 863 bool allowContentJS_; 864 865 public: 866 bool allowContentJS() const { return allowContentJS_; } 867 868 friend class js::AutoAssertNoContentJS; 869 870 private: 871 // Table of all atoms other than those in permanentAtoms and staticStrings. 872 js::WriteOnceData<js::AtomsTable*> atoms_; 873 874 // Set of all live symbols produced by Symbol.for(). All such symbols are 875 // allocated in the atoms zone. Reading or writing the symbol registry 876 // can only be done from the main thread. 877 js::MainThreadOrGCTaskData<js::SymbolRegistry> symbolRegistry_; 878 879 js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms_; 880 881 public: 882 bool initializeAtoms(JSContext* cx); 883 void finishAtoms(); 884 bool atomsAreFinished() const { return !atoms_; } 885 886 js::AtomsTable* atomsForSweeping() { 887 MOZ_ASSERT(JS::RuntimeHeapIsCollecting()); 888 return atoms_; 889 } 890 891 js::AtomsTable& atoms() { 892 MOZ_ASSERT(atoms_); 893 return *atoms_; 894 } 895 896 JS::Zone* atomsZone() { 897 MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(this)); 898 return unsafeAtomsZone(); 899 } 900 JS::Zone* unsafeAtomsZone() { return gc.atomsZone(); } 901 902 #ifdef DEBUG 903 bool isAtomsZone(const JS::Zone* zone) const { 904 return JS::shadow::Zone::from(zone)->isAtomsZone(); 905 } 906 #endif 907 908 bool activeGCInAtomsZone(); 909 910 js::SymbolRegistry& symbolRegistry() { return symbolRegistry_.ref(); } 911 912 // Permanent atoms are fixed during initialization of the runtime and are 913 // not modified or collected until the runtime is destroyed. These may be 914 // shared with another, longer living runtime through |parentRuntime| and 915 // can be freely accessed with no locking necessary. 916 917 // Permanent atoms pre-allocated for general use. 918 js::WriteOnceData<js::StaticStrings*> staticStrings; 919 920 // Cached pointers to various permanent property names. 921 js::WriteOnceData<JSAtomState*> commonNames; 922 923 // All permanent atoms in the runtime, other than those in staticStrings. 924 // Access to this does not require a lock because it is frozen and thus 925 // read-only. 926 const js::FrozenAtomSet* permanentAtoms() const { 927 MOZ_ASSERT(permanentAtomsPopulated()); 928 return permanentAtoms_.ref(); 929 } 930 931 // The permanent atoms table is populated during initialization. 932 bool permanentAtomsPopulated() const { return permanentAtoms_; } 933 934 // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms, 935 // these are shared with the parentRuntime, if any. 936 js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols; 937 938 #ifdef JS_HAS_INTL_API 939 /* Shared Intl data for this runtime. */ 940 js::MainThreadData<js::intl::SharedIntlData> sharedIntlData; 941 942 void traceSharedIntlData(JSTracer* trc); 943 #endif 944 945 private: 946 js::SharedScriptDataTableHolder scriptDataTableHolder_; 947 948 public: 949 // Returns the runtime's local script data table holder. 950 js::SharedScriptDataTableHolder& scriptDataTableHolder(); 951 952 private: 953 static mozilla::Atomic<size_t> liveRuntimesCount; 954 955 public: 956 static bool hasLiveRuntimes() { return liveRuntimesCount > 0; } 957 static bool hasSingleLiveRuntime() { return liveRuntimesCount == 1; } 958 959 explicit JSRuntime(JSRuntime* parentRuntime); 960 ~JSRuntime(); 961 962 // destroyRuntime is used instead of a destructor, to ensure the downcast 963 // to JSContext remains valid. The final GC triggered here depends on this. 964 void destroyRuntime(); 965 966 bool init(JSContext* cx, uint32_t maxbytes); 967 968 JSRuntime* thisFromCtor() { return this; } 969 970 private: 971 // Number of live SharedArrayBuffer objects, including those in Wasm shared 972 // memories. uint64_t to avoid any risk of overflow. 973 js::MainThreadData<uint64_t> liveSABs; 974 975 public: 976 void incSABCount() { 977 MOZ_RELEASE_ASSERT(liveSABs != UINT64_MAX); 978 liveSABs++; 979 } 980 981 void decSABCount() { 982 MOZ_RELEASE_ASSERT(liveSABs > 0); 983 liveSABs--; 984 } 985 986 bool hasLiveSABs() const { return liveSABs > 0; } 987 988 public: 989 js::MainThreadData<JS::BeforeWaitCallback> beforeWaitCallback; 990 js::MainThreadData<JS::AfterWaitCallback> afterWaitCallback; 991 992 public: 993 void reportAllocationOverflow() { 994 js::ReportAllocationOverflow(static_cast<JSContext*>(nullptr)); 995 } 996 997 /* 998 * This should be called after system malloc/calloc/realloc returns nullptr 999 * to try to recove some memory or to report an error. For realloc, the 1000 * original pointer must be passed as reallocPtr. 1001 * 1002 * The function must be called outside the GC lock. 1003 */ 1004 JS_PUBLIC_API void* onOutOfMemory(js::AllocFunction allocator, 1005 arena_id_t arena, size_t nbytes, 1006 void* reallocPtr = nullptr, 1007 JSContext* maybecx = nullptr); 1008 1009 /* onOutOfMemory but can call OnLargeAllocationFailure. */ 1010 JS_PUBLIC_API void* onOutOfMemoryCanGC(js::AllocFunction allocator, 1011 arena_id_t arena, size_t nbytes, 1012 void* reallocPtr = nullptr); 1013 1014 static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024; 1015 1016 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, 1017 JS::RuntimeSizes* rtSizes); 1018 1019 private: 1020 // Settings for how helper threads can be used. 1021 mozilla::Atomic<bool, mozilla::SequentiallyConsistent> 1022 offthreadBaselineCompilationEnabled_; 1023 mozilla::Atomic<bool, mozilla::SequentiallyConsistent> 1024 offthreadIonCompilationEnabled_; 1025 1026 js::MainThreadData<bool> autoWritableJitCodeActive_; 1027 1028 public: 1029 // Note: these values may be toggled dynamically (in response to about:config 1030 // prefs changing). 1031 void setOffthreadBaselineCompilationEnabled(bool value) { 1032 offthreadBaselineCompilationEnabled_ = value; 1033 } 1034 bool canUseOffthreadBaselineCompilation() const { 1035 return offthreadBaselineCompilationEnabled_; 1036 } 1037 void setOffthreadIonCompilationEnabled(bool value) { 1038 offthreadIonCompilationEnabled_ = value; 1039 } 1040 void setOffthreadCompilationEnabled(bool value) { 1041 setOffthreadBaselineCompilationEnabled(value); 1042 setOffthreadIonCompilationEnabled(value); 1043 } 1044 bool canUseOffthreadIonCompilation() const { 1045 return offthreadIonCompilationEnabled_; 1046 } 1047 void toggleAutoWritableJitCodeActive(bool b) { 1048 MOZ_ASSERT(autoWritableJitCodeActive_ != b, 1049 "AutoWritableJitCode should not be nested."); 1050 autoWritableJitCodeActive_ = b; 1051 } 1052 1053 /* See comment for JS::SetOutOfMemoryCallback in js/MemoryCallbacks.h. */ 1054 js::MainThreadData<JS::OutOfMemoryCallback> oomCallback; 1055 js::MainThreadData<void*> oomCallbackData; 1056 1057 /* 1058 * Debugger.Memory functions like takeCensus use this embedding-provided 1059 * function to assess the size of malloc'd blocks of memory. 1060 */ 1061 js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf; 1062 1063 /* Last time at which an animation was played for this runtime. */ 1064 js::MainThreadData<mozilla::TimeStamp> lastAnimationTime; 1065 1066 private: 1067 /* The stack format for the current runtime. Only valid on non-child 1068 * runtimes. */ 1069 mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_; 1070 1071 public: 1072 js::StackFormat stackFormat() const { 1073 const JSRuntime* rt = this; 1074 while (rt->parentRuntime) { 1075 MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default); 1076 rt = rt->parentRuntime; 1077 } 1078 MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default); 1079 return rt->stackFormat_; 1080 } 1081 void setStackFormat(js::StackFormat format) { 1082 MOZ_ASSERT(!parentRuntime); 1083 MOZ_ASSERT(format != js::StackFormat::Default); 1084 stackFormat_ = format; 1085 } 1086 1087 private: 1088 // Warning: no data should be accessed in these caches from another thread, 1089 // but Ion needs to be able to access addresses inside here, which should be 1090 // safe, as the actual cache lookups will be performed on the main thread 1091 // through jitted code. 1092 js::MainThreadOrIonCompileData<js::RuntimeCaches> caches_; 1093 1094 public: 1095 js::RuntimeCaches& caches() { return caches_.ref(); } 1096 1097 // List of all the live wasm::Instances in the runtime. Equal to the union 1098 // of all instances registered in all JS::Realms. Accessed from watchdog 1099 // threads for purposes of wasm::InterruptRunningCode(). 1100 js::ExclusiveData<js::wasm::InstanceVector> wasmInstances; 1101 1102 // The [[ModuleAsyncEvaluationCount]] field of agent records 1103 // 1104 // See https://tc39.es/ecma262/#sec-agents. 1105 js::MainThreadData<uint32_t> moduleAsyncEvaluatingPostOrder; 1106 1107 // A counter used to detect when there are no pending async modules, so 1108 // that we can reset [[ModuleAsyncEvaluationCount]] to 0. 1109 // 1110 // See the note in 1111 // https://tc39.es/ecma262/#sec-IncrementModuleAsyncEvaluationCount for use. 1112 js::MainThreadData<uint32_t> pendingAsyncModuleEvaluations; 1113 1114 // The implementation-defined abstract operation HostLoadImportedModule. 1115 js::MainThreadData<JS::ModuleLoadHook> moduleLoadHook; 1116 1117 // A hook that implements the abstract operations 1118 // HostGetImportMetaProperties and HostFinalizeImportMeta. 1119 js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook; 1120 1121 // Hooks called when script private references are created and destroyed. 1122 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook; 1123 js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook; 1124 1125 void addRefScriptPrivate(const JS::Value& value) { 1126 if (!value.isUndefined() && scriptPrivateAddRefHook) { 1127 scriptPrivateAddRefHook(value); 1128 } 1129 } 1130 1131 void releaseScriptPrivate(const JS::Value& value) { 1132 if (!value.isUndefined() && scriptPrivateReleaseHook) { 1133 scriptPrivateReleaseHook(value); 1134 } 1135 } 1136 1137 public: 1138 #if defined(NIGHTLY_BUILD) 1139 // Support for informing the embedding of any error thrown. 1140 // This mechanism is designed to let the embedding 1141 // log/report/fail in case certain errors are thrown 1142 // (e.g. SyntaxError, ReferenceError or TypeError 1143 // in critical code). 1144 struct ErrorInterceptionSupport { 1145 ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {} 1146 1147 // true if the error interceptor is currently executing, 1148 // false otherwise. Used to avoid infinite loops. 1149 bool isExecuting; 1150 1151 // if non-null, any call to `setPendingException` 1152 // in this runtime will trigger the call to `interceptor` 1153 JSErrorInterceptor* interceptor; 1154 }; 1155 ErrorInterceptionSupport errorInterception; 1156 #endif // defined(NIGHTLY_BUILD) 1157 1158 public: 1159 JS::GlobalInitializeCallback getShadowRealmInitializeGlobalCallback() { 1160 return shadowRealmInitializeGlobalCallback; 1161 } 1162 1163 JS::GlobalCreationCallback getShadowRealmGlobalCreationCallback() { 1164 return shadowRealmGlobalCreationCallback; 1165 } 1166 1167 js::MainThreadData<JS::GlobalInitializeCallback> 1168 shadowRealmInitializeGlobalCallback; 1169 1170 js::MainThreadData<JS::GlobalCreationCallback> 1171 shadowRealmGlobalCreationCallback; 1172 1173 js::MainThreadData<js::RuntimeFuses> runtimeFuses; 1174 }; 1175 1176 namespace js { 1177 1178 void Metrics::addTelemetry(JSMetric id, uint32_t sample) { 1179 rt_->addTelemetry(id, sample); 1180 } 1181 1182 extern const JSSecurityCallbacks NullSecurityCallbacks; 1183 1184 // This callback is set by JS::SetProcessLargeAllocationFailureCallback 1185 // and may be null. See comment in jsapi.h. 1186 extern mozilla::Atomic<JS::LargeAllocationFailureCallback> 1187 OnLargeAllocationFailure; 1188 1189 // This callback is set by JS::SetBuildIdOp and may be null. See comment in 1190 // jsapi.h. 1191 extern mozilla::Atomic<JS::BuildIdOp> GetBuildId; 1192 1193 extern JS::FilenameValidationCallback gFilenameValidationCallback; 1194 1195 } /* namespace js */ 1196 1197 #endif /* vm_Runtime_h */