mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1102858 - Fix tracing of debugger objects' private pointers for compacting GC r=terrence
This commit is contained in:
parent
af7b548b52
commit
8f1b446425
@ -454,7 +454,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc,
|
||||
if (!c->zone()->isCollecting())
|
||||
c->markCrossCompartmentWrappers(trc);
|
||||
}
|
||||
Debugger::markCrossCompartmentDebuggerObjectReferents(trc);
|
||||
Debugger::markAllCrossCompartmentEdges(trc);
|
||||
}
|
||||
|
||||
AutoGCRooter::traceAll(trc);
|
||||
|
@ -2662,7 +2662,7 @@ GCRuntime::updatePointersToRelocatedCells()
|
||||
// Mark roots to update them.
|
||||
markRuntime(&trc, MarkRuntime);
|
||||
Debugger::markAll(&trc);
|
||||
Debugger::markCrossCompartmentDebuggerObjectReferents(&trc);
|
||||
Debugger::markAllCrossCompartmentEdges(&trc);
|
||||
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
WeakMapBase::markAll(c, &trc);
|
||||
|
@ -93,6 +93,11 @@ enum {
|
||||
JSSLOT_DEBUGSOURCE_COUNT
|
||||
};
|
||||
|
||||
static void DebuggerObject_trace(JSTracer *trc, JSObject *obj);
|
||||
static void DebuggerEnv_trace(JSTracer *trc, JSObject *obj);
|
||||
static void DebuggerScript_trace(JSTracer *trc, JSObject *obj);
|
||||
static void DebuggerSource_trace(JSTracer *trc, JSObject *obj);
|
||||
|
||||
|
||||
/*** Utils ***************************************************************************************/
|
||||
|
||||
@ -2073,17 +2078,12 @@ Debugger::setObservesAllExecution(JSContext *cx, IsObserving observing)
|
||||
/*** Debugger JSObjects **************************************************************************/
|
||||
|
||||
void
|
||||
Debugger::markKeysInCompartment(JSTracer *trc)
|
||||
Debugger::markCrossCompartmentEdges(JSTracer *trc)
|
||||
{
|
||||
/*
|
||||
* WeakMap::Range is deliberately private, to discourage C++ code from
|
||||
* enumerating WeakMap keys. However in this case we need access, so we
|
||||
* make a base-class reference. Range is public in HashMap.
|
||||
*/
|
||||
objects.markKeys(trc);
|
||||
environments.markKeys(trc);
|
||||
scripts.markKeys(trc);
|
||||
sources.markKeys(trc);
|
||||
objects.markCrossCompartmentEdges<DebuggerObject_trace>(trc);
|
||||
environments.markCrossCompartmentEdges<DebuggerEnv_trace>(trc);
|
||||
scripts.markCrossCompartmentEdges<DebuggerScript_trace>(trc);
|
||||
sources.markCrossCompartmentEdges<DebuggerSource_trace>(trc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2091,35 +2091,30 @@ Debugger::markKeysInCompartment(JSTracer *trc)
|
||||
* discovered that the WeakMap was live; that is, some object containing the
|
||||
* WeakMap was marked during mark phase.
|
||||
*
|
||||
* However, during compartment GC, we have to do something about
|
||||
* cross-compartment WeakMaps in non-GC'd compartments. If their keys and values
|
||||
* might need to be marked, we have to do it manually.
|
||||
* However, during zone GC, we have to do something about cross-compartment
|
||||
* edges in non-GC'd compartments. Since the source may be live, we
|
||||
* conservatively assume it is and mark the edge.
|
||||
*
|
||||
* Each Debugger object keeps found cross-compartment WeakMaps: objects, scripts,
|
||||
* script source objects, and environments. They have the nice property that all
|
||||
* their values are in the same compartment as the Debugger object, so we only
|
||||
* need to mark the keys. We must simply mark all keys that are in a compartment
|
||||
* being GC'd.
|
||||
* Each Debugger object keeps four cross-compartment WeakMaps: objects, scripts,
|
||||
* script source objects, and environments. They have the property that all
|
||||
* their values are in the same compartment as the Debugger object, but we have
|
||||
* to mark the keys and the private pointer in the wrapper object.
|
||||
*
|
||||
* We must scan all Debugger objects regardless of whether they *currently*
|
||||
* have any debuggees in a compartment being GC'd, because the WeakMap
|
||||
* entries persist even when debuggees are removed.
|
||||
* We must scan all Debugger objects regardless of whether they *currently* have
|
||||
* any debuggees in a compartment being GC'd, because the WeakMap entries
|
||||
* persist even when debuggees are removed.
|
||||
*
|
||||
* This happens during the initial mark phase, not iterative marking, because
|
||||
* all the edges being reported here are strong references.
|
||||
*/
|
||||
/* static */ void
|
||||
Debugger::markCrossCompartmentDebuggerObjectReferents(JSTracer *trc)
|
||||
Debugger::markAllCrossCompartmentEdges(JSTracer *trc)
|
||||
{
|
||||
JSRuntime *rt = trc->runtime();
|
||||
|
||||
/*
|
||||
* Mark all objects in comp that are referents of Debugger.Objects in other
|
||||
* compartments.
|
||||
*/
|
||||
for (Debugger *dbg = rt->debuggerList.getFirst(); dbg; dbg = dbg->getNext()) {
|
||||
if (!dbg->object->zone()->isCollecting())
|
||||
dbg->markKeysInCompartment(trc);
|
||||
dbg->markCrossCompartmentEdges(trc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2213,7 +2208,6 @@ Debugger::markAll(JSTracer *trc)
|
||||
GlobalObjectSet &debuggees = dbg->debuggees;
|
||||
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
||||
GlobalObject *global = e.front();
|
||||
|
||||
MarkObjectUnbarriered(trc, &global, "Global Object");
|
||||
if (global != e.front())
|
||||
e.rekeyFront(global);
|
||||
|
@ -36,10 +36,9 @@ class Breakpoint;
|
||||
class DebuggerMemory;
|
||||
|
||||
/*
|
||||
* A weakmap that supports the keys being in different compartments to the
|
||||
* values, although all values must be in the same compartment.
|
||||
*
|
||||
* The Key and Value classes must support the compartment() method.
|
||||
* 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
|
||||
* compartment.
|
||||
*
|
||||
* The purpose of this is to allow the garbage collector to easily find edges
|
||||
* from debugee object compartments to debugger compartments when calculating
|
||||
@ -55,10 +54,13 @@ class DebuggerMemory;
|
||||
* debugger compartments. If it is false, we assert that such entries are never
|
||||
* created.
|
||||
*/
|
||||
template <class Key, class Value, bool InvisibleKeysOk=false>
|
||||
class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
|
||||
template <class UnbarrieredKey, bool InvisibleKeysOk=false>
|
||||
class DebuggerWeakMap : private WeakMap<PreBarriered<UnbarrieredKey>, RelocatablePtrObject>
|
||||
{
|
||||
private:
|
||||
typedef PreBarriered<UnbarrieredKey> Key;
|
||||
typedef RelocatablePtrObject Value;
|
||||
|
||||
typedef HashMap<JS::Zone *,
|
||||
uintptr_t,
|
||||
DefaultHasher<JS::Zone *>,
|
||||
@ -112,8 +114,10 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
|
||||
}
|
||||
|
||||
public:
|
||||
void markKeys(JSTracer *tracer) {
|
||||
template <void (traceValueEdges)(JSTracer *, JSObject *)>
|
||||
void markCrossCompartmentEdges(JSTracer *tracer) {
|
||||
for (Enum e(*static_cast<Base *>(this)); !e.empty(); e.popFront()) {
|
||||
traceValueEdges(tracer, e.front().value());
|
||||
Key key = e.front().key();
|
||||
gc::Mark(tracer, &key, "Debugger WeakMap key");
|
||||
if (key != e.front().key())
|
||||
@ -282,15 +286,15 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
FrameMap frames;
|
||||
|
||||
/* An ephemeral map from JSScript* to Debugger.Script instances. */
|
||||
typedef DebuggerWeakMap<PreBarrieredScript, RelocatablePtrObject> ScriptWeakMap;
|
||||
typedef DebuggerWeakMap<JSScript*> ScriptWeakMap;
|
||||
ScriptWeakMap scripts;
|
||||
|
||||
/* The map from debuggee source script objects to their Debugger.Source instances. */
|
||||
typedef DebuggerWeakMap<PreBarrieredObject, RelocatablePtrObject, true> SourceWeakMap;
|
||||
typedef DebuggerWeakMap<JSObject*, true> SourceWeakMap;
|
||||
SourceWeakMap sources;
|
||||
|
||||
/* The map from debuggee objects to their Debugger.Object instances. */
|
||||
typedef DebuggerWeakMap<PreBarrieredObject, RelocatablePtrObject> ObjectWeakMap;
|
||||
typedef DebuggerWeakMap<JSObject*> ObjectWeakMap;
|
||||
ObjectWeakMap objects;
|
||||
|
||||
/* The map from debuggee Envs to Debugger.Environment instances. */
|
||||
@ -356,7 +360,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
static void traceObject(JSTracer *trc, JSObject *obj);
|
||||
void trace(JSTracer *trc);
|
||||
static void finalize(FreeOp *fop, JSObject *obj);
|
||||
void markKeysInCompartment(JSTracer *tracer);
|
||||
void markCrossCompartmentEdges(JSTracer *tracer);
|
||||
|
||||
static const Class jsclass;
|
||||
|
||||
@ -506,7 +510,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
* Debugger objects that are definitely live but not yet marked, it marks
|
||||
* them and returns true. If not, it returns false.
|
||||
*/
|
||||
static void markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer);
|
||||
static void markAllCrossCompartmentEdges(JSTracer *tracer);
|
||||
static bool markAllIteratively(GCMarker *trc);
|
||||
static void markAll(JSTracer *trc);
|
||||
static void sweepAll(FreeOp *fop);
|
||||
|
Loading…
Reference in New Issue
Block a user