Backed out changeset 0064d8949f0c (
bug 1102541) for build bustage on a CLOSED TREE
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -467,55 +467,49 @@ typedef mozilla::Vector<SimpleEdge, 8, j
// runtime. Having a single root |ubi::Node| is useful for algorithms written
// with the assumption that there aren't multiple roots (such as computing
// dominator trees) and you want a single point of entry. It also ensures that
// the roots themselves get visited by |ubi::BreadthFirst| (they would otherwise
// only be used as starting points).
//
// RootList::init itself causes a minor collection, but once the list of roots
// has been created, GC must not occur, as the referent ubi::Nodes are not
-// stable across GC. The init calls emplace on |noGC|'s AutoCheckCannotGC, whose
+// stable across GC. The init calls emplace |gcp|'s AutoCheckCannotGC, whose
// lifetime must extend at least as long as the RootList itself.
//
// Example usage:
//
// {
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
// JS::ubi::RootList rootList(cx, maybeNoGC);
-// if (!rootList.init())
+// if (!rootList.init(cx))
// return false;
//
// // The AutoCheckCannotGC is guaranteed to exist if init returned true.
// MOZ_ASSERT(maybeNoGC.isSome());
//
// JS::ubi::Node root(&rootList);
//
// ...
// }
class MOZ_STACK_CLASS RootList {
Maybe<AutoCheckCannotGC> &noGC;
- JSContext *cx;
public:
SimpleEdgeVector edges;
bool wantNames;
RootList(JSContext *cx, Maybe<AutoCheckCannotGC> &noGC, bool wantNames = false);
// Find all GC roots.
- bool init();
+ bool init(JSContext *cx);
// Find only GC roots in the provided set of |Zone|s.
- bool init(ZoneSet &debuggees);
+ bool init(JSContext *cx, ZoneSet &debuggees);
// Find only GC roots in the given Debugger object's set of debuggee zones.
- bool init(HandleObject debuggees);
-
- // Explicitly add the given Node as a root in this RootList. If wantNames is
- // true, you must pass an edgeName. The RootList does not take ownership of
- // edgeName.
- bool addRoot(Node node, const char16_t *edgeName = nullptr);
+ bool init(JSContext *cx, HandleObject debuggees);
};
// Concrete classes for ubi::Node referent types.
template<>
struct Concrete<RootList> : public Base {
EdgeRange *edges(JSContext *cx, bool wantNames) const MOZ_OVERRIDE;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3554,25 +3554,33 @@ class MOZ_STACK_CLASS Debugger::ObjectQu
/*
* Traverse the heap to find all relevant objects and add them to the
* provided vector.
*/
bool findObjects(AutoObjectVector &objs) {
if (!prepareQuery())
return false;
+ // Ensure that all of our debuggee globals are rooted so that they are
+ // visible in the RootList.
+ JS::AutoObjectVector debuggees(cx);
+ for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
+ if (!debuggees.append(r.front()))
+ return false;
+ }
+
{
/*
* We can't tolerate the GC moving things around while we're
* searching the heap. Check that nothing we do causes a GC.
*/
Maybe<JS::AutoCheckCannotGC> maybeNoGC;
RootedObject dbgObj(cx, dbg->object);
JS::ubi::RootList rootList(cx, maybeNoGC);
- if (!rootList.init(dbgObj))
+ if (!rootList.init(cx, dbgObj))
return false;
Traversal traversal(cx, *this, maybeNoGC.ref());
if (!traversal.init())
return false;
traversal.wantNames = false;
if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -752,28 +752,32 @@ DebuggerMemory::takeCensus(JSContext *cx
if (!census.init())
return false;
dbg::DefaultCensusHandler handler(census);
if (!handler.init(census))
return false;
Debugger *dbg = memory->getDebugger();
- RootedObject dbgObj(cx, dbg->object);
- // Populate our target set of debuggee zones.
+ // Populate census.debuggeeZones and ensure that all of our debuggee globals
+ // are rooted so that they are visible in the RootList.
+ JS::AutoObjectVector debuggees(cx);
for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
- if (!census.debuggeeZones.put(r.front()->zone()))
+ if (!census.debuggeeZones.put(r.front()->zone()) ||
+ !debuggees.append(static_cast<JSObject *>(r.front())))
+ {
return false;
+ }
}
{
Maybe<JS::AutoCheckCannotGC> maybeNoGC;
JS::ubi::RootList rootList(cx, maybeNoGC);
- if (!rootList.init(dbgObj))
+ if (!rootList.init(cx, census.debuggeeZones))
return false;
dbg::DefaultCensusTraversal traversal(cx, handler, maybeNoGC.ref());
if (!traversal.init())
return false;
traversal.wantNames = false;
if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
--- a/js/src/vm/UbiNode.cpp
+++ b/js/src/vm/UbiNode.cpp
@@ -4,23 +4,21 @@
* 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/. */
#include "js/UbiNode.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Scoped.h"
-#include "mozilla/UniquePtr.h"
#include "jscntxt.h"
#include "jsinfer.h"
#include "jsobj.h"
#include "jsscript.h"
-#include "jsstr.h"
#include "jit/IonCode.h"
#include "js/Debug.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
#include "js/Vector.h"
#include "vm/GlobalObject.h"
@@ -260,35 +258,34 @@ template class TracerConcrete<js::types:
}
namespace JS {
namespace ubi {
RootList::RootList(JSContext *cx, Maybe<AutoCheckCannotGC> &noGC, bool wantNames /* = false */)
: noGC(noGC),
- cx(cx),
edges(cx),
wantNames(wantNames)
{ }
bool
-RootList::init()
+RootList::init(JSContext *cx)
{
SimpleEdgeVectorTracer tracer(cx, &edges, wantNames);
JS_TraceRuntime(&tracer);
if (!tracer.okay)
return false;
noGC.emplace(cx->runtime());
return true;
}
bool
-RootList::init(ZoneSet &debuggees)
+RootList::init(JSContext *cx, ZoneSet &debuggees)
{
SimpleEdgeVector allRootEdges(cx);
SimpleEdgeVectorTracer tracer(cx, &allRootEdges, wantNames);
JS_TraceRuntime(&tracer);
if (!tracer.okay)
return false;
JS_TraceIncomingCCWs(&tracer, debuggees);
@@ -304,59 +301,31 @@ RootList::init(ZoneSet &debuggees)
return false;
}
noGC.emplace(cx->runtime());
return true;
}
bool
-RootList::init(HandleObject debuggees)
+RootList::init(JSContext *cx, HandleObject debuggees)
{
MOZ_ASSERT(debuggees && JS::dbg::IsDebugger(ObjectValue(*debuggees)));
js::Debugger *dbg = js::Debugger::fromJSObject(debuggees);
ZoneSet debuggeeZones;
if (!debuggeeZones.init())
return false;
for (js::GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
if (!debuggeeZones.put(r.front()->zone()))
return false;
}
- if (!init(debuggeeZones))
- return false;
-
- // Ensure that each of our debuggee globals are in the root list.
- for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
- if (!addRoot(JS::ubi::Node(static_cast<JSObject *>(r.front())),
- MOZ_UTF16("debuggee global")))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool
-RootList::addRoot(Node node, const char16_t *edgeName)
-{
- MOZ_ASSERT(noGC.isSome());
- MOZ_ASSERT_IF(wantNames, edgeName);
-
- mozilla::UniquePtr<char16_t[], JS::FreePolicy> name;
- if (edgeName) {
- name = DuplicateString(cx, edgeName);
- if (!name)
- return false;
- }
-
- return edges.append(mozilla::Move(SimpleEdge(name.release(), node)));
+ return init(cx, debuggeeZones);
}
// An EdgeRange concrete class that holds a pre-existing vector of SimpleEdges.
class PreComputedEdgeRange : public EdgeRange {
SimpleEdgeVector &edges;
size_t i;
void settle() {