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/LinkedList.h"
13 #include "mozilla/MemoryReporting.h"
14 #include "mozilla/PodOperations.h"
15 #include "mozilla/Scoped.h"
16 #include "mozilla/ThreadLocal.h"
17 #include "mozilla/UniquePtr.h"
18 #include "mozilla/Vector.h"
19 
20 #include <setjmp.h>
21 
22 #include "jsatom.h"
23 #include "jsclist.h"
24 #include "jsscript.h"
25 
26 #ifdef XP_DARWIN
27 # include "asmjs/AsmJSSignalHandlers.h"
28 #endif
29 #include "builtin/AtomicsObject.h"
30 #include "ds/FixedSizeHash.h"
31 #include "frontend/ParseMaps.h"
32 #include "gc/GCRuntime.h"
33 #include "gc/Tracer.h"
34 #include "irregexp/RegExpStack.h"
35 #include "js/Debug.h"
36 #include "js/HashTable.h"
37 #ifdef DEBUG
38 # include "js/Proxy.h" // For AutoEnterPolicy
39 #endif
40 #include "js/TraceableVector.h"
41 #include "js/Vector.h"
42 #include "vm/CodeCoverage.h"
43 #include "vm/CommonPropertyNames.h"
44 #include "vm/DateTime.h"
45 #include "vm/MallocProvider.h"
46 #include "vm/SPSProfiler.h"
47 #include "vm/Stack.h"
48 #include "vm/Stopwatch.h"
49 #include "vm/Symbol.h"
50 
51 #ifdef _MSC_VER
52 #pragma warning(push)
53 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
54 #endif
55 
56 namespace js {
57 
58 class PerThreadData;
59 class ExclusiveContext;
60 class AutoKeepAtoms;
61 #ifdef JS_TRACE_LOGGING
62 class TraceLoggerThread;
63 #endif
64 
65 /* Thread Local Storage slot for storing the runtime for a thread. */
66 extern mozilla::ThreadLocal<PerThreadData*> TlsPerThreadData;
67 
68 } // namespace js
69 
70 struct DtoaState;
71 
72 #ifdef JS_SIMULATOR_ARM64
73 namespace vixl {
74 class Simulator;
75 }
76 #endif
77 
78 namespace js {
79 
80 extern MOZ_COLD void
81 ReportOutOfMemory(ExclusiveContext* cx);
82 
83 extern MOZ_COLD void
84 ReportAllocationOverflow(ExclusiveContext* maybecx);
85 
86 extern MOZ_COLD void
87 ReportOverRecursed(ExclusiveContext* cx);
88 
89 class Activation;
90 class ActivationIterator;
91 class AsmJSActivation;
92 class AsmJSModule;
93 class MathCache;
94 
95 namespace jit {
96 class JitRuntime;
97 class JitActivation;
98 struct PcScriptCache;
99 struct AutoFlushICache;
100 class CompileRuntime;
101 
102 #ifdef JS_SIMULATOR_ARM64
103 typedef vixl::Simulator Simulator;
104 #elif defined(JS_SIMULATOR)
105 class Simulator;
106 #endif
107 } // namespace jit
108 
109 /*
110  * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
111  * given pc in a script. We use the script->code pointer to tag the cache,
112  * instead of the script address itself, so that source notes are always found
113  * by offset from the bytecode with which they were generated.
114  */
115 struct GSNCache {
116     typedef HashMap<jsbytecode*,
117                     jssrcnote*,
118                     PointerHasher<jsbytecode*, 0>,
119                     SystemAllocPolicy> Map;
120 
121     jsbytecode*     code;
122     Map             map;
123 
GSNCacheGSNCache124     GSNCache() : code(nullptr) { }
125 
126     void purge();
127 };
128 
129 /*
130  * ScopeCoordinateName cache to avoid O(n^2) growth in finding the name
131  * associated with a given aliasedvar operation.
132  */
133 struct ScopeCoordinateNameCache {
134     typedef HashMap<uint32_t,
135                     jsid,
136                     DefaultHasher<uint32_t>,
137                     SystemAllocPolicy> Map;
138 
139     Shape* shape;
140     Map map;
141 
ScopeCoordinateNameCacheScopeCoordinateNameCache142     ScopeCoordinateNameCache() : shape(nullptr) {}
143     void purge();
144 };
145 
146 using ScriptAndCountsVector = TraceableVector<ScriptAndCounts, 0, SystemAllocPolicy>;
147 
148 struct EvalCacheEntry
149 {
150     JSLinearString* str;
151     JSScript* script;
152     JSScript* callerScript;
153     jsbytecode* pc;
154 };
155 
156 struct EvalCacheLookup
157 {
EvalCacheLookupEvalCacheLookup158     explicit EvalCacheLookup(JSContext* cx) : str(cx), callerScript(cx) {}
159     RootedLinearString str;
160     RootedScript callerScript;
161     JSVersion version;
162     jsbytecode* pc;
163 };
164 
165 struct EvalCacheHashPolicy
166 {
167     typedef EvalCacheLookup Lookup;
168 
169     static HashNumber hash(const Lookup& l);
170     static bool match(const EvalCacheEntry& entry, const EvalCacheLookup& l);
171 };
172 
173 typedef HashSet<EvalCacheEntry, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache;
174 
175 struct LazyScriptHashPolicy
176 {
177     struct Lookup {
178         JSContext* cx;
179         LazyScript* lazy;
180 
LookupLazyScriptHashPolicy::Lookup181         Lookup(JSContext* cx, LazyScript* lazy)
182           : cx(cx), lazy(lazy)
183         {}
184     };
185 
186     static const size_t NumHashes = 3;
187 
188     static void hash(const Lookup& lookup, HashNumber hashes[NumHashes]);
189     static bool match(JSScript* script, const Lookup& lookup);
190 
191     // Alternate methods for use when removing scripts from the hash without an
192     // explicit LazyScript lookup.
193     static void hash(JSScript* script, HashNumber hashes[NumHashes]);
matchLazyScriptHashPolicy194     static bool match(JSScript* script, JSScript* lookup) { return script == lookup; }
195 
clearLazyScriptHashPolicy196     static void clear(JSScript** pscript) { *pscript = nullptr; }
isClearedLazyScriptHashPolicy197     static bool isCleared(JSScript* script) { return !script; }
198 };
199 
200 typedef FixedSizeHashSet<JSScript*, LazyScriptHashPolicy, 769> LazyScriptCache;
201 
202 class PropertyIteratorObject;
203 
204 class NativeIterCache
205 {
206     static const size_t SIZE = size_t(1) << 8;
207 
208     /* Cached native iterators. */
209     PropertyIteratorObject* data[SIZE];
210 
getIndex(uint32_t key)211     static size_t getIndex(uint32_t key) {
212         return size_t(key) % SIZE;
213     }
214 
215   public:
216     /* Native iterator most recently started. */
217     PropertyIteratorObject* last;
218 
NativeIterCache()219     NativeIterCache()
220       : last(nullptr)
221     {
222         mozilla::PodArrayZero(data);
223     }
224 
purge()225     void purge() {
226         last = nullptr;
227         mozilla::PodArrayZero(data);
228     }
229 
get(uint32_t key)230     PropertyIteratorObject* get(uint32_t key) const {
231         return data[getIndex(key)];
232     }
233 
set(uint32_t key,PropertyIteratorObject * iterobj)234     void set(uint32_t key, PropertyIteratorObject* iterobj) {
235         data[getIndex(key)] = iterobj;
236     }
237 };
238 
239 /*
240  * Cache for speeding up repetitive creation of objects in the VM.
241  * When an object is created which matches the criteria in the 'key' section
242  * below, an entry is filled with the resulting object.
243  */
244 class NewObjectCache
245 {
246     /* Statically asserted to be equal to sizeof(JSObject_Slots16) */
247     static const unsigned MAX_OBJ_SIZE = 4 * sizeof(void*) + 16 * sizeof(Value);
248 
staticAsserts()249     static void staticAsserts() {
250         JS_STATIC_ASSERT(NewObjectCache::MAX_OBJ_SIZE == sizeof(JSObject_Slots16));
251         JS_STATIC_ASSERT(gc::AllocKind::OBJECT_LAST == gc::AllocKind::OBJECT16_BACKGROUND);
252     }
253 
254     struct Entry
255     {
256         /* Class of the constructed object. */
257         const Class* clasp;
258 
259         /*
260          * Key with one of three possible values:
261          *
262          * - Global for the object. The object must have a standard class for
263          *   which the global's prototype can be determined, and the object's
264          *   parent will be the global.
265          *
266          * - Prototype for the object (cannot be global). The object's parent
267          *   will be the prototype's parent.
268          *
269          * - Type for the object. The object's parent will be the type's
270          *   prototype's parent.
271          */
272         gc::Cell* key;
273 
274         /* Allocation kind for the constructed object. */
275         gc::AllocKind kind;
276 
277         /* Number of bytes to copy from the template object. */
278         uint32_t nbytes;
279 
280         /*
281          * Template object to copy from, with the initial values of fields,
282          * fixed slots (undefined) and private data (nullptr).
283          */
284         char templateObject[MAX_OBJ_SIZE];
285     };
286 
287     Entry entries[41];  // TODO: reconsider size
288 
289   public:
290 
291     typedef int EntryIndex;
292 
NewObjectCache()293     NewObjectCache() { mozilla::PodZero(this); }
purge()294     void purge() { mozilla::PodZero(this); }
295 
296     /* Remove any cached items keyed on moved objects. */
297     void clearNurseryObjects(JSRuntime* rt);
298 
299     /*
300      * Get the entry index for the given lookup, return whether there was a hit
301      * on an existing entry.
302      */
303     inline bool lookupProto(const Class* clasp, JSObject* proto, gc::AllocKind kind, EntryIndex* pentry);
304     inline bool lookupGlobal(const Class* clasp, js::GlobalObject* global, gc::AllocKind kind,
305                              EntryIndex* pentry);
306 
lookupGroup(js::ObjectGroup * group,gc::AllocKind kind,EntryIndex * pentry)307     bool lookupGroup(js::ObjectGroup* group, gc::AllocKind kind, EntryIndex* pentry) {
308         return lookup(group->clasp(), group, kind, pentry);
309     }
310 
311     /*
312      * Return a new object from a cache hit produced by a lookup method, or
313      * nullptr if returning the object could possibly trigger GC (does not
314      * indicate failure).
315      */
316     inline NativeObject* newObjectFromHit(JSContext* cx, EntryIndex entry, js::gc::InitialHeap heap);
317 
318     /* Fill an entry after a cache miss. */
319     void fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto proto,
320                    gc::AllocKind kind, NativeObject* obj);
321 
322     inline void fillGlobal(EntryIndex entry, const Class* clasp, js::GlobalObject* global,
323                            gc::AllocKind kind, NativeObject* obj);
324 
fillGroup(EntryIndex entry,js::ObjectGroup * group,gc::AllocKind kind,NativeObject * obj)325     void fillGroup(EntryIndex entry, js::ObjectGroup* group, gc::AllocKind kind,
326                    NativeObject* obj)
327     {
328         MOZ_ASSERT(obj->group() == group);
329         return fill(entry, group->clasp(), group, kind, obj);
330     }
331 
332     /* Invalidate any entries which might produce an object with shape/proto. */
333     void invalidateEntriesForShape(JSContext* cx, HandleShape shape, HandleObject proto);
334 
335   private:
makeIndex(const Class * clasp,gc::Cell * key,gc::AllocKind kind)336     EntryIndex makeIndex(const Class* clasp, gc::Cell* key, gc::AllocKind kind) {
337         uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + size_t(kind);
338         return hash % mozilla::ArrayLength(entries);
339     }
340 
lookup(const Class * clasp,gc::Cell * key,gc::AllocKind kind,EntryIndex * pentry)341     bool lookup(const Class* clasp, gc::Cell* key, gc::AllocKind kind, EntryIndex* pentry) {
342         *pentry = makeIndex(clasp, key, kind);
343         Entry* entry = &entries[*pentry];
344 
345         /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
346         return entry->clasp == clasp && entry->key == key;
347     }
348 
fill(EntryIndex entry_,const Class * clasp,gc::Cell * key,gc::AllocKind kind,NativeObject * obj)349     void fill(EntryIndex entry_, const Class* clasp, gc::Cell* key, gc::AllocKind kind,
350               NativeObject* obj) {
351         MOZ_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
352         MOZ_ASSERT(entry_ == makeIndex(clasp, key, kind));
353         Entry* entry = &entries[entry_];
354 
355         entry->clasp = clasp;
356         entry->key = key;
357         entry->kind = kind;
358 
359         entry->nbytes = gc::Arena::thingSize(kind);
360         js_memcpy(&entry->templateObject, obj, entry->nbytes);
361     }
362 
copyCachedToObject(NativeObject * dst,NativeObject * src,gc::AllocKind kind)363     static void copyCachedToObject(NativeObject* dst, NativeObject* src, gc::AllocKind kind) {
364         js_memcpy(dst, src, gc::Arena::thingSize(kind));
365         Shape::writeBarrierPost(&dst->shape_, nullptr, dst->shape_);
366         ObjectGroup::writeBarrierPost(&dst->group_, nullptr, dst->group_);
367     }
368 };
369 
370 /*
371  * A FreeOp can do one thing: free memory. For convenience, it has delete_
372  * convenience methods that also call destructors.
373  *
374  * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
375  * need to pass a JSContext to those hooks.
376  */
377 class FreeOp : public JSFreeOp
378 {
379     Vector<void*, 0, SystemAllocPolicy> freeLaterList;
380     ThreadType threadType;
381 
382   public:
get(JSFreeOp * fop)383     static FreeOp* get(JSFreeOp* fop) {
384         return static_cast<FreeOp*>(fop);
385     }
386 
387     explicit FreeOp(JSRuntime* rt, ThreadType thread = MainThread)
JSFreeOp(rt)388       : JSFreeOp(rt), threadType(thread)
389     {}
390 
~FreeOp()391     ~FreeOp() {
392         for (size_t i = 0; i < freeLaterList.length(); i++)
393             free_(freeLaterList[i]);
394     }
395 
onBackgroundThread()396     bool onBackgroundThread() {
397         return threadType == BackgroundThread;
398     }
399 
400     inline void free_(void* p);
401     inline void freeLater(void* p);
402 
403     template <class T>
delete_(T * p)404     inline void delete_(T* p) {
405         if (p) {
406             p->~T();
407             free_(p);
408         }
409     }
410 };
411 
412 } /* namespace js */
413 
414 namespace JS {
415 struct RuntimeSizes;
416 } // namespace JS
417 
418 /* Various built-in or commonly-used names pinned on first context. */
419 struct JSAtomState
420 {
421 #define PROPERTYNAME_FIELD(idpart, id, text) js::ImmutablePropertyNamePtr id;
422     FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
423 #undef PROPERTYNAME_FIELD
424 #define PROPERTYNAME_FIELD(name, code, init, clasp) js::ImmutablePropertyNamePtr name;
JS_FOR_EACH_PROTOTYPEJSAtomState425     JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
426 #undef PROPERTYNAME_FIELD
427 
428     js::ImmutablePropertyNamePtr* wellKnownSymbolDescriptions() {
429         return &Symbol_iterator;
430     }
431 };
432 
433 namespace js {
434 
435 /*
436  * Storage for well-known symbols. It's a separate struct from the Runtime so
437  * that it can be shared across multiple runtimes. As in JSAtomState, each
438  * field is a smart pointer that's immutable once initialized.
439  * `rt->wellKnownSymbols->iterator` is convertible to Handle<Symbol*>.
440  *
441  * Well-known symbols are never GC'd. The description() of each well-known
442  * symbol is a permanent atom.
443  */
444 struct WellKnownSymbols
445 {
446     js::ImmutableSymbolPtr iterator;
447     js::ImmutableSymbolPtr match;
448     js::ImmutableSymbolPtr species;
449     js::ImmutableSymbolPtr toPrimitive;
450 
getWellKnownSymbols451     const ImmutableSymbolPtr& get(size_t u) const {
452         MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
453         const ImmutableSymbolPtr* symbols = reinterpret_cast<const ImmutableSymbolPtr*>(this);
454         return symbols[u];
455     }
456 
getWellKnownSymbols457     const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
458         return get(size_t(code));
459     }
460 };
461 
462 #define NAME_OFFSET(name)       offsetof(JSAtomState, name)
463 
464 inline HandlePropertyName
AtomStateOffsetToName(const JSAtomState & atomState,size_t offset)465 AtomStateOffsetToName(const JSAtomState& atomState, size_t offset)
466 {
467     return *reinterpret_cast<js::ImmutablePropertyNamePtr*>((char*)&atomState + offset);
468 }
469 
470 // There are several coarse locks in the enum below. These may be either
471 // per-runtime or per-process. When acquiring more than one of these locks,
472 // the acquisition must be done in the order below to avoid deadlocks.
473 enum RuntimeLock {
474     ExclusiveAccessLock,
475     HelperThreadStateLock,
476     GCLock
477 };
478 
479 #ifdef DEBUG
480 void AssertCurrentThreadCanLock(RuntimeLock which);
481 #else
AssertCurrentThreadCanLock(RuntimeLock which)482 inline void AssertCurrentThreadCanLock(RuntimeLock which) {}
483 #endif
484 
485 inline bool
CanUseExtraThreads()486 CanUseExtraThreads()
487 {
488     extern bool gCanUseExtraThreads;
489     return gCanUseExtraThreads;
490 }
491 
492 void DisableExtraThreads();
493 
494 /*
495  * Encapsulates portions of the runtime/context that are tied to a
496  * single active thread.  Instances of this structure can occur for
497  * the main thread as |JSRuntime::mainThread|, for select operations
498  * performed off thread, such as parsing.
499  */
500 class PerThreadData : public PerThreadDataFriendFields
501 {
502 #ifdef DEBUG
503     // Grant access to runtime_.
504     friend void js::AssertCurrentThreadCanLock(RuntimeLock which);
505 #endif
506 
507     /*
508      * Backpointer to the full shared JSRuntime* with which this
509      * thread is associated.  This is private because accessing the
510      * fields of this runtime can provoke race conditions, so the
511      * intention is that access will be mediated through safe
512      * functions like |runtimeFromMainThread| and |associatedWith()| below.
513      */
514     JSRuntime* runtime_;
515 
516   public:
517 #ifdef JS_TRACE_LOGGING
518     TraceLoggerThread*  traceLogger;
519 #endif
520 
521     /* Pointer to the current AutoFlushICache. */
522     js::jit::AutoFlushICache* autoFlushICache_;
523 
524   public:
525     /* State used by jsdtoa.cpp. */
526     DtoaState*          dtoaState;
527 
528     /*
529      * When this flag is non-zero, any attempt to GC will be skipped. It is used
530      * to suppress GC when reporting an OOM (see ReportOutOfMemory) and in
531      * debugging facilities that cannot tolerate a GC and would rather OOM
532      * immediately, such as utilities exposed to GDB. Setting this flag is
533      * extremely dangerous and should only be used when in an OOM situation or
534      * in non-exposed debugging facilities.
535      */
536     int32_t suppressGC;
537 
538 #ifdef DEBUG
539     // Whether this thread is actively Ion compiling.
540     bool ionCompiling;
541 
542     // Whether this thread is actively Ion compiling in a context where a minor
543     // GC could happen simultaneously. If this is true, this thread cannot use
544     // any pointers into the nursery.
545     bool ionCompilingSafeForMinorGC;
546 
547     // Whether this thread is currently sweeping GC things.
548     bool gcSweeping;
549 #endif
550 
551     // Number of active bytecode compilation on this thread.
552     unsigned activeCompilations;
553 
554     explicit PerThreadData(JSRuntime* runtime);
555     ~PerThreadData();
556 
557     bool init();
558 
associatedWith(const JSRuntime * rt)559     bool associatedWith(const JSRuntime* rt) { return runtime_ == rt; }
560     inline JSRuntime* runtimeFromMainThread();
561     inline JSRuntime* runtimeIfOnOwnerThread();
562 
563     inline bool exclusiveThreadsPresent();
564     inline void addActiveCompilation();
565     inline void removeActiveCompilation();
566 
567     // For threads which may be associated with different runtimes, depending
568     // on the work they are doing.
569     class MOZ_STACK_CLASS AutoEnterRuntime
570     {
571         PerThreadData* pt;
572 
573       public:
AutoEnterRuntime(PerThreadData * pt,JSRuntime * rt)574         AutoEnterRuntime(PerThreadData* pt, JSRuntime* rt)
575           : pt(pt)
576         {
577             MOZ_ASSERT(!pt->runtime_);
578             pt->runtime_ = rt;
579         }
580 
~AutoEnterRuntime()581         ~AutoEnterRuntime() {
582             pt->runtime_ = nullptr;
583         }
584     };
585 
586     js::jit::AutoFlushICache* autoFlushICache() const;
587     void setAutoFlushICache(js::jit::AutoFlushICache* afc);
588 
589 #ifdef JS_SIMULATOR
590     js::jit::Simulator* simulator() const;
591 #endif
592 };
593 
594 class AutoLockForExclusiveAccess;
595 } // namespace js
596 
597 struct JSRuntime : public JS::shadow::Runtime,
598                    public js::MallocProvider<JSRuntime>
599 {
600     /*
601      * Per-thread data for the main thread that is associated with
602      * this JSRuntime, as opposed to any worker threads used in
603      * parallel sections.  See definition of |PerThreadData| struct
604      * above for more details.
605      *
606      * NB: This field is statically asserted to be at offset
607      * sizeof(js::shadow::Runtime). See
608      * PerThreadDataFriendFields::getMainThread.
609      */
610     js::PerThreadData mainThread;
611 
612     /*
613      * If Baseline or Ion code is on the stack, and has called into C++, this
614      * will be aligned to an exit frame.
615      */
616     uint8_t*            jitTop;
617 
618     /*
619      * The current JSContext when entering JIT code. This field may only be used
620      * from JIT code and C++ directly called by JIT code (otherwise it may refer
621      * to the wrong JSContext).
622      */
623     JSContext*          jitJSContext;
624 
625      /*
626      * Points to the most recent JitActivation pushed on the thread.
627      * See JitActivation constructor in vm/Stack.cpp
628      */
629     js::jit::JitActivation* jitActivation;
630 
631     /* See comment for JSRuntime::interrupt_. */
632   private:
633     mozilla::Atomic<uintptr_t, mozilla::Relaxed> jitStackLimit_;
634     void resetJitStackLimit();
635 
636     // Like jitStackLimit_, but not reset to trigger interrupts.
637     uintptr_t jitStackLimitNoInterrupt_;
638 
639   public:
640     void initJitStackLimit();
641 
jitStackLimitJSRuntime642     uintptr_t jitStackLimit() const { return jitStackLimit_; }
643 
644     // For read-only JIT use:
addressOfJitStackLimitJSRuntime645     void* addressOfJitStackLimit() { return &jitStackLimit_; }
offsetOfJitStackLimitJSRuntime646     static size_t offsetOfJitStackLimit() { return offsetof(JSRuntime, jitStackLimit_); }
647 
addressOfJitStackLimitNoInterruptJSRuntime648     void* addressOfJitStackLimitNoInterrupt() { return &jitStackLimitNoInterrupt_; }
649 
650     // Information about the heap allocated backtrack stack used by RegExp JIT code.
651     js::irregexp::RegExpStack regexpStack;
652 
653   private:
654     friend class js::Activation;
655     friend class js::ActivationIterator;
656     friend class js::jit::JitActivation;
657     friend class js::AsmJSActivation;
658     friend class js::jit::CompileRuntime;
659 #ifdef DEBUG
660     friend void js::AssertCurrentThreadCanLock(js::RuntimeLock which);
661 #endif
662 
663     /*
664      * Points to the most recent activation running on the thread.
665      * See Activation comment in vm/Stack.h.
666      */
667     js::Activation* activation_;
668 
669     /*
670      * Points to the most recent profiling activation running on the
671      * thread.
672      */
673     js::Activation * volatile profilingActivation_;
674 
675     /*
676      * The profiler sampler generation after the latest sample.
677      *
678      * The lapCount indicates the number of largest number of 'laps'
679      * (wrapping from high to low) that occurred when writing entries
680      * into the sample buffer.  All JitcodeGlobalMap entries referenced
681      * from a given sample are assigned the generation of the sample buffer
682      * at the START of the run.  If multiple laps occur, then some entries
683      * (towards the end) will be written out with the "wrong" generation.
684      * The lapCount indicates the required fudge factor to use to compare
685      * entry generations with the sample buffer generation.
686      */
687     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferGen_;
688     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> profilerSampleBufferLapCount_;
689 
690     /* See AsmJSActivation comment. */
691     js::AsmJSActivation * volatile asmJSActivationStack_;
692 
693   public:
694     /*
695      * Youngest frame of a saved stack that will be picked up as an async stack
696      * by any new Activation, and is nullptr when no async stack should be used.
697      *
698      * The JS::AutoSetAsyncStackForNewCalls class can be used to set this.
699      *
700      * New activations will reset this to nullptr on construction after getting
701      * the current value, and will restore the previous value on destruction.
702      */
703     JS::PersistentRooted<js::SavedFrame*> asyncStackForNewActivations;
704 
705     /*
706      * Value of asyncCause to be attached to asyncStackForNewActivations.
707      */
708     JS::PersistentRooted<JSString*> asyncCauseForNewActivations;
709 
710     /*
711      * True if the async call was explicitly requested, e.g. via
712      * callFunctionWithAsyncStack.
713      */
714     bool asyncCallIsExplicit;
715 
716     /* If non-null, report JavaScript entry points to this monitor. */
717     JS::dbg::AutoEntryMonitor* entryMonitor;
718 
addressOfActivationJSRuntime719     js::Activation* const* addressOfActivation() const {
720         return &activation_;
721     }
offsetOfActivationJSRuntime722     static unsigned offsetOfActivation() {
723         return offsetof(JSRuntime, activation_);
724     }
725 
profilingActivationJSRuntime726     js::Activation* profilingActivation() const {
727         return profilingActivation_;
728     }
addressOfProfilingActivationJSRuntime729     void* addressOfProfilingActivation() {
730         return (void*) &profilingActivation_;
731     }
offsetOfProfilingActivationJSRuntime732     static unsigned offsetOfProfilingActivation() {
733         return offsetof(JSRuntime, profilingActivation_);
734     }
735 
profilerSampleBufferGenJSRuntime736     uint32_t profilerSampleBufferGen() {
737         return profilerSampleBufferGen_;
738     }
resetProfilerSampleBufferGenJSRuntime739     void resetProfilerSampleBufferGen() {
740         profilerSampleBufferGen_ = 0;
741     }
setProfilerSampleBufferGenJSRuntime742     void setProfilerSampleBufferGen(uint32_t gen) {
743         // May be called from sampler thread or signal handler; use
744         // compareExchange to make sure we have monotonic increase.
745         for (;;) {
746             uint32_t curGen = profilerSampleBufferGen_;
747             if (curGen >= gen)
748                 break;
749 
750             if (profilerSampleBufferGen_.compareExchange(curGen, gen))
751                 break;
752         }
753     }
754 
profilerSampleBufferLapCountJSRuntime755     uint32_t profilerSampleBufferLapCount() {
756         MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
757         return profilerSampleBufferLapCount_;
758     }
resetProfilerSampleBufferLapCountJSRuntime759     void resetProfilerSampleBufferLapCount() {
760         profilerSampleBufferLapCount_ = 1;
761     }
updateProfilerSampleBufferLapCountJSRuntime762     void updateProfilerSampleBufferLapCount(uint32_t lapCount) {
763         MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
764 
765         // May be called from sampler thread or signal handler; use
766         // compareExchange to make sure we have monotonic increase.
767         for (;;) {
768             uint32_t curLapCount = profilerSampleBufferLapCount_;
769             if (curLapCount >= lapCount)
770                 break;
771 
772             if (profilerSampleBufferLapCount_.compareExchange(curLapCount, lapCount))
773                 break;
774         }
775     }
776 
asmJSActivationStackJSRuntime777     js::AsmJSActivation* asmJSActivationStack() const {
778         return asmJSActivationStack_;
779     }
innermostAsmJSActivationJSRuntime780     static js::AsmJSActivation* innermostAsmJSActivation() {
781         js::PerThreadData* ptd = js::TlsPerThreadData.get();
782         return ptd ? ptd->runtimeFromMainThread()->asmJSActivationStack_ : nullptr;
783     }
784 
activationJSRuntime785     js::Activation* activation() const {
786         return activation_;
787     }
788 
789     /*
790      * If non-null, another runtime guaranteed to outlive this one and whose
791      * permanent data may be used by this one where possible.
792      */
793     JSRuntime* parentRuntime;
794 
795   private:
796     mozilla::Atomic<uint32_t, mozilla::Relaxed> interrupt_;
797 
798     /* Call this to accumulate telemetry data. */
799     JSAccumulateTelemetryDataCallback telemetryCallback;
800   public:
801     // Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
802     // histogram. |key| provides an additional key to identify the histogram.
803     // |sample| is the data to add to the histogram.
804     void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
805 
806     void setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
807 
808     enum InterruptMode {
809         RequestInterruptUrgent,
810         RequestInterruptCanWait
811     };
812 
813     // Any thread can call requestInterrupt() to request that the main JS thread
814     // stop running and call the interrupt callback (allowing the interrupt
815     // callback to halt execution). To stop the main JS thread, requestInterrupt
816     // sets two fields: interrupt_ (set to true) and jitStackLimit_ (set to
817     // UINTPTR_MAX). The JS engine must continually poll one of these fields
818     // and call handleInterrupt if either field has the interrupt value. (The
819     // point of setting jitStackLimit_ to UINTPTR_MAX is that JIT code already
820     // needs to guard on jitStackLimit_ in every function prologue to avoid
821     // stack overflow, so we avoid a second branch on interrupt_ by setting
822     // jitStackLimit_ to a value that is guaranteed to fail the guard.)
823     //
824     // Note that the writes to interrupt_ and jitStackLimit_ use a Relaxed
825     // Atomic so, while the writes are guaranteed to eventually be visible to
826     // the main thread, it can happen in any order. handleInterrupt calls the
827     // interrupt callback if either is set, so it really doesn't matter as long
828     // as the JS engine is continually polling at least one field. In corner
829     // cases, this relaxed ordering could lead to an interrupt handler being
830     // called twice in succession after a single requestInterrupt call, but
831     // that's fine.
832     void requestInterrupt(InterruptMode mode);
833     bool handleInterrupt(JSContext* cx);
834 
hasPendingInterruptJSRuntime835     MOZ_ALWAYS_INLINE bool hasPendingInterrupt() const {
836         return interrupt_;
837     }
838 
839     // For read-only JIT use:
addressOfInterruptUint32JSRuntime840     void* addressOfInterruptUint32() {
841         static_assert(sizeof(interrupt_) == sizeof(uint32_t), "Assumed by JIT callers");
842         return &interrupt_;
843     }
844 
845     /* Set when handling a signal for a thread associated with this runtime. */
846     bool handlingSignal;
847 
848     JSInterruptCallback interruptCallback;
849 
850 #ifdef DEBUG
851     void assertCanLock(js::RuntimeLock which);
852 #else
assertCanLockJSRuntime853     void assertCanLock(js::RuntimeLock which) {}
854 #endif
855 
856   private:
857     /*
858      * Lock taken when using per-runtime or per-zone data that could otherwise
859      * be accessed simultaneously by both the main thread and another thread
860      * with an ExclusiveContext.
861      *
862      * Locking this only occurs if there is actually a thread other than the
863      * main thread with an ExclusiveContext which could access such data.
864      */
865     PRLock* exclusiveAccessLock;
866     mozilla::DebugOnly<PRThread*> exclusiveAccessOwner;
867     mozilla::DebugOnly<bool> mainThreadHasExclusiveAccess;
868 
869     /* Number of non-main threads with an ExclusiveContext. */
870     size_t numExclusiveThreads;
871 
872     friend class js::AutoLockForExclusiveAccess;
873 
874   public:
875     void setUsedByExclusiveThread(JS::Zone* zone);
876     void clearUsedByExclusiveThread(JS::Zone* zone);
877 
878 #ifdef DEBUG
currentThreadHasExclusiveAccessJSRuntime879     bool currentThreadHasExclusiveAccess() {
880         return (!numExclusiveThreads && mainThreadHasExclusiveAccess) ||
881                exclusiveAccessOwner == PR_GetCurrentThread();
882     }
883 #endif // DEBUG
884 
exclusiveThreadsPresentJSRuntime885     bool exclusiveThreadsPresent() const {
886         return numExclusiveThreads > 0;
887     }
888 
889     // How many compartments there are across all zones. This number includes
890     // ExclusiveContext compartments, so it isn't necessarily equal to the
891     // number of compartments visited by CompartmentsIter.
892     size_t              numCompartments;
893 
894     /* Locale-specific callbacks for string conversion. */
895     const JSLocaleCallbacks* localeCallbacks;
896 
897     /* Default locale for Internationalization API */
898     char* defaultLocale;
899 
900     /* Default JSVersion. */
901     JSVersion defaultVersion_;
902 
903     /* Futex state, used by futexWait and futexWake on the Atomics object */
904     js::FutexRuntime fx;
905 
906   private:
907     /* See comment for JS_AbortIfWrongThread in jsapi.h. */
908     void* ownerThread_;
909     size_t ownerThreadNative_;
910     friend bool js::CurrentThreadCanAccessRuntime(JSRuntime* rt);
911   public:
912 
ownerThreadNativeJSRuntime913     size_t ownerThreadNative() const {
914         return ownerThreadNative_;
915     }
916 
917     /* Temporary arena pool used while compiling and decompiling. */
918     static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
919     js::LifoAlloc tempLifoAlloc;
920 
921   private:
922     js::jit::JitRuntime* jitRuntime_;
923 
924     /*
925      * Self-hosting state cloned on demand into other compartments. Shared with the parent
926      * runtime if there is one.
927      */
928     js::NativeObject* selfHostingGlobal_;
929 
930     static js::GlobalObject*
931     createSelfHostingGlobal(JSContext* cx);
932 
933     /* Space for interpreter frames. */
934     js::InterpreterStack interpreterStack_;
935 
936     js::jit::JitRuntime* createJitRuntime(JSContext* cx);
937 
938   public:
getJitRuntimeJSRuntime939     js::jit::JitRuntime* getJitRuntime(JSContext* cx) {
940         return jitRuntime_ ? jitRuntime_ : createJitRuntime(cx);
941     }
jitRuntimeJSRuntime942     js::jit::JitRuntime* jitRuntime() const {
943         return jitRuntime_;
944     }
hasJitRuntimeJSRuntime945     bool hasJitRuntime() const {
946         return !!jitRuntime_;
947     }
interpreterStackJSRuntime948     js::InterpreterStack& interpreterStack() {
949         return interpreterStack_;
950     }
951 
952   private:
953     // Used to generate random keys for hash tables.
954     mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
955     mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
956 
957   public:
958     mozilla::HashCodeScrambler randomHashCodeScrambler();
959     mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
960 
961     //-------------------------------------------------------------------------
962     // Self-hosting support
963     //-------------------------------------------------------------------------
964 
965     bool initSelfHosting(JSContext* cx);
966     void finishSelfHosting();
967     void markSelfHostingGlobal(JSTracer* trc);
isSelfHostingGlobalJSRuntime968     bool isSelfHostingGlobal(JSObject* global) {
969         return global == selfHostingGlobal_;
970     }
971     bool isSelfHostingCompartment(JSCompartment* comp) const;
972     bool isSelfHostingZone(const JS::Zone* zone) const;
973     bool cloneSelfHostedFunctionScript(JSContext* cx, js::Handle<js::PropertyName*> name,
974                                        js::Handle<JSFunction*> targetFun);
975     bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
976                               js::MutableHandleValue vp);
977 
978     //-------------------------------------------------------------------------
979     // Locale information
980     //-------------------------------------------------------------------------
981 
982     /*
983      * Set the default locale for the ECMAScript Internationalization API
984      * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
985      * Note that the Internationalization API encourages clients to
986      * specify their own locales.
987      * The locale string remains owned by the caller.
988      */
989     bool setDefaultLocale(const char* locale);
990 
991     /* Reset the default locale to OS defaults. */
992     void resetDefaultLocale();
993 
994     /* Gets current default locale. String remains owned by context. */
995     const char* getDefaultLocale();
996 
defaultVersionJSRuntime997     JSVersion defaultVersion() { return defaultVersion_; }
setDefaultVersionJSRuntime998     void setDefaultVersion(JSVersion v) { defaultVersion_ = v; }
999 
1000     /* Base address of the native stack for the current thread. */
1001     const uintptr_t     nativeStackBase;
1002 
1003     /* The native stack size limit that runtime should not exceed. */
1004     size_t              nativeStackQuota[js::StackKindCount];
1005 
1006     /* Context create/destroy callback. */
1007     JSContextCallback   cxCallback;
1008     void*              cxCallbackData;
1009 
1010     /* Compartment destroy callback. */
1011     JSDestroyCompartmentCallback destroyCompartmentCallback;
1012 
1013     /* Zone destroy callback. */
1014     JSZoneCallback destroyZoneCallback;
1015 
1016     /* Zone sweep callback. */
1017     JSZoneCallback sweepZoneCallback;
1018 
1019     /* Call this to get the name of a compartment. */
1020     JSCompartmentNameCallback compartmentNameCallback;
1021 
1022     js::ActivityCallback  activityCallback;
1023     void*                activityCallbackArg;
1024     void triggerActivityCallback(bool active);
1025 
1026     /* The request depth for this thread. */
1027     unsigned            requestDepth;
1028 
1029 #ifdef DEBUG
1030     unsigned            checkRequestDepth;
1031 
1032     /*
1033      * To help embedders enforce their invariants, we allow them to specify in
1034      * advance which JSContext should be passed to JSAPI calls. If this is set
1035      * to a non-null value, the assertSameCompartment machinery does double-
1036      * duty (in debug builds) to verify that it matches the cx being used.
1037      */
1038     JSContext*         activeContext;
1039 #endif
1040 
1041     /* Garbage collector state, used by jsgc.c. */
1042     js::gc::GCRuntime   gc;
1043 
1044     /* Garbage collector state has been successfully initialized. */
1045     bool                gcInitialized;
1046 
gcZealJSRuntime1047     int gcZeal() { return gc.zeal(); }
1048 
lockGCJSRuntime1049     void lockGC() {
1050         assertCanLock(js::GCLock);
1051         gc.lockGC();
1052     }
1053 
unlockGCJSRuntime1054     void unlockGC() {
1055         gc.unlockGC();
1056     }
1057 
1058 #ifdef JS_SIMULATOR
1059     js::jit::Simulator* simulator_;
1060 #endif
1061 
1062   public:
1063 #ifdef JS_SIMULATOR
1064     js::jit::Simulator* simulator() const;
1065     uintptr_t* addressOfSimulatorStackLimit();
1066 #endif
1067 
1068     /* Strong references on scripts held for PCCount profiling API. */
1069     JS::PersistentRooted<js::ScriptAndCountsVector>* scriptAndCountsVector;
1070 
1071     /* Code coverage output. */
1072     js::coverage::LCovRuntime lcovOutput;
1073 
1074     /* Well-known numbers held for use by this runtime's contexts. */
1075     const js::Value     NaNValue;
1076     const js::Value     negativeInfinityValue;
1077     const js::Value     positiveInfinityValue;
1078 
1079     js::PropertyName*   emptyString;
1080 
1081     /* List of active contexts sharing this runtime. */
1082     mozilla::LinkedList<JSContext> contextList;
1083 
hasContextsJSRuntime1084     bool hasContexts() const {
1085         return !contextList.isEmpty();
1086     }
1087 
1088     mozilla::UniquePtr<js::SourceHook> sourceHook;
1089 
1090     /* SPS profiling metadata */
1091     js::SPSProfiler     spsProfiler;
1092 
1093     /* If true, new scripts must be created with PC counter information. */
1094     bool                profilingScripts;
1095 
1096     /* Whether sampling should be enabled or not. */
1097   private:
1098     mozilla::Atomic<bool, mozilla::SequentiallyConsistent> suppressProfilerSampling;
1099 
1100   public:
isProfilerSamplingEnabledJSRuntime1101     bool isProfilerSamplingEnabled() const {
1102         return !suppressProfilerSampling;
1103     }
disableProfilerSamplingJSRuntime1104     void disableProfilerSampling() {
1105         suppressProfilerSampling = true;
1106     }
enableProfilerSamplingJSRuntime1107     void enableProfilerSampling() {
1108         suppressProfilerSampling = false;
1109     }
1110 
1111     /* Had an out-of-memory error which did not populate an exception. */
1112     bool                hadOutOfMemory;
1113 
1114     /* A context has been created on this runtime. */
1115     bool                haveCreatedContext;
1116 
1117     /*
1118      * Allow relazifying functions in compartments that are active. This is
1119      * only used by the relazifyFunctions() testing function.
1120      */
1121     bool                allowRelazificationForTesting;
1122 
1123     /* Linked list of all Debugger objects in the runtime. */
1124     mozilla::LinkedList<js::Debugger> debuggerList;
1125 
1126     /*
1127      * Head of circular list of all enabled Debuggers that have
1128      * onNewGlobalObject handler methods established.
1129      */
1130     JSCList             onNewGlobalObjectWatchers;
1131 
1132     /* Client opaque pointers */
1133     void*               data;
1134 
1135 #if defined(XP_DARWIN) && defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB)
1136     js::AsmJSMachExceptionHandler asmJSMachExceptionHandler;
1137 #endif
1138 
1139   private:
1140     // Whether EnsureSignalHandlersInstalled succeeded in installing all the
1141     // relevant handlers for this platform.
1142     bool signalHandlersInstalled_;
1143 
1144     // Whether we should use them or they have been disabled for making
1145     // debugging easier. If signal handlers aren't installed, it is set to false.
1146     bool canUseSignalHandlers_;
1147 
1148   public:
canUseSignalHandlersJSRuntime1149     bool canUseSignalHandlers() const {
1150         return canUseSignalHandlers_;
1151     }
setCanUseSignalHandlersJSRuntime1152     void setCanUseSignalHandlers(bool enable) {
1153         canUseSignalHandlers_ = signalHandlersInstalled_ && enable;
1154     }
1155 
1156   private:
1157     js::FreeOp          defaultFreeOp_;
1158 
1159   public:
defaultFreeOpJSRuntime1160     js::FreeOp* defaultFreeOp() {
1161         return &defaultFreeOp_;
1162     }
1163 
1164     uint32_t            debuggerMutations;
1165 
1166     const JSSecurityCallbacks* securityCallbacks;
1167     const js::DOMCallbacks* DOMcallbacks;
1168     JSDestroyPrincipalsOp destroyPrincipals;
1169     JSReadPrincipalsOp readPrincipals;
1170 
1171     /* Optional error reporter. */
1172     JSErrorReporter     errorReporter;
1173 
1174     /* AsmJSCache callbacks are runtime-wide. */
1175     JS::AsmJSCacheOps   asmJSCacheOps;
1176 
1177     /* Head of the linked list of linked asm.js modules. */
1178     js::AsmJSModule*   linkedAsmJSModules;
1179 
1180     /*
1181      * The propertyRemovals counter is incremented for every JSObject::clear,
1182      * and for each JSObject::remove method call that frees a slot in the given
1183      * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
1184      */
1185     uint32_t            propertyRemovals;
1186 
1187 #if !EXPOSE_INTL_API
1188     /* Number localization, used by jsnum.cpp. */
1189     const char*         thousandsSeparator;
1190     const char*         decimalSeparator;
1191     const char*         numGrouping;
1192 #endif
1193 
1194   private:
1195     js::MathCache* mathCache_;
1196     js::MathCache* createMathCache(JSContext* cx);
1197   public:
getMathCacheJSRuntime1198     js::MathCache* getMathCache(JSContext* cx) {
1199         return mathCache_ ? mathCache_ : createMathCache(cx);
1200     }
maybeGetMathCacheJSRuntime1201     js::MathCache* maybeGetMathCache() {
1202         return mathCache_;
1203     }
1204 
1205     js::GSNCache        gsnCache;
1206     js::ScopeCoordinateNameCache scopeCoordinateNameCache;
1207     js::NewObjectCache  newObjectCache;
1208     js::NativeIterCache nativeIterCache;
1209     js::UncompressedSourceCache uncompressedSourceCache;
1210     js::EvalCache       evalCache;
1211     js::LazyScriptCache lazyScriptCache;
1212 
1213     js::CompressedSourceSet compressedSourceSet;
1214 
1215     // Pool of maps used during parse/emit. This may be modified by threads
1216     // with an ExclusiveContext and requires a lock. Active compilations
1217     // prevent the pool from being purged during GCs.
1218   private:
1219     js::frontend::ParseMapPool parseMapPool_;
1220     unsigned activeCompilations_;
1221   public:
parseMapPoolJSRuntime1222     js::frontend::ParseMapPool& parseMapPool() {
1223         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1224         return parseMapPool_;
1225     }
hasActiveCompilationsJSRuntime1226     bool hasActiveCompilations() {
1227         return activeCompilations_ != 0;
1228     }
addActiveCompilationJSRuntime1229     void addActiveCompilation() {
1230         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1231         activeCompilations_++;
1232     }
removeActiveCompilationJSRuntime1233     void removeActiveCompilation() {
1234         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1235         activeCompilations_--;
1236     }
1237 
1238     // Count of AutoKeepAtoms instances on the main thread's stack. When any
1239     // instances exist, atoms in the runtime will not be collected. Threads
1240     // with an ExclusiveContext do not increment this value, but the presence
1241     // of any such threads also inhibits collection of atoms. We don't scan the
1242     // stacks of exclusive threads, so we need to avoid collecting their
1243     // objects in another way. The only GC thing pointers they have are to
1244     // their exclusive compartment (which is not collected) or to the atoms
1245     // compartment. Therefore, we avoid collecting the atoms compartment when
1246     // exclusive threads are running.
1247   private:
1248     unsigned keepAtoms_;
1249     friend class js::AutoKeepAtoms;
1250   public:
keepAtomsJSRuntime1251     bool keepAtoms() {
1252         MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
1253         return keepAtoms_ != 0 || exclusiveThreadsPresent();
1254     }
1255 
1256   private:
1257     const JSPrincipals* trustedPrincipals_;
1258   public:
setTrustedPrincipalsJSRuntime1259     void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
trustedPrincipalsJSRuntime1260     const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
1261 
1262   private:
1263     bool beingDestroyed_;
1264   public:
isBeingDestroyedJSRuntime1265     bool isBeingDestroyed() const {
1266         return beingDestroyed_;
1267     }
1268 
1269   private:
1270     // Set of all atoms other than those in permanentAtoms and staticStrings.
1271     // Reading or writing this set requires the calling thread to have an
1272     // ExclusiveContext and hold a lock. Use AutoLockForExclusiveAccess.
1273     js::AtomSet* atoms_;
1274 
1275     // Compartment and associated zone containing all atoms in the runtime, as
1276     // well as runtime wide IonCode stubs. Modifying the contents of this
1277     // compartment requires the calling thread to have an ExclusiveContext and
1278     // hold a lock. Use AutoLockForExclusiveAccess.
1279     JSCompartment* atomsCompartment_;
1280 
1281     // Set of all live symbols produced by Symbol.for(). All such symbols are
1282     // allocated in the atomsCompartment. Reading or writing the symbol
1283     // registry requires the calling thread to have an ExclusiveContext and
1284     // hold a lock. Use AutoLockForExclusiveAccess.
1285     js::SymbolRegistry symbolRegistry_;
1286 
1287   public:
1288     bool initializeAtoms(JSContext* cx);
1289     void finishAtoms();
1290 
1291     void sweepAtoms();
1292 
atomsJSRuntime1293     js::AtomSet& atoms() {
1294         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1295         return *atoms_;
1296     }
atomsCompartmentJSRuntime1297     JSCompartment* atomsCompartment() {
1298         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1299         return atomsCompartment_;
1300     }
1301 
isAtomsCompartmentJSRuntime1302     bool isAtomsCompartment(JSCompartment* comp) {
1303         return comp == atomsCompartment_;
1304     }
1305 
1306     // The atoms compartment is the only one in its zone.
1307     inline bool isAtomsZone(const JS::Zone* zone) const;
1308 
1309     bool activeGCInAtomsZone();
1310 
symbolRegistryJSRuntime1311     js::SymbolRegistry& symbolRegistry() {
1312         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1313         return symbolRegistry_;
1314     }
1315 
1316     // Permanent atoms are fixed during initialization of the runtime and are
1317     // not modified or collected until the runtime is destroyed. These may be
1318     // shared with another, longer living runtime through |parentRuntime| and
1319     // can be freely accessed with no locking necessary.
1320 
1321     // Permanent atoms pre-allocated for general use.
1322     js::StaticStrings* staticStrings;
1323 
1324     // Cached pointers to various permanent property names.
1325     JSAtomState* commonNames;
1326 
1327     // All permanent atoms in the runtime, other than those in staticStrings.
1328     // Unlike |atoms_|, access to this does not require
1329     // AutoLockForExclusiveAccess because it is frozen and thus read-only.
1330     js::FrozenAtomSet* permanentAtoms;
1331 
1332     bool transformToPermanentAtoms(JSContext* cx);
1333 
1334     // Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
1335     // these are shared with the parentRuntime, if any.
1336     js::WellKnownSymbols* wellKnownSymbols;
1337 
1338     const JSWrapObjectCallbacks*           wrapObjectCallbacks;
1339     js::PreserveWrapperCallback            preserveWrapperCallback;
1340 
1341     // Table of bytecode and other data that may be shared across scripts
1342     // within the runtime. This may be modified by threads with an
1343     // ExclusiveContext and requires a lock.
1344   private:
1345     js::ScriptDataTable scriptDataTable_;
1346   public:
scriptDataTableJSRuntime1347     js::ScriptDataTable& scriptDataTable() {
1348         MOZ_ASSERT(currentThreadHasExclusiveAccess());
1349         return scriptDataTable_;
1350     }
1351 
1352     bool                jitSupportsFloatingPoint;
1353     bool                jitSupportsSimd;
1354 
1355     // Cache for jit::GetPcScript().
1356     js::jit::PcScriptCache* ionPcScriptCache;
1357 
1358     js::ScriptEnvironmentPreparer* scriptEnvironmentPreparer;
1359 
1360     js::CTypesActivityCallback  ctypesActivityCallback;
1361 
1362   private:
1363     static mozilla::Atomic<size_t> liveRuntimesCount;
1364 
1365   public:
hasLiveRuntimesJSRuntime1366     static bool hasLiveRuntimes() {
1367         return liveRuntimesCount > 0;
1368     }
1369 
1370     explicit JSRuntime(JSRuntime* parentRuntime);
1371     ~JSRuntime();
1372 
1373     bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
1374 
thisFromCtorJSRuntime1375     JSRuntime* thisFromCtor() { return this; }
1376 
1377     /*
1378      * Call this after allocating memory held by GC things, to update memory
1379      * pressure counters or report the OOM error if necessary. If oomError and
1380      * cx is not null the function also reports OOM error.
1381      *
1382      * The function must be called outside the GC lock and in case of OOM error
1383      * the caller must ensure that no deadlock possible during OOM reporting.
1384      */
1385     void updateMallocCounter(size_t nbytes);
1386     void updateMallocCounter(JS::Zone* zone, size_t nbytes);
1387 
reportAllocationOverflowJSRuntime1388     void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
1389 
1390     /*
1391      * This should be called after system malloc/calloc/realloc returns nullptr
1392      * to try to recove some memory or to report an error.  For realloc, the
1393      * original pointer must be passed as reallocPtr.
1394      *
1395      * The function must be called outside the GC lock.
1396      */
1397     JS_FRIEND_API(void*) onOutOfMemory(js::AllocFunction allocator, size_t nbytes,
1398                                        void* reallocPtr = nullptr, JSContext* maybecx = nullptr);
1399 
1400     /*  onOutOfMemory but can call the largeAllocationFailureCallback. */
1401     JS_FRIEND_API(void*) onOutOfMemoryCanGC(js::AllocFunction allocator, size_t nbytes,
1402                                             void* reallocPtr = nullptr);
1403 
1404     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* runtime);
1405 
1406   private:
1407     JS::RuntimeOptions options_;
1408     const js::Class* windowProxyClass_;
1409 
1410     // Settings for how helper threads can be used.
1411     bool offthreadIonCompilationEnabled_;
1412     bool parallelParsingEnabled_;
1413 
1414     bool autoWritableJitCodeActive_;
1415 
1416   public:
1417 
1418     // Note: these values may be toggled dynamically (in response to about:config
1419     // prefs changing).
setOffthreadIonCompilationEnabledJSRuntime1420     void setOffthreadIonCompilationEnabled(bool value) {
1421         offthreadIonCompilationEnabled_ = value;
1422     }
canUseOffthreadIonCompilationJSRuntime1423     bool canUseOffthreadIonCompilation() const {
1424         return offthreadIonCompilationEnabled_;
1425     }
setParallelParsingEnabledJSRuntime1426     void setParallelParsingEnabled(bool value) {
1427         parallelParsingEnabled_ = value;
1428     }
canUseParallelParsingJSRuntime1429     bool canUseParallelParsing() const {
1430         return parallelParsingEnabled_;
1431     }
1432 
toggleAutoWritableJitCodeActiveJSRuntime1433     void toggleAutoWritableJitCodeActive(bool b) {
1434         MOZ_ASSERT(autoWritableJitCodeActive_ != b, "AutoWritableJitCode should not be nested.");
1435         MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
1436         autoWritableJitCodeActive_ = b;
1437     }
1438 
optionsJSRuntime1439     const JS::RuntimeOptions& options() const {
1440         return options_;
1441     }
optionsJSRuntime1442     JS::RuntimeOptions& options() {
1443         return options_;
1444     }
1445 
maybeWindowProxyClassJSRuntime1446     const js::Class* maybeWindowProxyClass() const {
1447         return windowProxyClass_;
1448     }
setWindowProxyClassJSRuntime1449     void setWindowProxyClass(const js::Class* clasp) {
1450         windowProxyClass_ = clasp;
1451     }
1452 
1453 #ifdef DEBUG
1454   public:
1455     js::AutoEnterPolicy* enteredPolicy;
1456 #endif
1457 
1458     /* See comment for JS::SetLargeAllocationFailureCallback in jsapi.h. */
1459     JS::LargeAllocationFailureCallback largeAllocationFailureCallback;
1460     void* largeAllocationFailureCallbackData;
1461 
1462     /* See comment for JS::SetOutOfMemoryCallback in jsapi.h. */
1463     JS::OutOfMemoryCallback oomCallback;
1464     void* oomCallbackData;
1465 
1466     /*
1467      * These variations of malloc/calloc/realloc will call the
1468      * large-allocation-failure callback on OOM and retry the allocation.
1469      */
1470 
1471     static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
1472 
1473     template <typename T>
pod_callocCanGCJSRuntime1474     T* pod_callocCanGC(size_t numElems) {
1475         T* p = pod_calloc<T>(numElems);
1476         if (MOZ_LIKELY(!!p))
1477             return p;
1478         size_t bytes;
1479         if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(numElems, &bytes))) {
1480             reportAllocationOverflow();
1481             return nullptr;
1482         }
1483         return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Calloc, bytes));
1484     }
1485 
1486     template <typename T>
pod_reallocCanGCJSRuntime1487     T* pod_reallocCanGC(T* p, size_t oldSize, size_t newSize) {
1488         T* p2 = pod_realloc<T>(p, oldSize, newSize);
1489         if (MOZ_LIKELY(!!p2))
1490             return p2;
1491         size_t bytes;
1492         if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(newSize, &bytes))) {
1493             reportAllocationOverflow();
1494             return nullptr;
1495         }
1496         return static_cast<T*>(onOutOfMemoryCanGC(js::AllocFunction::Realloc, bytes, p));
1497     }
1498 
1499     /*
1500      * Debugger.Memory functions like takeCensus use this embedding-provided
1501      * function to assess the size of malloc'd blocks of memory.
1502      */
1503     mozilla::MallocSizeOf debuggerMallocSizeOf;
1504 
1505     /* Last time at which an animation was played for this runtime. */
1506     int64_t lastAnimationTime;
1507 
1508   public:
1509     js::PerformanceMonitoring performanceMonitoring;
1510 };
1511 
1512 namespace js {
1513 
1514 // When entering JIT code, the calling JSContext* is stored into the thread's
1515 // PerThreadData. This function retrieves the JSContext with the pre-condition
1516 // that the caller is JIT code or C++ called directly from JIT code. This
1517 // function should not be called from arbitrary locations since the JSContext
1518 // may be the wrong one.
1519 static inline JSContext*
GetJSContextFromJitCode()1520 GetJSContextFromJitCode()
1521 {
1522     JSContext* cx = js::TlsPerThreadData.get()->runtimeFromMainThread()->jitJSContext;
1523     MOZ_ASSERT(cx);
1524     return cx;
1525 }
1526 
1527 /*
1528  * Flags accompany script version data so that a) dynamically created scripts
1529  * can inherit their caller's compile-time properties and b) scripts can be
1530  * appropriately compared in the eval cache across global option changes. An
1531  * example of the latter is enabling the top-level-anonymous-function-is-error
1532  * option: subsequent evals of the same, previously-valid script text may have
1533  * become invalid.
1534  */
1535 namespace VersionFlags {
1536 static const unsigned MASK      = 0x0FFF; /* see JSVersion in jspubtd.h */
1537 } /* namespace VersionFlags */
1538 
1539 static inline JSVersion
VersionNumber(JSVersion version)1540 VersionNumber(JSVersion version)
1541 {
1542     return JSVersion(uint32_t(version) & VersionFlags::MASK);
1543 }
1544 
1545 static inline JSVersion
VersionExtractFlags(JSVersion version)1546 VersionExtractFlags(JSVersion version)
1547 {
1548     return JSVersion(uint32_t(version) & ~VersionFlags::MASK);
1549 }
1550 
1551 static inline void
VersionCopyFlags(JSVersion * version,JSVersion from)1552 VersionCopyFlags(JSVersion* version, JSVersion from)
1553 {
1554     *version = JSVersion(VersionNumber(*version) | VersionExtractFlags(from));
1555 }
1556 
1557 static inline bool
VersionHasFlags(JSVersion version)1558 VersionHasFlags(JSVersion version)
1559 {
1560     return !!VersionExtractFlags(version);
1561 }
1562 
1563 static inline bool
VersionIsKnown(JSVersion version)1564 VersionIsKnown(JSVersion version)
1565 {
1566     return VersionNumber(version) != JSVERSION_UNKNOWN;
1567 }
1568 
1569 inline void
free_(void * p)1570 FreeOp::free_(void* p)
1571 {
1572     js_free(p);
1573 }
1574 
1575 inline void
freeLater(void * p)1576 FreeOp::freeLater(void* p)
1577 {
1578     // FreeOps other than the defaultFreeOp() are constructed on the stack,
1579     // and won't hold onto the pointers to free indefinitely.
1580     MOZ_ASSERT(this != runtime()->defaultFreeOp());
1581 
1582     AutoEnterOOMUnsafeRegion oomUnsafe;
1583     if (!freeLaterList.append(p))
1584         oomUnsafe.crash("FreeOp::freeLater");
1585 }
1586 
1587 /*
1588  * RAII class that takes the GC lock while it is live.
1589  *
1590  * Note that the lock may be temporarily released by use of AutoUnlockGC when
1591  * passed a non-const reference to this class.
1592  */
1593 class MOZ_RAII AutoLockGC
1594 {
1595   public:
AutoLockGC(JSRuntime * rt MOZ_GUARD_OBJECT_NOTIFIER_PARAM)1596     explicit AutoLockGC(JSRuntime* rt
1597                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1598       : runtime_(rt), wasUnlocked_(false)
1599     {
1600         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1601         lock();
1602     }
1603 
~AutoLockGC()1604     ~AutoLockGC() {
1605         unlock();
1606     }
1607 
lock()1608     void lock() {
1609         runtime_->lockGC();
1610     }
1611 
unlock()1612     void unlock() {
1613         runtime_->unlockGC();
1614         wasUnlocked_ = true;
1615     }
1616 
1617 #ifdef DEBUG
wasUnlocked()1618     bool wasUnlocked() {
1619         return wasUnlocked_;
1620     }
1621 #endif
1622 
1623   private:
1624     JSRuntime* runtime_;
1625     mozilla::DebugOnly<bool> wasUnlocked_;
1626     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1627 
1628     AutoLockGC(const AutoLockGC&) = delete;
1629     AutoLockGC& operator=(const AutoLockGC&) = delete;
1630 };
1631 
1632 class MOZ_RAII AutoUnlockGC
1633 {
1634   public:
AutoUnlockGC(AutoLockGC & lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)1635     explicit AutoUnlockGC(AutoLockGC& lock
1636                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1637       : lock(lock)
1638     {
1639         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1640         lock.unlock();
1641     }
1642 
~AutoUnlockGC()1643     ~AutoUnlockGC() {
1644         lock.lock();
1645     }
1646 
1647   private:
1648     AutoLockGC& lock;
1649     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1650 
1651     AutoUnlockGC(const AutoUnlockGC&) = delete;
1652     AutoUnlockGC& operator=(const AutoUnlockGC&) = delete;
1653 };
1654 
1655 class MOZ_RAII AutoKeepAtoms
1656 {
1657     PerThreadData* pt;
1658     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1659 
1660   public:
AutoKeepAtoms(PerThreadData * pt MOZ_GUARD_OBJECT_NOTIFIER_PARAM)1661     explicit AutoKeepAtoms(PerThreadData* pt
1662                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1663       : pt(pt)
1664     {
1665         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1666         if (JSRuntime* rt = pt->runtimeIfOnOwnerThread()) {
1667             rt->keepAtoms_++;
1668         } else {
1669             // This should be a thread with an exclusive context, which will
1670             // always inhibit collection of atoms.
1671             MOZ_ASSERT(pt->exclusiveThreadsPresent());
1672         }
1673     }
~AutoKeepAtoms()1674     ~AutoKeepAtoms() {
1675         if (JSRuntime* rt = pt->runtimeIfOnOwnerThread()) {
1676             MOZ_ASSERT(rt->keepAtoms_);
1677             rt->keepAtoms_--;
1678             if (rt->gc.fullGCForAtomsRequested() && !rt->keepAtoms())
1679                 rt->gc.triggerFullGCForAtoms();
1680         }
1681     }
1682 };
1683 
1684 inline JSRuntime*
runtimeFromMainThread()1685 PerThreadData::runtimeFromMainThread()
1686 {
1687     MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_));
1688     return runtime_;
1689 }
1690 
1691 inline JSRuntime*
runtimeIfOnOwnerThread()1692 PerThreadData::runtimeIfOnOwnerThread()
1693 {
1694     return (runtime_ && CurrentThreadCanAccessRuntime(runtime_)) ? runtime_ : nullptr;
1695 }
1696 
1697 inline bool
exclusiveThreadsPresent()1698 PerThreadData::exclusiveThreadsPresent()
1699 {
1700     return runtime_->exclusiveThreadsPresent();
1701 }
1702 
1703 inline void
addActiveCompilation()1704 PerThreadData::addActiveCompilation()
1705 {
1706     activeCompilations++;
1707     runtime_->addActiveCompilation();
1708 }
1709 
1710 inline void
removeActiveCompilation()1711 PerThreadData::removeActiveCompilation()
1712 {
1713     MOZ_ASSERT(activeCompilations);
1714     activeCompilations--;
1715     runtime_->removeActiveCompilation();
1716 }
1717 
1718 /************************************************************************/
1719 
1720 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(Value * vec,size_t len)1721 MakeRangeGCSafe(Value* vec, size_t len)
1722 {
1723     mozilla::PodZero(vec, len);
1724 }
1725 
1726 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(Value * beg,Value * end)1727 MakeRangeGCSafe(Value* beg, Value* end)
1728 {
1729     mozilla::PodZero(beg, end - beg);
1730 }
1731 
1732 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(jsid * beg,jsid * end)1733 MakeRangeGCSafe(jsid* beg, jsid* end)
1734 {
1735     for (jsid* id = beg; id != end; ++id)
1736         *id = INT_TO_JSID(0);
1737 }
1738 
1739 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(jsid * vec,size_t len)1740 MakeRangeGCSafe(jsid* vec, size_t len)
1741 {
1742     MakeRangeGCSafe(vec, vec + len);
1743 }
1744 
1745 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(Shape ** beg,Shape ** end)1746 MakeRangeGCSafe(Shape** beg, Shape** end)
1747 {
1748     mozilla::PodZero(beg, end - beg);
1749 }
1750 
1751 static MOZ_ALWAYS_INLINE void
MakeRangeGCSafe(Shape ** vec,size_t len)1752 MakeRangeGCSafe(Shape** vec, size_t len)
1753 {
1754     mozilla::PodZero(vec, len);
1755 }
1756 
1757 static MOZ_ALWAYS_INLINE void
SetValueRangeToUndefined(Value * beg,Value * end)1758 SetValueRangeToUndefined(Value* beg, Value* end)
1759 {
1760     for (Value* v = beg; v != end; ++v)
1761         v->setUndefined();
1762 }
1763 
1764 static MOZ_ALWAYS_INLINE void
SetValueRangeToUndefined(Value * vec,size_t len)1765 SetValueRangeToUndefined(Value* vec, size_t len)
1766 {
1767     SetValueRangeToUndefined(vec, vec + len);
1768 }
1769 
1770 static MOZ_ALWAYS_INLINE void
SetValueRangeToNull(Value * beg,Value * end)1771 SetValueRangeToNull(Value* beg, Value* end)
1772 {
1773     for (Value* v = beg; v != end; ++v)
1774         v->setNull();
1775 }
1776 
1777 static MOZ_ALWAYS_INLINE void
SetValueRangeToNull(Value * vec,size_t len)1778 SetValueRangeToNull(Value* vec, size_t len)
1779 {
1780     SetValueRangeToNull(vec, vec + len);
1781 }
1782 
1783 /*
1784  * Allocation policy that uses JSRuntime::pod_malloc and friends, so that
1785  * memory pressure is properly accounted for. This is suitable for
1786  * long-lived objects owned by the JSRuntime.
1787  *
1788  * Since it doesn't hold a JSContext (those may not live long enough), it
1789  * can't report out-of-memory conditions itself; the caller must check for
1790  * OOM and take the appropriate action.
1791  *
1792  * FIXME bug 647103 - replace these *AllocPolicy names.
1793  */
1794 class RuntimeAllocPolicy
1795 {
1796     JSRuntime* const runtime;
1797 
1798   public:
RuntimeAllocPolicy(JSRuntime * rt)1799     MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime* rt) : runtime(rt) {}
1800 
1801     template <typename T>
maybe_pod_malloc(size_t numElems)1802     T* maybe_pod_malloc(size_t numElems) {
1803         return runtime->maybe_pod_malloc<T>(numElems);
1804     }
1805 
1806     template <typename T>
maybe_pod_calloc(size_t numElems)1807     T* maybe_pod_calloc(size_t numElems) {
1808         return runtime->maybe_pod_calloc<T>(numElems);
1809     }
1810 
1811     template <typename T>
maybe_pod_realloc(T * p,size_t oldSize,size_t newSize)1812     T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
1813         return runtime->maybe_pod_realloc<T>(p, oldSize, newSize);
1814     }
1815 
1816     template <typename T>
pod_malloc(size_t numElems)1817     T* pod_malloc(size_t numElems) {
1818         return runtime->pod_malloc<T>(numElems);
1819     }
1820 
1821     template <typename T>
pod_calloc(size_t numElems)1822     T* pod_calloc(size_t numElems) {
1823         return runtime->pod_calloc<T>(numElems);
1824     }
1825 
1826     template <typename T>
pod_realloc(T * p,size_t oldSize,size_t newSize)1827     T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
1828         return runtime->pod_realloc<T>(p, oldSize, newSize);
1829     }
1830 
free_(void * p)1831     void free_(void* p) { js_free(p); }
reportAllocOverflow()1832     void reportAllocOverflow() const {}
1833 
checkSimulatedOOM()1834     bool checkSimulatedOOM() const {
1835         return !js::oom::ShouldFailWithOOM();
1836     }
1837 };
1838 
1839 extern const JSSecurityCallbacks NullSecurityCallbacks;
1840 
1841 // Debugging RAII class which marks the current thread as performing an Ion
1842 // compilation, for use by CurrentThreadCan{Read,Write}CompilationData
1843 class MOZ_RAII AutoEnterIonCompilation
1844 {
1845   public:
AutoEnterIonCompilation(bool safeForMinorGC MOZ_GUARD_OBJECT_NOTIFIER_PARAM)1846     explicit AutoEnterIonCompilation(bool safeForMinorGC
1847                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
1848         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1849 
1850 #ifdef DEBUG
1851         PerThreadData* pt = js::TlsPerThreadData.get();
1852         MOZ_ASSERT(!pt->ionCompiling);
1853         MOZ_ASSERT(!pt->ionCompilingSafeForMinorGC);
1854         pt->ionCompiling = true;
1855         pt->ionCompilingSafeForMinorGC = safeForMinorGC;
1856 #endif
1857     }
1858 
~AutoEnterIonCompilation()1859     ~AutoEnterIonCompilation() {
1860 #ifdef DEBUG
1861         PerThreadData* pt = js::TlsPerThreadData.get();
1862         MOZ_ASSERT(pt->ionCompiling);
1863         pt->ionCompiling = false;
1864         pt->ionCompilingSafeForMinorGC = false;
1865 #endif
1866     }
1867 
1868     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1869 };
1870 
1871 /*
1872  * Provides a delete policy that can be used for objects which have their
1873  * lifetime managed by the GC and can only safely be destroyed while the nursery
1874  * is empty.
1875  *
1876  * This is necessary when initializing such an object may fail after the initial
1877  * allocation.  The partially-initialized object must be destroyed, but it may
1878  * not be safe to do so at the current time.  This policy puts the object on a
1879  * queue to be destroyed at a safe time.
1880  */
1881 template <typename T>
1882 struct GCManagedDeletePolicy
1883 {
operatorGCManagedDeletePolicy1884     void operator()(const T* ptr) {
1885         if (ptr) {
1886             JSRuntime* rt = TlsPerThreadData.get()->runtimeIfOnOwnerThread();
1887             if (rt)
1888                 rt->gc.callAfterMinorGC(deletePtr, const_cast<T*>(ptr));
1889             else
1890                 js_delete(const_cast<T*>(ptr));
1891         }
1892     }
1893 
1894   private:
deletePtrGCManagedDeletePolicy1895     static void deletePtr(void* data) {
1896         js_delete(reinterpret_cast<T*>(data));
1897     }
1898 };
1899 
1900 } /* namespace js */
1901 
1902 namespace JS {
1903 
1904 template <typename T>
1905 struct DeletePolicy<js::HeapPtr<T>> : public js::GCManagedDeletePolicy<js::HeapPtr<T>>
1906 {};
1907 
1908 } /* namespace JS */
1909 
1910 #ifdef _MSC_VER
1911 #pragma warning(pop)
1912 #endif
1913 
1914 #endif /* vm_Runtime_h */
1915