mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 02:25:34 +00:00
Bug 1182653 - Use JSRuntime* instead of JSContext* in ubi::Node infrastructure; r=sfink
This enables the use of ubi::Node in situations where a JSContext* is not available, and paves the way for debugging utilities to dump shortest paths from GC roots to a given ubi::Node that can be used while paused in a debugger.
This commit is contained in:
parent
407f41a2b0
commit
54a8708a3a
@ -108,8 +108,8 @@ class DeserializedEdgeRange : public EdgeRange
|
||||
}
|
||||
|
||||
public:
|
||||
explicit DeserializedEdgeRange(JSContext* cx)
|
||||
: edges(cx)
|
||||
explicit DeserializedEdgeRange()
|
||||
: edges()
|
||||
, i(0)
|
||||
{
|
||||
settle();
|
||||
@ -160,10 +160,10 @@ Concrete<DeserializedNode>::allocationStack() const
|
||||
|
||||
|
||||
UniquePtr<EdgeRange>
|
||||
Concrete<DeserializedNode>::edges(JSContext* cx, bool) const
|
||||
Concrete<DeserializedNode>::edges(JSRuntime* rt, bool) const
|
||||
{
|
||||
UniquePtr<DeserializedEdgeRange, JS::DeletePolicy<DeserializedEdgeRange>> range(
|
||||
js_new<DeserializedEdgeRange>(cx));
|
||||
js_new<DeserializedEdgeRange>());
|
||||
|
||||
if (!range || !range->init(get()))
|
||||
return nullptr;
|
||||
|
@ -265,7 +265,7 @@ public:
|
||||
|
||||
// We ignore the `bool wantNames` parameter because we can't control whether
|
||||
// the core dump was serialized with edge names or not.
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool) const override;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@ -384,7 +384,7 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
||||
JS::ubi::CensusTraversal traversal(cx, handler, nogc);
|
||||
JS::ubi::CensusTraversal traversal(JS_GetRuntime(cx), handler, nogc);
|
||||
if (NS_WARN_IF(!traversal.init())) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
@ -684,7 +684,7 @@ public:
|
||||
}
|
||||
|
||||
if (includeEdges) {
|
||||
auto edges = ubiNode.edges(cx, wantNames);
|
||||
auto edges = ubiNode.edges(JS_GetRuntime(cx), wantNames);
|
||||
if (NS_WARN_IF(!edges))
|
||||
return false;
|
||||
|
||||
@ -795,7 +795,7 @@ WriteHeapGraph(JSContext* cx,
|
||||
// core dump.
|
||||
|
||||
HeapSnapshotHandler handler(writer, zones);
|
||||
HeapSnapshotHandler::Traversal traversal(cx, handler, noGC);
|
||||
HeapSnapshotHandler::Traversal traversal(JS_GetRuntime(cx), handler, noGC);
|
||||
if (!traversal.init())
|
||||
return false;
|
||||
traversal.wantNames = wantNames;
|
||||
@ -960,7 +960,7 @@ ThreadSafeChromeUtils::SaveHeapSnapshot(GlobalObject& global,
|
||||
|
||||
{
|
||||
Maybe<AutoCheckCannotGC> maybeNoGC;
|
||||
ubi::RootList rootList(cx, maybeNoGC, wantNames);
|
||||
ubi::RootList rootList(JS_GetRuntime(cx), maybeNoGC, wantNames);
|
||||
if (!EstablishBoundaries(cx, rv, boundaries, rootList, zones))
|
||||
return;
|
||||
|
||||
|
@ -97,5 +97,5 @@ DEF_TEST(DeserializedNodeUbiNodes, {
|
||||
.Times(1)
|
||||
.WillOnce(Return(JS::ubi::Node(referent3.get())));
|
||||
|
||||
ubi.edges(cx);
|
||||
ubi.edges(JS_GetRuntime(cx));
|
||||
});
|
||||
|
@ -162,8 +162,8 @@ public:
|
||||
JS::Zone* zone;
|
||||
size_t size;
|
||||
|
||||
explicit FakeNode(JSContext* cx)
|
||||
: edges(cx),
|
||||
explicit FakeNode()
|
||||
: edges(),
|
||||
compartment(nullptr),
|
||||
zone(nullptr),
|
||||
size(1)
|
||||
@ -182,8 +182,8 @@ class Concrete<FakeNode> : public Base
|
||||
return concreteTypeName;
|
||||
}
|
||||
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override {
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(cx, get().edges));
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override {
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
|
||||
}
|
||||
|
||||
Size size(mozilla::MallocSizeOf) const override {
|
||||
@ -233,8 +233,8 @@ void AddEdge(FakeNode& node, FakeNode& referent, const char16_t* edgeName = null
|
||||
namespace testing {
|
||||
|
||||
// Ensure that given node has the expected number of edges.
|
||||
MATCHER_P2(EdgesLength, cx, expectedLength, "") {
|
||||
auto edges = arg.edges(cx);
|
||||
MATCHER_P2(EdgesLength, rt, expectedLength, "") {
|
||||
auto edges = arg.edges(rt);
|
||||
if (!edges)
|
||||
return false;
|
||||
|
||||
@ -247,8 +247,8 @@ MATCHER_P2(EdgesLength, cx, expectedLength, "") {
|
||||
}
|
||||
|
||||
// Get the nth edge and match it with the given matcher.
|
||||
MATCHER_P3(Edge, cx, n, matcher, "") {
|
||||
auto edges = arg.edges(cx);
|
||||
MATCHER_P3(Edge, rt, n, matcher, "") {
|
||||
auto edges = arg.edges(rt);
|
||||
if (!edges)
|
||||
return false;
|
||||
|
||||
|
@ -29,10 +29,10 @@ DEF_TEST(DoesCrossZoneBoundaries, {
|
||||
ASSERT_TRUE(targetZones.put(zone));
|
||||
ASSERT_TRUE(targetZones.put(newZone));
|
||||
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeD(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
FakeNode nodeD;
|
||||
|
||||
nodeA.zone = zone;
|
||||
nodeB.zone = nullptr;
|
||||
|
@ -29,9 +29,9 @@ DEF_TEST(DoesntCrossZoneBoundaries, {
|
||||
ASSERT_TRUE(targetZones.init());
|
||||
ASSERT_TRUE(targetZones.put(zone));
|
||||
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
|
||||
nodeA.zone = zone;
|
||||
nodeB.zone = nullptr;
|
||||
|
@ -13,8 +13,8 @@ using testing::Property;
|
||||
using testing::Return;
|
||||
|
||||
DEF_TEST(SerializesEdgeNames, {
|
||||
FakeNode node(cx);
|
||||
FakeNode referent(cx);
|
||||
FakeNode node;
|
||||
FakeNode referent;
|
||||
|
||||
const char16_t edgeName[] = MOZ_UTF16("edge name");
|
||||
const char16_t emptyStr[] = MOZ_UTF16("");
|
||||
@ -28,12 +28,12 @@ DEF_TEST(SerializesEdgeNames, {
|
||||
// Should get the node with edges once.
|
||||
EXPECT_CALL(
|
||||
writer,
|
||||
writeNode(AllOf(EdgesLength(cx, 3),
|
||||
Edge(cx, 0, Field(&JS::ubi::Edge::name,
|
||||
writeNode(AllOf(EdgesLength(rt, 3),
|
||||
Edge(rt, 0, Field(&JS::ubi::Edge::name,
|
||||
UTF16StrEq(edgeName))),
|
||||
Edge(cx, 1, Field(&JS::ubi::Edge::name,
|
||||
Edge(rt, 1, Field(&JS::ubi::Edge::name,
|
||||
UTF16StrEq(emptyStr))),
|
||||
Edge(cx, 2, Field(&JS::ubi::Edge::name,
|
||||
Edge(rt, 2, Field(&JS::ubi::Edge::name,
|
||||
IsNull()))),
|
||||
_)
|
||||
)
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include "DevTools.h"
|
||||
|
||||
DEF_TEST(SerializesEverythingInHeapGraphOnce, {
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeD(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
FakeNode nodeD;
|
||||
|
||||
AddEdge(nodeA, nodeB);
|
||||
AddEdge(nodeB, nodeC);
|
||||
|
@ -11,7 +11,7 @@ using testing::Property;
|
||||
using testing::Return;
|
||||
|
||||
DEF_TEST(SerializesTypeNames, {
|
||||
FakeNode node(cx);
|
||||
FakeNode node;
|
||||
|
||||
::testing::NiceMock<MockWriter> writer;
|
||||
EXPECT_CALL(writer, writeNode(Property(&JS::ubi::Node::typeName,
|
||||
|
@ -569,7 +569,7 @@ class Base {
|
||||
//
|
||||
// If wantNames is true, compute names for edges. Doing so can be expensive
|
||||
// in time and memory.
|
||||
virtual UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
|
||||
virtual UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
|
||||
|
||||
// Return the Zone to which this node's referent belongs, or nullptr if the
|
||||
// referent is not of a type allocated in SpiderMonkey Zones.
|
||||
@ -756,8 +756,8 @@ class Node {
|
||||
return base()->size(mallocSizeof);
|
||||
}
|
||||
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
|
||||
return base()->edges(cx, wantNames);
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
|
||||
return base()->edges(rt, wantNames);
|
||||
}
|
||||
|
||||
bool hasAllocationStack() const { return base()->hasAllocationStack(); }
|
||||
@ -868,7 +868,7 @@ class EdgeRange {
|
||||
};
|
||||
|
||||
|
||||
typedef mozilla::Vector<Edge, 8, js::TempAllocPolicy> EdgeVector;
|
||||
typedef mozilla::Vector<Edge, 8, js::SystemAllocPolicy> EdgeVector;
|
||||
|
||||
// An EdgeRange concrete class that holds a pre-existing vector of
|
||||
// Edges. A PreComputedEdgeRange does not take ownership of its
|
||||
@ -883,7 +883,7 @@ class PreComputedEdgeRange : public EdgeRange {
|
||||
}
|
||||
|
||||
public:
|
||||
explicit PreComputedEdgeRange(JSContext* cx, EdgeVector& edges)
|
||||
explicit PreComputedEdgeRange(EdgeVector& edges)
|
||||
: edges(edges),
|
||||
i(0)
|
||||
{
|
||||
@ -916,7 +916,7 @@ class PreComputedEdgeRange : public EdgeRange {
|
||||
//
|
||||
// {
|
||||
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
|
||||
// JS::ubi::RootList rootList(cx, maybeNoGC);
|
||||
// JS::ubi::RootList rootList(rt, maybeNoGC);
|
||||
// if (!rootList.init())
|
||||
// return false;
|
||||
//
|
||||
@ -929,13 +929,13 @@ class PreComputedEdgeRange : public EdgeRange {
|
||||
// }
|
||||
class MOZ_STACK_CLASS RootList {
|
||||
Maybe<AutoCheckCannotGC>& noGC;
|
||||
JSContext* cx;
|
||||
|
||||
public:
|
||||
JSRuntime* rt;
|
||||
EdgeVector edges;
|
||||
bool wantNames;
|
||||
|
||||
RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
|
||||
RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
|
||||
|
||||
// Find all GC roots.
|
||||
bool init();
|
||||
@ -959,7 +959,7 @@ class MOZ_STACK_CLASS RootList {
|
||||
|
||||
template<>
|
||||
struct Concrete<RootList> : public Base {
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
const char16_t* typeName() const override { return concreteTypeName; }
|
||||
|
||||
protected:
|
||||
@ -976,7 +976,7 @@ struct Concrete<RootList> : public Base {
|
||||
template<typename Referent>
|
||||
class TracerConcrete : public Base {
|
||||
const char16_t* typeName() const override { return concreteTypeName; }
|
||||
UniquePtr<EdgeRange> edges(JSContext*, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
JS::Zone* zone() const override;
|
||||
|
||||
protected:
|
||||
@ -1069,7 +1069,7 @@ template<>
|
||||
class Concrete<void> : public Base {
|
||||
const char16_t* typeName() const override;
|
||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
JS::Zone* zone() const override;
|
||||
JSCompartment* compartment() const override;
|
||||
CoarseType coarseType() const final;
|
||||
|
@ -78,13 +78,13 @@ template<typename Handler>
|
||||
struct BreadthFirst {
|
||||
|
||||
// Construct a breadth-first traversal object that reports the nodes it
|
||||
// reaches to |handler|. The traversal object reports OOM on |cx|, and
|
||||
// asserts that no GC happens in |cx|'s runtime during its lifetime.
|
||||
// reaches to |handler|. The traversal asserts that no GC happens in its
|
||||
// runtime during its lifetime.
|
||||
//
|
||||
// We do nothing with noGC, other than require it to exist, with a lifetime
|
||||
// that encloses our own.
|
||||
BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
|
||||
: wantNames(true), cx(cx), visited(cx), handler(handler), pending(cx),
|
||||
BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
|
||||
: wantNames(true), rt(rt), visited(), handler(handler), pending(),
|
||||
traversalBegun(false), stopRequested(false), abandonRequested(false)
|
||||
{ }
|
||||
|
||||
@ -126,7 +126,7 @@ struct BreadthFirst {
|
||||
pending.popFront();
|
||||
|
||||
// Get a range containing all origin's outgoing edges.
|
||||
auto range = origin.edges(cx, wantNames);
|
||||
auto range = origin.edges(rt, wantNames);
|
||||
if (!range)
|
||||
return false;
|
||||
|
||||
@ -181,13 +181,14 @@ struct BreadthFirst {
|
||||
// Other edges *to* that referent will still be traversed.
|
||||
void abandonReferent() { abandonRequested = true; }
|
||||
|
||||
// The context with which we were constructed.
|
||||
JSContext* cx;
|
||||
// The runtime with which we were constructed.
|
||||
JSRuntime* rt;
|
||||
|
||||
// A map associating each node N that we have reached with a
|
||||
// Handler::NodeData, for |handler|'s use. This is public, so that
|
||||
// |handler| can access it to see the traversal thus far.
|
||||
typedef js::HashMap<Node, typename Handler::NodeData> NodeMap;
|
||||
using NodeMap = js::HashMap<Node, typename Handler::NodeData, js::DefaultHasher<Node>,
|
||||
js::SystemAllocPolicy>;
|
||||
NodeMap visited;
|
||||
|
||||
private:
|
||||
@ -199,10 +200,10 @@ struct BreadthFirst {
|
||||
// current population.
|
||||
template <typename T>
|
||||
class Queue {
|
||||
js::Vector<T, 0> head, tail;
|
||||
js::Vector<T, 0, js::SystemAllocPolicy> head, tail;
|
||||
size_t frontIndex;
|
||||
public:
|
||||
explicit Queue(JSContext* cx) : head(cx), tail(cx), frontIndex(0) { }
|
||||
Queue() : head(), tail(), frontIndex(0) { }
|
||||
bool empty() { return frontIndex >= head.length(); }
|
||||
T& front() {
|
||||
MOZ_ASSERT(!empty());
|
||||
|
@ -2127,9 +2127,9 @@ struct FindPathHandler {
|
||||
typedef BackEdge NodeData;
|
||||
typedef JS::ubi::BreadthFirst<FindPathHandler> Traversal;
|
||||
|
||||
FindPathHandler(JS::ubi::Node start, JS::ubi::Node target,
|
||||
FindPathHandler(JSContext*cx, JS::ubi::Node start, JS::ubi::Node target,
|
||||
AutoValueVector& nodes, Vector<EdgeName>& edges)
|
||||
: start(start), target(target), foundPath(false),
|
||||
: cx(cx), start(start), target(target), foundPath(false),
|
||||
nodes(nodes), edges(edges) { }
|
||||
|
||||
bool
|
||||
@ -2143,7 +2143,7 @@ struct FindPathHandler {
|
||||
|
||||
// Record how we reached this node. This is the last edge on a
|
||||
// shortest path to this node.
|
||||
EdgeName edgeName = DuplicateString(traversal.cx, edge.name);
|
||||
EdgeName edgeName = DuplicateString(cx, edge.name);
|
||||
if (!edgeName)
|
||||
return false;
|
||||
*backEdge = mozilla::Move(BackEdge(origin, Move(edgeName)));
|
||||
@ -2180,6 +2180,8 @@ struct FindPathHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
JSContext* cx;
|
||||
|
||||
// The node we're starting from.
|
||||
JS::ubi::Node start;
|
||||
|
||||
@ -2238,8 +2240,8 @@ FindPath(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
JS::ubi::Node start(args[0]), target(args[1]);
|
||||
|
||||
heaptools::FindPathHandler handler(start, target, nodes, edges);
|
||||
heaptools::FindPathHandler::Traversal traversal(cx, handler, autoCannotGC);
|
||||
heaptools::FindPathHandler handler(cx, start, target, nodes, edges);
|
||||
heaptools::FindPathHandler::Traversal traversal(cx->runtime(), handler, autoCannotGC);
|
||||
if (!traversal.init() || !traversal.addStart(start))
|
||||
return false;
|
||||
|
||||
|
@ -4543,6 +4543,17 @@ js::DuplicateString(js::ExclusiveContext* cx, const char16_t* s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniquePtr<char16_t[], JS::FreePolicy>
|
||||
js::DuplicateString(const char16_t* s)
|
||||
{
|
||||
size_t n = js_strlen(s) + 1;
|
||||
UniquePtr<char16_t[], JS::FreePolicy> ret(js_pod_malloc<char16_t>(n));
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
PodCopy(ret.get(), s, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
const CharT*
|
||||
js_strchr_limit(const CharT* s, char16_t c, const CharT* limit)
|
||||
|
@ -129,6 +129,11 @@ DuplicateString(ExclusiveContext* cx, const char* s);
|
||||
extern mozilla::UniquePtr<char16_t[], JS::FreePolicy>
|
||||
DuplicateString(ExclusiveContext* cx, const char16_t* s);
|
||||
|
||||
// This variant does not report OOMs, you must arrange for OOMs to be reported
|
||||
// yourself.
|
||||
extern mozilla::UniquePtr<char16_t[], JS::FreePolicy>
|
||||
DuplicateString(const char16_t* s);
|
||||
|
||||
/*
|
||||
* Convert a non-string value to a string, returning null after reporting an
|
||||
* error, otherwise returning a new string reference.
|
||||
|
@ -4049,13 +4049,17 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||
*/
|
||||
Maybe<JS::AutoCheckCannotGC> maybeNoGC;
|
||||
RootedObject dbgObj(cx, dbg->object);
|
||||
JS::ubi::RootList rootList(cx, maybeNoGC);
|
||||
if (!rootList.init(dbgObj))
|
||||
JS::ubi::RootList rootList(cx->runtime(), maybeNoGC);
|
||||
if (!rootList.init(dbgObj)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
Traversal traversal(cx, *this, maybeNoGC.ref());
|
||||
if (!traversal.init())
|
||||
Traversal traversal(cx->runtime(), *this, maybeNoGC.ref());
|
||||
if (!traversal.init()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
traversal.wantNames = false;
|
||||
|
||||
return traversal.addStart(JS::ubi::Node(&rootList)) &&
|
||||
|
@ -540,18 +540,23 @@ DebuggerMemory::takeCensus(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
{
|
||||
Maybe<JS::AutoCheckCannotGC> maybeNoGC;
|
||||
JS::ubi::RootList rootList(cx, maybeNoGC);
|
||||
if (!rootList.init(dbgObj))
|
||||
JS::ubi::RootList rootList(cx->runtime(), maybeNoGC);
|
||||
if (!rootList.init(dbgObj)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::ubi::CensusTraversal traversal(cx, handler, maybeNoGC.ref());
|
||||
if (!traversal.init())
|
||||
JS::ubi::CensusTraversal traversal(cx->runtime(), handler, maybeNoGC.ref());
|
||||
if (!traversal.init()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
traversal.wantNames = false;
|
||||
|
||||
if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
|
||||
!traversal.traverse())
|
||||
{
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ JS::Zone* Concrete<void>::zone() const { MOZ_CRASH("null ubi::Node")
|
||||
JSCompartment* Concrete<void>::compartment() const { MOZ_CRASH("null ubi::Node"); }
|
||||
|
||||
UniquePtr<EdgeRange>
|
||||
Concrete<void>::edges(JSContext*, bool) const {
|
||||
Concrete<void>::edges(JSRuntime*, bool) const {
|
||||
MOZ_CRASH("null ubi::Node");
|
||||
}
|
||||
|
||||
@ -255,8 +255,8 @@ class EdgeVectorTracer : public JS::CallbackTracer {
|
||||
// True if no errors (OOM, say) have yet occurred.
|
||||
bool okay;
|
||||
|
||||
EdgeVectorTracer(JSContext* cx, EdgeVector* vec, bool wantNames)
|
||||
: JS::CallbackTracer(JS_GetRuntime(cx)),
|
||||
EdgeVectorTracer(JSRuntime* rt, EdgeVector* vec, bool wantNames)
|
||||
: JS::CallbackTracer(rt),
|
||||
vec(vec),
|
||||
wantNames(wantNames),
|
||||
okay(true)
|
||||
@ -275,10 +275,10 @@ class SimpleEdgeRange : public EdgeRange {
|
||||
}
|
||||
|
||||
public:
|
||||
explicit SimpleEdgeRange(JSContext* cx) : edges(cx), i(0) { }
|
||||
explicit SimpleEdgeRange() : edges(), i(0) { }
|
||||
|
||||
bool init(JSContext* cx, void* thing, JS::TraceKind kind, bool wantNames = true) {
|
||||
EdgeVectorTracer tracer(cx, &edges, wantNames);
|
||||
bool init(JSRuntime* rt, void* thing, JS::TraceKind kind, bool wantNames = true) {
|
||||
EdgeVectorTracer tracer(rt, &edges, wantNames);
|
||||
js::TraceChildren(&tracer, thing, kind);
|
||||
settle();
|
||||
return tracer.okay;
|
||||
@ -297,13 +297,12 @@ TracerConcrete<Referent>::zone() const
|
||||
|
||||
template<typename Referent>
|
||||
UniquePtr<EdgeRange>
|
||||
TracerConcrete<Referent>::edges(JSContext* cx, bool wantNames) const {
|
||||
UniquePtr<SimpleEdgeRange, JS::DeletePolicy<SimpleEdgeRange>> range(
|
||||
cx->new_<SimpleEdgeRange>(cx));
|
||||
TracerConcrete<Referent>::edges(JSRuntime* rt, bool wantNames) const {
|
||||
UniquePtr<SimpleEdgeRange, JS::DeletePolicy<SimpleEdgeRange>> range(js_new<SimpleEdgeRange>());
|
||||
if (!range)
|
||||
return nullptr;
|
||||
|
||||
if (!range->init(cx, ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
if (!range->init(rt, ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
return nullptr;
|
||||
|
||||
return UniquePtr<EdgeRange>(range.release());
|
||||
@ -395,10 +394,10 @@ template class TracerConcrete<js::ObjectGroup>;
|
||||
namespace JS {
|
||||
namespace ubi {
|
||||
|
||||
RootList::RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames /* = false */)
|
||||
RootList::RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames /* = false */)
|
||||
: noGC(noGC),
|
||||
cx(cx),
|
||||
edges(cx),
|
||||
rt(rt),
|
||||
edges(),
|
||||
wantNames(wantNames)
|
||||
{ }
|
||||
|
||||
@ -406,19 +405,19 @@ RootList::RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames
|
||||
bool
|
||||
RootList::init()
|
||||
{
|
||||
EdgeVectorTracer tracer(cx, &edges, wantNames);
|
||||
EdgeVectorTracer tracer(rt, &edges, wantNames);
|
||||
JS_TraceRuntime(&tracer);
|
||||
if (!tracer.okay)
|
||||
return false;
|
||||
noGC.emplace(cx->runtime());
|
||||
noGC.emplace(rt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RootList::init(ZoneSet& debuggees)
|
||||
{
|
||||
EdgeVector allRootEdges(cx);
|
||||
EdgeVectorTracer tracer(cx, &allRootEdges, wantNames);
|
||||
EdgeVector allRootEdges;
|
||||
EdgeVectorTracer tracer(rt, &allRootEdges, wantNames);
|
||||
|
||||
JS_TraceRuntime(&tracer);
|
||||
if (!tracer.okay)
|
||||
@ -436,7 +435,7 @@ RootList::init(ZoneSet& debuggees)
|
||||
return false;
|
||||
}
|
||||
|
||||
noGC.emplace(cx->runtime());
|
||||
noGC.emplace(rt);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -478,7 +477,7 @@ RootList::addRoot(Node node, const char16_t* edgeName)
|
||||
|
||||
UniquePtr<char16_t[], JS::FreePolicy> name;
|
||||
if (edgeName) {
|
||||
name = DuplicateString(cx, edgeName);
|
||||
name = DuplicateString(edgeName);
|
||||
if (!name)
|
||||
return false;
|
||||
}
|
||||
@ -489,9 +488,9 @@ RootList::addRoot(Node node, const char16_t* edgeName)
|
||||
const char16_t Concrete<RootList>::concreteTypeName[] = MOZ_UTF16("RootList");
|
||||
|
||||
UniquePtr<EdgeRange>
|
||||
Concrete<RootList>::edges(JSContext* cx, bool wantNames) const {
|
||||
Concrete<RootList>::edges(JSRuntime* rt, bool wantNames) const {
|
||||
MOZ_ASSERT_IF(wantNames, get().wantNames);
|
||||
return UniquePtr<EdgeRange>(cx->new_<PreComputedEdgeRange>(cx, get().edges));
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
|
||||
}
|
||||
|
||||
} // namespace ubi
|
||||
|
Loading…
Reference in New Issue
Block a user