mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1051115: Let users tell ubi::Edge not to provide edge names, as they're expensive to compute, and not everyone needs them. r=terrence
This commit is contained in:
parent
09c17f52c5
commit
b155d53d07
@ -198,7 +198,10 @@ class Base {
|
||||
// edges. The EdgeRange should be freed with 'js_delete'. (You could use
|
||||
// ScopedDJSeletePtr<EdgeRange> to manage it.) On OOM, report an exception
|
||||
// on |cx| and return nullptr.
|
||||
virtual EdgeRange *edges(JSContext *cx) const = 0;
|
||||
//
|
||||
// If wantNames is true, compute names for edges. Doing so can be expensive
|
||||
// in time and memory.
|
||||
virtual EdgeRange *edges(JSContext *cx, 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.
|
||||
@ -333,9 +336,11 @@ class Node {
|
||||
|
||||
const jschar *typeName() const { return base()->typeName(); }
|
||||
size_t size() const { return base()->size(); }
|
||||
EdgeRange *edges(JSContext *cx) const { return base()->edges(cx); }
|
||||
JS::Zone *zone() const { return base()->zone(); }
|
||||
JSCompartment *compartment() const { return base()->compartment(); }
|
||||
EdgeRange *edges(JSContext *cx, bool wantNames = true) const {
|
||||
return base()->edges(cx, wantNames);
|
||||
}
|
||||
|
||||
// A hash policy for ubi::Nodes.
|
||||
// This simply uses the stock PointerHasher on the ubi::Node's pointer.
|
||||
@ -365,7 +370,8 @@ class Edge {
|
||||
virtual ~Edge() { }
|
||||
|
||||
public:
|
||||
// This edge's name.
|
||||
// This edge's name. This may be nullptr, if Node::edges was called with
|
||||
// false as the wantNames parameter.
|
||||
//
|
||||
// The storage is owned by this Edge, and will be freed when this Edge is
|
||||
// destructed.
|
||||
@ -428,7 +434,7 @@ template<typename Referent>
|
||||
class TracerConcrete : public Base {
|
||||
const jschar *typeName() const MOZ_OVERRIDE { return concreteTypeName; }
|
||||
size_t size() const MOZ_OVERRIDE { return 0; } // not implemented yet; bug 1011300
|
||||
EdgeRange *edges(JSContext *) const MOZ_OVERRIDE;
|
||||
EdgeRange *edges(JSContext *, bool wantNames) const MOZ_OVERRIDE;
|
||||
JS::Zone *zone() const MOZ_OVERRIDE { return get().zone(); }
|
||||
JSCompartment *compartment() const MOZ_OVERRIDE { return nullptr; }
|
||||
|
||||
@ -472,7 +478,7 @@ template<>
|
||||
class Concrete<void> : public Base {
|
||||
const jschar *typeName() const MOZ_OVERRIDE;
|
||||
size_t size() const MOZ_OVERRIDE;
|
||||
EdgeRange *edges(JSContext *cx) const MOZ_OVERRIDE;
|
||||
EdgeRange *edges(JSContext *cx, bool wantNames) const MOZ_OVERRIDE;
|
||||
JS::Zone *zone() const MOZ_OVERRIDE;
|
||||
JSCompartment *compartment() const MOZ_OVERRIDE;
|
||||
|
||||
|
@ -84,7 +84,7 @@ struct BreadthFirst {
|
||||
// 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)
|
||||
: cx(cx), visited(cx), handler(handler), pending(cx),
|
||||
: wantNames(true), cx(cx), visited(cx), handler(handler), pending(cx),
|
||||
traversalBegun(false), stopRequested(false), abandonRequested(false)
|
||||
{ }
|
||||
|
||||
@ -95,6 +95,10 @@ struct BreadthFirst {
|
||||
// as many starting points as you like. Return false on OOM.
|
||||
bool addStart(Node node) { return pending.append(node); }
|
||||
|
||||
// True if the handler wants us to compute edge names; doing so can be
|
||||
// expensive in time and memory. True by default.
|
||||
bool wantNames;
|
||||
|
||||
// Traverse the graph in breadth-first order, starting at the given
|
||||
// start nodes, applying |handler::operator()| for each edge traversed
|
||||
// as described above.
|
||||
@ -113,7 +117,7 @@ struct BreadthFirst {
|
||||
pending.popFront();
|
||||
|
||||
// Get a range containing all origin's outgoing edges.
|
||||
js::ScopedJSDeletePtr<EdgeRange> range(origin.edges(cx));
|
||||
js::ScopedJSDeletePtr<EdgeRange> range(origin.edges(cx, wantNames));
|
||||
if (!range)
|
||||
return false;
|
||||
|
||||
|
@ -643,6 +643,7 @@ DebuggerMemory::takeCensus(JSContext *cx, unsigned argc, Value *vp)
|
||||
dbg::DefaultCensusTraversal traversal(cx, handler, noGC);
|
||||
if (!traversal.init())
|
||||
return false;
|
||||
traversal.wantNames = false;
|
||||
|
||||
// Walk the debuggee compartments, using it to set the starting points
|
||||
// (the debuggee globals) for the traversal, and to populate
|
||||
|
@ -28,11 +28,11 @@ using JS::ubi::Node;
|
||||
using JS::ubi::TracerConcrete;
|
||||
|
||||
// All operations on null ubi::Nodes crash.
|
||||
const jschar *Concrete<void>::typeName() const { MOZ_CRASH("null ubi::Node"); }
|
||||
size_t Concrete<void>::size() const { MOZ_CRASH("null ubi::Node"); }
|
||||
EdgeRange *Concrete<void>::edges(JSContext *) 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"); }
|
||||
const jschar *Concrete<void>::typeName() const { MOZ_CRASH("null ubi::Node"); }
|
||||
size_t Concrete<void>::size() const { MOZ_CRASH("null ubi::Node"); }
|
||||
EdgeRange *Concrete<void>::edges(JSContext *, bool) 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"); }
|
||||
|
||||
Node::Node(JSGCTraceKind kind, void *ptr)
|
||||
{
|
||||
@ -132,6 +132,9 @@ class SimpleEdgeVectorTracer : public JSTracer {
|
||||
// The vector to which we add SimpleEdges.
|
||||
SimpleEdgeVector *vec;
|
||||
|
||||
// True if we should populate the edge's names.
|
||||
bool wantNames;
|
||||
|
||||
static void staticCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind) {
|
||||
static_cast<SimpleEdgeVectorTracer *>(trc)->callback(thingp, kind);
|
||||
}
|
||||
@ -140,22 +143,25 @@ class SimpleEdgeVectorTracer : public JSTracer {
|
||||
if (!okay)
|
||||
return;
|
||||
|
||||
// Ask the tracer to compute an edge name for us.
|
||||
char buffer[1024];
|
||||
const char *name = getTracingEdgeName(buffer, sizeof(buffer));
|
||||
jschar *jsname = nullptr;
|
||||
if (wantNames) {
|
||||
// Ask the tracer to compute an edge name for us.
|
||||
char buffer[1024];
|
||||
const char *name = getTracingEdgeName(buffer, sizeof(buffer));
|
||||
|
||||
// Convert the name to jschars.
|
||||
jschar *jsname = js_pod_malloc<jschar>(strlen(name) + 1);
|
||||
if (!jsname) {
|
||||
okay = false;
|
||||
return;
|
||||
// Convert the name to jschars.
|
||||
jsname = js_pod_malloc<jschar>(strlen(name) + 1);
|
||||
if (!jsname) {
|
||||
okay = false;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; name[i]; i++)
|
||||
jsname[i] = name[i];
|
||||
jsname[i] = '\0';
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; name[i]; i++)
|
||||
jsname[i] = name[i];
|
||||
jsname[i] = '\0';
|
||||
|
||||
// The simplest code is correct! The temporary SimpleEdge takes
|
||||
// ownership of name; if the append succeeds, the vector element
|
||||
// then takes ownership; if the append fails, then the temporary
|
||||
@ -170,9 +176,12 @@ class SimpleEdgeVectorTracer : public JSTracer {
|
||||
// True if no errors (OOM, say) have yet occurred.
|
||||
bool okay;
|
||||
|
||||
SimpleEdgeVectorTracer(JSContext *cx, SimpleEdgeVector *vec)
|
||||
: JSTracer(JS_GetRuntime(cx), staticCallback), vec(vec), okay(true) {
|
||||
}
|
||||
SimpleEdgeVectorTracer(JSContext *cx, SimpleEdgeVector *vec, bool wantNames)
|
||||
: JSTracer(JS_GetRuntime(cx), staticCallback),
|
||||
vec(vec),
|
||||
wantNames(wantNames),
|
||||
okay(true)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@ -189,8 +198,8 @@ class SimpleEdgeRange : public EdgeRange {
|
||||
public:
|
||||
explicit SimpleEdgeRange(JSContext *cx) : edges(cx), i(0) { }
|
||||
|
||||
bool init(JSContext *cx, void *thing, JSGCTraceKind kind) {
|
||||
SimpleEdgeVectorTracer tracer(cx, &edges);
|
||||
bool init(JSContext *cx, void *thing, JSGCTraceKind kind, bool wantNames = true) {
|
||||
SimpleEdgeVectorTracer tracer(cx, &edges, wantNames);
|
||||
JS_TraceChildren(&tracer, thing, kind);
|
||||
settle();
|
||||
return tracer.okay;
|
||||
@ -202,12 +211,12 @@ class SimpleEdgeRange : public EdgeRange {
|
||||
|
||||
template<typename Referent>
|
||||
EdgeRange *
|
||||
TracerConcrete<Referent>::edges(JSContext *cx) const {
|
||||
TracerConcrete<Referent>::edges(JSContext *cx, bool wantNames) const {
|
||||
js::ScopedJSDeletePtr<SimpleEdgeRange> r(js_new<SimpleEdgeRange>(cx));
|
||||
if (!r)
|
||||
return nullptr;
|
||||
|
||||
if (!r->init(cx, ptr, ::js::gc::MapTypeToTraceKind<Referent>::kind))
|
||||
if (!r->init(cx, ptr, ::js::gc::MapTypeToTraceKind<Referent>::kind, wantNames))
|
||||
return nullptr;
|
||||
|
||||
return r.forget();
|
||||
|
Loading…
Reference in New Issue
Block a user