Bug 1196634 - Part 0: Define a JS::ubi::CoarseType enum; r=sfink

This commit defines the JS::ubi::CoarseType enum and a corresponding method
coarseType() on JS::ubi::Node base and concrete classes. It implements the
overrides for all concrete specializations whose referent does not belong to the
default Other type.
This commit is contained in:
Nick Fitzgerald 2015-08-27 16:16:57 -07:00
Родитель 8c7417603d
Коммит ae6af42629
5 изменённых файлов: 89 добавлений и 3 удалений

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

@ -437,6 +437,25 @@ bool ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
/*** ubi::Node ************************************************************************************/
// A concrete node specialization can claim its referent is a member of a
// particular "coarse type" which is less specific than the actual
// implementation type but generally more palatable for web developers. For
// example, JitCode can be considered to have a coarse type of "Script". This is
// used by some analyses for putting nodes into different buckets. The default,
// if a concrete specialization does not provide its own mapping to a CoarseType
// variant, is "Other".
//
// NB: the values associated with a particular enum variant must not change or
// be reused for new variants. Doing so will cause inspecting ubi::Node's backed
// by an offline heap snapshot from an older SpiderMonkey/Firefox version to
// break. Consider this enum append only.
enum class CoarseType: uint32_t {
Object = 0,
Script = 1,
String = 2,
Other = 3
};
// The base class implemented by each ubi::Node referent type. Subclasses must
// not add data members to this class.
class Base {
@ -485,6 +504,9 @@ class Base {
// otherwise.
virtual bool isLive() const { return true; };
// Return the coarse-grained type-of-thing that this node represents.
virtual CoarseType coarseType() const { return CoarseType::Other; }
// Return a human-readable name for the referent's type. The result should
// be statically allocated. (You can use MOZ_UTF16("strings") for this.)
//
@ -680,6 +702,7 @@ class Node {
// not all!) JSObjects can be exposed.
JS::Value exposeToJS() const;
CoarseType coarseType() const { return base()->coarseType(); }
const char16_t* typeName() const { return base()->typeName(); }
JS::Zone* zone() const { return base()->zone(); }
JSCompartment* compartment() const { return base()->compartment(); }
@ -963,7 +986,16 @@ class TracerConcreteWithCompartment : public TracerConcrete<Referent> {
// Define specializations for some commonly-used public JSAPI types.
// These can use the generic templates above.
template<> struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { };
template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> { };
template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment<JSScript>(ptr) { }
public:
static void construct(void *storage, JSScript *ptr) { new (storage) Concrete(ptr); }
};
// The JSObject specialization.
template<>
@ -976,6 +1008,8 @@ class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
bool hasAllocationStack() const override;
StackFrame allocationStack() const override;
CoarseType coarseType() const final { return CoarseType::Object; }
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
@ -989,6 +1023,8 @@ class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
template<> struct Concrete<JSString> : TracerConcrete<JSString> {
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
CoarseType coarseType() const final { return CoarseType::String; }
protected:
explicit Concrete(JSString *ptr) : TracerConcrete<JSString>(ptr) { }
@ -1004,6 +1040,7 @@ class Concrete<void> : public Base {
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
JSCompartment* compartment() const override;
CoarseType coarseType() const final;
explicit Concrete(void* ptr) : Base(ptr) { }

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

@ -776,7 +776,17 @@ IsMarked(const jit::VMFunction*)
// instances with no associated compartment.
namespace JS {
namespace ubi {
template<> struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { };
template<>
struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete<js::jit::JitCode>(ptr) { }
public:
static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); }
};
} // namespace ubi
} // namespace JS

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

@ -195,3 +195,31 @@ BEGIN_TEST(test_ubiStackFrame)
return true;
}
END_TEST(test_ubiStackFrame)
BEGIN_TEST(test_ubiCoarseType)
{
// Test that our explicit coarseType() overrides work as expected.
JSObject* obj = nullptr;
CHECK(JS::ubi::Node(obj).coarseType() == JS::ubi::CoarseType::Object);
JSScript* script = nullptr;
CHECK(JS::ubi::Node(script).coarseType() == JS::ubi::CoarseType::Script);
js::LazyScript* lazyScript = nullptr;
CHECK(JS::ubi::Node(lazyScript).coarseType() == JS::ubi::CoarseType::Script);
js::jit::JitCode* jitCode = nullptr;
CHECK(JS::ubi::Node(jitCode).coarseType() == JS::ubi::CoarseType::Script);
JSString* str = nullptr;
CHECK(JS::ubi::Node(str).coarseType() == JS::ubi::CoarseType::String);
// Test that the default when coarseType() is not overridden is Other.
JS::Symbol* sym = nullptr;
CHECK(JS::ubi::Node(sym).coarseType() == JS::ubi::CoarseType::Other);
return true;
}
END_TEST(test_ubiCoarseType)

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

@ -2408,7 +2408,16 @@ CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScri
// with no associated compartment.
namespace JS {
namespace ubi {
template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { };
template<>
struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(js::LazyScript *ptr) : TracerConcrete<js::LazyScript>(ptr) { }
public:
static void construct(void *storage, js::LazyScript *ptr) { new (storage) Concrete(ptr); }
};
} // namespace ubi
} // namespace JS

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

@ -42,6 +42,7 @@ using JS::HandleValue;
using JS::Value;
using JS::ZoneSet;
using JS::ubi::AtomOrTwoByteChars;
using JS::ubi::CoarseType;
using JS::ubi::Concrete;
using JS::ubi::Edge;
using JS::ubi::EdgeRange;
@ -272,6 +273,7 @@ Node::getCanonicalTypeName(const char16_t* dupe, size_t length)
}
// All operations on null ubi::Nodes crash.
CoarseType Concrete<void>::coarseType() const { MOZ_CRASH("null ubi::Node"); }
const char16_t* Concrete<void>::typeName() const { MOZ_CRASH("null ubi::Node"); }
JS::Zone* Concrete<void>::zone() const { MOZ_CRASH("null ubi::Node"); }
JSCompartment* Concrete<void>::compartment() const { MOZ_CRASH("null ubi::Node"); }