зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1137478 - Add a read barrier for Debugger::debuggees r=terrence
This commit is contained in:
Родитель
63c7f31b12
Коммит
979e646fd3
|
@ -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")))
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче