Bug 1243888 - Derive RootKind automatically from TraceKind; r=sfink

--HG--
extra : rebase_source : 4ea174eb95c36ac1452baa0ed44b4c99ff517d9e
This commit is contained in:
Terrence Cole 2016-01-27 09:54:53 -08:00
Родитель ec95f4bf71
Коммит 309f950dae
13 изменённых файлов: 117 добавлений и 121 удалений

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

@ -509,23 +509,6 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
namespace js {
/**
* By default, things should use the inheritance hierarchy to find their
* ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
* Rooted<T> may be used without the class definition being available.
*/
template <typename T>
struct RootKind
{
static ThingRootKind rootKind() { return T::rootKind(); }
};
template <typename T>
struct RootKind<T*>
{
static ThingRootKind rootKind() { return T::rootKind(); }
};
template <typename T>
struct BarrierMethods<T*>
{
@ -607,8 +590,6 @@ namespace JS {
// |static void trace(T*, JSTracer*)|
class Traceable
{
public:
static js::ThingRootKind rootKind() { return js::THING_ROOT_TRACEABLE; }
};
} /* namespace JS */
@ -694,8 +675,7 @@ class MOZ_RAII Rooted : public js::RootedBase<T>
/* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
void registerWithRootLists(js::RootLists& roots) {
js::ThingRootKind kind = js::RootKind<T>::rootKind();
this->stack = &roots.stackRoots_[kind];
this->stack = &roots.stackRoots_[JS::MapTypeToRootKind<T>::kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
}
@ -1012,16 +992,16 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
void registerWithRootLists(js::RootLists& roots) {
MOZ_ASSERT(!initialized());
js::ThingRootKind kind = js::RootKind<T>::rootKind();
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
roots.heapRoots_[kind].insertBack(reinterpret_cast<JS::PersistentRooted<void*>*>(this));
// Until marking and destruction support the full set, we assert that
// we don't try to add any unsupported types.
MOZ_ASSERT(kind == js::THING_ROOT_OBJECT ||
kind == js::THING_ROOT_SCRIPT ||
kind == js::THING_ROOT_STRING ||
kind == js::THING_ROOT_ID ||
kind == js::THING_ROOT_VALUE ||
kind == js::THING_ROOT_TRACEABLE);
MOZ_ASSERT(kind == JS::RootKind::Object ||
kind == JS::RootKind::Script ||
kind == JS::RootKind::String ||
kind == JS::RootKind::Id ||
kind == JS::RootKind::Value ||
kind == JS::RootKind::Traceable);
}
public:

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

@ -60,6 +60,16 @@ static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mas
static_assert(uintptr_t(JS::TraceKind::JitCode) & OutOfLineTraceKindMask, "mask bits are set");
static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "mask bits are set");
// When this header is imported inside SpiderMonkey, the class definitions are
// available and we can query those definitions to find the correct kind
// directly from the class hierarchy.
template <typename T>
struct MapTypeToTraceKind {
static const JS::TraceKind kind = T::TraceKind;
};
// When this header is used outside SpiderMonkey, the class definitions are not
// available, so the following table containing all public GC types is used.
#define JS_FOR_EACH_TRACEKIND(D) \
/* PrettyName TypeName AddToCCKind */ \
D(BaseShape, js::BaseShape, true) \
@ -72,8 +82,7 @@ static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "ma
D(String, JSString, false) \
D(Symbol, JS::Symbol, false)
// Map from base trace type to the trace kind.
template <typename T> struct MapTypeToTraceKind {};
// Map from all public types to their trace kind.
#define JS_EXPAND_DEF(name, type, _) \
template <> struct MapTypeToTraceKind<type> { \
static const JS::TraceKind kind = JS::TraceKind::name; \
@ -81,6 +90,61 @@ template <typename T> struct MapTypeToTraceKind {};
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
// RootKind is closely related to TraceKind. Whereas TraceKind's indices are
// laid out for convenient embedding as a pointer tag, the indicies of RootKind
// are designed for use as array keys via EnumeratedArray.
enum class RootKind : int8_t
{
// These map 1:1 with trace kinds.
BaseShape = 0,
JitCode,
LazyScript,
Object,
ObjectGroup,
Script,
Shape,
String,
Symbol,
// These tagged pointers are special-cased for performance.
Id,
Value,
// Everything else.
Traceable,
Limit
};
// Most RootKind correspond directly to a trace kind.
template <TraceKind traceKind> struct MapTraceKindToRootKind {};
#define JS_EXPAND_DEF(name, _0, _1) \
template <> struct MapTraceKindToRootKind<JS::TraceKind::name> { \
static const JS::RootKind kind = JS::RootKind::name; \
};
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
#undef JS_EXPAND_DEF
// Specify the RootKind for all types. Value and jsid map to special cases;
// pointer types we can derive directly from the TraceKind; everything else
// should go in the Traceable list and use GCPolicy<T>::trace for tracing.
template <typename T>
struct MapTypeToRootKind {
static const JS::RootKind kind = JS::RootKind::Traceable;
};
template <typename T>
struct MapTypeToRootKind<T*> {
static const JS::RootKind kind = \
JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind;
};
template <> struct MapTypeToRootKind<JS::Value> {
static const JS::RootKind kind = JS::RootKind::Value;
};
template <> struct MapTypeToRootKind<jsid> {
static const JS::RootKind kind = JS::RootKind::Id;
};
template <> struct MapTypeToRootKind<JSFunction*> : public MapTypeToRootKind<JSObject*> {};
// Fortunately, few places in the system need to deal with fully abstract
// cells. In those places that do, we generally want to move to a layout
// templated function as soon as possible. This template wraps the upcast

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

@ -42,43 +42,36 @@ typedef RootedValueMap::Enum RootEnum;
template <typename T>
using TraceFunction = void (*)(JSTracer* trc, T* ref, const char* name);
template <class T, TraceFunction<T> TraceFn = TraceNullableRoot, class Source>
template <class T, TraceFunction<T> TraceFn = TraceNullableRoot>
static inline void
MarkExactStackRootList(JSTracer* trc, Source* s, const char* name)
MarkExactStackRootList(JSTracer* trc, JS::Rooted<void*>* rooter, const char* name)
{
Rooted<T>* rooter = s->roots.template gcRooters<T>();
while (rooter) {
T* addr = rooter->address();
T* addr = reinterpret_cast<JS::Rooted<T>*>(rooter)->address();
TraceFn(trc, addr, name);
rooter = rooter->previous();
}
}
template<class T>
static void
MarkExactStackRootsAcrossTypes(T context, JSTracer* trc)
void
js::RootLists::traceStackRoots(JSTracer* trc)
{
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*>(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");
#define MARK_ROOTS(name, type, _) \
MarkExactStackRootList<type*>(trc, stackRoots_[JS::RootKind::name], "exact-" #name);
JS_FOR_EACH_TRACEKIND(MARK_ROOTS)
#undef MARK_ROOTS
MarkExactStackRootList<jsid>(trc, stackRoots_[JS::RootKind::Id], "exact-id");
MarkExactStackRootList<Value>(trc, stackRoots_[JS::RootKind::Value], "exact-value");
MarkExactStackRootList<JS::Traceable, js::DispatchWrapper<JS::Traceable>::TraceWrapped>(
trc, context, "Traceable");
trc, stackRoots_[JS::RootKind::Traceable], "Traceable");
}
static void
MarkExactStackRoots(JSRuntime* rt, JSTracer* trc)
{
for (ContextIter cx(rt); !cx.done(); cx.next())
MarkExactStackRootsAcrossTypes<JSContext*>(cx.get(), trc);
MarkExactStackRootsAcrossTypes<PerThreadData*>(&rt->mainThread, trc);
cx->roots.traceStackRoots(trc);
rt->mainThread.roots.traceStackRoots(trc);
}
inline void
@ -246,7 +239,7 @@ js::gc::MarkPersistentRootedChainsInLists(RootLists& roots, JSTracer* trc)
PersistentRootedMarker<JS::Traceable>::markChain<
js::DispatchWrapper<JS::Traceable>::TraceWrapped>(trc,
reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Traceable>>&>(
roots.heapRoots_[THING_ROOT_TRACEABLE]),
roots.heapRoots_[JS::RootKind::Traceable]),
"PersistentRooted<Traceable>");
}

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

@ -160,7 +160,7 @@ class JitCode : public gc::TenuredCell
ExecutablePool* pool, CodeKind kind);
public:
static inline ThingRootKind rootKind() { return THING_ROOT_JIT_CODE; }
static const JS::TraceKind TraceKind = JS::TraceKind::JitCode;
};
class SnapshotWriter;

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

@ -186,8 +186,9 @@ js::DestroyContext(JSContext* cx, DestroyContextMode mode)
void
RootLists::checkNoGCRooters() {
#ifdef DEBUG
for (int i = 0; i < THING_ROOT_LIMIT; ++i)
MOZ_ASSERT(stackRoots_[i] == nullptr);
for (auto const& stackRootPtr : stackRoots_) {
MOZ_ASSERT(stackRootPtr == nullptr);
}
#endif
}

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

@ -1389,7 +1389,7 @@ js::gc::FinishPersistentRootedChains(RootLists& roots)
FinishPersistentRootedChain(roots.getPersistentRootedList<JSString*>());
FinishPersistentRootedChain(roots.getPersistentRootedList<jsid>());
FinishPersistentRootedChain(roots.getPersistentRootedList<Value>());
FinishPersistentRootedChain(roots.heapRoots_[THING_ROOT_TRACEABLE]);
FinishPersistentRootedChain(roots.heapRoots_[JS::RootKind::Traceable]);
}
void

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

@ -292,7 +292,7 @@ class JSObject : public js::gc::Cell
void fixupAfterMovingGC();
static js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
static const JS::TraceKind TraceKind = JS::TraceKind::Object;
static const size_t MaxTagBits = 3;
static bool isNullLike(const JSObject* obj) { return uintptr_t(obj) < (1 << MaxTagBits); }

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

@ -12,12 +12,14 @@
*/
#include "mozilla/Assertions.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/LinkedList.h"
#include "mozilla/PodOperations.h"
#include "jsprototypes.h"
#include "jstypes.h"
#include "js/TraceKind.h"
#include "js/TypeDecls.h"
#if defined(JS_GC_ZEAL) || defined(DEBUG)
@ -262,52 +264,12 @@ enum StackKind
StackKindCount
};
enum ThingRootKind
{
THING_ROOT_OBJECT,
THING_ROOT_SHAPE,
THING_ROOT_BASE_SHAPE,
THING_ROOT_OBJECT_GROUP,
THING_ROOT_STRING,
THING_ROOT_SYMBOL,
THING_ROOT_JIT_CODE,
THING_ROOT_SCRIPT,
THING_ROOT_LAZY_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_TRACEABLE,
THING_ROOT_LIMIT
};
template <typename T>
struct RootKind;
/*
* Specifically mark the ThingRootKind of externally visible types, so that
* JSAPI users may use JSRooted... types without having the class definition
* available.
*/
template<typename T, ThingRootKind Kind>
struct SpecificRootKind
{
static ThingRootKind rootKind() { return Kind; }
};
template <> struct RootKind<JSObject*> : SpecificRootKind<JSObject*, THING_ROOT_OBJECT> {};
template <> struct RootKind<JSFlatString*> : SpecificRootKind<JSFlatString*, THING_ROOT_STRING> {};
template <> struct RootKind<JSFunction*> : SpecificRootKind<JSFunction*, THING_ROOT_OBJECT> {};
template <> struct RootKind<JSString*> : SpecificRootKind<JSString*, THING_ROOT_STRING> {};
template <> struct RootKind<JS::Symbol*> : SpecificRootKind<JS::Symbol*, THING_ROOT_SYMBOL> {};
template <> struct RootKind<JSScript*> : SpecificRootKind<JSScript*, THING_ROOT_SCRIPT> {};
template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {};
template <> struct RootKind<JS::Value> : SpecificRootKind<JS::Value, THING_ROOT_VALUE> {};
// Abstracts JS rooting mechanisms so they can be shared between the JSContext
// and JSRuntime.
class RootLists
{
// Stack GC roots for stack-allocated GC heap pointers.
JS::Rooted<void*>* stackRoots_[THING_ROOT_LIMIT];
mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit, JS::Rooted<void*>*> stackRoots_;
template <typename T> friend class JS::Rooted;
// Stack GC roots for stack-allocated AutoFooRooter classes.
@ -316,14 +278,12 @@ class RootLists
public:
RootLists() : autoGCRooters_(nullptr) {
mozilla::PodArrayZero(stackRoots_);
for (auto& stackRootPtr : stackRoots_) {
stackRootPtr = nullptr;
}
}
template <class T>
inline JS::Rooted<T>* gcRooters() {
js::ThingRootKind kind = RootKind<T>::rootKind();
return reinterpret_cast<JS::Rooted<T>*>(stackRoots_[kind]);
}
void traceStackRoots(JSTracer* trc);
void checkNoGCRooters();
@ -334,7 +294,8 @@ class RootLists
friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*);
friend void js::gc::FinishPersistentRootedChains(RootLists&);
mozilla::LinkedList<JS::PersistentRooted<void*>> heapRoots_[THING_ROOT_LIMIT];
mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
mozilla::LinkedList<JS::PersistentRooted<void*>>> heapRoots_;
/* Specializations of this return references to the appropriate list. */
template<typename Referent>
@ -345,42 +306,42 @@ template<>
inline mozilla::LinkedList<JS::PersistentRootedFunction>&
RootLists::getPersistentRootedList<JSFunction*>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSFunction*>>&>(
heapRoots_[THING_ROOT_OBJECT]);
heapRoots_[JS::RootKind::Object]);
}
template<>
inline mozilla::LinkedList<JS::PersistentRootedObject>&
RootLists::getPersistentRootedList<JSObject*>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSObject*>>&>(
heapRoots_[THING_ROOT_OBJECT]);
heapRoots_[JS::RootKind::Object]);
}
template<>
inline mozilla::LinkedList<JS::PersistentRootedId>&
RootLists::getPersistentRootedList<jsid>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<jsid>>&>(
heapRoots_[THING_ROOT_ID]);
heapRoots_[JS::RootKind::Id]);
}
template<>
inline mozilla::LinkedList<JS::PersistentRootedScript>&
RootLists::getPersistentRootedList<JSScript*>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSScript*>>&>(
heapRoots_[THING_ROOT_SCRIPT]);
heapRoots_[JS::RootKind::Script]);
}
template<>
inline mozilla::LinkedList<JS::PersistentRootedString>&
RootLists::getPersistentRootedList<JSString*>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSString*>>&>(
heapRoots_[THING_ROOT_STRING]);
heapRoots_[JS::RootKind::String]);
}
template<>
inline mozilla::LinkedList<JS::PersistentRootedValue>&
RootLists::getPersistentRootedList<JS::Value>() {
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Value>>&>(
heapRoots_[THING_ROOT_VALUE]);
heapRoots_[JS::RootKind::Value]);
}
struct ContextFriendFields

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

@ -1947,7 +1947,7 @@ class JSScript : public js::gc::TenuredCell
void finalize(js::FreeOp* fop);
void fixupAfterMovingGC() {}
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
static const JS::TraceKind TraceKind = JS::TraceKind::Script;
void traceChildren(JSTracer* trc);
@ -2389,7 +2389,7 @@ class LazyScript : public gc::TenuredCell
void finalize(js::FreeOp* fop);
void fixupAfterMovingGC() {}
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }
static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{

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

@ -421,7 +421,7 @@ class ObjectGroup : public gc::TenuredCell
void finalize(FreeOp* fop);
void fixupAfterMovingGC() {}
static inline ThingRootKind rootKind() { return THING_ROOT_OBJECT_GROUP; }
static const JS::TraceKind TraceKind = JS::TraceKind::ObjectGroup;
static inline uint32_t offsetOfClasp() {
return offsetof(ObjectGroup, clasp_);

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

@ -446,7 +446,7 @@ class BaseShape : public gc::TenuredCell
/* For JIT usage */
static inline size_t offsetOfFlags() { return offsetof(BaseShape, flags); }
static inline ThingRootKind rootKind() { return THING_ROOT_BASE_SHAPE; }
static const JS::TraceKind TraceKind = JS::TraceKind::BaseShape;
void traceChildren(JSTracer* trc);
@ -947,7 +947,7 @@ class Shape : public gc::TenuredCell
void finalize(FreeOp* fop);
void removeChild(Shape* child);
static inline ThingRootKind rootKind() { return THING_ROOT_SHAPE; }
static const JS::TraceKind TraceKind = JS::TraceKind::Shape;
void traceChildren(JSTracer* trc);
@ -1406,9 +1406,6 @@ Shape::matches(const StackShape& other) const
other.rawGetter, other.rawSetter);
}
template<> struct RootKind<Shape*> : SpecificRootKind<Shape*, THING_ROOT_SHAPE> {};
template<> struct RootKind<BaseShape*> : SpecificRootKind<BaseShape*, THING_ROOT_BASE_SHAPE> {};
// Property lookup hooks on objects are required to return a non-nullptr shape
// to signify that the property has been found. For cases where the property is
// not actually represented by a Shape, use a dummy value. This includes all

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

@ -492,7 +492,7 @@ class JSString : public js::gc::TenuredCell
return offsetof(JSString, d.s.u2.nonInlineCharsTwoByte);
}
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_STRING; }
static const JS::TraceKind TraceKind = JS::TraceKind::String;
#ifdef DEBUG
void dump();

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

@ -56,7 +56,7 @@ class Symbol : public js::gc::TenuredCell
bool isWellKnownSymbol() const { return uint32_t(code_) < WellKnownSymbolLimit; }
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SYMBOL; }
static const JS::TraceKind TraceKind = JS::TraceKind::Symbol;
inline void traceChildren(JSTracer* trc) {
if (description_)
js::TraceManuallyBarrieredEdge(trc, &description_, "description");