Bug 1137478 - Add a read barrier for Debugger::debuggees r=terrence

This commit is contained in:
Jon Coppeard 2015-03-04 10:25:07 +00:00
Родитель 63c7f31b12
Коммит 979e646fd3
5 изменённых файлов: 47 добавлений и 24 удалений

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

@ -682,7 +682,7 @@ struct HeapPtrHasher
/* Specialized hashing policy for HeapPtrs. */
template <class T>
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
struct DefaultHasher<HeapPtr<T>> : HeapPtrHasher<T> { };
template <class T>
struct PreBarrieredHasher
@ -696,7 +696,7 @@ struct PreBarrieredHasher
};
template <class T>
struct DefaultHasher< PreBarriered<T> > : PreBarrieredHasher<T> { };
struct DefaultHasher<PreBarriered<T>> : PreBarrieredHasher<T> { };
/*
* Incremental GC requires that weak pointers have read barriers. This is mostly
@ -740,6 +740,22 @@ class ReadBarriered
void set(T v) { value = v; }
};
/* Useful for hashtables with a ReadBarriered as key. */
template <class T>
struct ReadBarrieredHasher
{
typedef ReadBarriered<T> Key;
typedef T Lookup;
static HashNumber hash(Lookup obj) { return DefaultHasher<T>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
static void rekey(Key &k, const Key& newKey) { k.set(newKey); }
};
/* Specialized hashing policy for ReadBarriereds. */
template <class T>
struct DefaultHasher<ReadBarriered<T>> : ReadBarrieredHasher<T> { };
class ArrayObject;
class ArrayBufferObject;
class NestedScopeObject;

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

@ -2048,7 +2048,7 @@ Debugger::updateObservesAllExecutionOnDebuggees(JSContext *cx, IsObserving obser
if (!obs.init())
return false;
for (GlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject *global = r.front();
JSCompartment *comp = global->compartment();
@ -2069,7 +2069,7 @@ Debugger::updateObservesAllExecutionOnDebuggees(JSContext *cx, IsObserving obser
void
Debugger::updateObservesAsmJSOnDebuggees(IsObserving observing)
{
for (GlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject *global = r.front();
JSCompartment *comp = global->compartment();
@ -2212,12 +2212,12 @@ Debugger::markAll(JSTracer *trc)
{
JSRuntime *rt = trc->runtime();
for (Debugger *dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
GlobalObjectSet &debuggees = dbg->debuggees;
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
WeakGlobalObjectSet &debuggees = dbg->debuggees;
for (WeakGlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
GlobalObject *global = e.front();
MarkObjectUnbarriered(trc, &global, "Global Object");
if (global != e.front())
e.rekeyFront(global);
e.rekeyFront(ReadBarrieredGlobalObject(global));
}
HeapPtrNativeObject &dbgobj = dbg->toJSObjectRef();
@ -2295,7 +2295,7 @@ Debugger::sweepAll(FreeOp *fop)
* might be GC'd too. Since detaching requires access to both
* objects, this must be done before finalize time.
*/
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
dbg->removeDebuggeeGlobal(fop, e.front(), &e);
}
}
@ -2625,7 +2625,7 @@ Debugger::setAllowUnobservedAsmJS(JSContext *cx, unsigned argc, Value *vp)
return false;
dbg->allowUnobservedAsmJS = ToBoolean(args[0]);
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject *global = r.front();
JSCompartment *comp = global->compartment();
comp->updateDebuggerObservesAsmJS();
@ -2783,7 +2783,7 @@ Debugger::removeAllDebuggees(JSContext *cx, unsigned argc, Value *vp)
if (!obs.init())
return false;
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) {
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) {
Rooted<GlobalObject *> global(cx, e.front());
dbg->removeDebuggeeGlobal(cx->runtime()->defaultFreeOp(), global, &e);
@ -2826,8 +2826,8 @@ Debugger::getDebuggees(JSContext *cx, unsigned argc, Value *vp)
unsigned i = 0;
{
JS::AutoCheckCannotGC nogc;
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
debuggees[i++].setObject(*e.front());
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
debuggees[i++].setObject(*e.front().get());
}
RootedArrayObject arrobj(cx, NewDenseFullyAllocatedArray(cx, count));
@ -2872,7 +2872,7 @@ Debugger::getNewestFrame(JSContext *cx, unsigned argc, Value *vp)
Debugger::clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "clearAllBreakpoints", args, dbg);
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
r.front()->compartment()->clearBreakpointsIn(cx->runtime()->defaultFreeOp(),
dbg, NullPtr());
return true;
@ -3040,7 +3040,8 @@ Debugger::addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> global)
}
void
Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global, GlobalObjectSet::Enum *debugEnum)
Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
WeakGlobalObjectSet::Enum *debugEnum)
{
/*
* The caller might have found global by enumerating this->debuggees; if
@ -3394,7 +3395,7 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
bool matchAllDebuggeeGlobals() {
MOZ_ASSERT(compartments.count() == 0);
/* Build our compartment set from the debugger's set of debuggee globals. */
for (GlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
if (!addCompartment(r.front()->compartment())) {
ReportOutOfMemory(cx);
return false;

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

@ -35,6 +35,10 @@ namespace js {
class Breakpoint;
class DebuggerMemory;
typedef HashSet<ReadBarrieredGlobalObject,
DefaultHasher<ReadBarrieredGlobalObject>,
SystemAllocPolicy> WeakGlobalObjectSet;
/*
* A weakmap from GC thing keys to JSObject values that supports the keys being
* in different compartments to the values. All values must be in the same
@ -238,7 +242,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
private:
HeapPtrNativeObject object; /* The Debugger object. Strong reference. */
GlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
WeakGlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
bool enabled;
JSCList breakpoints; /* Circular list of all js::Breakpoints in this debugger */
@ -325,7 +329,8 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
class ObjectQuery;
bool addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> obj);
void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global, GlobalObjectSet::Enum *debugEnum);
void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
WeakGlobalObjectSet::Enum *debugEnum);
/*
* Cope with an error or exception in a debugger hook.
@ -529,7 +534,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
bool hasMemory() const;
DebuggerMemory &memory() const;
GlobalObjectSet::Range allDebuggees() const { return debuggees.all(); }
WeakGlobalObjectSet::Range allDebuggees() const { return debuggees.all(); }
/*********************************** Methods for interaction with the GC. */
@ -889,7 +894,8 @@ Debugger::observesNewGlobalObject() const
bool
Debugger::observesGlobal(GlobalObject *global) const
{
return debuggees.has(global);
ReadBarriered<GlobalObject*> debuggee(global);
return debuggees.has(debuggee);
}
/* static */ void

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

@ -139,7 +139,7 @@ DebuggerMemory::setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *
}
if (enabling) {
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
JSCompartment *compartment = r.front()->compartment();
if (compartment->hasObjectMetadataCallback()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
@ -149,7 +149,7 @@ DebuggerMemory::setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *
}
}
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
if (enabling) {
r.front()->compartment()->setObjectMetadataCallback(SavedStacksMetadataCallback);
} else {
@ -778,7 +778,7 @@ DebuggerMemory::takeCensus(JSContext *cx, unsigned argc, Value *vp)
RootedObject dbgObj(cx, dbg->object);
// Populate our target set of debuggee zones.
for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
for (WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
if (!census.debuggeeZones.put(r.front()->zone()))
return false;
}

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

@ -317,7 +317,7 @@ RootList::init(HandleObject debuggees)
if (!debuggeeZones.init())
return false;
for (js::GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
for (js::WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
if (!debuggeeZones.put(r.front()->zone()))
return false;
}
@ -326,7 +326,7 @@ RootList::init(HandleObject debuggees)
return false;
// Ensure that each of our debuggee globals are in the root list.
for (js::GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
for (js::WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
if (!addRoot(JS::ubi::Node(static_cast<JSObject *>(r.front())),
MOZ_UTF16("debuggee global")))
{