Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/MemoryReporting.h"
15 : #include "mozilla/PodOperations.h"
16 : #include "mozilla/Scoped.h"
17 : #include "mozilla/ThreadLocal.h"
18 : #include "mozilla/Vector.h"
19 :
20 : #include <setjmp.h>
21 :
22 : #include "jsatom.h"
23 : #include "jsscript.h"
24 :
25 : #ifdef XP_DARWIN
26 : # include "wasm/WasmSignalHandlers.h"
27 : #endif
28 : #include "builtin/AtomicsObject.h"
29 : #include "builtin/Intl.h"
30 : #include "builtin/Promise.h"
31 : #include "ds/FixedSizeHash.h"
32 : #include "frontend/NameCollections.h"
33 : #include "gc/GCRuntime.h"
34 : #include "gc/Tracer.h"
35 : #include "gc/ZoneGroup.h"
36 : #include "irregexp/RegExpStack.h"
37 : #include "js/Debug.h"
38 : #include "js/GCVector.h"
39 : #include "js/HashTable.h"
40 : #ifdef DEBUG
41 : # include "js/Proxy.h" // For AutoEnterPolicy
42 : #endif
43 : #include "js/UniquePtr.h"
44 : #include "js/Vector.h"
45 : #include "threading/Thread.h"
46 : #include "vm/Caches.h"
47 : #include "vm/CodeCoverage.h"
48 : #include "vm/CommonPropertyNames.h"
49 : #include "vm/DateTime.h"
50 : #include "vm/GeckoProfiler.h"
51 : #include "vm/MallocProvider.h"
52 : #include "vm/Scope.h"
53 : #include "vm/SharedImmutableStringsCache.h"
54 : #include "vm/Stack.h"
55 : #include "vm/Stopwatch.h"
56 : #include "vm/Symbol.h"
57 :
58 : #ifdef _MSC_VER
59 : #pragma warning(push)
60 : #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
61 : #endif
62 :
63 : namespace js {
64 :
65 : class AutoAssertNoContentJS;
66 : class AutoKeepAtoms;
67 : class EnterDebuggeeNoExecute;
68 : #ifdef JS_TRACE_LOGGING
69 : class TraceLoggerThread;
70 : #endif
71 :
72 : typedef Vector<UniquePtr<PromiseTask>, 0, SystemAllocPolicy> PromiseTaskPtrVector;
73 :
74 : } // namespace js
75 :
76 : struct DtoaState;
77 :
78 : #ifdef JS_SIMULATOR_ARM64
79 : namespace vixl {
80 : class Simulator;
81 : }
82 : #endif
83 :
84 : namespace js {
85 :
86 : extern MOZ_COLD void
87 : ReportOutOfMemory(JSContext* cx);
88 :
89 : /* Different signature because the return type has MOZ_MUST_USE_TYPE. */
90 : extern MOZ_COLD mozilla::GenericErrorResult<OOM&>
91 : ReportOutOfMemoryResult(JSContext* cx);
92 :
93 : extern MOZ_COLD void
94 : ReportAllocationOverflow(JSContext* maybecx);
95 :
96 : extern MOZ_COLD void
97 : ReportOverRecursed(JSContext* cx);
98 :
99 : class Activation;
100 : class ActivationIterator;
101 : class WasmActivation;
102 :
103 : namespace jit {
104 : class JitRuntime;
105 : class JitActivation;
106 : struct PcScriptCache;
107 : struct AutoFlushICache;
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 : // JS Engine Threading
118 : //
119 : // Multiple threads may interact with a JS runtime. JS has run-to-completion
120 : // semantics, which means that scripts cannot observe changes in behavior
121 : // due to activities performed on other threads (there is an exception to this
122 : // for shared array buffers and related APIs).
123 : //
124 : // The main way we ensure that run-to-completion semantics are preserved is
125 : // by dividing content into zone groups. Pieces of web content will be in the
126 : // the same zone group if they have the same tab/origin or can otherwise
127 : // observe changes in each other via Window.opener and so forth. When a thread
128 : // executes JS in a zone group, it acquires that group --- including exclusive
129 : // access to most of the group's content --- and does not relinquish control of
130 : // the zone group until the script finishes executing.
131 : //
132 : // Threads interacting with a runtime are divided into two categories:
133 : //
134 : // - Cooperating threads are capable of running JS. At most one cooperating
135 : // thread may be |active| at a time in a runtime, but they may yield control
136 : // to each other so that their execution is interleaved. As described above,
137 : // each thread owns the zone groups it is operating on so that this
138 : // interleaving does not cause observable changes in a script's behavior.
139 : //
140 : // - Helper threads do not run JS, and are controlled or triggered by activity
141 : // in the cooperating threads. Helper threads may have exclusive access to
142 : // zone groups created for them, for parsing and similar tasks, but their
143 : // activities do not cause observable changes in script behaviors. Activity
144 : // on helper threads may be referred to as happening 'off thread' or on a
145 : // background thread in some parts of the VM.
146 :
147 : /*
148 : * A FreeOp can do one thing: free memory. For convenience, it has delete_
149 : * convenience methods that also call destructors.
150 : *
151 : * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
152 : * need to pass a JSContext to those hooks.
153 : */
154 : class FreeOp : public JSFreeOp
155 : {
156 : Vector<void*, 0, SystemAllocPolicy> freeLaterList;
157 : jit::JitPoisonRangeVector jitPoisonRanges;
158 :
159 : public:
160 0 : static FreeOp* get(JSFreeOp* fop) {
161 0 : return static_cast<FreeOp*>(fop);
162 : }
163 :
164 : explicit FreeOp(JSRuntime* maybeRuntime);
165 : ~FreeOp();
166 :
167 0 : bool onActiveCooperatingThread() const {
168 0 : return runtime_ != nullptr;
169 : }
170 :
171 0 : bool maybeOnHelperThread() const {
172 : // Sometimes background finalization happens on the active thread so
173 : // runtime_ being null doesn't always mean we are off thread.
174 0 : return !runtime_;
175 : }
176 :
177 : bool isDefaultFreeOp() const;
178 :
179 : inline void free_(void* p);
180 : inline void freeLater(void* p);
181 :
182 : inline bool appendJitPoisonRange(const jit::JitPoisonRange& range);
183 :
184 : template <class T>
185 551 : inline void delete_(T* p) {
186 551 : if (p) {
187 551 : p->~T();
188 551 : free_(p);
189 : }
190 551 : }
191 : };
192 :
193 : } /* namespace js */
194 :
195 : namespace JS {
196 : struct RuntimeSizes;
197 : } // namespace JS
198 :
199 : /* Various built-in or commonly-used names pinned on first context. */
200 : struct JSAtomState
201 : {
202 : #define PROPERTYNAME_FIELD(idpart, id, text) js::ImmutablePropertyNamePtr id;
203 : FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
204 : #undef PROPERTYNAME_FIELD
205 : #define PROPERTYNAME_FIELD(name, code, init, clasp) js::ImmutablePropertyNamePtr name;
206 : JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
207 : #undef PROPERTYNAME_FIELD
208 : #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr name;
209 : JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
210 : #undef PROPERTYNAME_FIELD
211 : #define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr Symbol_##name;
212 : JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
213 : #undef PROPERTYNAME_FIELD
214 :
215 13 : js::ImmutablePropertyNamePtr* wellKnownSymbolNames() {
216 : #define FIRST_PROPERTYNAME_FIELD(name) return &name;
217 13 : JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
218 : #undef FIRST_PROPERTYNAME_FIELD
219 : }
220 :
221 3 : js::ImmutablePropertyNamePtr* wellKnownSymbolDescriptions() {
222 : #define FIRST_PROPERTYNAME_FIELD(name) return &Symbol_ ##name;
223 3 : JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
224 : #undef FIRST_PROPERTYNAME_FIELD
225 : }
226 : };
227 :
228 : namespace js {
229 :
230 : /*
231 : * Storage for well-known symbols. It's a separate struct from the Runtime so
232 : * that it can be shared across multiple runtimes. As in JSAtomState, each
233 : * field is a smart pointer that's immutable once initialized.
234 : * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
235 : *
236 : * Well-known symbols are never GC'd. The description() of each well-known
237 : * symbol is a permanent atom.
238 : */
239 : struct WellKnownSymbols
240 : {
241 : #define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
242 : JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
243 : #undef DECLARE_SYMBOL
244 :
245 7598 : const ImmutableSymbolPtr& get(size_t u) const {
246 7598 : MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
247 7598 : const ImmutableSymbolPtr* symbols = reinterpret_cast<const ImmutableSymbolPtr*>(this);
248 7598 : return symbols[u];
249 : }
250 :
251 3453 : const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
252 3453 : return get(size_t(code));
253 : }
254 :
255 3 : WellKnownSymbols() {}
256 : WellKnownSymbols(const WellKnownSymbols&) = delete;
257 : WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
258 : };
259 :
260 : #define NAME_OFFSET(name) offsetof(JSAtomState, name)
261 :
262 : inline HandlePropertyName
263 1190483 : AtomStateOffsetToName(const JSAtomState& atomState, size_t offset)
264 : {
265 1190483 : return *reinterpret_cast<js::ImmutablePropertyNamePtr*>((char*)&atomState + offset);
266 : }
267 :
268 : // There are several coarse locks in the enum below. These may be either
269 : // per-runtime or per-process. When acquiring more than one of these locks,
270 : // the acquisition must be done in the order below to avoid deadlocks.
271 : enum RuntimeLock {
272 : ExclusiveAccessLock,
273 : HelperThreadStateLock,
274 : GCLock
275 : };
276 :
277 : inline bool
278 541 : CanUseExtraThreads()
279 : {
280 : extern bool gCanUseExtraThreads;
281 541 : return gCanUseExtraThreads;
282 : }
283 :
284 : void DisableExtraThreads();
285 :
286 : using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
287 :
288 : class AutoLockForExclusiveAccess;
289 :
290 : } // namespace js
291 :
292 : struct JSRuntime : public js::MallocProvider<JSRuntime>
293 : {
294 : private:
295 : friend class js::Activation;
296 : friend class js::ActivationIterator;
297 : friend class js::jit::JitActivation;
298 : friend class js::WasmActivation;
299 : friend class js::jit::CompileRuntime;
300 :
301 : public:
302 : /*
303 : * If non-null, another runtime guaranteed to outlive this one and whose
304 : * permanent data may be used by this one where possible.
305 : */
306 : JSRuntime* const parentRuntime;
307 :
308 : #ifdef DEBUG
309 : /* The number of child runtimes that have this runtime as their parent. */
310 : mozilla::Atomic<size_t> childRuntimeCount;
311 :
312 : class AutoUpdateChildRuntimeCount
313 : {
314 : JSRuntime* parent_;
315 :
316 : public:
317 4 : explicit AutoUpdateChildRuntimeCount(JSRuntime* parent)
318 4 : : parent_(parent)
319 : {
320 4 : if (parent_)
321 1 : parent_->childRuntimeCount++;
322 4 : }
323 :
324 0 : ~AutoUpdateChildRuntimeCount() {
325 0 : if (parent_)
326 0 : parent_->childRuntimeCount--;
327 0 : }
328 : };
329 :
330 : AutoUpdateChildRuntimeCount updateChildRuntimeCount;
331 : #endif
332 :
333 : private:
334 : #ifdef DEBUG
335 : js::WriteOnceData<bool> initialized_;
336 : #endif
337 :
338 : // The context for the thread which currently has exclusive access to most
339 : // contents of the runtime. When execution on the runtime is cooperatively
340 : // scheduled, this is the thread which is currently running.
341 : mozilla::Atomic<JSContext*, mozilla::ReleaseAcquire> activeContext_;
342 :
343 : // All contexts participating in cooperative scheduling. All threads other
344 : // than |activeContext_| are suspended.
345 : js::ActiveThreadData<js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>> cooperatingContexts_;
346 :
347 : // Count of AutoProhibitActiveContextChange instances on the active context.
348 : js::ActiveThreadData<size_t> activeContextChangeProhibited_;
349 :
350 : // Count of beginSingleThreadedExecution() calls that have occurred with no
351 : // matching endSingleThreadedExecution().
352 : js::ActiveThreadData<size_t> singleThreadedExecutionRequired_;
353 :
354 : // Whether some thread has called beginSingleThreadedExecution() and we are
355 : // in the associated callback (which may execute JS on other threads).
356 : js::ActiveThreadData<bool> startingSingleThreadedExecution_;
357 :
358 : public:
359 49017676 : JSContext* activeContext() const { return activeContext_; }
360 1064 : const void* addressOfActiveContext() { return &activeContext_; }
361 :
362 : void setActiveContext(JSContext* cx);
363 : void setNewbornActiveContext(JSContext* cx);
364 : void deleteActiveContext(JSContext* cx);
365 :
366 : inline JSContext* activeContextFromOwnThread();
367 :
368 73 : js::Vector<js::CooperatingContext, 4, js::SystemAllocPolicy>& cooperatingContexts() {
369 73 : return cooperatingContexts_.ref();
370 : }
371 :
372 : class MOZ_RAII AutoProhibitActiveContextChange
373 : {
374 : JSRuntime* rt;
375 :
376 : public:
377 632 : explicit AutoProhibitActiveContextChange(JSRuntime* rt)
378 632 : : rt(rt)
379 : {
380 632 : rt->activeContextChangeProhibited_++;
381 632 : }
382 :
383 632 : ~AutoProhibitActiveContextChange()
384 632 : {
385 632 : rt->activeContextChangeProhibited_--;
386 632 : }
387 : };
388 :
389 93 : bool activeContextChangeProhibited() { return activeContextChangeProhibited_; }
390 0 : bool singleThreadedExecutionRequired() { return singleThreadedExecutionRequired_; }
391 :
392 : js::ActiveThreadData<JS::BeginSingleThreadedExecutionCallback> beginSingleThreadedExecutionCallback;
393 : js::ActiveThreadData<JS::EndSingleThreadedExecutionCallback> endSingleThreadedExecutionCallback;
394 :
395 : // Ensure there is only a single thread interacting with this runtime.
396 : // beginSingleThreadedExecution() returns false if some context has already
397 : // started forcing this runtime to be single threaded. Calls to these
398 : // functions must be balanced.
399 : bool beginSingleThreadedExecution(JSContext* cx);
400 : void endSingleThreadedExecution(JSContext* cx);
401 :
402 : /*
403 : * The profiler sampler generation after the latest sample.
404 : *
405 : * The lapCount indicates the number of largest number of 'laps'
406 : * (wrapping from high to low) that occurred when writing entries
407 : * into the sample buffer. All JitcodeGlobalMap entries referenced
408 : * from a given sample are assigned the generation of the sample buffer
409 : * at the START of the run. If multiple laps occur, then some entries
410 : * (towards the end) will be written out with the "wrong" generation.
411 : * The lapCount indicates the required fudge factor to use to compare
412 : * entry generations with the sample buffer generation.
413 : */
414 : mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferGen_;
415 : mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferLapCount_;
416 :
417 0 : uint32_t profilerSampleBufferGen() {
418 0 : return profilerSampleBufferGen_;
419 : }
420 0 : void resetProfilerSampleBufferGen() {
421 0 : profilerSampleBufferGen_ = 0;
422 0 : }
423 0 : void setProfilerSampleBufferGen(uint32_t gen) {
424 : // May be called from sampler thread or signal handler; use
425 : // compareExchange to make sure we have monotonic increase.
426 : for (;;) {
427 0 : uint32_t curGen = profilerSampleBufferGen_;
428 0 : if (curGen >= gen)
429 0 : break;
430 :
431 0 : if (profilerSampleBufferGen_.compareExchange(curGen, gen))
432 0 : break;
433 0 : }
434 0 : }
435 :
436 0 : uint32_t profilerSampleBufferLapCount() {
437 0 : MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
438 0 : return profilerSampleBufferLapCount_;
439 : }
440 0 : void resetProfilerSampleBufferLapCount() {
441 0 : profilerSampleBufferLapCount_ = 1;
442 0 : }
443 0 : void updateProfilerSampleBufferLapCount(uint32_t lapCount) {
444 0 : MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
445 :
446 : // May be called from sampler thread or signal handler; use
447 : // compareExchange to make sure we have monotonic increase.
448 : for (;;) {
449 0 : uint32_t curLapCount = profilerSampleBufferLapCount_;
450 0 : if (curLapCount >= lapCount)
451 0 : break;
452 :
453 0 : if (profilerSampleBufferLapCount_.compareExchange(curLapCount, lapCount))
454 0 : break;
455 0 : }
456 0 : }
457 :
458 : /* Call this to accumulate telemetry data. */
459 : js::ActiveThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
460 : public:
461 : // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
462 : // histogram. |key| provides an additional key to identify the histogram.
463 : // |sample| is the data to add to the histogram.
464 : void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
465 :
466 : void setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
467 :
468 : public:
469 : js::ActiveThreadData<JS::StartAsyncTaskCallback> startAsyncTaskCallback;
470 : js::UnprotectedData<JS::FinishAsyncTaskCallback> finishAsyncTaskCallback;
471 : js::ExclusiveData<js::PromiseTaskPtrVector> promiseTasksToDestroy;
472 :
473 : JSObject* getIncumbentGlobal(JSContext* cx);
474 : bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job, js::HandleObject promise,
475 : js::HandleObject incumbentGlobal);
476 : void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
477 : void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
478 :
479 : /* Had an out-of-memory error which did not populate an exception. */
480 : mozilla::Atomic<bool> hadOutOfMemory;
481 :
482 : /*
483 : * Allow relazifying functions in compartments that are active. This is
484 : * only used by the relazifyFunctions() testing function.
485 : */
486 : js::ActiveThreadData<bool> allowRelazificationForTesting;
487 :
488 : /* Compartment destroy callback. */
489 : js::ActiveThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
490 :
491 : /* Compartment memory reporting callback. */
492 : js::ActiveThreadData<JSSizeOfIncludingThisCompartmentCallback> sizeOfIncludingThisCompartmentCallback;
493 :
494 : /* Call this to get the name of a compartment. */
495 : js::ActiveThreadData<JSCompartmentNameCallback> compartmentNameCallback;
496 :
497 : /* Callback for doing memory reporting on external strings. */
498 : js::ActiveThreadData<JSExternalStringSizeofCallback> externalStringSizeofCallback;
499 :
500 : js::ActiveThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
501 :
502 : js::ActiveThreadData<const JSSecurityCallbacks*> securityCallbacks;
503 : js::ActiveThreadData<const js::DOMCallbacks*> DOMcallbacks;
504 : js::ActiveThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
505 : js::ActiveThreadData<JSReadPrincipalsOp> readPrincipals;
506 :
507 : /* Optional warning reporter. */
508 : js::ActiveThreadData<JS::WarningReporter> warningReporter;
509 :
510 : private:
511 : /* Gecko profiling metadata */
512 : js::UnprotectedData<js::GeckoProfiler> geckoProfiler_;
513 : public:
514 39217 : js::GeckoProfiler& geckoProfiler() { return geckoProfiler_.ref(); }
515 :
516 : // Heap GC roots for PersistentRooted pointers.
517 : js::ActiveThreadData<mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
518 : mozilla::LinkedList<JS::PersistentRooted<void*>>>> heapRoots;
519 :
520 : void tracePersistentRoots(JSTracer* trc);
521 : void finishPersistentRoots();
522 :
523 : void finishRoots();
524 :
525 : public:
526 : js::UnprotectedData<JS::BuildIdOp> buildIdOp;
527 :
528 : /* AsmJSCache callbacks are runtime-wide. */
529 : js::UnprotectedData<JS::AsmJSCacheOps> asmJSCacheOps;
530 :
531 : private:
532 : js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
533 : public:
534 3 : void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
535 13432 : const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
536 :
537 : js::ActiveThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
538 : js::ActiveThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
539 :
540 : js::ActiveThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
541 :
542 : js::ActiveThreadData<js::CTypesActivityCallback> ctypesActivityCallback;
543 :
544 : private:
545 : js::WriteOnceData<const js::Class*> windowProxyClass_;
546 :
547 : public:
548 48822 : const js::Class* maybeWindowProxyClass() const {
549 48822 : return windowProxyClass_;
550 : }
551 3 : void setWindowProxyClass(const js::Class* clasp) {
552 3 : windowProxyClass_ = clasp;
553 3 : }
554 :
555 : private:
556 : // List of non-ephemeron weak containers to sweep during beginSweepingSweepGroup.
557 : js::ActiveThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>> weakCaches_;
558 : public:
559 0 : mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() { return weakCaches_.ref(); }
560 0 : void registerWeakCache(JS::detail::WeakCacheBase* cachep) {
561 0 : weakCaches().insertBack(cachep);
562 0 : }
563 :
564 : template <typename T>
565 : struct GlobalObjectWatchersSiblingAccess {
566 0 : static T* GetNext(T* elm) {
567 0 : return elm->onNewGlobalObjectWatchersLink.mNext;
568 : }
569 0 : static void SetNext(T* elm, T* next) {
570 0 : elm->onNewGlobalObjectWatchersLink.mNext = next;
571 0 : }
572 0 : static T* GetPrev(T* elm) {
573 0 : return elm->onNewGlobalObjectWatchersLink.mPrev;
574 : }
575 0 : static void SetPrev(T* elm, T* prev) {
576 0 : elm->onNewGlobalObjectWatchersLink.mPrev = prev;
577 0 : }
578 : };
579 :
580 : using WatchersList =
581 : mozilla::DoublyLinkedList<js::Debugger,
582 : GlobalObjectWatchersSiblingAccess<js::Debugger>>;
583 : private:
584 : /*
585 : * List of all enabled Debuggers that have onNewGlobalObject handler
586 : * methods established.
587 : */
588 : js::ActiveThreadData<WatchersList> onNewGlobalObjectWatchers_;
589 :
590 : public:
591 311 : WatchersList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); }
592 :
593 : private:
594 : /*
595 : * Lock taken when using per-runtime or per-zone data that could otherwise
596 : * be accessed simultaneously by multiple threads.
597 : *
598 : * Locking this only occurs if there is actually a thread other than the
599 : * active thread which could access such data.
600 : */
601 : js::Mutex exclusiveAccessLock;
602 : #ifdef DEBUG
603 : bool activeThreadHasExclusiveAccess;
604 : #endif
605 :
606 : /* Number of zones which may be operated on by non-cooperating helper threads. */
607 : js::UnprotectedData<size_t> numHelperThreadZones;
608 :
609 : friend class js::AutoLockForExclusiveAccess;
610 :
611 : public:
612 : void setUsedByHelperThread(JS::Zone* zone);
613 : void clearUsedByHelperThread(JS::Zone* zone);
614 :
615 3573865 : bool hasHelperThreadZones() const {
616 3573865 : return numHelperThreadZones > 0;
617 : }
618 :
619 : #ifdef DEBUG
620 2381943 : bool currentThreadHasExclusiveAccess() const {
621 3472461 : return (!hasHelperThreadZones() && activeThreadHasExclusiveAccess) ||
622 3472503 : exclusiveAccessLock.ownedByCurrentThread();
623 : }
624 : #endif
625 :
626 : // How many compartments there are across all zones. This number includes
627 : // off thread context compartments, so it isn't necessarily equal to the
628 : // number of compartments visited by CompartmentsIter.
629 : js::ActiveThreadData<size_t> numCompartments;
630 :
631 : /* Locale-specific callbacks for string conversion. */
632 : js::ActiveThreadData<const JSLocaleCallbacks*> localeCallbacks;
633 :
634 : /* Default locale for Internationalization API */
635 : js::ActiveThreadData<char*> defaultLocale;
636 :
637 : /* Default JSVersion. */
638 : js::ActiveThreadData<JSVersion> defaultVersion_;
639 :
640 : /* If true, new scripts must be created with PC counter information. */
641 : js::ActiveThreadOrIonCompileData<bool> profilingScripts;
642 :
643 : /* Strong references on scripts held for PCCount profiling API. */
644 : js::ActiveThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*> scriptAndCountsVector;
645 :
646 : private:
647 : /* Code coverage output. */
648 : js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
649 : public:
650 36910 : js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
651 :
652 : private:
653 : js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
654 :
655 : /*
656 : * Self-hosting state cloned on demand into other compartments. Shared with the parent
657 : * runtime if there is one.
658 : */
659 : js::WriteOnceData<js::NativeObject*> selfHostingGlobal_;
660 :
661 : static js::GlobalObject*
662 : createSelfHostingGlobal(JSContext* cx);
663 :
664 : bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
665 : js::MutableHandleValue vp);
666 : JSFunction* getUnclonedSelfHostedFunction(JSContext* cx, js::HandlePropertyName name);
667 :
668 : js::jit::JitRuntime* createJitRuntime(JSContext* cx);
669 :
670 : public:
671 13 : js::jit::JitRuntime* getJitRuntime(JSContext* cx) {
672 13 : return jitRuntime_ ? jitRuntime_.ref() : createJitRuntime(cx);
673 : }
674 40309 : js::jit::JitRuntime* jitRuntime() const {
675 40309 : return jitRuntime_.ref();
676 : }
677 7 : bool hasJitRuntime() const {
678 7 : return !!jitRuntime_;
679 : }
680 :
681 : private:
682 : // Used to generate random keys for hash tables.
683 : mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
684 : mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
685 :
686 : public:
687 : mozilla::HashCodeScrambler randomHashCodeScrambler();
688 : mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
689 :
690 : //-------------------------------------------------------------------------
691 : // Self-hosting support
692 : //-------------------------------------------------------------------------
693 :
694 312 : bool hasInitializedSelfHosting() const {
695 312 : return selfHostingGlobal_;
696 : }
697 :
698 : bool initSelfHosting(JSContext* cx);
699 : void finishSelfHosting();
700 : void traceSelfHostingGlobal(JSTracer* trc);
701 90487 : bool isSelfHostingGlobal(JSObject* global) {
702 90487 : return global == selfHostingGlobal_;
703 : }
704 : bool isSelfHostingCompartment(JSCompartment* comp) const;
705 : bool isSelfHostingZone(const JS::Zone* zone) const;
706 : bool createLazySelfHostedFunctionClone(JSContext* cx, js::HandlePropertyName selfHostedName,
707 : js::HandleAtom name, unsigned nargs,
708 : js::HandleObject proto,
709 : js::NewObjectKind newKind,
710 : js::MutableHandleFunction fun);
711 : bool cloneSelfHostedFunctionScript(JSContext* cx, js::Handle<js::PropertyName*> name,
712 : js::Handle<JSFunction*> targetFun);
713 : bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
714 : js::MutableHandleValue vp);
715 : void assertSelfHostedFunctionHasCanonicalName(JSContext* cx, js::HandlePropertyName name);
716 :
717 : //-------------------------------------------------------------------------
718 : // Locale information
719 : //-------------------------------------------------------------------------
720 :
721 : /*
722 : * Set the default locale for the ECMAScript Internationalization API
723 : * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
724 : * Note that the Internationalization API encourages clients to
725 : * specify their own locales.
726 : * The locale string remains owned by the caller.
727 : */
728 : bool setDefaultLocale(const char* locale);
729 :
730 : /* Reset the default locale to OS defaults. */
731 : void resetDefaultLocale();
732 :
733 : /* Gets current default locale. String remains owned by context. */
734 : const char* getDefaultLocale();
735 :
736 3412 : JSVersion defaultVersion() const { return defaultVersion_; }
737 : void setDefaultVersion(JSVersion v) { defaultVersion_ = v; }
738 :
739 : /* Garbage collector state, used by jsgc.c. */
740 : js::gc::GCRuntime gc;
741 :
742 : /* Garbage collector state has been successfully initialized. */
743 : js::WriteOnceData<bool> gcInitialized;
744 :
745 184 : bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
746 :
747 : void lockGC() {
748 : gc.lockGC();
749 : }
750 :
751 : void unlockGC() {
752 : gc.unlockGC();
753 : }
754 :
755 : /* Well-known numbers. */
756 : const js::Value NaNValue;
757 : const js::Value negativeInfinityValue;
758 : const js::Value positiveInfinityValue;
759 :
760 : js::WriteOnceData<js::PropertyName*> emptyString;
761 :
762 : private:
763 : js::WriteOnceData<js::FreeOp*> defaultFreeOp_;
764 :
765 : public:
766 121212 : js::FreeOp* defaultFreeOp() {
767 121212 : MOZ_ASSERT(defaultFreeOp_);
768 121213 : return defaultFreeOp_;
769 : }
770 :
771 : #if !EXPOSE_INTL_API
772 : /* Number localization, used by jsnum.cpp. */
773 : js::WriteOnceData<const char*> thousandsSeparator;
774 : js::WriteOnceData<const char*> decimalSeparator;
775 : js::WriteOnceData<const char*> numGrouping;
776 : #endif
777 :
778 : private:
779 : mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
780 :
781 : public:
782 : // If this particular JSRuntime has a SharedImmutableStringsCache, return a
783 : // pointer to it, otherwise return nullptr.
784 1 : js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
785 1 : return sharedImmutableStrings_.isSome() ? &*sharedImmutableStrings_ : nullptr;
786 : }
787 :
788 : // Get a reference to this JSRuntime's or its parent's
789 : // SharedImmutableStringsCache.
790 1714 : js::SharedImmutableStringsCache& sharedImmutableStrings() {
791 1714 : MOZ_ASSERT_IF(parentRuntime, !sharedImmutableStrings_);
792 1714 : MOZ_ASSERT_IF(!parentRuntime, sharedImmutableStrings_);
793 1714 : return parentRuntime ? parentRuntime->sharedImmutableStrings() : *sharedImmutableStrings_;
794 : }
795 :
796 : private:
797 : js::WriteOnceData<bool> beingDestroyed_;
798 : public:
799 4 : bool isBeingDestroyed() const {
800 4 : return beingDestroyed_;
801 : }
802 :
803 : private:
804 : bool allowContentJS_;
805 : public:
806 68 : bool allowContentJS() const {
807 68 : return allowContentJS_;
808 : }
809 :
810 : friend class js::AutoAssertNoContentJS;
811 :
812 : private:
813 : // Set of all atoms other than those in permanentAtoms and staticStrings.
814 : // Reading or writing this set requires the calling thread to use
815 : // AutoLockForExclusiveAccess.
816 : js::ExclusiveAccessLockOrGCTaskData<js::AtomSet*> atoms_;
817 :
818 : // Set of all atoms added while the main atoms table is being swept.
819 : js::ExclusiveAccessLockData<js::AtomSet*> atomsAddedWhileSweeping_;
820 :
821 : // Compartment and associated zone containing all atoms in the runtime, as
822 : // well as runtime wide IonCode stubs. Modifying the contents of this
823 : // compartment requires the calling thread to use AutoLockForExclusiveAccess.
824 : js::WriteOnceData<JSCompartment*> atomsCompartment_;
825 :
826 : // Set of all live symbols produced by Symbol.for(). All such symbols are
827 : // allocated in the atomsCompartment. Reading or writing the symbol
828 : // registry requires the calling thread to use AutoLockForExclusiveAccess.
829 : js::ExclusiveAccessLockOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
830 :
831 : public:
832 : bool initializeAtoms(JSContext* cx);
833 : void finishAtoms();
834 2 : bool atomsAreFinished() const { return !atoms_; }
835 :
836 0 : js::AtomSet* atomsForSweeping() {
837 0 : MOZ_ASSERT(JS::CurrentThreadIsHeapCollecting());
838 0 : return atoms_;
839 : }
840 :
841 95256 : js::AtomSet& atoms(js::AutoLockForExclusiveAccess& lock) {
842 95256 : MOZ_ASSERT(atoms_);
843 95256 : return *atoms_;
844 : }
845 487368 : js::AtomSet& unsafeAtoms() {
846 487368 : MOZ_ASSERT(atoms_);
847 487368 : return *atoms_;
848 : }
849 :
850 : bool createAtomsAddedWhileSweepingTable();
851 : void destroyAtomsAddedWhileSweepingTable();
852 95256 : js::AtomSet* atomsAddedWhileSweeping() {
853 95256 : return atomsAddedWhileSweeping_;
854 : }
855 :
856 62684 : JSCompartment* atomsCompartment(js::AutoLockForExclusiveAccess& lock) {
857 62684 : return atomsCompartment_;
858 : }
859 0 : JSCompartment* unsafeAtomsCompartment() {
860 0 : return atomsCompartment_;
861 : }
862 :
863 1688878 : bool isAtomsCompartment(JSCompartment* comp) {
864 1688878 : return comp == atomsCompartment_;
865 : }
866 :
867 0 : const JS::Zone* atomsZone(js::AutoLockForExclusiveAccess& lock) const {
868 0 : return gc.atomsZone;
869 : }
870 :
871 : // The atoms compartment is the only one in its zone.
872 3643352 : bool isAtomsZone(const JS::Zone* zone) const {
873 3643352 : return zone == gc.atomsZone;
874 : }
875 :
876 : bool activeGCInAtomsZone();
877 :
878 0 : js::SymbolRegistry& symbolRegistry(js::AutoLockForExclusiveAccess& lock) {
879 0 : return symbolRegistry_.ref();
880 : }
881 0 : js::SymbolRegistry& unsafeSymbolRegistry() {
882 0 : return symbolRegistry_.ref();
883 : }
884 :
885 : // Permanent atoms are fixed during initialization of the runtime and are
886 : // not modified or collected until the runtime is destroyed. These may be
887 : // shared with another, longer living runtime through |parentRuntime| and
888 : // can be freely accessed with no locking necessary.
889 :
890 : // Permanent atoms pre-allocated for general use.
891 : js::WriteOnceData<js::StaticStrings*> staticStrings;
892 :
893 : // Cached pointers to various permanent property names.
894 : js::WriteOnceData<JSAtomState*> commonNames;
895 :
896 : // All permanent atoms in the runtime, other than those in staticStrings.
897 : // Unlike |atoms_|, access to this does not require
898 : // AutoLockForExclusiveAccess because it is frozen and thus read-only.
899 : js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms;
900 :
901 : bool transformToPermanentAtoms(JSContext* cx);
902 :
903 : // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
904 : // these are shared with the parentRuntime, if any.
905 : js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
906 :
907 : /* Shared Intl data for this runtime. */
908 : js::ActiveThreadData<js::SharedIntlData> sharedIntlData;
909 :
910 : void traceSharedIntlData(JSTracer* trc);
911 :
912 : // Table of bytecode and other data that may be shared across scripts
913 : // within the runtime. This may be modified by threads using
914 : // AutoLockForExclusiveAccess.
915 : private:
916 : js::ExclusiveAccessLockData<js::ScriptDataTable> scriptDataTable_;
917 : public:
918 29397 : js::ScriptDataTable& scriptDataTable(js::AutoLockForExclusiveAccess& lock) {
919 29397 : return scriptDataTable_.ref();
920 : }
921 :
922 : js::WriteOnceData<bool> jitSupportsFloatingPoint;
923 : js::WriteOnceData<bool> jitSupportsUnalignedAccesses;
924 : js::WriteOnceData<bool> jitSupportsSimd;
925 :
926 : private:
927 : static mozilla::Atomic<size_t> liveRuntimesCount;
928 :
929 : public:
930 3 : static bool hasLiveRuntimes() {
931 3 : return liveRuntimesCount > 0;
932 : }
933 :
934 : explicit JSRuntime(JSRuntime* parentRuntime);
935 : ~JSRuntime();
936 :
937 : // destroyRuntime is used instead of a destructor, to ensure the downcast
938 : // to JSContext remains valid. The final GC triggered here depends on this.
939 : void destroyRuntime();
940 :
941 : bool init(JSContext* cx, uint32_t maxbytes, uint32_t maxNurseryBytes);
942 :
943 12 : JSRuntime* thisFromCtor() { return this; }
944 :
945 : public:
946 : /*
947 : * Call this after allocating memory held by GC things, to update memory
948 : * pressure counters or report the OOM error if necessary. If oomError and
949 : * cx is not null the function also reports OOM error.
950 : *
951 : * The function must be called outside the GC lock and in case of OOM error
952 : * the caller must ensure that no deadlock possible during OOM reporting.
953 : */
954 : void updateMallocCounter(size_t nbytes);
955 : void updateMallocCounter(JS::Zone* zone, size_t nbytes);
956 :
957 0 : void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
958 :
959 : /*
960 : * This should be called after system malloc/calloc/realloc returns nullptr
961 : * to try to recove some memory or to report an error. For realloc, the
962 : * original pointer must be passed as reallocPtr.
963 : *
964 : * The function must be called outside the GC lock.
965 : */
966 : JS_FRIEND_API(void*) onOutOfMemory(js::AllocFunction allocator, size_t nbytes,
967 : void* reallocPtr = nullptr, JSContext* maybecx = nullptr);
968 :
969 : /* onOutOfMemory but can call OnLargeAllocationFailure. */
970 : JS_FRIEND_API(void*) onOutOfMemoryCanGC(js::AllocFunction allocator, size_t nbytes,
971 : void* reallocPtr = nullptr);
972 :
973 : void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* runtime);
974 :
975 : private:
976 : // Settings for how helper threads can be used.
977 : mozilla::Atomic<bool> offthreadIonCompilationEnabled_;
978 : mozilla::Atomic<bool> parallelParsingEnabled_;
979 :
980 : js::ActiveThreadData<bool> autoWritableJitCodeActive_;
981 :
982 : public:
983 :
984 : // Note: these values may be toggled dynamically (in response to about:config
985 : // prefs changing).
986 3 : void setOffthreadIonCompilationEnabled(bool value) {
987 3 : offthreadIonCompilationEnabled_ = value;
988 3 : }
989 175 : bool canUseOffthreadIonCompilation() const {
990 175 : return offthreadIonCompilationEnabled_;
991 : }
992 3 : void setParallelParsingEnabled(bool value) {
993 3 : parallelParsingEnabled_ = value;
994 3 : }
995 32 : bool canUseParallelParsing() const {
996 32 : return parallelParsingEnabled_;
997 : }
998 :
999 8998 : void toggleAutoWritableJitCodeActive(bool b) {
1000 8998 : MOZ_ASSERT(autoWritableJitCodeActive_ != b, "AutoWritableJitCode should not be nested.");
1001 8998 : autoWritableJitCodeActive_ = b;
1002 8998 : }
1003 :
1004 : /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
1005 : js::ActiveThreadData<JS::OutOfMemoryCallback> oomCallback;
1006 : js::ActiveThreadData<void*> oomCallbackData;
1007 :
1008 : /*
1009 : * These variations of malloc/calloc/realloc will call the
1010 : * large-allocation-failure callback on OOM and retry the allocation.
1011 : */
1012 : static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
1013 :
1014 : template <typename T>
1015 0 : T* pod_callocCanGC(size_t numElems) {
1016 0 : T* p = pod_calloc<T>(numElems);
1017 0 : if (MOZ_LIKELY(!!p))
1018 0 : return p;
1019 : size_t bytes;
1020 0 : if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(numElems, &bytes))) {
1021 0 : reportAllocationOverflow();
1022 0 : return nullptr;
1023 : }
1024 0 : return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Calloc, bytes));
1025 : }
1026 :
1027 : template <typename T>
1028 : T* pod_reallocCanGC(T* p, size_t oldSize, size_t newSize) {
1029 : T* p2 = pod_realloc<T>(p, oldSize, newSize);
1030 : if (MOZ_LIKELY(!!p2))
1031 : return p2;
1032 : size_t bytes;
1033 : if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(newSize, &bytes))) {
1034 : reportAllocationOverflow();
1035 : return nullptr;
1036 : }
1037 : return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Realloc, bytes, p));
1038 : }
1039 :
1040 : /*
1041 : * Debugger.Memory functions like takeCensus use this embedding-provided
1042 : * function to assess the size of malloc'd blocks of memory.
1043 : */
1044 : js::ActiveThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
1045 :
1046 : /* Last time at which an animation was played for this runtime. */
1047 : mozilla::Atomic<int64_t> lastAnimationTime;
1048 :
1049 : private:
1050 : js::ActiveThreadData<js::PerformanceMonitoring> performanceMonitoring_;
1051 : public:
1052 37229 : js::PerformanceMonitoring& performanceMonitoring() { return performanceMonitoring_.ref(); }
1053 :
1054 : private:
1055 : /* The stack format for the current runtime. Only valid on non-child
1056 : * runtimes. */
1057 : mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
1058 :
1059 : public:
1060 0 : js::StackFormat stackFormat() const {
1061 0 : const JSRuntime* rt = this;
1062 0 : while (rt->parentRuntime) {
1063 0 : MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
1064 0 : rt = rt->parentRuntime;
1065 : }
1066 0 : MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
1067 0 : return rt->stackFormat_;
1068 : }
1069 0 : void setStackFormat(js::StackFormat format) {
1070 0 : MOZ_ASSERT(!parentRuntime);
1071 0 : MOZ_ASSERT(format != js::StackFormat::Default);
1072 0 : stackFormat_ = format;
1073 0 : }
1074 :
1075 : // For inherited heap state accessors.
1076 : friend class js::gc::AutoTraceSession;
1077 : friend class JS::AutoEnterCycleCollection;
1078 :
1079 : private:
1080 : js::ActiveThreadData<js::RuntimeCaches> caches_;
1081 : public:
1082 41763 : js::RuntimeCaches& caches() { return caches_.ref(); }
1083 :
1084 : private:
1085 : // When wasm is interrupted, the pc at which we should return if the
1086 : // interrupt hasn't stopped execution of the current running code. Since
1087 : // this is used only by the interrupt handler and the latter is not
1088 : // reentrant, this value can't be clobbered so there is at most one
1089 : // resume PC at a time.
1090 : js::ActiveThreadData<void*> wasmResumePC_;
1091 :
1092 : // To ensure a consistent state of fp/pc, the unwound pc might be
1093 : // different from the resumePC, especially at call boundaries.
1094 : js::ActiveThreadData<void*> wasmUnwindPC_;
1095 :
1096 : public:
1097 0 : void startWasmInterrupt(void* resumePC, void* unwindPC) {
1098 0 : MOZ_ASSERT(resumePC && unwindPC);
1099 0 : wasmResumePC_ = resumePC;
1100 0 : wasmUnwindPC_ = unwindPC;
1101 0 : }
1102 0 : void finishWasmInterrupt() {
1103 0 : MOZ_ASSERT(wasmResumePC_ && wasmUnwindPC_);
1104 0 : wasmResumePC_ = nullptr;
1105 0 : wasmUnwindPC_ = nullptr;
1106 0 : }
1107 0 : void* wasmResumePC() const {
1108 0 : return wasmResumePC_;
1109 : }
1110 0 : void* wasmUnwindPC() const {
1111 0 : return wasmUnwindPC_;
1112 : }
1113 : };
1114 :
1115 : namespace js {
1116 :
1117 : /*
1118 : * Flags accompany script version data so that a) dynamically created scripts
1119 : * can inherit their caller's compile-time properties and b) scripts can be
1120 : * appropriately compared in the eval cache across global option changes. An
1121 : * example of the latter is enabling the top-level-anonymous-function-is-error
1122 : * option: subsequent evals of the same, previously-valid script text may have
1123 : * become invalid.
1124 : */
1125 : namespace VersionFlags {
1126 : static const unsigned MASK = 0x0FFF; /* see JSVersion in jspubtd.h */
1127 : } /* namespace VersionFlags */
1128 :
1129 : static inline JSVersion
1130 2137 : VersionNumber(JSVersion version)
1131 : {
1132 2137 : return JSVersion(uint32_t(version) & VersionFlags::MASK);
1133 : }
1134 :
1135 : static inline JSVersion
1136 : VersionExtractFlags(JSVersion version)
1137 : {
1138 : return JSVersion(uint32_t(version) & ~VersionFlags::MASK);
1139 : }
1140 :
1141 : static inline void
1142 : VersionCopyFlags(JSVersion* version, JSVersion from)
1143 : {
1144 : *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
1145 : }
1146 :
1147 : static inline bool
1148 : VersionHasFlags(JSVersion version)
1149 : {
1150 : return !!VersionExtractFlags(version);
1151 : }
1152 :
1153 : static inline bool
1154 : VersionIsKnown(JSVersion version)
1155 : {
1156 : return VersionNumber(version) != JSVERSION_UNKNOWN;
1157 : }
1158 :
1159 : inline void
1160 555 : FreeOp::free_(void* p)
1161 : {
1162 555 : js_free(p);
1163 555 : }
1164 :
1165 : inline void
1166 0 : FreeOp::freeLater(void* p)
1167 : {
1168 : // FreeOps other than the defaultFreeOp() are constructed on the stack,
1169 : // and won't hold onto the pointers to free indefinitely.
1170 0 : MOZ_ASSERT(!isDefaultFreeOp());
1171 :
1172 0 : AutoEnterOOMUnsafeRegion oomUnsafe;
1173 0 : if (!freeLaterList.append(p))
1174 0 : oomUnsafe.crash("FreeOp::freeLater");
1175 0 : }
1176 :
1177 : inline bool
1178 0 : FreeOp::appendJitPoisonRange(const jit::JitPoisonRange& range)
1179 : {
1180 : // FreeOps other than the defaultFreeOp() are constructed on the stack,
1181 : // and won't hold onto the pointers to free indefinitely.
1182 0 : MOZ_ASSERT(!isDefaultFreeOp());
1183 :
1184 0 : return jitPoisonRanges.append(range);
1185 : }
1186 :
1187 : /*
1188 : * RAII class that takes the GC lock while it is live.
1189 : *
1190 : * Note that the lock may be temporarily released by use of AutoUnlockGC when
1191 : * passed a non-const reference to this class.
1192 : */
1193 : class MOZ_RAII AutoLockGC
1194 : {
1195 : public:
1196 7212 : explicit AutoLockGC(JSRuntime* rt
1197 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1198 7212 : : runtime_(rt)
1199 : {
1200 7212 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1201 7212 : lock();
1202 7212 : }
1203 :
1204 14424 : ~AutoLockGC() {
1205 7212 : unlock();
1206 7212 : }
1207 :
1208 7229 : void lock() {
1209 7229 : MOZ_ASSERT(lockGuard_.isNothing());
1210 7229 : lockGuard_.emplace(runtime_->gc.lock);
1211 7229 : }
1212 :
1213 7229 : void unlock() {
1214 7229 : MOZ_ASSERT(lockGuard_.isSome());
1215 7229 : lockGuard_.reset();
1216 7229 : }
1217 :
1218 0 : js::LockGuard<js::Mutex>& guard() {
1219 0 : return lockGuard_.ref();
1220 : }
1221 :
1222 : private:
1223 : JSRuntime* runtime_;
1224 : mozilla::Maybe<js::LockGuard<js::Mutex>> lockGuard_;
1225 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1226 :
1227 : AutoLockGC(const AutoLockGC&) = delete;
1228 : AutoLockGC& operator=(const AutoLockGC&) = delete;
1229 : };
1230 :
1231 : class MOZ_RAII AutoUnlockGC
1232 : {
1233 : public:
1234 17 : explicit AutoUnlockGC(AutoLockGC& lock
1235 : MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1236 17 : : lock(lock)
1237 : {
1238 17 : MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1239 17 : lock.unlock();
1240 17 : }
1241 :
1242 34 : ~AutoUnlockGC() {
1243 17 : lock.lock();
1244 17 : }
1245 :
1246 : private:
1247 : AutoLockGC& lock;
1248 : MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1249 :
1250 : AutoUnlockGC(const AutoUnlockGC&) = delete;
1251 : AutoUnlockGC& operator=(const AutoUnlockGC&) = delete;
1252 : };
1253 :
1254 : /************************************************************************/
1255 :
1256 : static MOZ_ALWAYS_INLINE void
1257 : MakeRangeGCSafe(Value* vec, size_t len)
1258 : {
1259 : mozilla::PodZero(vec, len);
1260 : }
1261 :
1262 : static MOZ_ALWAYS_INLINE void
1263 : MakeRangeGCSafe(Value* beg, Value* end)
1264 : {
1265 : mozilla::PodZero(beg, end - beg);
1266 : }
1267 :
1268 : static MOZ_ALWAYS_INLINE void
1269 : MakeRangeGCSafe(jsid* beg, jsid* end)
1270 : {
1271 : for (jsid* id = beg; id != end; ++id)
1272 : *id = INT_TO_JSID(0);
1273 : }
1274 :
1275 : static MOZ_ALWAYS_INLINE void
1276 : MakeRangeGCSafe(jsid* vec, size_t len)
1277 : {
1278 : MakeRangeGCSafe(vec, vec + len);
1279 : }
1280 :
1281 : static MOZ_ALWAYS_INLINE void
1282 : MakeRangeGCSafe(Shape** beg, Shape** end)
1283 : {
1284 : mozilla::PodZero(beg, end - beg);
1285 : }
1286 :
1287 : static MOZ_ALWAYS_INLINE void
1288 : MakeRangeGCSafe(Shape** vec, size_t len)
1289 : {
1290 : mozilla::PodZero(vec, len);
1291 : }
1292 :
1293 : static MOZ_ALWAYS_INLINE void
1294 13157 : SetValueRangeToUndefined(Value* beg, Value* end)
1295 : {
1296 35838 : for (Value* v = beg; v != end; ++v)
1297 22681 : v->setUndefined();
1298 13157 : }
1299 :
1300 : static MOZ_ALWAYS_INLINE void
1301 13157 : SetValueRangeToUndefined(Value* vec, size_t len)
1302 : {
1303 13157 : SetValueRangeToUndefined(vec, vec + len);
1304 13157 : }
1305 :
1306 : static MOZ_ALWAYS_INLINE void
1307 : SetValueRangeToNull(Value* beg, Value* end)
1308 : {
1309 : for (Value* v = beg; v != end; ++v)
1310 : v->setNull();
1311 : }
1312 :
1313 : static MOZ_ALWAYS_INLINE void
1314 : SetValueRangeToNull(Value* vec, size_t len)
1315 : {
1316 : SetValueRangeToNull(vec, vec + len);
1317 : }
1318 :
1319 : /*
1320 : * Allocation policy that uses JSRuntime::pod_malloc and friends, so that
1321 : * memory pressure is properly accounted for. This is suitable for
1322 : * long-lived objects owned by the JSRuntime.
1323 : *
1324 : * Since it doesn't hold a JSContext (those may not live long enough), it
1325 : * can't report out-of-memory conditions itself; the caller must check for
1326 : * OOM and take the appropriate action.
1327 : *
1328 : * FIXME bug 647103 - replace these *AllocPolicy names.
1329 : */
1330 : class RuntimeAllocPolicy
1331 : {
1332 : JSRuntime* const runtime;
1333 :
1334 : public:
1335 744 : MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime* rt) : runtime(rt) {}
1336 :
1337 : template <typename T>
1338 : T* maybe_pod_malloc(size_t numElems) {
1339 : return runtime->maybe_pod_malloc<T>(numElems);
1340 : }
1341 :
1342 : template <typename T>
1343 7 : T* maybe_pod_calloc(size_t numElems) {
1344 7 : return runtime->maybe_pod_calloc<T>(numElems);
1345 : }
1346 :
1347 : template <typename T>
1348 : T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
1349 : return runtime->maybe_pod_realloc<T>(p, oldSize, newSize);
1350 : }
1351 :
1352 : template <typename T>
1353 958 : T* pod_malloc(size_t numElems) {
1354 958 : return runtime->pod_malloc<T>(numElems);
1355 : }
1356 :
1357 : template <typename T>
1358 403 : T* pod_calloc(size_t numElems) {
1359 403 : return runtime->pod_calloc<T>(numElems);
1360 : }
1361 :
1362 : template <typename T>
1363 : T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
1364 : return runtime->pod_realloc<T>(p, oldSize, newSize);
1365 : }
1366 :
1367 216 : void free_(void* p) { js_free(p); }
1368 0 : void reportAllocOverflow() const {}
1369 :
1370 2551 : bool checkSimulatedOOM() const {
1371 2551 : return !js::oom::ShouldFailWithOOM();
1372 : }
1373 : };
1374 :
1375 : extern const JSSecurityCallbacks NullSecurityCallbacks;
1376 :
1377 : inline Nursery&
1378 850 : ZoneGroup::nursery()
1379 : {
1380 850 : return runtime->gc.nursery();
1381 : }
1382 :
1383 : inline gc::StoreBuffer&
1384 547 : ZoneGroup::storeBuffer()
1385 : {
1386 547 : return runtime->gc.storeBuffer();
1387 : }
1388 :
1389 : // This callback is set by JS::SetProcessLargeAllocationFailureCallback
1390 : // and may be null. See comment in jsapi.h.
1391 : extern mozilla::Atomic<JS::LargeAllocationFailureCallback> OnLargeAllocationFailure;
1392 :
1393 : } /* namespace js */
1394 :
1395 : #ifdef _MSC_VER
1396 : #pragma warning(pop)
1397 : #endif
1398 :
1399 : #endif /* vm_Runtime_h */
|