# HG changeset patch # User Jeff Walden # Date 1467765672 25200 # Node ID 6c37be9cee51e14e1f04ebfb96ab58cc5113c477 # Parent 752282c3e152f3c56de2c66dd56cb05e79b05807 Bug 1282795 - Declare JS::ubi::Concrete::concreteTypeName within every JS::ubi::Concrete specialization to avoid use-before-declaration warnings related to templates. r=jimb # HG changeset patch # User Jeff Walden # Date 1468011117 25200 # Node ID 4548ba932bde3067a722b267f9b1e43256740d4e # Parent 6b82281bc9275e8961c11760624c781c99f0a497 Bug 1285652 - Instantiate two member functions of JS::ubi::TracerConcrete to fix ARM 32-bit simulator on OS X compile errors. r=sfink, f=gkw diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -636,38 +636,38 @@ class Base { virtual const char* scriptFilename() const { return nullptr; } private: Base(const Base& rhs) = delete; Base& operator=(const Base& rhs) = delete; }; // 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 also -// include the members described here. +// 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); template -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); -}; +class Concrete; // 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. class Node { // Storage in which we allocate Base subclasses. mozilla::AlignedStorage2 storage; Base* base() { return storage.addr(); } const Base* base() const { return storage.addr(); } @@ -989,43 +989,42 @@ class MOZ_STACK_CLASS RootList { // edgeName. bool addRoot(Node node, const char16_t* edgeName = nullptr); }; /*** Concrete classes for ubi::Node referent types ************************************************/ template<> -struct Concrete : public Base { - UniquePtr edges(JSRuntime* rt, bool wantNames) const override; - const char16_t* typeName() const override { return concreteTypeName; } - +class Concrete : public Base { 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); } + + 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; } UniquePtr edges(JSRuntime* rt, bool wantNames) const override; JS::Zone* zone() const override; protected: explicit TracerConcrete(Referent* ptr) : Base(ptr) { } Referent& get() const { return *static_cast(ptr); } public: - static const char16_t concreteTypeName[]; static void construct(void* storage, Referent* ptr) { new (storage) TracerConcrete(ptr); } }; // For JS::TraceChildren-based types that have a 'compartment' method. template class TracerConcreteWithCompartment : public TracerConcrete { typedef TracerConcrete TracerBase; JSCompartment* compartment() const override; @@ -1037,90 +1036,103 @@ class TracerConcreteWithCompartment : pu static void construct(void* storage, Referent* ptr) { new (storage) TracerConcreteWithCompartment(ptr); } }; // Define specializations for some commonly-used public JSAPI types. // These can use the generic templates above. template<> -struct Concrete : TracerConcrete { - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - +class Concrete : TracerConcrete { protected: explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { } public: 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<> struct Concrete : TracerConcreteWithCompartment { - CoarseType coarseType() const final { return CoarseType::Script; } - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - const char* scriptFilename() const final; - +template<> +class Concrete : TracerConcreteWithCompartment { 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; bool jsObjectConstructorName(JSContext* cx, UniquePtr& outName) const override; Size size(mozilla::MallocSizeOf mallocSizeOf) const override; bool hasAllocationStack() const override; StackFrame allocationStack() const override; CoarseType coarseType() const final { return CoarseType::Object; } - protected: - explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { } - - public: - static void construct(void* storage, JSObject* ptr) { - new (storage) Concrete(ptr); - } + const char16_t* typeName() const override { return concreteTypeName; } + static const char16_t concreteTypeName[]; }; // For JSString, we extend the generic template with a 'size' implementation. -template<> struct Concrete : TracerConcrete { - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - - CoarseType coarseType() const final { return CoarseType::String; } - +template<> +class Concrete : TracerConcrete { 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. template<> class Concrete : public Base { const char16_t* typeName() const override; Size size(mozilla::MallocSizeOf mallocSizeOf) const override; UniquePtr edges(JSRuntime* rt, bool wantNames) const override; JS::Zone* zone() const override; JSCompartment* compartment() const override; CoarseType coarseType() const final; explicit Concrete(void* ptr) : Base(ptr) { } public: static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); } - static const char16_t concreteTypeName[]; }; } // namespace ubi } // namespace JS namespace js { diff --git a/js/src/jit/IonCode.h b/js/src/jit/IonCode.h --- a/js/src/jit/IonCode.h +++ b/js/src/jit/IonCode.h @@ -783,31 +783,34 @@ IsMarked(const jit::VMFunction*) } // namespace js // JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell // instances with no associated compartment. namespace JS { namespace ubi { template<> -struct Concrete : TracerConcrete { +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); } + CoarseType coarseType() const final { return CoarseType::Script; } Size size(mozilla::MallocSizeOf mallocSizeOf) const override { Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind()); size += get().bufferSize(); size += get().headerSize(); return size; } - protected: - explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete(ptr) { } - - public: - static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); } + const char16_t* typeName() const override { return concreteTypeName; } + static const char16_t concreteTypeName[]; }; } // namespace ubi } // namespace JS #endif /* jit_IonCode_h */ diff --git a/js/src/jsapi-tests/testUbiNode.cpp b/js/src/jsapi-tests/testUbiNode.cpp --- a/js/src/jsapi-tests/testUbiNode.cpp +++ b/js/src/jsapi-tests/testUbiNode.cpp @@ -36,34 +36,35 @@ struct FakeNode return edges.emplaceBack(nullptr, node); } }; namespace JS { namespace ubi { template<> -struct Concrete : public Base +class Concrete : public Base { - static const char16_t concreteTypeName[]; - const char16_t* typeName() const override { return concreteTypeName; } + 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); } UniquePtr edges(JSRuntime* rt, bool wantNames) const override { return UniquePtr(js_new(get().edges)); } Node::Size size(mozilla::MallocSizeOf) const override { return 1; } - 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); } + static const char16_t concreteTypeName[]; + const char16_t* typeName() const override { return concreteTypeName; } }; const char16_t Concrete::concreteTypeName[] = MOZ_UTF16("FakeNode"); } // namespace ubi } // namespace JS // ubi::Node::zone works diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3826,18 +3826,17 @@ JS::ubi::Concrete::size(mozill if (!obj.isTenured()) return obj.sizeOfIncludingThisInNursery(); JS::ClassInfo info; obj.addSizeOfExcludingThis(mallocSizeOf, &info); return obj.tenuredSizeOfThis() + info.sizeOfAllThings(); } -template<> const char16_t JS::ubi::TracerConcrete::concreteTypeName[] = - MOZ_UTF16("JSObject"); +const char16_t JS::ubi::Concrete::concreteTypeName[] = MOZ_UTF16("JSObject"); void JSObject::traceChildren(JSTracer* trc) { TraceEdge(trc, &group_, "group"); const Class* clasp = group_->clasp(); if (clasp->isNative()) { diff --git a/js/src/jsscript.h b/js/src/jsscript.h --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -2547,23 +2547,26 @@ CloneGlobalScript(JSContext* cx, Handle< } /* namespace js */ // JS::ubi::Nodes can point to js::LazyScripts; they're js::gc::Cell instances // with no associated compartment. namespace JS { namespace ubi { template<> -struct Concrete : TracerConcrete { - CoarseType coarseType() const final { return CoarseType::Script; } - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - const char* scriptFilename() const final; - +class Concrete : TracerConcrete { 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 #endif /* jsscript_h */ diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -533,17 +533,17 @@ class Shape : public gc::TenuredCell friend class ::JSFunction; friend class Bindings; friend class NativeObject; friend class PropertyTree; friend class StaticBlockObject; friend class TenuringTracer; friend struct StackBaseShape; friend struct StackShape; - friend struct JS::ubi::Concrete; + friend class JS::ubi::Concrete; protected: HeapPtrBaseShape base_; PreBarrieredId propid_; enum SlotInfo : uint32_t { /* Number of fixed slots in objects with this shape. */ @@ -1454,32 +1454,40 @@ ReshapeForAllocKind(JSContext* cx, Shape #pragma warning(pop) #endif // JS::ubi::Nodes can point to Shapes and BaseShapes; they're js::gc::Cell // instances that occupy a compartment. namespace JS { namespace ubi { -template<> struct Concrete : TracerConcreteWithCompartment { - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - +template<> +class Concrete : TracerConcreteWithCompartment { 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<> struct Concrete : TracerConcreteWithCompartment { - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - +template<> +class Concrete : TracerConcreteWithCompartment { 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 } // namespace JS #endif /* vm_Shape_h */ diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp --- a/js/src/vm/String.cpp +++ b/js/src/vm/String.cpp @@ -77,18 +77,17 @@ JS::ubi::Concrete::size(mozill // We can't use mallocSizeof on things in the nursery. At the moment, // strings are never in the nursery, but that may change. MOZ_ASSERT(!IsInsideNursery(&str)); size += str.sizeOfExcludingThis(mallocSizeOf); return size; } -template<> const char16_t JS::ubi::TracerConcrete::concreteTypeName[] = - MOZ_UTF16("JSString"); +const char16_t JS::ubi::Concrete::concreteTypeName[] = MOZ_UTF16("JSString"); #ifdef DEBUG template /*static */ void JSString::dumpChars(const CharT* s, size_t n, FILE* fp) { if (n == SIZE_MAX) { diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h --- a/js/src/vm/TypeInference.h +++ b/js/src/vm/TypeInference.h @@ -1320,22 +1320,25 @@ PrintTypes(JSContext* cx, JSCompartment* } /* namespace js */ // JS::ubi::Nodes can point to object groups; they're js::gc::Cell instances // with no associated compartment. namespace JS { namespace ubi { template<> -struct Concrete : TracerConcrete { - Size size(mozilla::MallocSizeOf mallocSizeOf) const override; - +class Concrete : TracerConcrete { 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 } // namespace JS #endif /* vm_TypeInference_h */ diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -303,36 +303,56 @@ class SimpleEdgeRange : public EdgeRange template JS::Zone* TracerConcrete::zone() const { return get().zoneFromAnyThread(); } +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; +template JS::Zone* TracerConcrete::zone() const; + template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const { UniquePtr> range(js_new()); if (!range) return nullptr; if (!range->init(rt, ptr, JS::MapTypeToTraceKind::kind, wantNames)) return nullptr; return UniquePtr(range.release()); } +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; +template UniquePtr TracerConcrete::edges(JSRuntime* rt, bool wantNames) const; + template JSCompartment* TracerConcreteWithCompartment::compartment() const { return TracerBase::get().compartment(); } +template JSCompartment* TracerConcreteWithCompartment::compartment() const; +template JSCompartment* TracerConcreteWithCompartment::compartment() const; +template JSCompartment* TracerConcreteWithCompartment::compartment() const; + bool Concrete::hasAllocationStack() const { return !!js::Debugger::getObjectAllocationSite(get()); } StackFrame Concrete::allocationStack() const @@ -366,47 +384,23 @@ Concrete::jsObjectConstructorN mozilla::Range chars(outName.get(), size); if (!JS_CopyStringChars(cx, chars, name)) return false; outName[len] = '\0'; return true; } -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 +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"); namespace JS { namespace ubi { RootList::RootList(JSRuntime* rt, Maybe& noGC, bool wantNames /* = false */) : noGC(noGC), rt(rt), edges(),