Bug 1526375 - Replace DispatchTaceKindTyped for cell pointers with another version of MapGCThingTyped and use this where possible r=sfink

This commit is contained in:
Jon Coppeard 2019-02-09 08:29:51 +00:00
Родитель 1aa258e905
Коммит 510569c075
4 изменённых файлов: 55 добавлений и 60 удалений

Просмотреть файл

@ -226,20 +226,33 @@ auto DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args) {
}
#undef JS_DEPENDENT_TEMPLATE_HINT
template <typename F, typename... Args>
auto DispatchTraceKindTyped(F f, void* thing, JS::TraceKind traceKind,
Args&&... args) {
// Given a GC thing specified by pointer and trace kind, calls the functor |f|
// with a template argument of the actual type of the pointer and returns the
// result.
template <typename F>
auto MapGCThingTyped(void* thing, JS::TraceKind traceKind, F&& f) {
switch (traceKind) {
#define JS_EXPAND_DEF(name, type, _) \
case JS::TraceKind::name: \
return f(static_cast<type*>(thing), std::forward<Args>(args)...);
return f(static_cast<type*>(thing));
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
default:
MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
MOZ_CRASH("Invalid trace kind in MapGCThingTyped.");
}
}
// Given a GC thing specified by pointer and trace kind, calls the functor |f|
// with a template argument of the actual type of the pointer and ignores the
// result.
template <typename F>
void ApplyGCThingTyped(void* thing, JS::TraceKind traceKind, F&& f) {
// This function doesn't do anything but is supplied for symmetry with other
// MapGCThingTyped/ApplyGCThingTyped implementations that have to wrap the
// functor to return a dummy value that is ignored.
MapGCThingTyped(thing, traceKind, std::move(f));
}
} // namespace JS
#endif // js_TraceKind_h

Просмотреть файл

@ -3674,21 +3674,16 @@ void GCRuntime::freeFromBackgroundThread(AutoLockHelperThreadState& lock) {
void GCRuntime::waitBackgroundFreeEnd() { freeTask.join(); }
struct IsAboutToBeFinalizedFunctor {
template <typename T>
bool operator()(Cell** t) {
mozilla::DebugOnly<const Cell*> prior = *t;
bool result = IsAboutToBeFinalizedUnbarriered(reinterpret_cast<T**>(t));
/* static */ bool UniqueIdGCPolicy::needsSweep(Cell** cellp, uint64_t*) {
Cell* cell = *cellp;
return MapGCThingTyped(cell, cell->getTraceKind(), [](auto t) {
mozilla::DebugOnly<const Cell*> prior = t;
bool result = IsAboutToBeFinalizedUnbarriered(&t);
// Sweep should not have to deal with moved pointers, since moving GC
// handles updating the UID table manually.
MOZ_ASSERT(*t == prior);
MOZ_ASSERT(t == prior);
return result;
}
};
/* static */ bool UniqueIdGCPolicy::needsSweep(Cell** cell, uint64_t*) {
return DispatchTraceKindTyped(IsAboutToBeFinalizedFunctor(),
(*cell)->getTraceKind(), cell);
});
}
void JS::Zone::sweepUniqueIds() { uniqueIds().sweep(); }
@ -4037,13 +4032,6 @@ static bool InCrossCompartmentMap(JSObject* src, JS::GCCellPtr dst) {
return false;
}
struct MaybeCompartmentFunctor {
template <typename T>
JS::Compartment* operator()(T* t) {
return t->maybeCompartment();
}
};
void CompartmentCheckTracer::onChild(const JS::GCCellPtr& thing) {
Compartment* comp = MapGCThingTyped(thing, [](auto t) {
return t->maybeCompartment();
@ -4074,8 +4062,9 @@ void GCRuntime::checkForCompartmentMismatches() {
i.next()) {
trc.src = i.getCell();
trc.srcKind = MapAllocToTraceKind(thingKind);
trc.compartment = DispatchTraceKindTyped(MaybeCompartmentFunctor(),
trc.src, trc.srcKind);
trc.compartment = MapGCThingTyped(trc.src, trc.srcKind, [](auto t) {
return t->maybeCompartment();
});
js::TraceChildren(&trc, trc.src, trc.srcKind);
}
}

Просмотреть файл

@ -6,6 +6,7 @@
#include "gc/Marking-inl.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/ReentrancyGuard.h"
@ -512,40 +513,40 @@ template void js::TraceProcessGlobalRoot<JSAtom>(JSTracer*, JSAtom*,
template void js::TraceProcessGlobalRoot<JS::Symbol>(JSTracer*, JS::Symbol*,
const char*);
// A typed functor adaptor for TraceRoot.
struct TraceRootFunctor {
template <typename T>
void operator()(JSTracer* trc, Cell** thingp, const char* name) {
TraceRoot(trc, reinterpret_cast<T**>(thingp), name);
}
};
void js::TraceGenericPointerRoot(JSTracer* trc, Cell** thingp,
const char* name) {
MOZ_ASSERT(thingp);
if (!*thingp) {
Cell* thing = *thingp;
if (!thing) {
return;
}
TraceRootFunctor f;
DispatchTraceKindTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
}
// A typed functor adaptor for TraceManuallyBarrieredEdge.
struct TraceManuallyBarrieredEdgeFunctor {
template <typename T>
void operator()(JSTracer* trc, Cell** thingp, const char* name) {
TraceManuallyBarrieredEdge(trc, reinterpret_cast<T**>(thingp), name);
auto traced = MapGCThingTyped(thing, thing->getTraceKind(),
[trc, name](auto t) -> Cell* {
TraceRoot(trc, &t, name);
return t;
});
if (traced != thing) {
*thingp = traced;
}
};
}
void js::TraceManuallyBarrieredGenericPointerEdge(JSTracer* trc, Cell** thingp,
const char* name) {
MOZ_ASSERT(thingp);
Cell* thing = *thingp;
if (!*thingp) {
return;
}
TraceManuallyBarrieredEdgeFunctor f;
DispatchTraceKindTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
auto traced = MapGCThingTyped(thing, thing->getTraceKind(),
[trc, name](auto t) -> Cell* {
TraceManuallyBarrieredEdge(trc, &t, name);
return t;
});
if (traced != thing) {
*thingp = traced;
}
}
// This method is responsible for dynamic dispatch to the real tracer

Просмотреть файл

@ -88,22 +88,14 @@ JS_PUBLIC_API void JS::TraceChildren(JSTracer* trc, GCCellPtr thing) {
js::TraceChildren(trc, thing.asCell(), thing.kind());
}
struct TraceChildrenFunctor {
template <typename T>
void operator()(JSTracer* trc, void* thingArg) {
T* thing = static_cast<T*>(thingArg);
MOZ_ASSERT_IF(thing->runtimeFromAnyThread() != trc->runtime(),
ThingIsPermanentAtomOrWellKnownSymbol(thing) ||
thing->zoneFromAnyThread()->isSelfHostingZone());
thing->traceChildren(trc);
}
};
void js::TraceChildren(JSTracer* trc, void* thing, JS::TraceKind kind) {
MOZ_ASSERT(thing);
TraceChildrenFunctor f;
DispatchTraceKindTyped(f, kind, trc, thing);
ApplyGCThingTyped(thing, kind, [trc](auto t) {
MOZ_ASSERT_IF(t->runtimeFromAnyThread() != trc->runtime(),
ThingIsPermanentAtomOrWellKnownSymbol(t) ||
t->zoneFromAnyThread()->isSelfHostingZone());
t->traceChildren(trc);
});
}
JS_PUBLIC_API void JS::TraceIncomingCCWs(