Bug 1182658 - Add TraceNullableRoot and use it to simplify RootedMarking; r=jonco

--HG--
extra : rebase_source : 8b0bb07a2da4f15928da18a5a9ab08037f9bddb8
This commit is contained in:
Terrence Cole 2015-07-15 16:42:32 -07:00
parent 698096b26d
commit d75b7ebb0d
4 changed files with 47 additions and 56 deletions

View File

@ -235,7 +235,13 @@ struct InternalGCMethods {};
template <typename T>
struct InternalGCMethods<T*>
{
static bool isMarkable(T* v) { return v != nullptr; }
static bool isMarkable(T* v) {
return mozilla::IsBaseOf<JSObject, T>::value
? !IsNullTaggedPointer(v)
: mozilla::IsBaseOf<Shape, T>::value
? uintptr_t(v) > 1
: v != nullptr;
}
static void preBarrier(T* v) { T::writeBarrierPre(v); }

View File

@ -449,6 +449,15 @@ js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
void
js::TraceNullableRoot(JSTracer* trc, T* thingp, const char* name)
{
AssertRootMarkingPhase(trc);
if (InternalGCMethods<T>::isMarkable(*thingp))
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
void
js::TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* vec, const char* name)
@ -479,6 +488,7 @@ js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name)
template void js::TraceEdge<type>(JSTracer*, BarrieredBase<type>*, const char*); \
template void js::TraceManuallyBarrieredEdge<type>(JSTracer*, type*, const char*); \
template void js::TraceRoot<type>(JSTracer*, type*, const char*); \
template void js::TraceNullableRoot<type>(JSTracer*, type*, const char*); \
template void js::TraceRange<type>(JSTracer*, size_t, BarrieredBase<type>*, const char*); \
template void js::TraceRootRange<type>(JSTracer*, size_t, type*, const char*);
FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS)

View File

@ -50,36 +50,17 @@ MarkPropertyDescriptorRoot(JSTracer* trc, JSPropertyDescriptor* pd, const char*
pd->trace(trc);
}
template <class T>
static inline bool
IgnoreExactRoot(T* thingp)
{
return false;
}
template <typename T>
using TraceFunction = void (*)(JSTracer* trc, T* ref, const char* name);
template <class T>
inline bool
IgnoreExactRoot(T** thingp)
{
return IsNullTaggedPointer(*thingp);
}
template <>
inline bool
IgnoreExactRoot(JSObject** thingp)
{
return IsNullTaggedPointer(*thingp) || *thingp == TaggedProto::LazyProto;
}
template <class T, void MarkFunc(JSTracer* trc, T* ref, const char* name), class Source>
template <class T, TraceFunction<T> TraceFn = TraceNullableRoot, class Source>
static inline void
MarkExactStackRootList(JSTracer* trc, Source* s, const char* name)
{
Rooted<T>* rooter = s->roots.template gcRooters<T>();
while (rooter) {
T* addr = rooter->address();
if (!IgnoreExactRoot(addr))
MarkFunc(trc, addr, name);
TraceFn(trc, addr, name);
rooter = rooter->previous();
}
}
@ -88,18 +69,18 @@ template<class T>
static void
MarkExactStackRootsAcrossTypes(T context, JSTracer* trc)
{
MarkExactStackRootList<JSObject*, TraceRoot>(trc, context, "exact-object");
MarkExactStackRootList<Shape*, TraceRoot>(trc, context, "exact-shape");
MarkExactStackRootList<BaseShape*, TraceRoot>(trc, context, "exact-baseshape");
MarkExactStackRootList<ObjectGroup*, TraceRoot>(
MarkExactStackRootList<JSObject*>(trc, context, "exact-object");
MarkExactStackRootList<Shape*>(trc, context, "exact-shape");
MarkExactStackRootList<BaseShape*>(trc, context, "exact-baseshape");
MarkExactStackRootList<ObjectGroup*>(
trc, context, "exact-objectgroup");
MarkExactStackRootList<JSString*, TraceRoot>(trc, context, "exact-string");
MarkExactStackRootList<JS::Symbol*, TraceRoot>(trc, context, "exact-symbol");
MarkExactStackRootList<jit::JitCode*, TraceRoot>(trc, context, "exact-jitcode");
MarkExactStackRootList<JSScript*, TraceRoot>(trc, context, "exact-script");
MarkExactStackRootList<LazyScript*, TraceRoot>(trc, context, "exact-lazy-script");
MarkExactStackRootList<jsid, TraceRoot>(trc, context, "exact-id");
MarkExactStackRootList<Value, TraceRoot>(trc, context, "exact-value");
MarkExactStackRootList<JSString*>(trc, context, "exact-string");
MarkExactStackRootList<JS::Symbol*>(trc, context, "exact-symbol");
MarkExactStackRootList<jit::JitCode*>(trc, context, "exact-jitcode");
MarkExactStackRootList<JSScript*>(trc, context, "exact-script");
MarkExactStackRootList<LazyScript*>(trc, context, "exact-lazy-script");
MarkExactStackRootList<jsid>(trc, context, "exact-id");
MarkExactStackRootList<Value>(trc, context, "exact-value");
MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
trc, context, "JSPropertyDescriptor");
MarkExactStackRootList<JS::StaticTraceable,
@ -333,20 +314,11 @@ struct PersistentRootedMarker
typedef mozilla::LinkedList<Element> List;
typedef void (*MarkFunc)(JSTracer* trc, T* ref, const char* name);
static void
markChainIfNotNull(JSTracer* trc, List& list, const char* name)
{
for (Element* r = list.getFirst(); r; r = r->getNext()) {
if (r->get())
TraceRoot(trc, r->address(), name);
}
}
static void
markChain(JSTracer* trc, List& list, const char* name)
{
for (Element* r = list.getFirst(); r; r = r->getNext())
TraceRoot(trc, r->address(), name);
TraceNullableRoot(trc, r->address(), name);
}
};
@ -358,17 +330,14 @@ js::gc::MarkPersistentRootedChains(JSTracer* trc)
{
JSRuntime* rt = trc->runtime();
// Mark the PersistentRooted chains of types that may be null.
PersistentRootedMarker<JSFunction*>::markChainIfNotNull(trc, rt->functionPersistentRooteds,
"PersistentRooted<JSFunction*>");
PersistentRootedMarker<JSObject*>::markChainIfNotNull(trc, rt->objectPersistentRooteds,
"PersistentRooted<JSObject*>");
PersistentRootedMarker<JSScript*>::markChainIfNotNull(trc, rt->scriptPersistentRooteds,
"PersistentRooted<JSScript*>");
PersistentRootedMarker<JSString*>::markChainIfNotNull(trc, rt->stringPersistentRooteds,
"PersistentRooted<JSString*>");
// Mark the PersistentRooted chains of types that are never null.
PersistentRootedMarker<JSFunction*>::markChain(trc, rt->functionPersistentRooteds,
"PersistentRooted<JSFunction*>");
PersistentRootedMarker<JSObject*>::markChain(trc, rt->objectPersistentRooteds,
"PersistentRooted<JSObject*>");
PersistentRootedMarker<JSScript*>::markChain(trc, rt->scriptPersistentRooteds,
"PersistentRooted<JSScript*>");
PersistentRootedMarker<JSString*>::markChain(trc, rt->stringPersistentRooteds,
"PersistentRooted<JSString*>");
PersistentRootedMarker<jsid>::markChain(trc, rt->idPersistentRooteds,
"PersistentRooted<jsid>");
PersistentRootedMarker<Value>::markChain(trc, rt->valuePersistentRooteds,

View File

@ -62,6 +62,12 @@ template <typename T>
void
TraceRoot(JSTracer* trc, T* thingp, const char* name);
// Idential to TraceRoot, except that this variant will not crash if |*thingp|
// is null.
template <typename T>
void
TraceNullableRoot(JSTracer* trc, T* thingp, const char* name);
// Like TraceEdge, but for edges that do not use one of the automatic barrier
// classes and, thus, must be treated specially for moving GC. This method is
// separate from TraceEdge to make accidental use of such edges more obvious.