Bug 1244365 - Remove Traceable; r=sfink

This commit is contained in:
Terrence Cole 2016-01-29 16:56:11 -08:00
parent a29e90546e
commit 39d47b5f4a
23 changed files with 90 additions and 104 deletions

View File

@ -298,7 +298,7 @@ txXPCOMExtensionFunctionCall::GetParamType(const nsXPTParamInfo &aParam,
}
}
class txParamArrayHolder : public JS::Traceable
class txParamArrayHolder
{
public:
txParamArrayHolder()
@ -319,7 +319,6 @@ public:
return mArray.get();
}
static void trace(txParamArrayHolder* holder, JSTracer* trc) { holder->trace(trc); }
void trace(JSTracer* trc) {
for (uint8_t i = 0; i < mCount; ++i) {
if (mArray[i].type == nsXPTType::T_JSVAL) {

View File

@ -49,8 +49,7 @@ template <typename Key,
typename HashPolicy = DefaultHasher<Key>,
typename AllocPolicy = TempAllocPolicy,
typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>>
class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
public JS::Traceable
class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>
{
using Base = HashMap<Key, Value, HashPolicy, AllocPolicy>;
@ -226,8 +225,7 @@ class HandleBase<GCHashMap<A,B,C,D,E>>
template <typename T,
typename HashPolicy = DefaultHasher<T>,
typename AllocPolicy = TempAllocPolicy>
class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
public JS::Traceable
class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>
{
using Base = HashSet<T, HashPolicy, AllocPolicy>;

View File

@ -33,7 +33,7 @@ namespace js {
template <typename T,
size_t MinInlineCapacity = 0,
typename AllocPolicy = TempAllocPolicy>
class GCVector : public JS::Traceable
class GCVector
{
mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;

View File

@ -581,28 +581,15 @@ struct JS_PUBLIC_API(MovableCellHasher<JS::Heap<T>>)
} /* namespace js */
namespace JS {
// Non pointer types -- structs or classes that contain GC pointers, either as
// a member or in a more complex container layout -- can also be stored in a
// [Persistent]Rooted if it derives from JS::Traceable. A JS::Traceable stored
// in a [Persistent]Rooted must implement the method:
// |static void trace(T*, JSTracer*)|
class Traceable
{
};
} /* namespace JS */
namespace js {
template <typename T>
class DispatchWrapper
{
static_assert(mozilla::IsBaseOf<JS::Traceable, T>::value,
static_assert(JS::MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
"DispatchWrapper is intended only for usage with a Traceable");
using TraceFn = void (*)(T*, JSTracer*);
using TraceFn = void (*)(JSTracer*, T*, const char*);
TraceFn tracer;
#if JS_BITS_PER_WORD == 32
uint32_t padding; // Ensure the storage fields have CellSize alignment.
@ -612,7 +599,7 @@ class DispatchWrapper
public:
template <typename U>
MOZ_IMPLICIT DispatchWrapper(U&& initial)
: tracer(&T::trace),
: tracer(&GCPolicy<T>::trace),
storage(mozilla::Forward<U>(initial))
{ }
@ -624,10 +611,10 @@ class DispatchWrapper
// Trace the contained storage (of unknown type) using the trace function
// we set aside when we did know the type.
static void TraceWrapped(JSTracer* trc, JS::Traceable* thingp, const char* name) {
static void TraceWrapped(JSTracer* trc, T* thingp, const char* name) {
auto wrapper = reinterpret_cast<DispatchWrapper*>(
uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
wrapper->tracer(&wrapper->storage, trc);
wrapper->tracer(trc, &wrapper->storage, name);
}
};
@ -670,9 +657,6 @@ namespace JS {
template <typename T>
class MOZ_RAII Rooted : public js::RootedBase<T>
{
static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
"Rooted takes pointer or Traceable types but not Traceable* type");
/* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
void registerWithRootLists(js::RootLists& roots) {
this->stack = &roots.stackRoots_[JS::MapTypeToRootKind<T>::kind];
@ -727,14 +711,14 @@ class MOZ_RAII Rooted : public js::RootedBase<T>
/*
* For pointer types, the TraceKind for tracing is based on the list it is
* in (selected via rootKind), so no additional storage is required here.
* All Traceable, however, share the same list, so the function to
* call for tracing is stored adjacent to the struct. Since C++ cannot
* templatize on storage class, this is implemented via the wrapper class
* DispatchWrapper.
* in (selected via MapTypeToRootKind), so no additional storage is
* required here. Non-pointer types, however, share the same list, so the
* function to call for tracing is stored adjacent to the struct. Since C++
* cannot templatize on storage class, this is implemented via the wrapper
* class DispatchWrapper.
*/
using MaybeWrapped = typename mozilla::Conditional<
mozilla::IsBaseOf<Traceable, T>::value,
MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;
MaybeWrapped ptr;
@ -1071,7 +1055,7 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
// See the comment above Rooted::ptr.
using MaybeWrapped = typename mozilla::Conditional<
mozilla::IsBaseOf<Traceable, T>::value,
MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;

View File

@ -308,7 +308,7 @@ template<typename T> class ConcreteStackFrame;
// valid within the scope of an AutoCheckCannotGC; if the graph being analyzed
// is an offline heap snapshot, the JS::ubi::StackFrame is valid as long as the
// offline heap snapshot is alive.
class StackFrame : public JS::Traceable {
class StackFrame {
// Storage in which we allocate BaseStackFrame subclasses.
mozilla::AlignedStorage2<BaseStackFrame> storage;
@ -398,12 +398,6 @@ class StackFrame : public JS::Traceable {
size_t sourceLength();
size_t functionDisplayNameLength();
// JS::Traceable implementation just forwards to our virtual trace method.
static void trace(StackFrame* frame, JSTracer* trc) {
if (frame)
frame->trace(trc);
}
// Methods that forward to virtual calls through BaseStackFrame.
void trace(JSTracer* trc) { base()->trace(trc); }

View File

@ -22,7 +22,7 @@ namespace js {
*
* All values except ropes are hashable as-is.
*/
class HashableValue : public JS::Traceable
class HashableValue
{
PreBarrieredValue value;
@ -43,8 +43,8 @@ class HashableValue : public JS::Traceable
HashableValue mark(JSTracer* trc) const;
Value get() const { return value.get(); }
static void trace(HashableValue* value, JSTracer* trc) {
TraceEdge(trc, &value->value, "HashableValue");
void trace(JSTracer* trc) {
TraceEdge(trc, &value, "HashableValue");
}
};

View File

@ -31,9 +31,7 @@ namespace js {
template <typename T,
size_t MinInlineCapacity = 0,
typename AllocPolicy = TempAllocPolicy>
class TraceableFifo
: public js::Fifo<T, MinInlineCapacity, AllocPolicy>,
public JS::Traceable
class TraceableFifo : public js::Fifo<T, MinInlineCapacity, AllocPolicy>
{
using Base = js::Fifo<T, MinInlineCapacity, AllocPolicy>;
@ -46,11 +44,11 @@ class TraceableFifo
TraceableFifo(const TraceableFifo&) = delete;
TraceableFifo& operator=(const TraceableFifo&) = delete;
static void trace(TraceableFifo* tf, JSTracer* trc) {
for (size_t i = 0; i < tf->front_.length(); ++i)
GCPolicy<T>::trace(trc, &tf->front_[i], "fifo element");
for (size_t i = 0; i < tf->rear_.length(); ++i)
GCPolicy<T>::trace(trc, &tf->rear_[i], "fifo element");
void trace(JSTracer* trc) {
for (size_t i = 0; i < this->front_.length(); ++i)
GCPolicy<T>::trace(trc, &this->front_[i], "fifo element");
for (size_t i = 0; i < this->rear_.length(); ++i)
GCPolicy<T>::trace(trc, &this->rear_[i], "fifo element");
}
};

View File

@ -42,6 +42,18 @@ typedef RootedValueMap::Enum RootEnum;
template <typename T>
using TraceFunction = void (*)(JSTracer* trc, T* ref, const char* name);
// For more detail see JS::Rooted::ptr and js::DispatchWrapper.
//
// The JS::RootKind::Traceable list contains a bunch of totally disparate
// types, but the instantiations of DispatchWrapper below need /something/ in
// the type field. We use the following type as a compatible stand-in. No
// actual methods from ConcreteTraceable type are actually used at runtime --
// the real trace function has been stored inline in the DispatchWrapper.
struct ConcreteTraceable {
ConcreteTraceable() { MOZ_CRASH("instantiation of ConcreteTraceable"); }
void trace(JSTracer*) {}
};
template <typename T, TraceFunction<T> TraceFn = TraceNullableRoot>
static inline void
MarkExactStackRootList(JSTracer* trc, JS::Rooted<void*>* rooter, const char* name)
@ -62,7 +74,8 @@ 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>(
MarkExactStackRootList<ConcreteTraceable,
js::DispatchWrapper<ConcreteTraceable>::TraceWrapped>(
trc, stackRoots_[JS::RootKind::Traceable], "Traceable");
}
@ -92,7 +105,8 @@ JS_FOR_EACH_TRACEKIND(MARK_ROOTS)
#undef MARK_ROOTS
MarkPersistentRootedList<jsid>(trc, heapRoots_[JS::RootKind::Id], "persistent-id");
MarkPersistentRootedList<Value>(trc, heapRoots_[JS::RootKind::Value], "persistent-value");
MarkPersistentRootedList<JS::Traceable, js::DispatchWrapper<JS::Traceable>::TraceWrapped>(trc,
MarkPersistentRootedList<ConcreteTraceable,
js::DispatchWrapper<ConcreteTraceable>::TraceWrapped>(trc,
heapRoots_[JS::RootKind::Traceable], "persistent-traceable");
}
@ -108,8 +122,9 @@ template <typename T>
static void
FinishPersistentRootedChain(mozilla::LinkedList<PersistentRooted<void*>>& listArg)
{
while (!listArg.isEmpty())
listArg.getFirst()->reset();
auto& list = reinterpret_cast<mozilla::LinkedList<PersistentRooted<T>>&>(listArg);
while (!list.isEmpty())
list.getFirst()->reset();
}
void
@ -121,7 +136,7 @@ JS_FOR_EACH_TRACEKIND(FINISH_ROOT_LIST)
#undef FINISH_ROOT_LIST
FinishPersistentRootedChain<jsid>(heapRoots_[JS::RootKind::Id]);
FinishPersistentRootedChain<Value>(heapRoots_[JS::RootKind::Value]);
FinishPersistentRootedChain<JS::Traceable>(heapRoots_[JS::RootKind::Traceable]);
FinishPersistentRootedChain<ConcreteTraceable>(heapRoots_[JS::RootKind::Traceable]);
}
inline void

View File

@ -44,17 +44,17 @@ BEGIN_TEST(testGCSuppressions)
}
END_TEST(testGCSuppressions)
struct MyContainer : public JS::Traceable
struct MyContainer
{
RelocatablePtrObject obj;
RelocatablePtrString str;
MyContainer() : obj(nullptr), str(nullptr) {}
static void trace(MyContainer* self, JSTracer* trc) {
if (self->obj)
js::TraceEdge(trc, &self->obj, "test container");
if (self->str)
js::TraceEdge(trc, &self->str, "test container");
void trace(JSTracer* trc) {
if (obj)
js::TraceEdge(trc, &obj, "test container");
if (str)
js::TraceEdge(trc, &str, "test container");
}
};

View File

@ -10,13 +10,13 @@
#include "jsapi-tests/tests.h"
struct MyHeap : JS::Traceable
struct MyHeap
{
explicit MyHeap(JSObject* obj) : weak(obj) {}
js::WeakRef<JSObject*> weak;
static void trace(MyHeap* self, JSTracer* trc) {
js::TraceWeakEdge(trc, &self->weak, "weak");
void trace(JSTracer* trc) {
js::TraceWeakEdge(trc, &weak, "weak");
}
};

View File

@ -2513,7 +2513,7 @@ JS_FreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
namespace JS {
struct PropertyDescriptor : public Traceable {
struct PropertyDescriptor {
JSObject* obj;
unsigned attrs;
JSGetterOp getter;

View File

@ -242,6 +242,13 @@ class JS_PUBLIC_API(AutoGCRooter)
void operator=(AutoGCRooter& ida) = delete;
};
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
// instantiation of MapTypeToRootKind.
template <>
struct MapTypeToRootKind<void*> {
static const RootKind kind = RootKind::Traceable;
};
} /* namespace JS */
namespace js {

View File

@ -166,7 +166,7 @@ class YieldOffsetArray {
}
};
class Binding : public JS::Traceable
class Binding
{
// One JSScript stores one Binding per formal/variable so we use a
// packed-word representation.
@ -215,7 +215,7 @@ JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t));
* both function and top-level scripts (the latter is needed to track names in
* strict mode eval code, to give such code its own lexical environment).
*/
class Bindings : public JS::Traceable
class Bindings
{
friend class BindingIter;
friend class AliasedFormalIter;

View File

@ -2480,7 +2480,7 @@ Debugger::markCrossCompartmentEdges(JSTracer* trc)
// `Debugger::logTenurePromotion`, we can't hold onto CCWs inside the log,
// and instead have unwrapped cross-compartment edges. We need to be sure to
// mark those here.
TenurePromotionsLog::trace(&tenurePromotionsLog, trc);
tenurePromotionsLog.trace(trc);
}
/*
@ -2656,8 +2656,8 @@ Debugger::trace(JSTracer* trc)
TraceEdge(trc, &frameobj, "live Debugger.Frame");
}
AllocationsLog::trace(&allocationsLog, trc);
TenurePromotionsLog::trace(&tenurePromotionsLog, trc);
allocationsLog.trace(trc);
tenurePromotionsLog.trace(trc);
/* Trace the weak map from JSScript instances to Debugger.Script objects. */
scripts.trace(trc);

View File

@ -282,7 +282,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
void logTenurePromotion(JSRuntime* rt, JSObject& obj, double when);
static SavedFrame* getObjectAllocationSite(JSObject& obj);
struct TenurePromotionsLogEntry : public JS::Traceable
struct TenurePromotionsLogEntry
{
TenurePromotionsLogEntry(JSRuntime* rt, JSObject& obj, double when);
@ -291,14 +291,13 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
RelocatablePtrObject frame;
size_t size;
static void trace(TenurePromotionsLogEntry* e, JSTracer* trc) { e->trace(trc); }
void trace(JSTracer* trc) {
if (frame)
TraceEdge(trc, &frame, "Debugger::TenurePromotionsLogEntry::frame");
}
};
struct AllocationsLogEntry : public JS::Traceable
struct AllocationsLogEntry
{
AllocationsLogEntry(HandleObject frame, double when, const char* className,
HandleAtom ctorName, size_t size, bool inNursery)
@ -319,7 +318,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
size_t size;
bool inNursery;
static void trace(AllocationsLogEntry* e, JSTracer* trc) { e->trace(trc); }
void trace(JSTracer* trc) {
if (frame)
TraceEdge(trc, &frame, "Debugger::AllocationsLogEntry::frame");

View File

@ -190,8 +190,7 @@ class MOZ_STACK_CLASS JSONParserBase
};
template <typename CharT>
class MOZ_STACK_CLASS JSONParser : public JSONParserBase,
public JS::Traceable
class MOZ_STACK_CLASS JSONParser : public JSONParserBase
{
private:
typedef mozilla::RangedPtr<const CharT> CharPtr;

View File

@ -1390,8 +1390,7 @@ ObjectGroup::newPlainObject(ExclusiveContext* cx, IdValuePair* properties, size_
// ObjectGroupCompartment AllocationSiteTable
/////////////////////////////////////////////////////////////////////
struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher<AllocationSiteKey>,
public JS::Traceable {
struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher<AllocationSiteKey> {
ReadBarrieredScript script;
uint32_t offset : 24;
@ -1433,9 +1432,9 @@ struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher<Allocati
MovableCellHasher<JSObject*>::match(a.proto, b.proto);
}
static void trace(AllocationSiteKey* key, JSTracer* trc) {
TraceRoot(trc, &key->script, "AllocationSiteKey script");
TraceNullableRoot(trc, &key->proto, "AllocationSiteKey proto");
void trace(JSTracer* trc) {
TraceRoot(trc, &script, "AllocationSiteKey script");
TraceNullableRoot(trc, &proto, "AllocationSiteKey proto");
}
bool needsSweep() {

View File

@ -65,13 +65,13 @@ LiveSavedFrameCache::getFramePtr(FrameIter& iter)
return Nothing();
}
/* static */ void
LiveSavedFrameCache::trace(LiveSavedFrameCache* cache, JSTracer* trc)
void
LiveSavedFrameCache::trace(JSTracer* trc)
{
if (!cache->initialized())
if (!initialized())
return;
for (auto* entry = cache->frames->begin(); entry < cache->frames->end(); entry++) {
for (auto* entry = frames->begin(); entry < frames->end(); entry++) {
TraceEdge(trc,
&entry->savedFrame,
"LiveSavedFrameCache::frames SavedFrame");

View File

@ -225,7 +225,7 @@ class SavedStacks {
};
public:
struct LocationValue : public JS::Traceable {
struct LocationValue {
LocationValue() : source(nullptr), line(0), column(0) { }
LocationValue(JSAtom* source, size_t line, uint32_t column)
: source(source),

View File

@ -1121,7 +1121,7 @@ struct InitialShapeEntry
using InitialShapeSet = js::GCHashSet<InitialShapeEntry, InitialShapeEntry, SystemAllocPolicy>;
struct StackShape : public JS::Traceable
struct StackShape
{
/* For performance, StackShape only roots when absolutely necessary. */
UnownedBaseShape* base;

View File

@ -1049,7 +1049,7 @@ struct DefaultHasher<AbstractFramePtr> {
// entries that must be scanned through, and to avoid the headaches of
// maintaining a cache for each compartment and invalidating stale cache entries
// in the presence of cross-compartment calls.
class LiveSavedFrameCache : public JS::Traceable
class LiveSavedFrameCache
{
public:
using FramePtr = mozilla::Variant<AbstractFramePtr, jit::CommonFrameLayout*>;
@ -1102,7 +1102,7 @@ class LiveSavedFrameCache : public JS::Traceable
}
static mozilla::Maybe<FramePtr> getFramePtr(FrameIter& iter);
static void trace(LiveSavedFrameCache* cache, JSTracer* trc);
void trace(JSTracer* trc);
void find(JSContext* cx, FrameIter& frameIter, MutableHandleSavedFrame frame) const;
bool insert(JSContext* cx, FramePtr& framePtr, jsbytecode* pc, HandleSavedFrame savedFrame);

View File

@ -14,7 +14,7 @@ namespace js {
// Information about an object prototype, which can be either a particular
// object, null, or a lazily generated object. The latter is only used by
// certain kinds of proxies.
class TaggedProto : public JS::Traceable
class TaggedProto
{
public:
static JSObject * const LazyProto;
@ -44,20 +44,15 @@ class TaggedProto : public JS::Traceable
bool operator ==(const TaggedProto& other) const { return proto == other.proto; }
bool operator !=(const TaggedProto& other) const { return proto != other.proto; }
static void trace(TaggedProto* protop, JSTracer* trc) {
TraceManuallyBarrieredEdge(trc, protop, "TaggedProto");
void trace(JSTracer* trc) {
if (isObject())
TraceManuallyBarrieredEdge(trc, &proto, "TaggedProto");
}
private:
JSObject* proto;
};
template <>
struct GCPolicy<TaggedProto>
{
static TaggedProto initial() { return TaggedProto(); }
};
template <>
struct InternalBarrierMethods<TaggedProto>
{

View File

@ -272,7 +272,7 @@ class TypeSet
// Information about a single concrete type. We pack this into one word,
// where small values are particular primitive or other singleton types and
// larger values are either specific JS objects or object groups.
class Type : public JS::Traceable
class Type
{
friend class TypeSet;
@ -350,8 +350,8 @@ class TypeSet
inline ObjectGroup* group() const;
inline ObjectGroup* groupNoBarrier() const;
static void trace(Type* v, JSTracer* trc) {
MarkTypeUnbarriered(trc, v, "TypeSet::Type");
void trace(JSTracer* trc) {
MarkTypeUnbarriered(trc, this, "TypeSet::Type");
}
bool operator == (Type o) const { return data == o.data; }