mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Use WeakMap for the Debug::objects, the mapping from referents to Debug.Objects. r=jorendorff, push=jorendorff.
This commit is contained in:
parent
fcfd80cfc5
commit
f79cb0d6c7
@ -150,7 +150,7 @@ enum {
|
|||||||
|
|
||||||
Debug::Debug(JSObject *dbg, JSObject *hooks)
|
Debug::Debug(JSObject *dbg, JSObject *hooks)
|
||||||
: object(dbg), hooksObject(hooks), uncaughtExceptionHook(NULL), enabled(true),
|
: object(dbg), hooksObject(hooks), uncaughtExceptionHook(NULL), enabled(true),
|
||||||
hasDebuggerHandler(false), hasThrowHandler(false)
|
hasDebuggerHandler(false), hasThrowHandler(false), objects(dbg->compartment()->rt)
|
||||||
{
|
{
|
||||||
// This always happens within a request on some cx.
|
// This always happens within a request on some cx.
|
||||||
JSRuntime *rt = dbg->compartment()->rt;
|
JSRuntime *rt = dbg->compartment()->rt;
|
||||||
@ -259,7 +259,7 @@ Debug::wrapDebuggeeValue(JSContext *cx, Value *vp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectMap::AddPtr p = objects.lookupForAdd(ccwobj);
|
ObjectWeakMap::AddPtr p = objects.lookupForAdd(ccwobj);
|
||||||
if (p) {
|
if (p) {
|
||||||
vp->setObject(*p->value);
|
vp->setObject(*p->value);
|
||||||
} else {
|
} else {
|
||||||
@ -560,36 +560,6 @@ Debug::mark(GCMarker *trc, JSCompartment *comp, JSGCInvocationKind gckind)
|
|||||||
markedAny = true;
|
markedAny = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handling Debug.Objects:
|
|
||||||
//
|
|
||||||
// If obj (the Debug object) hasn't been marked
|
|
||||||
// yet, it may not be live, so don't mark anything.
|
|
||||||
//
|
|
||||||
// If comp is the debuggee's compartment, do nothing. No
|
|
||||||
// referent objects will be collected, since we have a
|
|
||||||
// wrapper of each one.
|
|
||||||
//
|
|
||||||
// If comp is the debugger's compartment, mark all
|
|
||||||
// Debug.Objects, since the referents might be alive and
|
|
||||||
// therefore the table entries must remain.
|
|
||||||
//
|
|
||||||
// If comp is null, then for each key (referent-wrapper)
|
|
||||||
// that is marked, mark the corresponding value.
|
|
||||||
//
|
|
||||||
if (obj->isMarked() && (!comp || obj->compartment() == comp)) {
|
|
||||||
for (ObjectMap::Range r = dbg->objects.all(); !r.empty(); r.popFront()) {
|
|
||||||
// The unwrap() call below has the following effect: we
|
|
||||||
// mark the Debug.Object if the *referent* is alive,
|
|
||||||
// even if the CCW of the referent seems unreachable.
|
|
||||||
if (!r.front().value->isMarked() &&
|
|
||||||
(comp || r.front().key->unwrap()->isMarked())) {
|
|
||||||
MarkObject(trc, *r.front().value,
|
|
||||||
"Debug.Object with live referent");
|
|
||||||
markedAny = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,21 +568,29 @@ Debug::mark(GCMarker *trc, JSCompartment *comp, JSGCInvocationKind gckind)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Debug::trace(JSTracer *trc, JSObject *obj)
|
Debug::traceObject(JSTracer *trc, JSObject *obj)
|
||||||
{
|
{
|
||||||
if (Debug *dbg = (Debug *) obj->getPrivate()) {
|
if (Debug *dbg = Debug::fromJSObject(obj))
|
||||||
MarkObject(trc, *dbg->hooksObject, "hooks");
|
dbg->trace(trc);
|
||||||
if (dbg->uncaughtExceptionHook)
|
}
|
||||||
MarkObject(trc, *dbg->uncaughtExceptionHook, "hooks");
|
|
||||||
|
|
||||||
// Mark Debug.Frame objects that are reachable from JS if we look them up
|
void
|
||||||
// again (because the corresponding StackFrame is still on the stack).
|
Debug::trace(JSTracer *trc)
|
||||||
for (FrameMap::Enum e(dbg->frames); !e.empty(); e.popFront()) {
|
{
|
||||||
JSObject *frameobj = e.front().value;
|
MarkObject(trc, *hooksObject, "hooks");
|
||||||
JS_ASSERT(frameobj->getPrivate());
|
if (uncaughtExceptionHook)
|
||||||
MarkObject(trc, *frameobj, "live Debug.Frame");
|
MarkObject(trc, *uncaughtExceptionHook, "hooks");
|
||||||
}
|
|
||||||
|
// Mark Debug.Frame objects that are reachable from JS if we look them up
|
||||||
|
// again (because the corresponding StackFrame is still on the stack).
|
||||||
|
for (FrameMap::Enum e(frames); !e.empty(); e.popFront()) {
|
||||||
|
JSObject *frameobj = e.front().value;
|
||||||
|
JS_ASSERT(frameobj->getPrivate());
|
||||||
|
MarkObject(trc, *frameobj, "live Debug.Frame");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trace the referent -> Debug.Object weak map.
|
||||||
|
objects.trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -621,14 +599,7 @@ Debug::sweepAll(JSRuntime *rt)
|
|||||||
for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) {
|
for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) {
|
||||||
Debug *dbg = (Debug *) ((unsigned char *) p - offsetof(Debug, link));
|
Debug *dbg = (Debug *) ((unsigned char *) p - offsetof(Debug, link));
|
||||||
|
|
||||||
if (dbg->object->isMarked()) {
|
if (!dbg->object->isMarked()) {
|
||||||
// Sweep ObjectMap entries for referents being collected.
|
|
||||||
for (ObjectMap::Enum e(dbg->objects); !e.empty(); e.popFront()) {
|
|
||||||
JS_ASSERT(e.front().key->isMarked() == e.front().value->isMarked());
|
|
||||||
if (!e.front().value->isMarked())
|
|
||||||
e.removeFront();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If this Debug is being GC'd, detach it from its debuggees. In the case of
|
// If this Debug is being GC'd, detach it from its debuggees. In the case of
|
||||||
// runtime-wide GC, the debuggee might be GC'd too. Since detaching requires
|
// runtime-wide GC, the debuggee might be GC'd too. Since detaching requires
|
||||||
// access to both objects, this must be done before finalize time. However, in
|
// access to both objects, this must be done before finalize time. However, in
|
||||||
@ -690,7 +661,7 @@ Class Debug::jsclass = {
|
|||||||
NULL, /* construct */
|
NULL, /* construct */
|
||||||
NULL, /* xdrObject */
|
NULL, /* xdrObject */
|
||||||
NULL, /* hasInstance */
|
NULL, /* hasInstance */
|
||||||
Debug::trace
|
Debug::traceObject
|
||||||
};
|
};
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
#include "jsgc.h"
|
#include "jsgc.h"
|
||||||
#include "jshashtable.h"
|
#include "jshashtable.h"
|
||||||
|
#include "jsweakmap.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
#include "jsvalue.h"
|
#include "jsvalue.h"
|
||||||
#include "vm/GlobalObject.h"
|
#include "vm/GlobalObject.h"
|
||||||
@ -75,12 +76,28 @@ class Debug {
|
|||||||
FrameMap;
|
FrameMap;
|
||||||
FrameMap frames;
|
FrameMap frames;
|
||||||
|
|
||||||
|
// Mark policy for ObjectMap.
|
||||||
|
class ObjectMapMarkPolicy: public DefaultMarkPolicy<JSObject *, JSObject *> {
|
||||||
|
typedef DefaultMarkPolicy<JSObject *, JSObject *> Base;
|
||||||
|
public:
|
||||||
|
explicit ObjectMapMarkPolicy(JSTracer *tracer) : Base(tracer) { }
|
||||||
|
|
||||||
|
// The unwrap() call has the following effect: we mark the Debug.Object if the
|
||||||
|
// *referent* is alive, even if the CCW of the referent seems unreachable. Since
|
||||||
|
// the value always refers to the CCW, marking the value marks the CCW, so we
|
||||||
|
// needn't worry that the CCW will go dead.
|
||||||
|
bool keyMarked(JSObject *k) { return k->unwrap()->isMarked(); }
|
||||||
|
void markKey(JSObject *k, const char *description) {
|
||||||
|
js::gc::MarkObject(tracer, *k->unwrap(), description);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Keys are referents, values are Debug.Object objects. The combination of
|
// Keys are referents, values are Debug.Object objects. The combination of
|
||||||
// the a key being live and this Debug being live keeps the corresponding
|
// the a key being live and this Debug being live keeps the corresponding
|
||||||
// Debug.Object alive.
|
// Debug.Object alive.
|
||||||
typedef HashMap<JSObject *, JSObject *, DefaultHasher<JSObject *>, SystemAllocPolicy>
|
typedef WeakMap<JSObject *, JSObject *, DefaultHasher<JSObject *>, ObjectMapMarkPolicy>
|
||||||
ObjectMap;
|
ObjectWeakMap;
|
||||||
ObjectMap objects;
|
ObjectWeakMap objects;
|
||||||
|
|
||||||
bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
|
bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
|
||||||
void removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum,
|
void removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum,
|
||||||
@ -91,7 +108,8 @@ class Debug {
|
|||||||
bool callHook = true);
|
bool callHook = true);
|
||||||
JSObject *unwrapDebuggeeArgument(JSContext *cx, Value *vp);
|
JSObject *unwrapDebuggeeArgument(JSContext *cx, Value *vp);
|
||||||
|
|
||||||
static void trace(JSTracer *trc, JSObject *obj);
|
static void traceObject(JSTracer *trc, JSObject *obj);
|
||||||
|
void trace(JSTracer *trc);
|
||||||
static void finalize(JSContext *cx, JSObject *obj);
|
static void finalize(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
static Class jsclass;
|
static Class jsclass;
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
|
#include "jsgcmark.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
@ -158,7 +159,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
|||||||
typedef typename Base::Enum Enum;
|
typedef typename Base::Enum Enum;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WeakMap(JSContext *cx) : Base(cx) { }
|
explicit WeakMap(JSRuntime *rt) : Base(rt) { }
|
||||||
|
explicit WeakMap(JSContext *cx) : Base(cx) { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void nonMarkingTrace(JSTracer *tracer) {
|
void nonMarkingTrace(JSTracer *tracer) {
|
||||||
@ -199,7 +201,6 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Marking policy for maps from JSObject pointers to js::Values.
|
|
||||||
template <>
|
template <>
|
||||||
class DefaultMarkPolicy<JSObject *, Value> {
|
class DefaultMarkPolicy<JSObject *, Value> {
|
||||||
private:
|
private:
|
||||||
@ -220,6 +221,22 @@ class DefaultMarkPolicy<JSObject *, Value> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class DefaultMarkPolicy<JSObject *, JSObject *> {
|
||||||
|
public:
|
||||||
|
DefaultMarkPolicy(JSTracer *t) : tracer(t) { }
|
||||||
|
bool keyMarked(JSObject *k) { return !IsAboutToBeFinalized(tracer->context, k); }
|
||||||
|
bool valueMarked(JSObject *v) { return !IsAboutToBeFinalized(tracer->context, v); }
|
||||||
|
void markKey(JSObject *k, const char *description) {
|
||||||
|
js::gc::MarkObject(tracer, *k, description);
|
||||||
|
}
|
||||||
|
void markValue(JSObject *v, const char *description) {
|
||||||
|
js::gc::MarkObject(tracer, *v, description);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
JSTracer *tracer;
|
||||||
|
};
|
||||||
|
|
||||||
// The class of JavaScript WeakMap objects.
|
// The class of JavaScript WeakMap objects.
|
||||||
extern Class WeakMapClass;
|
extern Class WeakMapClass;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user