Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
7 #ifndef gc_Marking_h
8 #define gc_Marking_h
10 #include "gc/Barrier.h"
12 class JSAtom;
13 class JSLinearString;
15 namespace js {
17 class ArgumentsObject;
18 class ArrayBufferObject;
19 class ArrayBufferViewObject;
20 class SharedArrayBufferObject;
21 class BaseShape;
22 class DebugScopeObject;
23 struct GCMarker;
24 class GlobalObject;
25 class LazyScript;
26 class ScopeObject;
27 class Shape;
28 class UnownedBaseShape;
30 template<class, typename> class HeapPtr;
32 namespace jit {
33 class JitCode;
34 class IonScript;
35 class VMFunction;
36 }
38 namespace types {
39 class Type;
40 }
42 namespace gc {
44 /*** Object Marking ***/
46 /*
47 * These functions expose marking functionality for all of the different GC
48 * thing kinds. For each GC thing, there are several variants. As an example,
49 * these are the variants generated for JSObject. They are listed from most to
50 * least desirable for use:
51 *
52 * MarkObject(JSTracer *trc, const HeapPtr<JSObject> &thing, const char *name);
53 * This function should be used for marking JSObjects, in preference to all
54 * others below. Use it when you have HeapPtr<JSObject>, which
55 * automatically implements write barriers.
56 *
57 * MarkObjectRoot(JSTracer *trc, JSObject *thing, const char *name);
58 * This function is only valid during the root marking phase of GC (i.e.,
59 * when MarkRuntime is on the stack).
60 *
61 * MarkObjectUnbarriered(JSTracer *trc, JSObject *thing, const char *name);
62 * Like MarkObject, this function can be called at any time. It is more
63 * forgiving, since it doesn't demand a HeapPtr as an argument. Its use
64 * should always be accompanied by a comment explaining how write barriers
65 * are implemented for the given field.
66 *
67 * Additionally, the functions MarkObjectRange and MarkObjectRootRange are
68 * defined for marking arrays of object pointers.
69 *
70 * The following functions are provided to test whether a GC thing is marked
71 * under different circumstances:
72 *
73 * IsObjectAboutToBeFinalized(JSObject **thing);
74 * This function is indended to be used in code used to sweep GC things. It
75 * indicates whether the object will will be finialized in the current group
76 * of compartments being swept. Note that this will return false for any
77 * object not in the group of compartments currently being swept, as even if
78 * it is unmarked it may still become marked before it is swept.
79 *
80 * IsObjectMarked(JSObject **thing);
81 * This function is indended to be used in rare cases in code used to mark
82 * GC things. It indicates whether the object is currently marked.
83 *
84 * UpdateObjectIfRelocated(JSObject **thingp);
85 * In some circumstances -- e.g. optional weak marking -- it is necessary
86 * to look at the pointer before marking it strongly or weakly. In these
87 * cases, the following must be called to update the pointer before use.
88 */
90 #define DeclMarker(base, type) \
91 void Mark##base(JSTracer *trc, BarrieredPtr<type> *thing, const char *name); \
92 void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \
93 void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \
94 void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \
95 void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \
96 bool Is##base##Marked(type **thingp); \
97 bool Is##base##Marked(BarrieredPtr<type> *thingp); \
98 bool Is##base##AboutToBeFinalized(type **thingp); \
99 bool Is##base##AboutToBeFinalized(BarrieredPtr<type> *thingp); \
100 type *Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr<type> *thingp); \
101 type *Update##base##IfRelocated(JSRuntime *rt, type **thingp);
103 DeclMarker(BaseShape, BaseShape)
104 DeclMarker(BaseShape, UnownedBaseShape)
105 DeclMarker(JitCode, jit::JitCode)
106 DeclMarker(Object, ArgumentsObject)
107 DeclMarker(Object, ArrayBufferObject)
108 DeclMarker(Object, ArrayBufferViewObject)
109 DeclMarker(Object, SharedArrayBufferObject)
110 DeclMarker(Object, DebugScopeObject)
111 DeclMarker(Object, GlobalObject)
112 DeclMarker(Object, JSObject)
113 DeclMarker(Object, JSFunction)
114 DeclMarker(Object, ScopeObject)
115 DeclMarker(Script, JSScript)
116 DeclMarker(LazyScript, LazyScript)
117 DeclMarker(Shape, Shape)
118 DeclMarker(String, JSAtom)
119 DeclMarker(String, JSString)
120 DeclMarker(String, JSFlatString)
121 DeclMarker(String, JSLinearString)
122 DeclMarker(String, PropertyName)
123 DeclMarker(TypeObject, types::TypeObject)
125 #undef DeclMarker
127 void
128 MarkPermanentAtom(JSTracer *trc, JSAtom *atom, const char *name);
130 /* Return true if the pointer is nullptr, or if it is a tagged pointer to
131 * nullptr.
132 */
133 MOZ_ALWAYS_INLINE bool
134 IsNullTaggedPointer(void *p)
135 {
136 return uintptr_t(p) < 32;
137 }
139 /*** Externally Typed Marking ***/
141 /*
142 * Note: this must only be called by the GC and only when we are tracing through
143 * MarkRoots. It is explicitly for ConservativeStackMarking and should go away
144 * after we transition to exact rooting.
145 */
146 void
147 MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind);
149 void
150 MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name);
152 void
153 MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name);
155 /*** ID Marking ***/
157 void
158 MarkId(JSTracer *trc, BarrieredId *id, const char *name);
160 void
161 MarkIdRoot(JSTracer *trc, jsid *id, const char *name);
163 void
164 MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name);
166 void
167 MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name);
169 void
170 MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name);
172 /*** Value Marking ***/
174 void
175 MarkValue(JSTracer *trc, BarrieredValue *v, const char *name);
177 void
178 MarkValueRange(JSTracer *trc, size_t len, BarrieredValue *vec, const char *name);
180 inline void
181 MarkValueRange(JSTracer *trc, HeapValue *begin, HeapValue *end, const char *name)
182 {
183 return MarkValueRange(trc, end - begin, begin, name);
184 }
186 void
187 MarkValueRoot(JSTracer *trc, Value *v, const char *name);
189 void
190 MarkThingOrValueUnbarriered(JSTracer *trc, uintptr_t *word, const char *name);
192 void
193 MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name);
195 inline void
196 MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
197 {
198 MarkValueRootRange(trc, end - begin, begin, name);
199 }
201 void
202 MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name);
204 bool
205 IsValueMarked(Value *v);
207 bool
208 IsValueAboutToBeFinalized(Value *v);
210 /*** Slot Marking ***/
212 bool
213 IsSlotMarked(HeapSlot *s);
215 void
216 MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
218 void
219 MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
221 void
222 MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots);
224 void
225 MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject *src, JSObject **dst_obj,
226 const char *name);
228 void
229 MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSObject *src, JSScript **dst_script,
230 const char *name);
232 /*
233 * Mark a value that may be in a different compartment from the compartment
234 * being GC'd. (Although it won't be marked if it's in the wrong compartment.)
235 */
236 void
237 MarkCrossCompartmentSlot(JSTracer *trc, JSObject *src, HeapSlot *dst_slot, const char *name);
240 /*** Special Cases ***/
242 /*
243 * The unioned HeapPtr stored in script->globalObj needs special treatment to
244 * typecheck correctly.
245 */
246 void
247 MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name);
249 /*
250 * MarkChildren<JSObject> is exposed solely for preWriteBarrier on
251 * JSObject::TradeGuts. It should not be considered external interface.
252 */
253 void
254 MarkChildren(JSTracer *trc, JSObject *obj);
256 /*
257 * Trace through the shape and any shapes it contains to mark
258 * non-shape children. This is exposed to the JS API as
259 * JS_TraceShapeCycleCollectorChildren.
260 */
261 void
262 MarkCycleCollectorChildren(JSTracer *trc, Shape *shape);
264 void
265 PushArena(GCMarker *gcmarker, ArenaHeader *aheader);
267 /*** Generic ***/
269 /*
270 * The Mark() functions interface should only be used by code that must be
271 * templated. Other uses should use the more specific, type-named functions.
272 */
274 inline void
275 Mark(JSTracer *trc, BarrieredValue *v, const char *name)
276 {
277 MarkValue(trc, v, name);
278 }
280 inline void
281 Mark(JSTracer *trc, BarrieredPtrObject *o, const char *name)
282 {
283 MarkObject(trc, o, name);
284 }
286 inline void
287 Mark(JSTracer *trc, BarrieredPtrScript *o, const char *name)
288 {
289 MarkScript(trc, o, name);
290 }
292 inline void
293 Mark(JSTracer *trc, HeapPtr<jit::JitCode> *code, const char *name)
294 {
295 MarkJitCode(trc, code, name);
296 }
298 /* For use by WeakMap's HashKeyRef instantiation. */
299 inline void
300 Mark(JSTracer *trc, JSObject **objp, const char *name)
301 {
302 MarkObjectUnbarriered(trc, objp, name);
303 }
305 /* For use by Debugger::WeakMap's proxiedScopes HashKeyRef instantiation. */
306 inline void
307 Mark(JSTracer *trc, ScopeObject **obj, const char *name)
308 {
309 MarkObjectUnbarriered(trc, obj, name);
310 }
312 bool
313 IsCellMarked(Cell **thingp);
315 bool
316 IsCellAboutToBeFinalized(Cell **thing);
318 inline bool
319 IsMarked(BarrieredValue *v)
320 {
321 if (!v->isMarkable())
322 return true;
323 return IsValueMarked(v->unsafeGet());
324 }
326 inline bool
327 IsMarked(BarrieredPtrObject *objp)
328 {
329 return IsObjectMarked(objp);
330 }
332 inline bool
333 IsMarked(BarrieredPtrScript *scriptp)
334 {
335 return IsScriptMarked(scriptp);
336 }
338 inline bool
339 IsAboutToBeFinalized(BarrieredValue *v)
340 {
341 if (!v->isMarkable())
342 return false;
343 return IsValueAboutToBeFinalized(v->unsafeGet());
344 }
346 inline bool
347 IsAboutToBeFinalized(BarrieredPtrObject *objp)
348 {
349 return IsObjectAboutToBeFinalized(objp);
350 }
352 inline bool
353 IsAboutToBeFinalized(BarrieredPtrScript *scriptp)
354 {
355 return IsScriptAboutToBeFinalized(scriptp);
356 }
358 #ifdef JS_ION
359 /* Nonsense to get WeakCache to work with new Marking semantics. */
361 inline bool
362 IsAboutToBeFinalized(const js::jit::VMFunction **vmfunc)
363 {
364 /*
365 * Preserves entries in the WeakCache<VMFunction, JitCode>
366 * iff the JitCode has been marked.
367 */
368 return true;
369 }
371 inline bool
372 IsAboutToBeFinalized(ReadBarriered<js::jit::JitCode> code)
373 {
374 return IsJitCodeAboutToBeFinalized(code.unsafeGet());
375 }
376 #endif
378 inline Cell *
379 ToMarkable(const Value &v)
380 {
381 if (v.isMarkable())
382 return (Cell *)v.toGCThing();
383 return nullptr;
384 }
386 inline Cell *
387 ToMarkable(Cell *cell)
388 {
389 return cell;
390 }
392 inline JSGCTraceKind
393 TraceKind(const Value &v)
394 {
395 JS_ASSERT(v.isMarkable());
396 if (v.isObject())
397 return JSTRACE_OBJECT;
398 return JSTRACE_STRING;
399 }
401 inline JSGCTraceKind
402 TraceKind(JSObject *obj)
403 {
404 return JSTRACE_OBJECT;
405 }
407 inline JSGCTraceKind
408 TraceKind(JSScript *script)
409 {
410 return JSTRACE_SCRIPT;
411 }
413 inline JSGCTraceKind
414 TraceKind(LazyScript *lazy)
415 {
416 return JSTRACE_LAZY_SCRIPT;
417 }
419 } /* namespace gc */
421 void
422 TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
424 } /* namespace js */
426 #endif /* gc_Marking_h */