Bug 650161 - Add moving GC callback and use it to fix up ipc CPOW tables r=terrence

This commit is contained in:
Jon Coppeard 2014-09-02 11:07:22 +02:00
parent 2e443e6daf
commit fbd9cb9af7
9 changed files with 90 additions and 13 deletions

View File

@ -24,10 +24,16 @@ static void
FinalizeChild(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartment, void *data)
{
if (status == JSFINALIZE_GROUP_START) {
static_cast<JavaScriptChild *>(data)->finalize(fop);
static_cast<JavaScriptChild *>(data)->finalize();
}
}
static void
FixupChildAfterMovingGC(JSRuntime *rt, void *data)
{
static_cast<JavaScriptChild *>(data)->fixupAfterMovingGC();
}
JavaScriptChild::JavaScriptChild(JSRuntime *rt)
: JavaScriptShared(rt),
JavaScriptBase<PJavaScriptChild>(rt)
@ -37,6 +43,7 @@ JavaScriptChild::JavaScriptChild(JSRuntime *rt)
JavaScriptChild::~JavaScriptChild()
{
JS_RemoveFinalizeCallback(rt_, FinalizeChild);
JS_RemoveMovingGCCallback(rt_, FixupChildAfterMovingGC);
}
bool
@ -48,14 +55,15 @@ JavaScriptChild::init()
return false;
JS_AddFinalizeCallback(rt_, FinalizeChild, this);
JS_AddMovingGCCallback(rt_, FixupChildAfterMovingGC, this);
return true;
}
void
JavaScriptChild::finalize(JSFreeOp *fop)
JavaScriptChild::finalize()
{
objects_.finalize(fop);
objectIds_.finalize(fop);
objects_.sweep();
objectIds_.sweep();
}
JSObject *

View File

@ -21,7 +21,7 @@ class JavaScriptChild : public JavaScriptBase<PJavaScriptChild>
virtual ~JavaScriptChild();
bool init();
void finalize(JSFreeOp *fop);
void finalize();
void drop(JSObject *obj);

View File

@ -27,6 +27,12 @@ TraceParent(JSTracer *trc, void *data)
static_cast<JavaScriptParent *>(data)->trace(trc);
}
static void
FixupParentAfterMovingGC(JSRuntime *rt, void *data)
{
static_cast<JavaScriptParent *>(data)->fixupAfterMovingGC();
}
JavaScriptParent::JavaScriptParent(JSRuntime *rt)
: JavaScriptShared(rt),
JavaScriptBase<PJavaScriptParent>(rt)
@ -36,6 +42,7 @@ JavaScriptParent::JavaScriptParent(JSRuntime *rt)
JavaScriptParent::~JavaScriptParent()
{
JS_RemoveExtraGCRootsTracer(rt_, TraceParent, this);
JS_RemoveMovingGCCallback(rt_, FixupParentAfterMovingGC);
}
bool
@ -45,6 +52,7 @@ JavaScriptParent::init()
return false;
JS_AddExtraGCRootsTracer(rt_, TraceParent, this);
JS_AddMovingGCCallback(rt_, FixupParentAfterMovingGC, this);
return true;
}

View File

@ -41,14 +41,12 @@ IdToObjectMap::trace(JSTracer *trc)
}
void
IdToObjectMap::finalize(JSFreeOp *fop)
IdToObjectMap::sweep()
{
for (Table::Enum e(table_); !e.empty(); e.popFront()) {
DebugOnly<JSObject *> prior = e.front().value().get();
if (JS_IsAboutToBeFinalized(&e.front().value()))
e.removeFront();
else
MOZ_ASSERT(e.front().value() == prior);
}
}
@ -97,14 +95,14 @@ ObjectToIdMap::init()
}
void
ObjectToIdMap::finalize(JSFreeOp *fop)
ObjectToIdMap::sweep()
{
for (Table::Enum e(*table_); !e.empty(); e.popFront()) {
JSObject *obj = e.front().key();
if (JS_IsAboutToBeFinalizedUnbarriered(&obj))
e.removeFront();
else
MOZ_ASSERT(obj == e.front().key());
else if (obj != e.front().key())
e.rekeyFront(obj);
}
}
@ -596,3 +594,9 @@ JavaScriptShared::Wrap(JSContext *cx, HandleObject aObj, InfallibleTArray<CpowEn
return true;
}
void JavaScriptShared::fixupAfterMovingGC()
{
objects_.sweep();
cpows_.sweep();
objectIds_.sweep();
}

View File

@ -48,12 +48,14 @@ class IdToObjectMap
bool init();
void trace(JSTracer *trc);
void finalize(JSFreeOp *fop);
void sweep();
bool add(ObjectId id, JSObject *obj);
JSObject *find(ObjectId id);
void remove(ObjectId id);
void fixupAfterMovingGC();
private:
Table table_;
};
@ -69,12 +71,14 @@ class ObjectToIdMap
~ObjectToIdMap();
bool init();
void finalize(JSFreeOp *fop);
void sweep();
bool add(JSContext *cx, JSObject *obj, ObjectId id);
ObjectId find(JSObject *obj);
void remove(JSObject *obj);
void fixupAfterMovingGC();
private:
static void keyMarkCallback(JSTracer *trc, JSObject *key, void *data);
@ -100,6 +104,8 @@ class JavaScriptShared
bool Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows, JS::MutableHandleObject objp);
bool Wrap(JSContext *cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows);
void fixupAfterMovingGC();
protected:
bool toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to);
bool fromVariant(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to);

View File

@ -414,6 +414,8 @@ class GCRuntime
void setGCCallback(JSGCCallback callback, void *data);
bool addFinalizeCallback(JSFinalizeCallback callback, void *data);
void removeFinalizeCallback(JSFinalizeCallback func);
bool addMovingGCCallback(JSMovingGCCallback callback, void *data);
void removeMovingGCCallback(JSMovingGCCallback func);
JS::GCSliceCallback setSliceCallback(JS::GCSliceCallback callback);
void setValidate(bool enable);
@ -797,6 +799,7 @@ class GCRuntime
Callback<JSGCCallback> gcCallback;
CallbackVector<JSFinalizeCallback> finalizeCallbacks;
CallbackVector<JSMovingGCCallback> movingCallbacks;
/*
* Malloc counter to measure memory pressure for GC scheduling. It runs

View File

@ -1888,6 +1888,19 @@ JS_RemoveFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
rt->gc.removeFinalizeCallback(cb);
}
JS_PUBLIC_API(bool)
JS_AddMovingGCCallback(JSRuntime *rt, JSMovingGCCallback cb, void *data)
{
AssertHeapIsIdle(rt);
return rt->gc.addMovingGCCallback(cb, data);
}
JS_PUBLIC_API(void)
JS_RemoveMovingGCCallback(JSRuntime *rt, JSMovingGCCallback cb)
{
rt->gc.removeMovingGCCallback(cb);
}
JS_PUBLIC_API(bool)
JS_IsAboutToBeFinalized(JS::Heap<JSObject *> *objp)
{

View File

@ -689,6 +689,9 @@ typedef enum JSFinalizeStatus {
typedef void
(* JSFinalizeCallback)(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartment, void *data);
typedef void
(* JSMovingGCCallback)(JSRuntime *rt, void *data);
typedef bool
(* JSInterruptCallback)(JSContext *cx);
@ -2025,6 +2028,12 @@ JS_AddFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb, void *data);
extern JS_PUBLIC_API(void)
JS_RemoveFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb);
extern JS_PUBLIC_API(bool)
JS_AddMovingGCCallback(JSRuntime *rt, JSMovingGCCallback cb, void *data);
extern JS_PUBLIC_API(void)
JS_RemoveMovingGCCallback(JSRuntime *rt, JSMovingGCCallback cb);
extern JS_PUBLIC_API(bool)
JS_IsGCMarkingTracer(JSTracer *trc);

View File

@ -1595,6 +1595,25 @@ GCRuntime::removeFinalizeCallback(JSFinalizeCallback callback)
}
}
bool
GCRuntime::addMovingGCCallback(JSMovingGCCallback callback, void *data)
{
return movingCallbacks.append(Callback<JSMovingGCCallback>(callback, data));
}
void
GCRuntime::removeMovingGCCallback(JSMovingGCCallback callback)
{
for (Callback<JSMovingGCCallback> *p = movingCallbacks.begin();
p < movingCallbacks.end(); p++)
{
if (p->op == callback) {
movingCallbacks.erase(p);
break;
}
}
}
JS::GCSliceCallback
GCRuntime::setSliceCallback(JS::GCSliceCallback callback) {
return stats.setSliceCallback(callback);
@ -2426,6 +2445,13 @@ GCRuntime::updatePointersToRelocatedCells()
(*op)(&trc, grayRootTracer.data);
MovingTracer::Sweep(&trc);
// Call callbacks to get the rest of the system to fixup other untraced pointers.
for (Callback<JSMovingGCCallback> *p = rt->gc.movingCallbacks.begin();
p < rt->gc.movingCallbacks.end(); p++)
{
p->op(rt, p->data);
}
}
void