diff --git a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp index f70c096b44e1..e8d8b61d8845 100644 --- a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp +++ b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp @@ -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) { diff --git a/js/public/GCHashTable.h b/js/public/GCHashTable.h index cbc59d853415..a8be05b65c01 100644 --- a/js/public/GCHashTable.h +++ b/js/public/GCHashTable.h @@ -49,8 +49,7 @@ template , typename AllocPolicy = TempAllocPolicy, typename MapSweepPolicy = DefaultMapSweepPolicy> -class GCHashMap : public HashMap, - public JS::Traceable +class GCHashMap : public HashMap { using Base = HashMap; @@ -226,8 +225,7 @@ class HandleBase> template , typename AllocPolicy = TempAllocPolicy> -class GCHashSet : public HashSet, - public JS::Traceable +class GCHashSet : public HashSet { using Base = HashSet; diff --git a/js/public/GCVector.h b/js/public/GCVector.h index 37db34e988e0..53c05976e430 100644 --- a/js/public/GCVector.h +++ b/js/public/GCVector.h @@ -33,7 +33,7 @@ namespace js { template -class GCVector : public JS::Traceable +class GCVector { mozilla::Vector vector; diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 8069acb340a5..b29e90f1c6c0 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -581,28 +581,15 @@ struct JS_PUBLIC_API(MovableCellHasher>) } /* 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 class DispatchWrapper { - static_assert(mozilla::IsBaseOf::value, + static_assert(JS::MapTypeToRootKind::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 MOZ_IMPLICIT DispatchWrapper(U&& initial) - : tracer(&T::trace), + : tracer(&GCPolicy::trace), storage(mozilla::Forward(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( uintptr_t(thingp) - offsetof(DispatchWrapper, storage)); - wrapper->tracer(&wrapper->storage, trc); + wrapper->tracer(trc, &wrapper->storage, name); } }; @@ -670,9 +657,6 @@ namespace JS { template class MOZ_RAII Rooted : public js::RootedBase { - static_assert(!mozilla::IsConvertible::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::kind]; @@ -727,14 +711,14 @@ class MOZ_RAII Rooted : public js::RootedBase /* * 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::value, + MapTypeToRootKind::kind == JS::RootKind::Traceable, js::DispatchWrapper, T>::Type; MaybeWrapped ptr; @@ -1071,7 +1055,7 @@ class PersistentRooted : public js::PersistentRootedBase, // See the comment above Rooted::ptr. using MaybeWrapped = typename mozilla::Conditional< - mozilla::IsBaseOf::value, + MapTypeToRootKind::kind == JS::RootKind::Traceable, js::DispatchWrapper, T>::Type; diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index a9bd143d585a..0e1a231789d2 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -308,7 +308,7 @@ template 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 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); } diff --git a/js/src/builtin/MapObject.h b/js/src/builtin/MapObject.h index 1118675f8736..a3d57f7dd379 100644 --- a/js/src/builtin/MapObject.h +++ b/js/src/builtin/MapObject.h @@ -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"); } }; diff --git a/js/src/ds/TraceableFifo.h b/js/src/ds/TraceableFifo.h index e6b20a593ac5..3176e3e3ea7b 100644 --- a/js/src/ds/TraceableFifo.h +++ b/js/src/ds/TraceableFifo.h @@ -31,9 +31,7 @@ namespace js { template -class TraceableFifo - : public js::Fifo, - public JS::Traceable +class TraceableFifo : public js::Fifo { using Base = js::Fifo; @@ -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::trace(trc, &tf->front_[i], "fifo element"); - for (size_t i = 0; i < tf->rear_.length(); ++i) - GCPolicy::trace(trc, &tf->rear_[i], "fifo element"); + void trace(JSTracer* trc) { + for (size_t i = 0; i < this->front_.length(); ++i) + GCPolicy::trace(trc, &this->front_[i], "fifo element"); + for (size_t i = 0; i < this->rear_.length(); ++i) + GCPolicy::trace(trc, &this->rear_[i], "fifo element"); } }; diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 6b136247af29..2bacce9ffa25 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -42,6 +42,18 @@ typedef RootedValueMap::Enum RootEnum; template 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 TraceFn = TraceNullableRoot> static inline void MarkExactStackRootList(JSTracer* trc, JS::Rooted* rooter, const char* name) @@ -62,7 +74,8 @@ JS_FOR_EACH_TRACEKIND(MARK_ROOTS) #undef MARK_ROOTS MarkExactStackRootList(trc, stackRoots_[JS::RootKind::Id], "exact-id"); MarkExactStackRootList(trc, stackRoots_[JS::RootKind::Value], "exact-value"); - MarkExactStackRootList::TraceWrapped>( + MarkExactStackRootList::TraceWrapped>( trc, stackRoots_[JS::RootKind::Traceable], "Traceable"); } @@ -92,7 +105,8 @@ JS_FOR_EACH_TRACEKIND(MARK_ROOTS) #undef MARK_ROOTS MarkPersistentRootedList(trc, heapRoots_[JS::RootKind::Id], "persistent-id"); MarkPersistentRootedList(trc, heapRoots_[JS::RootKind::Value], "persistent-value"); - MarkPersistentRootedList::TraceWrapped>(trc, + MarkPersistentRootedList::TraceWrapped>(trc, heapRoots_[JS::RootKind::Traceable], "persistent-traceable"); } @@ -108,8 +122,9 @@ template static void FinishPersistentRootedChain(mozilla::LinkedList>& listArg) { - while (!listArg.isEmpty()) - listArg.getFirst()->reset(); + auto& list = reinterpret_cast>&>(listArg); + while (!list.isEmpty()) + list.getFirst()->reset(); } void @@ -121,7 +136,7 @@ JS_FOR_EACH_TRACEKIND(FINISH_ROOT_LIST) #undef FINISH_ROOT_LIST FinishPersistentRootedChain(heapRoots_[JS::RootKind::Id]); FinishPersistentRootedChain(heapRoots_[JS::RootKind::Value]); - FinishPersistentRootedChain(heapRoots_[JS::RootKind::Traceable]); + FinishPersistentRootedChain(heapRoots_[JS::RootKind::Traceable]); } inline void diff --git a/js/src/jsapi-tests/testGCExactRooting.cpp b/js/src/jsapi-tests/testGCExactRooting.cpp index c25691347772..01bb1fdf08a1 100644 --- a/js/src/jsapi-tests/testGCExactRooting.cpp +++ b/js/src/jsapi-tests/testGCExactRooting.cpp @@ -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"); } }; diff --git a/js/src/jsapi-tests/testGCWeakRef.cpp b/js/src/jsapi-tests/testGCWeakRef.cpp index fc7bc76c8a21..a072081c01c8 100644 --- a/js/src/jsapi-tests/testGCWeakRef.cpp +++ b/js/src/jsapi-tests/testGCWeakRef.cpp @@ -10,13 +10,13 @@ #include "jsapi-tests/tests.h" -struct MyHeap : JS::Traceable +struct MyHeap { explicit MyHeap(JSObject* obj) : weak(obj) {} js::WeakRef weak; - static void trace(MyHeap* self, JSTracer* trc) { - js::TraceWeakEdge(trc, &self->weak, "weak"); + void trace(JSTracer* trc) { + js::TraceWeakEdge(trc, &weak, "weak"); } }; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index c8da316bbaa5..693655d0c73a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2513,7 +2513,7 @@ JS_FreezeObject(JSContext* cx, JS::Handle obj); namespace JS { -struct PropertyDescriptor : public Traceable { +struct PropertyDescriptor { JSObject* obj; unsigned attrs; JSGetterOp getter; diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 4ea7c738f96f..5410252a101d 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -242,6 +242,13 @@ class JS_PUBLIC_API(AutoGCRooter) void operator=(AutoGCRooter& ida) = delete; }; +// Our instantiations of Rooted and PersistentRooted require an +// instantiation of MapTypeToRootKind. +template <> +struct MapTypeToRootKind { + static const RootKind kind = RootKind::Traceable; +}; + } /* namespace JS */ namespace js { diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 201177462a3b..b13598cbe0a0 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -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; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 295ec711df0e..cd5d41996f0c 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -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); diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index b35685a444c1..1acd3e1ec69a 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -282,7 +282,7 @@ class Debugger : private mozilla::LinkedListElement 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 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 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"); diff --git a/js/src/vm/JSONParser.h b/js/src/vm/JSONParser.h index 687972392b02..0b48e06091c2 100644 --- a/js/src/vm/JSONParser.h +++ b/js/src/vm/JSONParser.h @@ -190,8 +190,7 @@ class MOZ_STACK_CLASS JSONParserBase }; template -class MOZ_STACK_CLASS JSONParser : public JSONParserBase, - public JS::Traceable +class MOZ_STACK_CLASS JSONParser : public JSONParserBase { private: typedef mozilla::RangedPtr CharPtr; diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index 4cef20beb1fe..d1407d416db5 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -1390,8 +1390,7 @@ ObjectGroup::newPlainObject(ExclusiveContext* cx, IdValuePair* properties, size_ // ObjectGroupCompartment AllocationSiteTable ///////////////////////////////////////////////////////////////////// -struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher, - public JS::Traceable { +struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher { ReadBarrieredScript script; uint32_t offset : 24; @@ -1433,9 +1432,9 @@ struct ObjectGroupCompartment::AllocationSiteKey : public DefaultHasher::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() { diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index b6daaf8b8211..9c1f4d96e305 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -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"); diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h index 3e26b3fc58df..2abd9a383fd4 100644 --- a/js/src/vm/SavedStacks.h +++ b/js/src/vm/SavedStacks.h @@ -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), diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 9df058447f0f..809211f2b488 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1121,7 +1121,7 @@ struct InitialShapeEntry using InitialShapeSet = js::GCHashSet; -struct StackShape : public JS::Traceable +struct StackShape { /* For performance, StackShape only roots when absolutely necessary. */ UnownedBaseShape* base; diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index bbe9e2216e6d..f212289945e1 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1049,7 +1049,7 @@ struct DefaultHasher { // 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; @@ -1102,7 +1102,7 @@ class LiveSavedFrameCache : public JS::Traceable } static mozilla::Maybe 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); diff --git a/js/src/vm/TaggedProto.h b/js/src/vm/TaggedProto.h index 412961a08bdf..53c5fd575ce9 100644 --- a/js/src/vm/TaggedProto.h +++ b/js/src/vm/TaggedProto.h @@ -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 -{ - static TaggedProto initial() { return TaggedProto(); } -}; - template <> struct InternalBarrierMethods { diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h index 6090359c3155..aa39e7541019 100644 --- a/js/src/vm/TypeInference.h +++ b/js/src/vm/TypeInference.h @@ -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; }