Differential D3143 Diff 14286 ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNode.h
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNode.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- | ||||
* vim: set ts=8 sts=4 et sw=4 tw=99: | * vim: set ts=8 sts=2 et sw=2 tw=80: | ||||
* This Source Code Form is subject to the terms of the Mozilla Public | * This Source Code Form is subject to the terms of the Mozilla Public | ||||
* License, v. 2.0. If a copy of the MPL was not distributed with this | * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
#ifndef js_UbiNode_h | #ifndef js_UbiNode_h | ||||
#define js_UbiNode_h | #define js_UbiNode_h | ||||
#include "mozilla/Alignment.h" | #include "mozilla/Alignment.h" | ||||
Show All 13 Lines | |||||
#include "js/HashTable.h" | #include "js/HashTable.h" | ||||
#include "js/RootingAPI.h" | #include "js/RootingAPI.h" | ||||
#include "js/TracingAPI.h" | #include "js/TracingAPI.h" | ||||
#include "js/TypeDecls.h" | #include "js/TypeDecls.h" | ||||
#include "js/UniquePtr.h" | #include "js/UniquePtr.h" | ||||
#include "js/Value.h" | #include "js/Value.h" | ||||
#include "js/Vector.h" | #include "js/Vector.h" | ||||
// JS::ubi::Node | // [SMDOC] ubi::Node (Heap Analysis framework) | ||||
// | // | ||||
// JS::ubi::Node is a pointer-like type designed for internal use by heap | // JS::ubi::Node is a pointer-like type designed for internal use by heap | ||||
// analysis tools. A ubi::Node can refer to: | // analysis tools. A ubi::Node can refer to: | ||||
// | // | ||||
// - a JS value, like a string, object, or symbol; | // - a JS value, like a string, object, or symbol; | ||||
// - an internal SpiderMonkey structure, like a shape or a scope chain object | // - an internal SpiderMonkey structure, like a shape or a scope chain object | ||||
// - an instance of some embedding-provided type: in Firefox, an XPCOM | // - an instance of some embedding-provided type: in Firefox, an XPCOM | ||||
// object, or an internal DOM node class instance | // object, or an internal DOM node class instance | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | |||||
class StackFrame; | class StackFrame; | ||||
} // namespace ubi | } // namespace ubi | ||||
} // namespace JS | } // namespace JS | ||||
namespace JS { | namespace JS { | ||||
namespace ubi { | namespace ubi { | ||||
using mozilla::Forward; | |||||
using mozilla::Maybe; | using mozilla::Maybe; | ||||
using mozilla::Move; | |||||
using mozilla::RangedPtr; | using mozilla::RangedPtr; | ||||
using mozilla::Variant; | using mozilla::Variant; | ||||
template <typename T> | template <typename T> | ||||
using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>; | using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>; | ||||
/*** ubi::StackFrame **********************************************************/ | /*** ubi::StackFrame **********************************************************/ | ||||
// Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object | // Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object | ||||
// store their strings as JSAtom*, while deserialized stack frames from offline | // store their strings as JSAtom*, while deserialized stack frames from offline | ||||
// heap snapshots store their strings as const char16_t*. In order to provide | // heap snapshots store their strings as const char16_t*. In order to provide | ||||
// zero-cost accessors to these strings in a single interface that works with | // zero-cost accessors to these strings in a single interface that works with | ||||
// both cases, we use this variant type. | // both cases, we use this variant type. | ||||
class JS_PUBLIC_API AtomOrTwoByteChars | class JS_PUBLIC_API AtomOrTwoByteChars | ||||
: public Variant<JSAtom*, const char16_t*> { | : public Variant<JSAtom*, const char16_t*> { | ||||
using Base = Variant<JSAtom*, const char16_t*>; | using Base = Variant<JSAtom*, const char16_t*>; | ||||
public: | public: | ||||
template <typename T> | template <typename T> | ||||
MOZ_IMPLICIT AtomOrTwoByteChars(T&& rhs) : Base(Forward<T>(rhs)) {} | MOZ_IMPLICIT AtomOrTwoByteChars(T&& rhs) : Base(std::forward<T>(rhs)) {} | ||||
template <typename T> | template <typename T> | ||||
AtomOrTwoByteChars& operator=(T&& rhs) { | AtomOrTwoByteChars& operator=(T&& rhs) { | ||||
MOZ_ASSERT(this != &rhs, "self-move disallowed"); | MOZ_ASSERT(this != &rhs, "self-move disallowed"); | ||||
this->~AtomOrTwoByteChars(); | this->~AtomOrTwoByteChars(); | ||||
new (this) AtomOrTwoByteChars(Forward<T>(rhs)); | new (this) AtomOrTwoByteChars(std::forward<T>(rhs)); | ||||
return *this; | return *this; | ||||
} | } | ||||
// Return the length of the given AtomOrTwoByteChars string. | // Return the length of the given AtomOrTwoByteChars string. | ||||
size_t length(); | size_t length(); | ||||
// Copy the given AtomOrTwoByteChars string into the destination buffer, | // Copy the given AtomOrTwoByteChars string into the destination buffer, | ||||
// inflating if necessary. Does NOT null terminate. Returns the number of | // inflating if necessary. Does NOT null terminate. Returns the number of | ||||
Show All 28 Lines | public: | ||||
virtual uint32_t line() const = 0; | virtual uint32_t line() const = 0; | ||||
// Get this frame's column number. | // Get this frame's column number. | ||||
virtual uint32_t column() const = 0; | virtual uint32_t column() const = 0; | ||||
// Get this frame's source name. Never null. | // Get this frame's source name. Never null. | ||||
virtual AtomOrTwoByteChars source() const = 0; | virtual AtomOrTwoByteChars source() const = 0; | ||||
// Get a unique per-process ID for this frame's source. Defaults to zero. | |||||
virtual uint32_t sourceId() const = 0; | |||||
// Return this frame's function name if named, otherwise the inferred | // Return this frame's function name if named, otherwise the inferred | ||||
// display name. Can be null. | // display name. Can be null. | ||||
virtual AtomOrTwoByteChars functionDisplayName() const = 0; | virtual AtomOrTwoByteChars functionDisplayName() const = 0; | ||||
// Returns true if this frame's function is system JavaScript running with | // Returns true if this frame's function is system JavaScript running with | ||||
// trusted principals, false otherwise. | // trusted principals, false otherwise. | ||||
virtual bool isSystem() const = 0; | virtual bool isSystem() const = 0; | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | public: | ||||
uint64_t identifier() const { | uint64_t identifier() const { | ||||
auto id = base()->identifier(); | auto id = base()->identifier(); | ||||
MOZ_ASSERT(JS::Value::isNumberRepresentable(id)); | MOZ_ASSERT(JS::Value::isNumberRepresentable(id)); | ||||
return id; | return id; | ||||
} | } | ||||
uint32_t line() const { return base()->line(); } | uint32_t line() const { return base()->line(); } | ||||
uint32_t column() const { return base()->column(); } | uint32_t column() const { return base()->column(); } | ||||
AtomOrTwoByteChars source() const { return base()->source(); } | AtomOrTwoByteChars source() const { return base()->source(); } | ||||
uint32_t sourceId() const { return base()->sourceId(); } | |||||
AtomOrTwoByteChars functionDisplayName() const { | AtomOrTwoByteChars functionDisplayName() const { | ||||
return base()->functionDisplayName(); | return base()->functionDisplayName(); | ||||
} | } | ||||
StackFrame parent() const { return base()->parent(); } | StackFrame parent() const { return base()->parent(); } | ||||
bool isSystem() const { return base()->isSystem(); } | bool isSystem() const { return base()->isSystem(); } | ||||
bool isSelfHosted(JSContext* cx) const { return base()->isSelfHosted(cx); } | bool isSelfHosted(JSContext* cx) const { return base()->isSelfHosted(cx); } | ||||
MOZ_MUST_USE bool constructSavedFrameStack( | MOZ_MUST_USE bool constructSavedFrameStack( | ||||
JSContext* cx, MutableHandleObject outSavedFrameStack) const { | JSContext* cx, MutableHandleObject outSavedFrameStack) const { | ||||
Show All 34 Lines | MOZ_MUST_USE bool constructSavedFrameStack( | ||||
return true; | return true; | ||||
} | } | ||||
uint32_t line() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | uint32_t line() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | ||||
uint32_t column() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | uint32_t column() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | ||||
AtomOrTwoByteChars source() const override { | AtomOrTwoByteChars source() const override { | ||||
MOZ_CRASH("null JS::ubi::StackFrame"); | MOZ_CRASH("null JS::ubi::StackFrame"); | ||||
} | } | ||||
uint32_t sourceId() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | |||||
AtomOrTwoByteChars functionDisplayName() const override { | AtomOrTwoByteChars functionDisplayName() const override { | ||||
MOZ_CRASH("null JS::ubi::StackFrame"); | MOZ_CRASH("null JS::ubi::StackFrame"); | ||||
} | } | ||||
StackFrame parent() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | StackFrame parent() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | ||||
bool isSystem() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | bool isSystem() const override { MOZ_CRASH("null JS::ubi::StackFrame"); } | ||||
bool isSelfHosted(JSContext* cx) const override { | bool isSelfHosted(JSContext* cx) const override { | ||||
MOZ_CRASH("null JS::ubi::StackFrame"); | MOZ_CRASH("null JS::ubi::StackFrame"); | ||||
} | } | ||||
Show All 18 Lines | |||||
// be reused for new variants. Doing so will cause inspecting ubi::Nodes backed | // be reused for new variants. Doing so will cause inspecting ubi::Nodes backed | ||||
// by an offline heap snapshot from an older SpiderMonkey/Firefox version to | // by an offline heap snapshot from an older SpiderMonkey/Firefox version to | ||||
// break. Consider this enum append only. | // break. Consider this enum append only. | ||||
enum class CoarseType : uint32_t { | enum class CoarseType : uint32_t { | ||||
Other = 0, | Other = 0, | ||||
Object = 1, | Object = 1, | ||||
Script = 2, | Script = 2, | ||||
String = 3, | String = 3, | ||||
DOMNode = 4, | |||||
FIRST = Other, | FIRST = Other, | ||||
LAST = String | LAST = DOMNode | ||||
}; | }; | ||||
inline uint32_t CoarseTypeToUint32(CoarseType type) { | inline uint32_t CoarseTypeToUint32(CoarseType type) { | ||||
return static_cast<uint32_t>(type); | return static_cast<uint32_t>(type); | ||||
} | } | ||||
inline bool Uint32IsValidCoarseType(uint32_t n) { | inline bool Uint32IsValidCoarseType(uint32_t n) { | ||||
auto first = static_cast<uint32_t>(CoarseType::FIRST); | auto first = static_cast<uint32_t>(CoarseType::FIRST); | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | public: | ||||
virtual js::UniquePtr<EdgeRange> edges(JSContext* cx, | virtual js::UniquePtr<EdgeRange> edges(JSContext* cx, | ||||
bool wantNames) const = 0; | bool wantNames) const = 0; | ||||
// Return the Zone to which this node's referent belongs, or nullptr if the | // Return the Zone to which this node's referent belongs, or nullptr if the | ||||
// referent is not of a type allocated in SpiderMonkey Zones. | // referent is not of a type allocated in SpiderMonkey Zones. | ||||
virtual JS::Zone* zone() const { return nullptr; } | virtual JS::Zone* zone() const { return nullptr; } | ||||
// Return the compartment for this node. Some ubi::Node referents are not | // Return the compartment for this node. Some ubi::Node referents are not | ||||
// associated with JSCompartments, such as JSStrings (which are associated | // associated with Compartments, such as JSStrings (which are associated | ||||
// with Zones). When the referent is not associated with a compartment, | // with Zones). When the referent is not associated with a compartment, | ||||
// nullptr is returned. | // nullptr is returned. | ||||
virtual JSCompartment* compartment() const { return nullptr; } | virtual JS::Compartment* compartment() const { return nullptr; } | ||||
// Return the realm for this node. Some ubi::Node referents are not | |||||
// associated with Realms, such as JSStrings (which are associated | |||||
// with Zones) or cross-compartment wrappers (which are associated with | |||||
// compartments). When the referent is not associated with a realm, | |||||
// nullptr is returned. | |||||
virtual JS::Realm* realm() const { return nullptr; } | |||||
// Return whether this node's referent's allocation stack was captured. | // Return whether this node's referent's allocation stack was captured. | ||||
virtual bool hasAllocationStack() const { return false; } | virtual bool hasAllocationStack() const { return false; } | ||||
// Get the stack recorded at the time this node's referent was | // Get the stack recorded at the time this node's referent was | ||||
// allocated. This must only be called when hasAllocationStack() is true. | // allocated. This must only be called when hasAllocationStack() is true. | ||||
virtual StackFrame allocationStack() const { | virtual StackFrame allocationStack() const { | ||||
MOZ_CRASH( | MOZ_CRASH( | ||||
"Concrete classes that have an allocation stack must override both " | "Concrete classes that have an allocation stack must override both " | ||||
"hasAllocationStack and allocationStack."); | "hasAllocationStack and allocationStack."); | ||||
} | } | ||||
// In some cases, Concrete<T> can return a more descriptive | |||||
// referent type name than simply `T`. This method returns an | |||||
// identifier as specific as is efficiently available. | |||||
// The string returned is borrowed from the ubi::Node's referent. | |||||
// If nothing more specific than typeName() is available, return nullptr. | |||||
virtual const char16_t* descriptiveTypeName() const { return nullptr; } | |||||
// Methods for JSObject Referents | // Methods for JSObject Referents | ||||
// | // | ||||
// These methods are only semantically valid if the referent is either a | // These methods are only semantically valid if the referent is either a | ||||
// JSObject in the live heap, or represents a previously existing JSObject | // JSObject in the live heap, or represents a previously existing JSObject | ||||
// from some deserialized heap snapshot. | // from some deserialized heap snapshot. | ||||
// Return the object's [[Class]]'s name. | // Return the object's [[Class]]'s name. | ||||
virtual const char* jsObjectClassName() const { return nullptr; } | virtual const char* jsObjectClassName() const { return nullptr; } | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | public: | ||||
template <typename T> | template <typename T> | ||||
bool is() const { | bool is() const { | ||||
return base()->typeName() == canonicalTypeName<T>(); | return base()->typeName() == canonicalTypeName<T>(); | ||||
} | } | ||||
template <typename T> | template <typename T> | ||||
T* as() const { | T* as() const { | ||||
MOZ_ASSERT(isLive()); | MOZ_ASSERT(isLive()); | ||||
MOZ_ASSERT(is<T>()); | MOZ_ASSERT(this->is<T>()); | ||||
return static_cast<T*>(base()->ptr); | return static_cast<T*>(base()->ptr); | ||||
} | } | ||||
template <typename T> | template <typename T> | ||||
T* asOrNull() const { | T* asOrNull() const { | ||||
MOZ_ASSERT(isLive()); | MOZ_ASSERT(isLive()); | ||||
return is<T>() ? static_cast<T*>(base()->ptr) : nullptr; | return this->is<T>() ? static_cast<T*>(base()->ptr) : nullptr; | ||||
} | } | ||||
// If this node refers to something that can be represented as a JavaScript | // If this node refers to something that can be represented as a JavaScript | ||||
// value that is safe to expose to JavaScript code, return that value. | // value that is safe to expose to JavaScript code, return that value. | ||||
// Otherwise return UndefinedValue(). JSStrings, JS::Symbols, and some (but | // Otherwise return UndefinedValue(). JSStrings, JS::Symbols, and some (but | ||||
// not all!) JSObjects can be exposed. | // not all!) JSObjects can be exposed. | ||||
JS::Value exposeToJS() const; | JS::Value exposeToJS() const; | ||||
CoarseType coarseType() const { return base()->coarseType(); } | CoarseType coarseType() const { return base()->coarseType(); } | ||||
const char16_t* typeName() const { return base()->typeName(); } | const char16_t* typeName() const { return base()->typeName(); } | ||||
JS::Zone* zone() const { return base()->zone(); } | JS::Zone* zone() const { return base()->zone(); } | ||||
JSCompartment* compartment() const { return base()->compartment(); } | JS::Compartment* compartment() const { return base()->compartment(); } | ||||
JS::Realm* realm() const { return base()->realm(); } | |||||
const char* jsObjectClassName() const { return base()->jsObjectClassName(); } | const char* jsObjectClassName() const { return base()->jsObjectClassName(); } | ||||
const char16_t* descriptiveTypeName() const { | |||||
return base()->descriptiveTypeName(); | |||||
} | |||||
MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, | MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, | ||||
UniqueTwoByteChars& outName) const { | UniqueTwoByteChars& outName) const { | ||||
return base()->jsObjectConstructorName(cx, outName); | return base()->jsObjectConstructorName(cx, outName); | ||||
} | } | ||||
const char* scriptFilename() const { return base()->scriptFilename(); } | const char* scriptFilename() const { return base()->scriptFilename(); } | ||||
using Size = Base::Size; | using Size = Base::Size; | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
class Edge { | class Edge { | ||||
public: | public: | ||||
Edge() : name(nullptr), referent() {} | Edge() : name(nullptr), referent() {} | ||||
// Construct an initialized Edge, taking ownership of |name|. | // Construct an initialized Edge, taking ownership of |name|. | ||||
Edge(char16_t* name, const Node& referent) : name(name), referent(referent) {} | Edge(char16_t* name, const Node& referent) : name(name), referent(referent) {} | ||||
// Move construction and assignment. | // Move construction and assignment. | ||||
Edge(Edge&& rhs) : name(mozilla::Move(rhs.name)), referent(rhs.referent) {} | Edge(Edge&& rhs) : name(std::move(rhs.name)), referent(rhs.referent) {} | ||||
Edge& operator=(Edge&& rhs) { | Edge& operator=(Edge&& rhs) { | ||||
MOZ_ASSERT(&rhs != this); | MOZ_ASSERT(&rhs != this); | ||||
this->~Edge(); | this->~Edge(); | ||||
new (this) Edge(mozilla::Move(rhs)); | new (this) Edge(std::move(rhs)); | ||||
return *this; | return *this; | ||||
} | } | ||||
Edge(const Edge&) = delete; | Edge(const Edge&) = delete; | ||||
Edge& operator=(const Edge&) = delete; | Edge& operator=(const Edge&) = delete; | ||||
// This edge's name. This may be nullptr, if Node::edges was called with | // This edge's name. This may be nullptr, if Node::edges was called with | ||||
// false as the wantNames parameter. | // false as the wantNames parameter. | ||||
// | // | ||||
// The storage is owned by this Edge, and will be freed when this Edge is | // The storage is owned by this Edge, and will be freed when this Edge is | ||||
// destructed. You may take ownership of the name by `mozilla::Move`ing it | // destructed. You may take ownership of the name by `std::move`ing it | ||||
// out of the edge; it is just a UniquePtr. | // out of the edge; it is just a UniquePtr. | ||||
// | // | ||||
// (In real life we'll want a better representation for names, to avoid | // (In real life we'll want a better representation for names, to avoid | ||||
// creating tons of strings when the names follow a pattern; and we'll need | // creating tons of strings when the names follow a pattern; and we'll need | ||||
// to think about lifetimes carefully to ensure traversal stays cheap.) | // to think about lifetimes carefully to ensure traversal stays cheap.) | ||||
EdgeName name; | EdgeName name; | ||||
// This edge's referent. | // This edge's referent. | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
// stable across GC. The init calls emplace on |noGC|'s AutoCheckCannotGC, whose | // stable across GC. The init calls emplace on |noGC|'s AutoCheckCannotGC, whose | ||||
// lifetime must extend at least as long as the RootList itself. | // lifetime must extend at least as long as the RootList itself. | ||||
// | // | ||||
// Example usage: | // Example usage: | ||||
// | // | ||||
// { | // { | ||||
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC; | // mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC; | ||||
// JS::ubi::RootList rootList(cx, maybeNoGC); | // JS::ubi::RootList rootList(cx, maybeNoGC); | ||||
// if (!rootList.init()) | // if (!rootList.init()) { | ||||
// return false; | // return false; | ||||
// } | |||||
// | // | ||||
// // The AutoCheckCannotGC is guaranteed to exist if init returned true. | // // The AutoCheckCannotGC is guaranteed to exist if init returned true. | ||||
// MOZ_ASSERT(maybeNoGC.isSome()); | // MOZ_ASSERT(maybeNoGC.isSome()); | ||||
// | // | ||||
// JS::ubi::Node root(&rootList); | // JS::ubi::Node root(&rootList); | ||||
// | // | ||||
// ... | // ... | ||||
// } | // } | ||||
class MOZ_STACK_CLASS JS_PUBLIC_API RootList { | class MOZ_STACK_CLASS JS_PUBLIC_API RootList { | ||||
Maybe<AutoCheckCannotGC>& noGC; | Maybe<AutoCheckCannotGC>& noGC; | ||||
public: | public: | ||||
JSContext* cx; | JSContext* cx; | ||||
EdgeVector edges; | EdgeVector edges; | ||||
bool wantNames; | bool wantNames; | ||||
RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, | RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, | ||||
bool wantNames = false); | bool wantNames = false); | ||||
// Find all GC roots. | // Find all GC roots. | ||||
MOZ_MUST_USE bool init(); | MOZ_MUST_USE bool init(); | ||||
// Find only GC roots in the provided set of |JSCompartment|s. | // Find only GC roots in the provided set of |JS::Compartment|s. Note: it's | ||||
// important to take a CompartmentSet and not a RealmSet: objects in | |||||
// same-compartment realms can reference each other directly, without going | |||||
// through CCWs, so if we used a RealmSet here we would miss edges. | |||||
MOZ_MUST_USE bool init(CompartmentSet& debuggees); | MOZ_MUST_USE bool init(CompartmentSet& debuggees); | ||||
// Find only GC roots in the given Debugger object's set of debuggee | // Find only GC roots in the given Debugger object's set of debuggee | ||||
// compartments. | // compartments. | ||||
MOZ_MUST_USE bool init(HandleObject debuggees); | MOZ_MUST_USE bool init(HandleObject debuggees); | ||||
// Returns true if the RootList has been initialized successfully, false | // Returns true if the RootList has been initialized successfully, false | ||||
// otherwise. | // otherwise. | ||||
bool initialized() { return noGC.isSome(); } | bool initialized() { return noGC.isSome(); } | ||||
Show All 22 Lines | public: | ||||
const char16_t* typeName() const override { return concreteTypeName; } | const char16_t* typeName() const override { return concreteTypeName; } | ||||
static const char16_t concreteTypeName[]; | static const char16_t concreteTypeName[]; | ||||
}; | }; | ||||
// A reusable ubi::Concrete specialization base class for types supported by | // A reusable ubi::Concrete specialization base class for types supported by | ||||
// JS::TraceChildren. | // JS::TraceChildren. | ||||
template <typename Referent> | template <typename Referent> | ||||
class JS_PUBLIC_API TracerConcrete : public Base { | class JS_PUBLIC_API TracerConcrete : public Base { | ||||
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override; | |||||
JS::Zone* zone() const override; | JS::Zone* zone() const override; | ||||
public: | |||||
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override; | |||||
protected: | protected: | ||||
explicit TracerConcrete(Referent* ptr) : Base(ptr) {} | explicit TracerConcrete(Referent* ptr) : Base(ptr) {} | ||||
Referent& get() const { return *static_cast<Referent*>(ptr); } | Referent& get() const { return *static_cast<Referent*>(ptr); } | ||||
}; | }; | ||||
// For JS::TraceChildren-based types that have a 'compartment' method. | // For JS::TraceChildren-based types that have 'realm' and 'compartment' | ||||
// methods. | |||||
template <typename Referent> | template <typename Referent> | ||||
class JS_PUBLIC_API TracerConcreteWithCompartment | class JS_PUBLIC_API TracerConcreteWithRealm : public TracerConcrete<Referent> { | ||||
: public TracerConcrete<Referent> { | |||||
typedef TracerConcrete<Referent> TracerBase; | typedef TracerConcrete<Referent> TracerBase; | ||||
JSCompartment* compartment() const override; | JS::Compartment* compartment() const override; | ||||
JS::Realm* realm() const override; | |||||
protected: | protected: | ||||
explicit TracerConcreteWithCompartment(Referent* ptr) : TracerBase(ptr) {} | explicit TracerConcreteWithRealm(Referent* ptr) : TracerBase(ptr) {} | ||||
}; | }; | ||||
// Define specializations for some commonly-used public JSAPI types. | // Define specializations for some commonly-used public JSAPI types. | ||||
// These can use the generic templates above. | // These can use the generic templates above. | ||||
template <> | template <> | ||||
class JS_PUBLIC_API Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { | class JS_PUBLIC_API Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { | ||||
protected: | protected: | ||||
explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) {} | explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) {} | ||||
public: | public: | ||||
static void construct(void* storage, JS::Symbol* ptr) { | static void construct(void* storage, JS::Symbol* ptr) { | ||||
new (storage) Concrete(ptr); | new (storage) Concrete(ptr); | ||||
} | } | ||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | ||||
const char16_t* typeName() const override { return concreteTypeName; } | const char16_t* typeName() const override { return concreteTypeName; } | ||||
static const char16_t concreteTypeName[]; | static const char16_t concreteTypeName[]; | ||||
}; | }; | ||||
template <> | template <> | ||||
class JS_PUBLIC_API Concrete<JSScript> | class JS_PUBLIC_API Concrete<JS::BigInt> : TracerConcrete<JS::BigInt> { | ||||
: TracerConcreteWithCompartment<JSScript> { | |||||
protected: | protected: | ||||
explicit Concrete(JSScript* ptr) | explicit Concrete(JS::BigInt* ptr) : TracerConcrete(ptr) {} | ||||
: TracerConcreteWithCompartment<JSScript>(ptr) {} | |||||
public: | |||||
static void construct(void* storage, JS::BigInt* 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 JS_PUBLIC_API Concrete<JSScript> : TracerConcreteWithRealm<JSScript> { | |||||
protected: | |||||
explicit Concrete(JSScript* ptr) : TracerConcreteWithRealm<JSScript>(ptr) {} | |||||
public: | public: | ||||
static void construct(void* storage, JSScript* ptr) { | static void construct(void* storage, JSScript* ptr) { | ||||
new (storage) Concrete(ptr); | new (storage) Concrete(ptr); | ||||
} | } | ||||
CoarseType coarseType() const final { return CoarseType::Script; } | CoarseType coarseType() const final { return CoarseType::Script; } | ||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | ||||
const char* scriptFilename() const final; | const char* scriptFilename() const final; | ||||
const char16_t* typeName() const override { return concreteTypeName; } | const char16_t* typeName() const override { return concreteTypeName; } | ||||
static const char16_t concreteTypeName[]; | static const char16_t concreteTypeName[]; | ||||
}; | }; | ||||
// The JSObject specialization. | // The JSObject specialization. | ||||
template <> | template <> | ||||
class JS_PUBLIC_API Concrete<JSObject> | class JS_PUBLIC_API Concrete<JSObject> : public TracerConcrete<JSObject> { | ||||
: public TracerConcreteWithCompartment<JSObject> { | |||||
protected: | protected: | ||||
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) {} | explicit Concrete(JSObject* ptr) : TracerConcrete<JSObject>(ptr) {} | ||||
public: | public: | ||||
static void construct(void* storage, JSObject* ptr) { | static void construct(void* storage, JSObject* ptr); | ||||
new (storage) Concrete(ptr); | |||||
} | JS::Compartment* compartment() const override; | ||||
JS::Realm* realm() const override; | |||||
const char* jsObjectClassName() const override; | const char* jsObjectClassName() const override; | ||||
MOZ_MUST_USE bool jsObjectConstructorName( | MOZ_MUST_USE bool jsObjectConstructorName( | ||||
JSContext* cx, UniqueTwoByteChars& outName) const override; | JSContext* cx, UniqueTwoByteChars& outName) const override; | ||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | ||||
bool hasAllocationStack() const override; | bool hasAllocationStack() const override; | ||||
StackFrame allocationStack() const override; | StackFrame allocationStack() const override; | ||||
Show All 26 Lines | |||||
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node | // The ubi::Node null pointer. Any attempt to operate on a null ubi::Node | ||||
// asserts. | // asserts. | ||||
template <> | template <> | ||||
class JS_PUBLIC_API Concrete<void> : public Base { | class JS_PUBLIC_API Concrete<void> : public Base { | ||||
const char16_t* typeName() const override; | const char16_t* typeName() const override; | ||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | Size size(mozilla::MallocSizeOf mallocSizeOf) const override; | ||||
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override; | js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override; | ||||
JS::Zone* zone() const override; | JS::Zone* zone() const override; | ||||
JSCompartment* compartment() const override; | JS::Compartment* compartment() const override; | ||||
JS::Realm* realm() const override; | |||||
CoarseType coarseType() const final; | CoarseType coarseType() const final; | ||||
explicit Concrete(void* ptr) : Base(ptr) {} | explicit Concrete(void* ptr) : Base(ptr) {} | ||||
public: | public: | ||||
static void construct(void* storage, void* ptr) { | static void construct(void* storage, void* ptr) { | ||||
new (storage) Concrete(ptr); | new (storage) Concrete(ptr); | ||||
} | } | ||||
}; | }; | ||||
// The |callback| callback is much like the |Concrete<T>::construct| method: a | |||||
// call to |callback| should construct an instance of the most appropriate | |||||
// JS::ubi::Base subclass for |obj| in |storage|. The callback may assume that | |||||
// |obj->getClass()->isDOMClass()|, and that |storage| refers to the | |||||
// sizeof(JS::ubi::Base) bytes of space that all ubi::Base implementations | |||||
// should require. | |||||
// Set |cx|'s runtime hook for constructing ubi::Nodes for DOM classes to | |||||
// |callback|. | |||||
void SetConstructUbiNodeForDOMObjectCallback(JSContext* cx, | |||||
void (*callback)(void*, | |||||
JSObject*)); | |||||
} // namespace ubi | } // namespace ubi | ||||
} // namespace JS | } // namespace JS | ||||
namespace js { | namespace mozilla { | ||||
// Make ubi::Node::HashPolicy the default hash policy for ubi::Node. | // Make ubi::Node::HashPolicy the default hash policy for ubi::Node. | ||||
template <> | template <> | ||||
struct DefaultHasher<JS::ubi::Node> : JS::ubi::Node::HashPolicy {}; | struct DefaultHasher<JS::ubi::Node> : JS::ubi::Node::HashPolicy {}; | ||||
template <> | template <> | ||||
struct DefaultHasher<JS::ubi::StackFrame> : JS::ubi::StackFrame::HashPolicy {}; | struct DefaultHasher<JS::ubi::StackFrame> : JS::ubi::StackFrame::HashPolicy {}; | ||||
} // namespace js | } // namespace mozilla | ||||
#endif // js_UbiNode_h | #endif // js_UbiNode_h |
Wildfire Games · Phabricator