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 /*
8  * JS engine garbage collector API.
9  */
10 
11 #ifndef gc_GC_h
12 #define gc_GC_h
13 
14 #include "gc/AllocKind.h"
15 #include "gc/GCEnum.h"
16 #include "js/GCAPI.h"
17 #include "js/HeapAPI.h"
18 #include "js/RealmIterators.h"
19 #include "js/RealmOptions.h"
20 #include "js/TraceKind.h"
21 
22 class JSExternalString;
23 class JSFatInlineString;
24 class JSTracer;
25 
26 namespace js {
27 
28 class FatInlineAtom;
29 class NormalAtom;
30 
31 class Nursery;
32 
33 namespace gc {
34 
35 class Arena;
36 class TenuredChunk;
37 struct Cell;
38 
39 /*
40  * Map from C++ type to alloc kind for non-object types. JSObject does not have
41  * a 1:1 mapping, so must use Arena::thingSize.
42  *
43  * The AllocKind is available as MapTypeToFinalizeKind<SomeType>::kind.
44  */
45 template <typename T>
46 struct MapTypeToFinalizeKind {};
47 #define EXPAND_MAPTYPETOFINALIZEKIND(allocKind, traceKind, type, sizedType, \
48                                      bgFinal, nursery, compact)             \
49   template <>                                                               \
50   struct MapTypeToFinalizeKind<type> {                                      \
51     static const AllocKind kind = AllocKind::allocKind;                     \
52   };
53 FOR_EACH_NONOBJECT_ALLOCKIND(EXPAND_MAPTYPETOFINALIZEKIND)
54 #undef EXPAND_MAPTYPETOFINALIZEKIND
55 
56 } /* namespace gc */
57 
58 extern void TraceRuntime(JSTracer* trc);
59 
60 // Trace roots but don't evict the nursery first; used from DumpHeap.
61 extern void TraceRuntimeWithoutEviction(JSTracer* trc);
62 
63 extern void ReleaseAllJITCode(JSFreeOp* op);
64 
65 extern void PrepareForDebugGC(JSRuntime* rt);
66 
67 /* Functions for managing cross compartment gray pointers. */
68 
69 extern void NotifyGCNukeWrapper(JSObject* o);
70 
71 extern unsigned NotifyGCPreSwap(JSObject* a, JSObject* b);
72 
73 extern void NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned preResult);
74 
75 using IterateChunkCallback = void (*)(JSRuntime*, void*, gc::TenuredChunk*,
76                                       const JS::AutoRequireNoGC&);
77 using IterateZoneCallback = void (*)(JSRuntime*, void*, JS::Zone*,
78                                      const JS::AutoRequireNoGC&);
79 using IterateArenaCallback = void (*)(JSRuntime*, void*, gc::Arena*,
80                                       JS::TraceKind, size_t,
81                                       const JS::AutoRequireNoGC&);
82 using IterateCellCallback = void (*)(JSRuntime*, void*, JS::GCCellPtr, size_t,
83                                      const JS::AutoRequireNoGC&);
84 
85 /*
86  * This function calls |zoneCallback| on every zone, |realmCallback| on
87  * every realm, |arenaCallback| on every in-use arena, and |cellCallback|
88  * on every in-use cell in the GC heap.
89  *
90  * Note that no read barrier is triggered on the cells passed to cellCallback,
91  * so no these pointers must not escape the callback.
92  */
93 extern void IterateHeapUnbarriered(JSContext* cx, void* data,
94                                    IterateZoneCallback zoneCallback,
95                                    JS::IterateRealmCallback realmCallback,
96                                    IterateArenaCallback arenaCallback,
97                                    IterateCellCallback cellCallback);
98 
99 /*
100  * This function is like IterateHeapUnbarriered, but does it for a single zone.
101  */
102 extern void IterateHeapUnbarrieredForZone(
103     JSContext* cx, JS::Zone* zone, void* data, IterateZoneCallback zoneCallback,
104     JS::IterateRealmCallback realmCallback, IterateArenaCallback arenaCallback,
105     IterateCellCallback cellCallback);
106 
107 /*
108  * Invoke chunkCallback on every in-use chunk.
109  */
110 extern void IterateChunks(JSContext* cx, void* data,
111                           IterateChunkCallback chunkCallback);
112 
113 using IterateScriptCallback = void (*)(JSRuntime*, void*, BaseScript*,
114                                        const JS::AutoRequireNoGC&);
115 
116 /*
117  * Invoke scriptCallback on every in-use script for the given realm or for all
118  * realms if it is null. The scripts may or may not have bytecode.
119  */
120 extern void IterateScripts(JSContext* cx, JS::Realm* realm, void* data,
121                            IterateScriptCallback scriptCallback);
122 
123 JS::Realm* NewRealm(JSContext* cx, JSPrincipals* principals,
124                     const JS::RealmOptions& options);
125 
126 namespace gc {
127 
128 void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC);
129 
130 void WaitForBackgroundTasks(JSContext* cx);
131 
132 /*
133  * Merge all contents of source into target. This can only be used if source is
134  * the only realm in its zone.
135  */
136 void MergeRealms(JS::Realm* source, JS::Realm* target);
137 
138 void CollectSelfHostingZone(JSContext* cx);
139 
140 enum VerifierType { PreBarrierVerifier };
141 
142 #ifdef JS_GC_ZEAL
143 
144 extern const char ZealModeHelpText[];
145 
146 /* Check that write barriers have been used correctly. See gc/Verifier.cpp. */
147 void VerifyBarriers(JSRuntime* rt, VerifierType type);
148 
149 void MaybeVerifyBarriers(JSContext* cx, bool always = false);
150 
151 void DumpArenaInfo();
152 
153 #else
154 
VerifyBarriers(JSRuntime * rt,VerifierType type)155 static inline void VerifyBarriers(JSRuntime* rt, VerifierType type) {}
156 
157 static inline void MaybeVerifyBarriers(JSContext* cx, bool always = false) {}
158 
159 #endif
160 
161 /*
162  * Instances of this class prevent GC from happening while they are live. If an
163  * allocation causes a heap threshold to be exceeded, no GC will be performed
164  * and the allocation will succeed. Allocation may still fail for other reasons.
165  *
166  * Use of this class is highly discouraged, since without GC system memory can
167  * become exhausted and this can cause crashes at places where we can't handle
168  * allocation failure.
169  *
170  * Use of this is permissible in situations where it would be impossible (or at
171  * least very difficult) to tolerate GC and where only a fixed number of objects
172  * are allocated, such as:
173  *
174  *  - error reporting
175  *  - JIT bailout handling
176  *  - brain transplants (JSObject::swap)
177  *  - debugging utilities not exposed to the browser
178  *
179  * This works by updating the |JSContext::suppressGC| counter which is checked
180  * at the start of GC.
181  */
182 class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC {
183   int32_t& suppressGC_;
184 
185  public:
186   explicit AutoSuppressGC(JSContext* cx);
187 
~AutoSuppressGC()188   ~AutoSuppressGC() { suppressGC_--; }
189 };
190 
191 const char* StateName(State state);
192 
193 } /* namespace gc */
194 
195 /* Use this to avoid assertions when manipulating the wrapper map. */
196 class MOZ_RAII AutoDisableProxyCheck {
197  public:
198 #ifdef DEBUG
199   AutoDisableProxyCheck();
200   ~AutoDisableProxyCheck();
201 #else
202   AutoDisableProxyCheck() {}
203 #endif
204 };
205 
206 struct MOZ_RAII AutoDisableCompactingGC {
207   explicit AutoDisableCompactingGC(JSContext* cx);
208   ~AutoDisableCompactingGC();
209 
210  private:
211   JSContext* cx;
212 };
213 
214 } /* namespace js */
215 
216 #endif /* gc_GC_h */
217