diff --git a/devtools/shared/heapsnapshot/DeserializedNode.h b/devtools/shared/heapsnapshot/DeserializedNode.h index 888ba1da313f..068bb176fae7 100644 --- a/devtools/shared/heapsnapshot/DeserializedNode.h +++ b/devtools/shared/heapsnapshot/DeserializedNode.h @@ -244,7 +244,7 @@ using mozilla::devtools::DeserializedNode; using mozilla::devtools::DeserializedStackFrame; template<> -class Concrete : public Base +struct Concrete : public Base { protected: explicit Concrete(DeserializedNode* ptr) : Base(ptr) { } @@ -253,6 +253,8 @@ protected: } public: + static const char16_t concreteTypeName[]; + static void construct(void* storage, DeserializedNode* ptr) { new (storage) Concrete(ptr); } @@ -271,8 +273,6 @@ public: // We ignore the `bool wantNames` parameter because we can't control whether // the core dump was serialized with edge names or not. js::UniquePtr edges(JSRuntime* rt, bool) const override; - - static const char16_t concreteTypeName[]; }; template<> diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index 3e08b24afe17..f97e302a88d5 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -641,28 +641,28 @@ class Base { }; // A traits template with a specialization for each referent type that -// ubi::Node supports. The specialization must be the concrete subclass of Base -// that represents a pointer to the referent type. It must include these -// members: -// -// // The specific char16_t array returned by Concrete::typeName(). -// static const char16_t concreteTypeName[]; -// -// // Construct an instance of this concrete class in |storage| referring -// // to |referent|. Implementations typically use a placement 'new'. -// // -// // In some cases, |referent| will contain dynamic type information that -// // identifies it a some more specific subclass of |Referent|. For -// // example, when |Referent| is |JSObject|, then |referent->getClass()| -// // could tell us that it's actually a JSFunction. Similarly, if -// // |Referent| is |nsISupports|, we would like a ubi::Node that knows its -// // final implementation type. -// // -// // So we delegate the actual construction to this specialization, which -// // knows Referent's details. -// static void construct(void* storage, Referent* referent); +// ubi::Node supports. The specialization must be the concrete subclass of +// Base that represents a pointer to the referent type. It must also +// include the members described here. template -class Concrete; +struct Concrete { + // The specific char16_t array returned by Concrete::typeName. + static const char16_t concreteTypeName[]; + + // Construct an instance of this concrete class in |storage| referring + // to |referent|. Implementations typically use a placement 'new'. + // + // In some cases, |referent| will contain dynamic type information that + // identifies it a some more specific subclass of |Referent|. For example, + // when |Referent| is |JSObject|, then |referent->getClass()| could tell us + // that it's actually a JSFunction. Similarly, if |Referent| is + // |nsISupports|, we would like a ubi::Node that knows its final + // implementation type. + // + // So, we delegate the actual construction to this specialization, which + // knows Referent's details. + static void construct(void* storage, Referent* referent); +}; // A container for a Base instance; all members simply forward to the contained // instance. This container allows us to pass ubi::Node instances by value. @@ -994,24 +994,24 @@ class MOZ_STACK_CLASS RootList { /*** Concrete classes for ubi::Node referent types ************************************************/ template<> -class Concrete : public Base { +struct Concrete : public Base { + js::UniquePtr edges(JSRuntime* rt, bool wantNames) const override; + const char16_t* typeName() const override { return concreteTypeName; } + protected: explicit Concrete(RootList* ptr) : Base(ptr) { } RootList& get() const { return *static_cast(ptr); } public: - static void construct(void* storage, RootList* ptr) { new (storage) Concrete(ptr); } - - js::UniquePtr edges(JSRuntime* rt, bool wantNames) const override; - - const char16_t* typeName() const override { return concreteTypeName; } static const char16_t concreteTypeName[]; + static void construct(void* storage, RootList* ptr) { new (storage) Concrete(ptr); } }; // A reusable ubi::Concrete specialization base class for types supported by // JS::TraceChildren. template class TracerConcrete : public Base { + const char16_t* typeName() const override { return concreteTypeName; } js::UniquePtr edges(JSRuntime* rt, bool wantNames) const override; JS::Zone* zone() const override; @@ -1020,6 +1020,7 @@ class TracerConcrete : public Base { Referent& get() const { return *static_cast(ptr); } public: + static const char16_t concreteTypeName[]; static void construct(void* storage, Referent* ptr) { new (storage) TracerConcrete(ptr); } }; @@ -1041,7 +1042,9 @@ class TracerConcreteWithCompartment : public TracerConcrete { // Define specializations for some commonly-used public JSAPI types. // These can use the generic templates above. template<> -class Concrete : TracerConcrete { +struct Concrete : TracerConcrete { + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + protected: explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { } @@ -1049,40 +1052,23 @@ class Concrete : TracerConcrete { static void construct(void* storage, JS::Symbol* ptr) { new (storage) Concrete(ptr); } - - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; -template<> -class Concrete : TracerConcreteWithCompartment { +template<> struct Concrete : TracerConcreteWithCompartment { + CoarseType coarseType() const final { return CoarseType::Script; } + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + const char* scriptFilename() const final; + protected: explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment(ptr) { } public: static void construct(void *storage, JSScript *ptr) { new (storage) Concrete(ptr); } - - CoarseType coarseType() const final { return CoarseType::Script; } - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - const char* scriptFilename() const final; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; // The JSObject specialization. template<> class Concrete : public TracerConcreteWithCompartment { - protected: - explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { } - - public: - static void construct(void* storage, JSObject* ptr) { - new (storage) Concrete(ptr); - } - const char* jsObjectClassName() const override; MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName) const override; @@ -1093,25 +1079,26 @@ class Concrete : public TracerConcreteWithCompartment { CoarseType coarseType() const final { return CoarseType::Object; } - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; + protected: + explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { } + + public: + static void construct(void* storage, JSObject* ptr) { + new (storage) Concrete(ptr); + } }; // For JSString, we extend the generic template with a 'size' implementation. -template<> -class Concrete : TracerConcrete { +template<> struct Concrete : TracerConcrete { + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + + CoarseType coarseType() const final { return CoarseType::String; } + protected: explicit Concrete(JSString *ptr) : TracerConcrete(ptr) { } public: static void construct(void *storage, JSString *ptr) { new (storage) Concrete(ptr); } - - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - CoarseType coarseType() const final { return CoarseType::String; } - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; // The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts. @@ -1128,6 +1115,7 @@ class Concrete : public Base { public: static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); } + static const char16_t concreteTypeName[]; }; diff --git a/js/src/jit/IonCode.h b/js/src/jit/IonCode.h index c165fd7f5443..fbab4efc470e 100644 --- a/js/src/jit/IonCode.h +++ b/js/src/jit/IonCode.h @@ -788,13 +788,7 @@ IsMarked(const jit::VMFunction*) namespace JS { namespace ubi { template<> -class Concrete : TracerConcrete { - protected: - explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete(ptr) { } - - public: - static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); } - +struct Concrete : TracerConcrete { CoarseType coarseType() const final { return CoarseType::Script; } Size size(mozilla::MallocSizeOf mallocSizeOf) const override { @@ -804,8 +798,11 @@ class Concrete : TracerConcrete { return size; } - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; + protected: + explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete(ptr) { } + + public: + static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); } }; } // namespace ubi diff --git a/js/src/jsapi-tests/testUbiNode.cpp b/js/src/jsapi-tests/testUbiNode.cpp index 5c5c04890358..756eec55d779 100644 --- a/js/src/jsapi-tests/testUbiNode.cpp +++ b/js/src/jsapi-tests/testUbiNode.cpp @@ -41,14 +41,10 @@ namespace JS { namespace ubi { template<> -class Concrete : public Base +struct Concrete : public Base { - protected: - explicit Concrete(FakeNode* ptr) : Base(ptr) { } - FakeNode& get() const { return *static_cast(ptr); } - - public: - static void construct(void* storage, FakeNode* ptr) { new (storage) Concrete(ptr); } + static const char16_t concreteTypeName[]; + const char16_t* typeName() const override { return concreteTypeName; } UniquePtr edges(JSRuntime* rt, bool wantNames) const override { return UniquePtr(js_new(get().edges)); @@ -58,8 +54,11 @@ class Concrete : public Base return 1; } - static const char16_t concreteTypeName[]; - const char16_t* typeName() const override { return concreteTypeName; } + static void construct(void* storage, FakeNode* ptr) { new (storage) Concrete(ptr); } + + protected: + explicit Concrete(FakeNode* ptr) : Base(ptr) { } + FakeNode& get() const { return *static_cast(ptr); } }; const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("FakeNode"); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 3fd7ea31b918..1652317a9cf1 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3831,7 +3831,8 @@ JS::ubi::Concrete::size(mozilla::MallocSizeOf mallocSizeOf) const return obj.tenuredSizeOfThis() + info.sizeOfAllThings(); } -const char16_t JS::ubi::Concrete::concreteTypeName[] = MOZ_UTF16("JSObject"); +template<> const char16_t JS::ubi::TracerConcrete::concreteTypeName[] = + MOZ_UTF16("JSObject"); void JSObject::traceChildren(JSTracer* trc) diff --git a/js/src/jsscript.h b/js/src/jsscript.h index d978ae64c7e0..9d675c556371 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -2552,19 +2552,16 @@ CloneGlobalScript(JSContext* cx, Handle enclosingScope, HandleScri namespace JS { namespace ubi { template<> -class Concrete : TracerConcrete { +struct Concrete : TracerConcrete { + CoarseType coarseType() const final { return CoarseType::Script; } + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + const char* scriptFilename() const final; + protected: explicit Concrete(js::LazyScript *ptr) : TracerConcrete(ptr) { } public: static void construct(void *storage, js::LazyScript *ptr) { new (storage) Concrete(ptr); } - - CoarseType coarseType() const final { return CoarseType::Script; } - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - const char* scriptFilename() const final; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; } // namespace ubi } // namespace JS diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index d5fddab625fc..fe5841b6f001 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -538,7 +538,7 @@ class Shape : public gc::TenuredCell friend class TenuringTracer; friend struct StackBaseShape; friend struct StackShape; - friend class JS::ubi::Concrete; + friend struct JS::ubi::Concrete; friend class js::gc::RelocationOverlay; protected: @@ -1459,32 +1459,24 @@ ReshapeForAllocKind(JSContext* cx, Shape* shape, TaggedProto proto, namespace JS { namespace ubi { -template<> -class Concrete : TracerConcreteWithCompartment { +template<> struct Concrete : TracerConcreteWithCompartment { + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + protected: explicit Concrete(js::Shape *ptr) : TracerConcreteWithCompartment(ptr) { } public: static void construct(void *storage, js::Shape *ptr) { new (storage) Concrete(ptr); } - - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; -template<> -class Concrete : TracerConcreteWithCompartment { +template<> struct Concrete : TracerConcreteWithCompartment { + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + protected: explicit Concrete(js::BaseShape *ptr) : TracerConcreteWithCompartment(ptr) { } public: static void construct(void *storage, js::BaseShape *ptr) { new (storage) Concrete(ptr); } - - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; } // namespace ubi diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp index d1609e300b97..e3d44b924354 100644 --- a/js/src/vm/String.cpp +++ b/js/src/vm/String.cpp @@ -82,7 +82,8 @@ JS::ubi::Concrete::size(mozilla::MallocSizeOf mallocSizeOf) const return size; } -const char16_t JS::ubi::Concrete::concreteTypeName[] = MOZ_UTF16("JSString"); +template<> const char16_t JS::ubi::TracerConcrete::concreteTypeName[] = + MOZ_UTF16("JSString"); #ifdef DEBUG diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h index bc8ff0cbd0a3..297c311782e8 100644 --- a/js/src/vm/TypeInference.h +++ b/js/src/vm/TypeInference.h @@ -1325,17 +1325,14 @@ namespace JS { namespace ubi { template<> -class Concrete : TracerConcrete { +struct Concrete : TracerConcrete { + Size size(mozilla::MallocSizeOf mallocSizeOf) const override; + protected: explicit Concrete(js::ObjectGroup *ptr) : TracerConcrete(ptr) { } public: static void construct(void *storage, js::ObjectGroup *ptr) { new (storage) Concrete(ptr); } - - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - const char16_t* typeName() const override { return concreteTypeName; } - static const char16_t concreteTypeName[]; }; } // namespace ubi diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index ad86eeec0fde..2ed4ad76b5be 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -371,15 +371,38 @@ Concrete::jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& o return true; } -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("JS::Symbol"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("JSScript"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("js::LazyScript"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("js::jit::JitCode"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("js::Shape"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("js::BaseShape"); -const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("js::ObjectGroup"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("JS::Symbol"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("JSScript"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("js::LazyScript"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("js::jit::JitCode"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("js::Shape"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("js::BaseShape"); +template<> const char16_t TracerConcrete::concreteTypeName[] = + MOZ_UTF16("js::ObjectGroup"); +// Instantiate all the TracerConcrete and templates here, where +// we have the member functions' definitions in scope. +namespace JS { +namespace ubi { +template class TracerConcreteWithCompartment; +template class TracerConcrete; +template class TracerConcrete; +template class TracerConcreteWithCompartment; +template class TracerConcrete; +template class TracerConcrete; +template class TracerConcreteWithCompartment; +template class TracerConcreteWithCompartment; +template class TracerConcrete; +} // namespace ubi +} // namespace JS + namespace JS { namespace ubi {