1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/gc/Marking.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,426 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef gc_Marking_h 1.11 +#define gc_Marking_h 1.12 + 1.13 +#include "gc/Barrier.h" 1.14 + 1.15 +class JSAtom; 1.16 +class JSLinearString; 1.17 + 1.18 +namespace js { 1.19 + 1.20 +class ArgumentsObject; 1.21 +class ArrayBufferObject; 1.22 +class ArrayBufferViewObject; 1.23 +class SharedArrayBufferObject; 1.24 +class BaseShape; 1.25 +class DebugScopeObject; 1.26 +struct GCMarker; 1.27 +class GlobalObject; 1.28 +class LazyScript; 1.29 +class ScopeObject; 1.30 +class Shape; 1.31 +class UnownedBaseShape; 1.32 + 1.33 +template<class, typename> class HeapPtr; 1.34 + 1.35 +namespace jit { 1.36 +class JitCode; 1.37 +class IonScript; 1.38 +class VMFunction; 1.39 +} 1.40 + 1.41 +namespace types { 1.42 +class Type; 1.43 +} 1.44 + 1.45 +namespace gc { 1.46 + 1.47 +/*** Object Marking ***/ 1.48 + 1.49 +/* 1.50 + * These functions expose marking functionality for all of the different GC 1.51 + * thing kinds. For each GC thing, there are several variants. As an example, 1.52 + * these are the variants generated for JSObject. They are listed from most to 1.53 + * least desirable for use: 1.54 + * 1.55 + * MarkObject(JSTracer *trc, const HeapPtr<JSObject> &thing, const char *name); 1.56 + * This function should be used for marking JSObjects, in preference to all 1.57 + * others below. Use it when you have HeapPtr<JSObject>, which 1.58 + * automatically implements write barriers. 1.59 + * 1.60 + * MarkObjectRoot(JSTracer *trc, JSObject *thing, const char *name); 1.61 + * This function is only valid during the root marking phase of GC (i.e., 1.62 + * when MarkRuntime is on the stack). 1.63 + * 1.64 + * MarkObjectUnbarriered(JSTracer *trc, JSObject *thing, const char *name); 1.65 + * Like MarkObject, this function can be called at any time. It is more 1.66 + * forgiving, since it doesn't demand a HeapPtr as an argument. Its use 1.67 + * should always be accompanied by a comment explaining how write barriers 1.68 + * are implemented for the given field. 1.69 + * 1.70 + * Additionally, the functions MarkObjectRange and MarkObjectRootRange are 1.71 + * defined for marking arrays of object pointers. 1.72 + * 1.73 + * The following functions are provided to test whether a GC thing is marked 1.74 + * under different circumstances: 1.75 + * 1.76 + * IsObjectAboutToBeFinalized(JSObject **thing); 1.77 + * This function is indended to be used in code used to sweep GC things. It 1.78 + * indicates whether the object will will be finialized in the current group 1.79 + * of compartments being swept. Note that this will return false for any 1.80 + * object not in the group of compartments currently being swept, as even if 1.81 + * it is unmarked it may still become marked before it is swept. 1.82 + * 1.83 + * IsObjectMarked(JSObject **thing); 1.84 + * This function is indended to be used in rare cases in code used to mark 1.85 + * GC things. It indicates whether the object is currently marked. 1.86 + * 1.87 + * UpdateObjectIfRelocated(JSObject **thingp); 1.88 + * In some circumstances -- e.g. optional weak marking -- it is necessary 1.89 + * to look at the pointer before marking it strongly or weakly. In these 1.90 + * cases, the following must be called to update the pointer before use. 1.91 + */ 1.92 + 1.93 +#define DeclMarker(base, type) \ 1.94 +void Mark##base(JSTracer *trc, BarrieredPtr<type> *thing, const char *name); \ 1.95 +void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \ 1.96 +void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \ 1.97 +void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \ 1.98 +void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \ 1.99 +bool Is##base##Marked(type **thingp); \ 1.100 +bool Is##base##Marked(BarrieredPtr<type> *thingp); \ 1.101 +bool Is##base##AboutToBeFinalized(type **thingp); \ 1.102 +bool Is##base##AboutToBeFinalized(BarrieredPtr<type> *thingp); \ 1.103 +type *Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr<type> *thingp); \ 1.104 +type *Update##base##IfRelocated(JSRuntime *rt, type **thingp); 1.105 + 1.106 +DeclMarker(BaseShape, BaseShape) 1.107 +DeclMarker(BaseShape, UnownedBaseShape) 1.108 +DeclMarker(JitCode, jit::JitCode) 1.109 +DeclMarker(Object, ArgumentsObject) 1.110 +DeclMarker(Object, ArrayBufferObject) 1.111 +DeclMarker(Object, ArrayBufferViewObject) 1.112 +DeclMarker(Object, SharedArrayBufferObject) 1.113 +DeclMarker(Object, DebugScopeObject) 1.114 +DeclMarker(Object, GlobalObject) 1.115 +DeclMarker(Object, JSObject) 1.116 +DeclMarker(Object, JSFunction) 1.117 +DeclMarker(Object, ScopeObject) 1.118 +DeclMarker(Script, JSScript) 1.119 +DeclMarker(LazyScript, LazyScript) 1.120 +DeclMarker(Shape, Shape) 1.121 +DeclMarker(String, JSAtom) 1.122 +DeclMarker(String, JSString) 1.123 +DeclMarker(String, JSFlatString) 1.124 +DeclMarker(String, JSLinearString) 1.125 +DeclMarker(String, PropertyName) 1.126 +DeclMarker(TypeObject, types::TypeObject) 1.127 + 1.128 +#undef DeclMarker 1.129 + 1.130 +void 1.131 +MarkPermanentAtom(JSTracer *trc, JSAtom *atom, const char *name); 1.132 + 1.133 +/* Return true if the pointer is nullptr, or if it is a tagged pointer to 1.134 + * nullptr. 1.135 + */ 1.136 +MOZ_ALWAYS_INLINE bool 1.137 +IsNullTaggedPointer(void *p) 1.138 +{ 1.139 + return uintptr_t(p) < 32; 1.140 +} 1.141 + 1.142 +/*** Externally Typed Marking ***/ 1.143 + 1.144 +/* 1.145 + * Note: this must only be called by the GC and only when we are tracing through 1.146 + * MarkRoots. It is explicitly for ConservativeStackMarking and should go away 1.147 + * after we transition to exact rooting. 1.148 + */ 1.149 +void 1.150 +MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind); 1.151 + 1.152 +void 1.153 +MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name); 1.154 + 1.155 +void 1.156 +MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name); 1.157 + 1.158 +/*** ID Marking ***/ 1.159 + 1.160 +void 1.161 +MarkId(JSTracer *trc, BarrieredId *id, const char *name); 1.162 + 1.163 +void 1.164 +MarkIdRoot(JSTracer *trc, jsid *id, const char *name); 1.165 + 1.166 +void 1.167 +MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name); 1.168 + 1.169 +void 1.170 +MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name); 1.171 + 1.172 +void 1.173 +MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name); 1.174 + 1.175 +/*** Value Marking ***/ 1.176 + 1.177 +void 1.178 +MarkValue(JSTracer *trc, BarrieredValue *v, const char *name); 1.179 + 1.180 +void 1.181 +MarkValueRange(JSTracer *trc, size_t len, BarrieredValue *vec, const char *name); 1.182 + 1.183 +inline void 1.184 +MarkValueRange(JSTracer *trc, HeapValue *begin, HeapValue *end, const char *name) 1.185 +{ 1.186 + return MarkValueRange(trc, end - begin, begin, name); 1.187 +} 1.188 + 1.189 +void 1.190 +MarkValueRoot(JSTracer *trc, Value *v, const char *name); 1.191 + 1.192 +void 1.193 +MarkThingOrValueUnbarriered(JSTracer *trc, uintptr_t *word, const char *name); 1.194 + 1.195 +void 1.196 +MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name); 1.197 + 1.198 +inline void 1.199 +MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name) 1.200 +{ 1.201 + MarkValueRootRange(trc, end - begin, begin, name); 1.202 +} 1.203 + 1.204 +void 1.205 +MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name); 1.206 + 1.207 +bool 1.208 +IsValueMarked(Value *v); 1.209 + 1.210 +bool 1.211 +IsValueAboutToBeFinalized(Value *v); 1.212 + 1.213 +/*** Slot Marking ***/ 1.214 + 1.215 +bool 1.216 +IsSlotMarked(HeapSlot *s); 1.217 + 1.218 +void 1.219 +MarkSlot(JSTracer *trc, HeapSlot *s, const char *name); 1.220 + 1.221 +void 1.222 +MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name); 1.223 + 1.224 +void 1.225 +MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots); 1.226 + 1.227 +void 1.228 +MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject *src, JSObject **dst_obj, 1.229 + const char *name); 1.230 + 1.231 +void 1.232 +MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSObject *src, JSScript **dst_script, 1.233 + const char *name); 1.234 + 1.235 +/* 1.236 + * Mark a value that may be in a different compartment from the compartment 1.237 + * being GC'd. (Although it won't be marked if it's in the wrong compartment.) 1.238 + */ 1.239 +void 1.240 +MarkCrossCompartmentSlot(JSTracer *trc, JSObject *src, HeapSlot *dst_slot, const char *name); 1.241 + 1.242 + 1.243 +/*** Special Cases ***/ 1.244 + 1.245 +/* 1.246 + * The unioned HeapPtr stored in script->globalObj needs special treatment to 1.247 + * typecheck correctly. 1.248 + */ 1.249 +void 1.250 +MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name); 1.251 + 1.252 +/* 1.253 + * MarkChildren<JSObject> is exposed solely for preWriteBarrier on 1.254 + * JSObject::TradeGuts. It should not be considered external interface. 1.255 + */ 1.256 +void 1.257 +MarkChildren(JSTracer *trc, JSObject *obj); 1.258 + 1.259 +/* 1.260 + * Trace through the shape and any shapes it contains to mark 1.261 + * non-shape children. This is exposed to the JS API as 1.262 + * JS_TraceShapeCycleCollectorChildren. 1.263 + */ 1.264 +void 1.265 +MarkCycleCollectorChildren(JSTracer *trc, Shape *shape); 1.266 + 1.267 +void 1.268 +PushArena(GCMarker *gcmarker, ArenaHeader *aheader); 1.269 + 1.270 +/*** Generic ***/ 1.271 + 1.272 +/* 1.273 + * The Mark() functions interface should only be used by code that must be 1.274 + * templated. Other uses should use the more specific, type-named functions. 1.275 + */ 1.276 + 1.277 +inline void 1.278 +Mark(JSTracer *trc, BarrieredValue *v, const char *name) 1.279 +{ 1.280 + MarkValue(trc, v, name); 1.281 +} 1.282 + 1.283 +inline void 1.284 +Mark(JSTracer *trc, BarrieredPtrObject *o, const char *name) 1.285 +{ 1.286 + MarkObject(trc, o, name); 1.287 +} 1.288 + 1.289 +inline void 1.290 +Mark(JSTracer *trc, BarrieredPtrScript *o, const char *name) 1.291 +{ 1.292 + MarkScript(trc, o, name); 1.293 +} 1.294 + 1.295 +inline void 1.296 +Mark(JSTracer *trc, HeapPtr<jit::JitCode> *code, const char *name) 1.297 +{ 1.298 + MarkJitCode(trc, code, name); 1.299 +} 1.300 + 1.301 +/* For use by WeakMap's HashKeyRef instantiation. */ 1.302 +inline void 1.303 +Mark(JSTracer *trc, JSObject **objp, const char *name) 1.304 +{ 1.305 + MarkObjectUnbarriered(trc, objp, name); 1.306 +} 1.307 + 1.308 +/* For use by Debugger::WeakMap's proxiedScopes HashKeyRef instantiation. */ 1.309 +inline void 1.310 +Mark(JSTracer *trc, ScopeObject **obj, const char *name) 1.311 +{ 1.312 + MarkObjectUnbarriered(trc, obj, name); 1.313 +} 1.314 + 1.315 +bool 1.316 +IsCellMarked(Cell **thingp); 1.317 + 1.318 +bool 1.319 +IsCellAboutToBeFinalized(Cell **thing); 1.320 + 1.321 +inline bool 1.322 +IsMarked(BarrieredValue *v) 1.323 +{ 1.324 + if (!v->isMarkable()) 1.325 + return true; 1.326 + return IsValueMarked(v->unsafeGet()); 1.327 +} 1.328 + 1.329 +inline bool 1.330 +IsMarked(BarrieredPtrObject *objp) 1.331 +{ 1.332 + return IsObjectMarked(objp); 1.333 +} 1.334 + 1.335 +inline bool 1.336 +IsMarked(BarrieredPtrScript *scriptp) 1.337 +{ 1.338 + return IsScriptMarked(scriptp); 1.339 +} 1.340 + 1.341 +inline bool 1.342 +IsAboutToBeFinalized(BarrieredValue *v) 1.343 +{ 1.344 + if (!v->isMarkable()) 1.345 + return false; 1.346 + return IsValueAboutToBeFinalized(v->unsafeGet()); 1.347 +} 1.348 + 1.349 +inline bool 1.350 +IsAboutToBeFinalized(BarrieredPtrObject *objp) 1.351 +{ 1.352 + return IsObjectAboutToBeFinalized(objp); 1.353 +} 1.354 + 1.355 +inline bool 1.356 +IsAboutToBeFinalized(BarrieredPtrScript *scriptp) 1.357 +{ 1.358 + return IsScriptAboutToBeFinalized(scriptp); 1.359 +} 1.360 + 1.361 +#ifdef JS_ION 1.362 +/* Nonsense to get WeakCache to work with new Marking semantics. */ 1.363 + 1.364 +inline bool 1.365 +IsAboutToBeFinalized(const js::jit::VMFunction **vmfunc) 1.366 +{ 1.367 + /* 1.368 + * Preserves entries in the WeakCache<VMFunction, JitCode> 1.369 + * iff the JitCode has been marked. 1.370 + */ 1.371 + return true; 1.372 +} 1.373 + 1.374 +inline bool 1.375 +IsAboutToBeFinalized(ReadBarriered<js::jit::JitCode> code) 1.376 +{ 1.377 + return IsJitCodeAboutToBeFinalized(code.unsafeGet()); 1.378 +} 1.379 +#endif 1.380 + 1.381 +inline Cell * 1.382 +ToMarkable(const Value &v) 1.383 +{ 1.384 + if (v.isMarkable()) 1.385 + return (Cell *)v.toGCThing(); 1.386 + return nullptr; 1.387 +} 1.388 + 1.389 +inline Cell * 1.390 +ToMarkable(Cell *cell) 1.391 +{ 1.392 + return cell; 1.393 +} 1.394 + 1.395 +inline JSGCTraceKind 1.396 +TraceKind(const Value &v) 1.397 +{ 1.398 + JS_ASSERT(v.isMarkable()); 1.399 + if (v.isObject()) 1.400 + return JSTRACE_OBJECT; 1.401 + return JSTRACE_STRING; 1.402 +} 1.403 + 1.404 +inline JSGCTraceKind 1.405 +TraceKind(JSObject *obj) 1.406 +{ 1.407 + return JSTRACE_OBJECT; 1.408 +} 1.409 + 1.410 +inline JSGCTraceKind 1.411 +TraceKind(JSScript *script) 1.412 +{ 1.413 + return JSTRACE_SCRIPT; 1.414 +} 1.415 + 1.416 +inline JSGCTraceKind 1.417 +TraceKind(LazyScript *lazy) 1.418 +{ 1.419 + return JSTRACE_LAZY_SCRIPT; 1.420 +} 1.421 + 1.422 +} /* namespace gc */ 1.423 + 1.424 +void 1.425 +TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind); 1.426 + 1.427 +} /* namespace js */ 1.428 + 1.429 +#endif /* gc_Marking_h */