michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef gc_Marking_h michael@0: #define gc_Marking_h michael@0: michael@0: #include "gc/Barrier.h" michael@0: michael@0: class JSAtom; michael@0: class JSLinearString; michael@0: michael@0: namespace js { michael@0: michael@0: class ArgumentsObject; michael@0: class ArrayBufferObject; michael@0: class ArrayBufferViewObject; michael@0: class SharedArrayBufferObject; michael@0: class BaseShape; michael@0: class DebugScopeObject; michael@0: struct GCMarker; michael@0: class GlobalObject; michael@0: class LazyScript; michael@0: class ScopeObject; michael@0: class Shape; michael@0: class UnownedBaseShape; michael@0: michael@0: template class HeapPtr; michael@0: michael@0: namespace jit { michael@0: class JitCode; michael@0: class IonScript; michael@0: class VMFunction; michael@0: } michael@0: michael@0: namespace types { michael@0: class Type; michael@0: } michael@0: michael@0: namespace gc { michael@0: michael@0: /*** Object Marking ***/ michael@0: michael@0: /* michael@0: * These functions expose marking functionality for all of the different GC michael@0: * thing kinds. For each GC thing, there are several variants. As an example, michael@0: * these are the variants generated for JSObject. They are listed from most to michael@0: * least desirable for use: michael@0: * michael@0: * MarkObject(JSTracer *trc, const HeapPtr &thing, const char *name); michael@0: * This function should be used for marking JSObjects, in preference to all michael@0: * others below. Use it when you have HeapPtr, which michael@0: * automatically implements write barriers. michael@0: * michael@0: * MarkObjectRoot(JSTracer *trc, JSObject *thing, const char *name); michael@0: * This function is only valid during the root marking phase of GC (i.e., michael@0: * when MarkRuntime is on the stack). michael@0: * michael@0: * MarkObjectUnbarriered(JSTracer *trc, JSObject *thing, const char *name); michael@0: * Like MarkObject, this function can be called at any time. It is more michael@0: * forgiving, since it doesn't demand a HeapPtr as an argument. Its use michael@0: * should always be accompanied by a comment explaining how write barriers michael@0: * are implemented for the given field. michael@0: * michael@0: * Additionally, the functions MarkObjectRange and MarkObjectRootRange are michael@0: * defined for marking arrays of object pointers. michael@0: * michael@0: * The following functions are provided to test whether a GC thing is marked michael@0: * under different circumstances: michael@0: * michael@0: * IsObjectAboutToBeFinalized(JSObject **thing); michael@0: * This function is indended to be used in code used to sweep GC things. It michael@0: * indicates whether the object will will be finialized in the current group michael@0: * of compartments being swept. Note that this will return false for any michael@0: * object not in the group of compartments currently being swept, as even if michael@0: * it is unmarked it may still become marked before it is swept. michael@0: * michael@0: * IsObjectMarked(JSObject **thing); michael@0: * This function is indended to be used in rare cases in code used to mark michael@0: * GC things. It indicates whether the object is currently marked. michael@0: * michael@0: * UpdateObjectIfRelocated(JSObject **thingp); michael@0: * In some circumstances -- e.g. optional weak marking -- it is necessary michael@0: * to look at the pointer before marking it strongly or weakly. In these michael@0: * cases, the following must be called to update the pointer before use. michael@0: */ michael@0: michael@0: #define DeclMarker(base, type) \ michael@0: void Mark##base(JSTracer *trc, BarrieredPtr *thing, const char *name); \ michael@0: void Mark##base##Root(JSTracer *trc, type **thingp, const char *name); \ michael@0: void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name); \ michael@0: void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr *thing, const char *name); \ michael@0: void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \ michael@0: bool Is##base##Marked(type **thingp); \ michael@0: bool Is##base##Marked(BarrieredPtr *thingp); \ michael@0: bool Is##base##AboutToBeFinalized(type **thingp); \ michael@0: bool Is##base##AboutToBeFinalized(BarrieredPtr *thingp); \ michael@0: type *Update##base##IfRelocated(JSRuntime *rt, BarrieredPtr *thingp); \ michael@0: type *Update##base##IfRelocated(JSRuntime *rt, type **thingp); michael@0: michael@0: DeclMarker(BaseShape, BaseShape) michael@0: DeclMarker(BaseShape, UnownedBaseShape) michael@0: DeclMarker(JitCode, jit::JitCode) michael@0: DeclMarker(Object, ArgumentsObject) michael@0: DeclMarker(Object, ArrayBufferObject) michael@0: DeclMarker(Object, ArrayBufferViewObject) michael@0: DeclMarker(Object, SharedArrayBufferObject) michael@0: DeclMarker(Object, DebugScopeObject) michael@0: DeclMarker(Object, GlobalObject) michael@0: DeclMarker(Object, JSObject) michael@0: DeclMarker(Object, JSFunction) michael@0: DeclMarker(Object, ScopeObject) michael@0: DeclMarker(Script, JSScript) michael@0: DeclMarker(LazyScript, LazyScript) michael@0: DeclMarker(Shape, Shape) michael@0: DeclMarker(String, JSAtom) michael@0: DeclMarker(String, JSString) michael@0: DeclMarker(String, JSFlatString) michael@0: DeclMarker(String, JSLinearString) michael@0: DeclMarker(String, PropertyName) michael@0: DeclMarker(TypeObject, types::TypeObject) michael@0: michael@0: #undef DeclMarker michael@0: michael@0: void michael@0: MarkPermanentAtom(JSTracer *trc, JSAtom *atom, const char *name); michael@0: michael@0: /* Return true if the pointer is nullptr, or if it is a tagged pointer to michael@0: * nullptr. michael@0: */ michael@0: MOZ_ALWAYS_INLINE bool michael@0: IsNullTaggedPointer(void *p) michael@0: { michael@0: return uintptr_t(p) < 32; michael@0: } michael@0: michael@0: /*** Externally Typed Marking ***/ michael@0: michael@0: /* michael@0: * Note: this must only be called by the GC and only when we are tracing through michael@0: * MarkRoots. It is explicitly for ConservativeStackMarking and should go away michael@0: * after we transition to exact rooting. michael@0: */ michael@0: void michael@0: MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind); michael@0: michael@0: void michael@0: MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name); michael@0: michael@0: void michael@0: MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name); michael@0: michael@0: /*** ID Marking ***/ michael@0: michael@0: void michael@0: MarkId(JSTracer *trc, BarrieredId *id, const char *name); michael@0: michael@0: void michael@0: MarkIdRoot(JSTracer *trc, jsid *id, const char *name); michael@0: michael@0: void michael@0: MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name); michael@0: michael@0: void michael@0: MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name); michael@0: michael@0: void michael@0: MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name); michael@0: michael@0: /*** Value Marking ***/ michael@0: michael@0: void michael@0: MarkValue(JSTracer *trc, BarrieredValue *v, const char *name); michael@0: michael@0: void michael@0: MarkValueRange(JSTracer *trc, size_t len, BarrieredValue *vec, const char *name); michael@0: michael@0: inline void michael@0: MarkValueRange(JSTracer *trc, HeapValue *begin, HeapValue *end, const char *name) michael@0: { michael@0: return MarkValueRange(trc, end - begin, begin, name); michael@0: } michael@0: michael@0: void michael@0: MarkValueRoot(JSTracer *trc, Value *v, const char *name); michael@0: michael@0: void michael@0: MarkThingOrValueUnbarriered(JSTracer *trc, uintptr_t *word, const char *name); michael@0: michael@0: void michael@0: MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name); michael@0: michael@0: inline void michael@0: MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name) michael@0: { michael@0: MarkValueRootRange(trc, end - begin, begin, name); michael@0: } michael@0: michael@0: void michael@0: MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name); michael@0: michael@0: bool michael@0: IsValueMarked(Value *v); michael@0: michael@0: bool michael@0: IsValueAboutToBeFinalized(Value *v); michael@0: michael@0: /*** Slot Marking ***/ michael@0: michael@0: bool michael@0: IsSlotMarked(HeapSlot *s); michael@0: michael@0: void michael@0: MarkSlot(JSTracer *trc, HeapSlot *s, const char *name); michael@0: michael@0: void michael@0: MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name); michael@0: michael@0: void michael@0: MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots); michael@0: michael@0: void michael@0: MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject *src, JSObject **dst_obj, michael@0: const char *name); michael@0: michael@0: void michael@0: MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSObject *src, JSScript **dst_script, michael@0: const char *name); michael@0: michael@0: /* michael@0: * Mark a value that may be in a different compartment from the compartment michael@0: * being GC'd. (Although it won't be marked if it's in the wrong compartment.) michael@0: */ michael@0: void michael@0: MarkCrossCompartmentSlot(JSTracer *trc, JSObject *src, HeapSlot *dst_slot, const char *name); michael@0: michael@0: michael@0: /*** Special Cases ***/ michael@0: michael@0: /* michael@0: * The unioned HeapPtr stored in script->globalObj needs special treatment to michael@0: * typecheck correctly. michael@0: */ michael@0: void michael@0: MarkObject(JSTracer *trc, HeapPtr *thingp, const char *name); michael@0: michael@0: /* michael@0: * MarkChildren is exposed solely for preWriteBarrier on michael@0: * JSObject::TradeGuts. It should not be considered external interface. michael@0: */ michael@0: void michael@0: MarkChildren(JSTracer *trc, JSObject *obj); michael@0: michael@0: /* michael@0: * Trace through the shape and any shapes it contains to mark michael@0: * non-shape children. This is exposed to the JS API as michael@0: * JS_TraceShapeCycleCollectorChildren. michael@0: */ michael@0: void michael@0: MarkCycleCollectorChildren(JSTracer *trc, Shape *shape); michael@0: michael@0: void michael@0: PushArena(GCMarker *gcmarker, ArenaHeader *aheader); michael@0: michael@0: /*** Generic ***/ michael@0: michael@0: /* michael@0: * The Mark() functions interface should only be used by code that must be michael@0: * templated. Other uses should use the more specific, type-named functions. michael@0: */ michael@0: michael@0: inline void michael@0: Mark(JSTracer *trc, BarrieredValue *v, const char *name) michael@0: { michael@0: MarkValue(trc, v, name); michael@0: } michael@0: michael@0: inline void michael@0: Mark(JSTracer *trc, BarrieredPtrObject *o, const char *name) michael@0: { michael@0: MarkObject(trc, o, name); michael@0: } michael@0: michael@0: inline void michael@0: Mark(JSTracer *trc, BarrieredPtrScript *o, const char *name) michael@0: { michael@0: MarkScript(trc, o, name); michael@0: } michael@0: michael@0: inline void michael@0: Mark(JSTracer *trc, HeapPtr *code, const char *name) michael@0: { michael@0: MarkJitCode(trc, code, name); michael@0: } michael@0: michael@0: /* For use by WeakMap's HashKeyRef instantiation. */ michael@0: inline void michael@0: Mark(JSTracer *trc, JSObject **objp, const char *name) michael@0: { michael@0: MarkObjectUnbarriered(trc, objp, name); michael@0: } michael@0: michael@0: /* For use by Debugger::WeakMap's proxiedScopes HashKeyRef instantiation. */ michael@0: inline void michael@0: Mark(JSTracer *trc, ScopeObject **obj, const char *name) michael@0: { michael@0: MarkObjectUnbarriered(trc, obj, name); michael@0: } michael@0: michael@0: bool michael@0: IsCellMarked(Cell **thingp); michael@0: michael@0: bool michael@0: IsCellAboutToBeFinalized(Cell **thing); michael@0: michael@0: inline bool michael@0: IsMarked(BarrieredValue *v) michael@0: { michael@0: if (!v->isMarkable()) michael@0: return true; michael@0: return IsValueMarked(v->unsafeGet()); michael@0: } michael@0: michael@0: inline bool michael@0: IsMarked(BarrieredPtrObject *objp) michael@0: { michael@0: return IsObjectMarked(objp); michael@0: } michael@0: michael@0: inline bool michael@0: IsMarked(BarrieredPtrScript *scriptp) michael@0: { michael@0: return IsScriptMarked(scriptp); michael@0: } michael@0: michael@0: inline bool michael@0: IsAboutToBeFinalized(BarrieredValue *v) michael@0: { michael@0: if (!v->isMarkable()) michael@0: return false; michael@0: return IsValueAboutToBeFinalized(v->unsafeGet()); michael@0: } michael@0: michael@0: inline bool michael@0: IsAboutToBeFinalized(BarrieredPtrObject *objp) michael@0: { michael@0: return IsObjectAboutToBeFinalized(objp); michael@0: } michael@0: michael@0: inline bool michael@0: IsAboutToBeFinalized(BarrieredPtrScript *scriptp) michael@0: { michael@0: return IsScriptAboutToBeFinalized(scriptp); michael@0: } michael@0: michael@0: #ifdef JS_ION michael@0: /* Nonsense to get WeakCache to work with new Marking semantics. */ michael@0: michael@0: inline bool michael@0: IsAboutToBeFinalized(const js::jit::VMFunction **vmfunc) michael@0: { michael@0: /* michael@0: * Preserves entries in the WeakCache michael@0: * iff the JitCode has been marked. michael@0: */ michael@0: return true; michael@0: } michael@0: michael@0: inline bool michael@0: IsAboutToBeFinalized(ReadBarriered code) michael@0: { michael@0: return IsJitCodeAboutToBeFinalized(code.unsafeGet()); michael@0: } michael@0: #endif michael@0: michael@0: inline Cell * michael@0: ToMarkable(const Value &v) michael@0: { michael@0: if (v.isMarkable()) michael@0: return (Cell *)v.toGCThing(); michael@0: return nullptr; michael@0: } michael@0: michael@0: inline Cell * michael@0: ToMarkable(Cell *cell) michael@0: { michael@0: return cell; michael@0: } michael@0: michael@0: inline JSGCTraceKind michael@0: TraceKind(const Value &v) michael@0: { michael@0: JS_ASSERT(v.isMarkable()); michael@0: if (v.isObject()) michael@0: return JSTRACE_OBJECT; michael@0: return JSTRACE_STRING; michael@0: } michael@0: michael@0: inline JSGCTraceKind michael@0: TraceKind(JSObject *obj) michael@0: { michael@0: return JSTRACE_OBJECT; michael@0: } michael@0: michael@0: inline JSGCTraceKind michael@0: TraceKind(JSScript *script) michael@0: { michael@0: return JSTRACE_SCRIPT; michael@0: } michael@0: michael@0: inline JSGCTraceKind michael@0: TraceKind(LazyScript *lazy) michael@0: { michael@0: return JSTRACE_LAZY_SCRIPT; michael@0: } michael@0: michael@0: } /* namespace gc */ michael@0: michael@0: void michael@0: TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind); michael@0: michael@0: } /* namespace js */ michael@0: michael@0: #endif /* gc_Marking_h */