1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "jit/CompileWrappers.h"
8 
9 #include "gc/GC.h"
10 #include "gc/Heap.h"
11 #include "jit/Ion.h"
12 #include "jit/JitRealm.h"
13 
14 #include "vm/Realm-inl.h"
15 
16 using namespace js;
17 using namespace js::jit;
18 
runtime()19 JSRuntime* CompileRuntime::runtime() {
20   return reinterpret_cast<JSRuntime*>(this);
21 }
22 
23 /* static */
get(JSRuntime * rt)24 CompileRuntime* CompileRuntime::get(JSRuntime* rt) {
25   return reinterpret_cast<CompileRuntime*>(rt);
26 }
27 
28 #ifdef JS_GC_ZEAL
addressOfGCZealModeBits()29 const uint32_t* CompileRuntime::addressOfGCZealModeBits() {
30   return runtime()->gc.addressOfZealModeBits();
31 }
32 #endif
33 
jitRuntime()34 const JitRuntime* CompileRuntime::jitRuntime() {
35   return runtime()->jitRuntime();
36 }
37 
geckoProfiler()38 GeckoProfilerRuntime& CompileRuntime::geckoProfiler() {
39   return runtime()->geckoProfiler();
40 }
41 
hadOutOfMemory()42 bool CompileRuntime::hadOutOfMemory() { return runtime()->hadOutOfMemory; }
43 
profilingScripts()44 bool CompileRuntime::profilingScripts() { return runtime()->profilingScripts; }
45 
names()46 const JSAtomState& CompileRuntime::names() { return *runtime()->commonNames; }
47 
emptyString()48 const PropertyName* CompileRuntime::emptyString() {
49   return runtime()->emptyString;
50 }
51 
staticStrings()52 const StaticStrings& CompileRuntime::staticStrings() {
53   return *runtime()->staticStrings;
54 }
55 
wellKnownSymbols()56 const WellKnownSymbols& CompileRuntime::wellKnownSymbols() {
57   return *runtime()->wellKnownSymbols;
58 }
59 
mainContextPtr()60 const void* CompileRuntime::mainContextPtr() {
61   return runtime()->mainContextFromAnyThread();
62 }
63 
addressOfTenuredAllocCount()64 uint32_t* CompileRuntime::addressOfTenuredAllocCount() {
65   return runtime()->mainContextFromAnyThread()->addressOfTenuredAllocCount();
66 }
67 
addressOfJitStackLimit()68 const void* CompileRuntime::addressOfJitStackLimit() {
69   return runtime()->mainContextFromAnyThread()->addressOfJitStackLimit();
70 }
71 
addressOfInterruptBits()72 const void* CompileRuntime::addressOfInterruptBits() {
73   return runtime()->mainContextFromAnyThread()->addressOfInterruptBits();
74 }
75 
addressOfZone()76 const void* CompileRuntime::addressOfZone() {
77   return runtime()->mainContextFromAnyThread()->addressOfZone();
78 }
79 
DOMcallbacks()80 const DOMCallbacks* CompileRuntime::DOMcallbacks() {
81   return runtime()->DOMcallbacks;
82 }
83 
runtimeMatches(JSRuntime * rt)84 bool CompileRuntime::runtimeMatches(JSRuntime* rt) { return rt == runtime(); }
85 
zone()86 Zone* CompileZone::zone() { return reinterpret_cast<Zone*>(this); }
87 
88 /* static */
get(Zone * zone)89 CompileZone* CompileZone::get(Zone* zone) {
90   return reinterpret_cast<CompileZone*>(zone);
91 }
92 
runtime()93 CompileRuntime* CompileZone::runtime() {
94   return CompileRuntime::get(zone()->runtimeFromAnyThread());
95 }
96 
isAtomsZone()97 bool CompileZone::isAtomsZone() { return zone()->isAtomsZone(); }
98 
99 #ifdef DEBUG
addressOfIonBailAfterCounter()100 const void* CompileRuntime::addressOfIonBailAfterCounter() {
101   return runtime()->jitRuntime()->addressOfIonBailAfterCounter();
102 }
103 #endif
104 
addressOfNeedsIncrementalBarrier()105 const uint32_t* CompileZone::addressOfNeedsIncrementalBarrier() {
106   return zone()->addressOfNeedsIncrementalBarrier();
107 }
108 
addressOfFreeList(gc::AllocKind allocKind)109 gc::FreeSpan** CompileZone::addressOfFreeList(gc::AllocKind allocKind) {
110   return zone()->arenas.addressOfFreeList(allocKind);
111 }
112 
addressOfNurseryPosition()113 void* CompileZone::addressOfNurseryPosition() {
114   return zone()->runtimeFromAnyThread()->gc.addressOfNurseryPosition();
115 }
116 
addressOfStringNurseryPosition()117 void* CompileZone::addressOfStringNurseryPosition() {
118   // Objects and strings share a nursery, for now at least.
119   return zone()->runtimeFromAnyThread()->gc.addressOfNurseryPosition();
120 }
121 
addressOfBigIntNurseryPosition()122 void* CompileZone::addressOfBigIntNurseryPosition() {
123   // Objects and BigInts share a nursery, for now at least.
124   return zone()->runtimeFromAnyThread()->gc.addressOfNurseryPosition();
125 }
126 
addressOfNurseryCurrentEnd()127 const void* CompileZone::addressOfNurseryCurrentEnd() {
128   return zone()->runtimeFromAnyThread()->gc.addressOfNurseryCurrentEnd();
129 }
130 
addressOfStringNurseryCurrentEnd()131 const void* CompileZone::addressOfStringNurseryCurrentEnd() {
132   // Although objects and strings share a nursery (and this may change)
133   // there is still a separate string end address.  The only time it
134   // is different from the regular end address, is when nursery strings are
135   // disabled (it will be NULL).
136   //
137   // This function returns _a pointer to_ that end address.
138   return zone()->runtimeFromAnyThread()->gc.addressOfStringNurseryCurrentEnd();
139 }
140 
addressOfBigIntNurseryCurrentEnd()141 const void* CompileZone::addressOfBigIntNurseryCurrentEnd() {
142   // Similar to Strings, BigInts also share the nursery with other nursery
143   // allocatable things.
144   return zone()->runtimeFromAnyThread()->gc.addressOfBigIntNurseryCurrentEnd();
145 }
146 
addressOfNurseryAllocCount()147 uint32_t* CompileZone::addressOfNurseryAllocCount() {
148   return zone()->runtimeFromAnyThread()->gc.addressOfNurseryAllocCount();
149 }
150 
canNurseryAllocateStrings()151 bool CompileZone::canNurseryAllocateStrings() {
152   return zone()->runtimeFromAnyThread()->gc.nursery().canAllocateStrings() &&
153          zone()->allocNurseryStrings;
154 }
155 
canNurseryAllocateBigInts()156 bool CompileZone::canNurseryAllocateBigInts() {
157   return zone()->runtimeFromAnyThread()->gc.nursery().canAllocateBigInts() &&
158          zone()->allocNurseryBigInts;
159 }
160 
setMinorGCShouldCancelIonCompilations()161 void CompileZone::setMinorGCShouldCancelIonCompilations() {
162   MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
163   JSRuntime* rt = zone()->runtimeFromMainThread();
164   rt->gc.storeBuffer().setShouldCancelIonCompilations();
165 }
166 
nurseryCellHeader(JS::TraceKind kind)167 uintptr_t CompileZone::nurseryCellHeader(JS::TraceKind kind) {
168   return gc::NurseryCellHeader::MakeValue(zone(), kind);
169 }
170 
realm()171 JS::Realm* CompileRealm::realm() { return reinterpret_cast<JS::Realm*>(this); }
172 
173 /* static */
get(JS::Realm * realm)174 CompileRealm* CompileRealm::get(JS::Realm* realm) {
175   return reinterpret_cast<CompileRealm*>(realm);
176 }
177 
zone()178 CompileZone* CompileRealm::zone() { return CompileZone::get(realm()->zone()); }
179 
runtime()180 CompileRuntime* CompileRealm::runtime() {
181   return CompileRuntime::get(realm()->runtimeFromAnyThread());
182 }
183 
184 const mozilla::non_crypto::XorShift128PlusRNG*
addressOfRandomNumberGenerator()185 CompileRealm::addressOfRandomNumberGenerator() {
186   return realm()->addressOfRandomNumberGenerator();
187 }
188 
jitRealm()189 const JitRealm* CompileRealm::jitRealm() { return realm()->jitRealm(); }
190 
maybeGlobal()191 const GlobalObject* CompileRealm::maybeGlobal() {
192   // This uses unsafeUnbarrieredMaybeGlobal() so as not to trigger the read
193   // barrier on the global from off thread.  This is safe because we
194   // abort Ion compilation when we GC.
195   return realm()->unsafeUnbarrieredMaybeGlobal();
196 }
197 
addressOfGlobalWriteBarriered()198 const uint32_t* CompileRealm::addressOfGlobalWriteBarriered() {
199   return &realm()->globalWriteBarriered;
200 }
201 
hasAllocationMetadataBuilder()202 bool CompileRealm::hasAllocationMetadataBuilder() {
203   return realm()->hasAllocationMetadataBuilder();
204 }
205 
206 // Note: This function is thread-safe because setSingletonAsValue sets a boolean
207 // variable to false, and this boolean variable has no way to be resetted to
208 // true. So even if there is a concurrent write, this concurrent write will
209 // always have the same value.  If there is a concurrent read, then we will
210 // clone a singleton instead of using the value which is baked in the JSScript,
211 // and this would be an unfortunate allocation, but this will not change the
212 // semantics of the JavaScript code which is executed.
setSingletonsAsValues()213 void CompileRealm::setSingletonsAsValues() {
214   realm()->behaviors().setSingletonsAsValues();
215 }
216 
JitCompileOptions()217 JitCompileOptions::JitCompileOptions()
218     : cloneSingletons_(false),
219       profilerSlowAssertionsEnabled_(false),
220       offThreadCompilationAvailable_(false) {}
221 
JitCompileOptions(JSContext * cx)222 JitCompileOptions::JitCompileOptions(JSContext* cx) {
223   cloneSingletons_ = cx->realm()->creationOptions().cloneSingletons();
224   profilerSlowAssertionsEnabled_ =
225       cx->runtime()->geckoProfiler().enabled() &&
226       cx->runtime()->geckoProfiler().slowAssertionsEnabled();
227   offThreadCompilationAvailable_ = OffThreadCompilationAvailable(cx);
228 #ifdef DEBUG
229   ionBailAfterEnabled_ = cx->runtime()->jitRuntime()->ionBailAfterEnabled();
230 #endif
231 }
232