зеркало из https://github.com/mozilla/gecko-dev.git
Bug 903548 - GC: What do we do for UnmarkGray on a Nursery GCThing? r=billm
This commit is contained in:
Родитель
9552f14f02
Коммит
d54dda2c97
|
@ -256,7 +256,7 @@ class ObjectPtr
|
||||||
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
|
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
|
||||||
* JSTRACE_SHAPE. |thing| should be non-null.
|
* JSTRACE_SHAPE. |thing| should be non-null.
|
||||||
*/
|
*/
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(bool)
|
||||||
UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind);
|
UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -128,6 +128,16 @@ GetObjectZone(JSObject *obj)
|
||||||
static JS_ALWAYS_INLINE bool
|
static JS_ALWAYS_INLINE bool
|
||||||
GCThingIsMarkedGray(void *thing)
|
GCThingIsMarkedGray(void *thing)
|
||||||
{
|
{
|
||||||
|
#ifdef JSGC_GENERATIONAL
|
||||||
|
/*
|
||||||
|
* GC things residing in the nursery cannot be gray: they have no mark bits.
|
||||||
|
* All live objects in the nursery are moved to tenured at the beginning of
|
||||||
|
* each GC slice, so the gray marker never sees nursery things.
|
||||||
|
*/
|
||||||
|
JS::shadow::Runtime *rt = js::gc::GetGCThingRuntime(thing);
|
||||||
|
if (uintptr_t(thing) >= rt->gcNurseryStart_ && uintptr_t(thing) < rt->gcNurseryEnd_)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
uintptr_t *word, mask;
|
uintptr_t *word, mask;
|
||||||
js::gc::GetGCThingMarkWordAndMask(thing, js::gc::GRAY, &word, &mask);
|
js::gc::GetGCThingMarkWordAndMask(thing, js::gc::GRAY, &word, &mask);
|
||||||
return *word & mask;
|
return *word & mask;
|
||||||
|
|
|
@ -651,10 +651,15 @@ ShouldMarkCrossCompartment(JSTracer *trc, JSObject *src, Cell *cell)
|
||||||
if (!IS_GC_MARKING_TRACER(trc))
|
if (!IS_GC_MARKING_TRACER(trc))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
JS::Zone *zone = cell->tenuredZone();
|
|
||||||
uint32_t color = AsGCMarker(trc)->getMarkColor();
|
uint32_t color = AsGCMarker(trc)->getMarkColor();
|
||||||
|
|
||||||
JS_ASSERT(color == BLACK || color == GRAY);
|
JS_ASSERT(color == BLACK || color == GRAY);
|
||||||
|
|
||||||
|
if (IsInsideNursery(trc->runtime, cell)) {
|
||||||
|
JS_ASSERT(color == BLACK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Zone *zone = cell->tenuredZone();
|
||||||
if (color == BLACK) {
|
if (color == BLACK) {
|
||||||
/*
|
/*
|
||||||
* Having black->gray edges violates our promise to the cycle
|
* Having black->gray edges violates our promise to the cycle
|
||||||
|
@ -1578,14 +1583,14 @@ struct UnmarkGrayTracer : public JSTracer
|
||||||
* up any color mismatches involving weakmaps when it runs.
|
* up any color mismatches involving weakmaps when it runs.
|
||||||
*/
|
*/
|
||||||
UnmarkGrayTracer(JSRuntime *rt)
|
UnmarkGrayTracer(JSRuntime *rt)
|
||||||
: tracingShape(false), previousShape(NULL)
|
: tracingShape(false), previousShape(NULL), unmarkedAny(false)
|
||||||
{
|
{
|
||||||
JS_TracerInit(this, rt, UnmarkGrayChildren);
|
JS_TracerInit(this, rt, UnmarkGrayChildren);
|
||||||
eagerlyTraceWeakMaps = DoNotTraceWeakMaps;
|
eagerlyTraceWeakMaps = DoNotTraceWeakMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnmarkGrayTracer(JSTracer *trc, bool tracingShape)
|
UnmarkGrayTracer(JSTracer *trc, bool tracingShape)
|
||||||
: tracingShape(tracingShape), previousShape(NULL)
|
: tracingShape(tracingShape), previousShape(NULL), unmarkedAny(false)
|
||||||
{
|
{
|
||||||
JS_TracerInit(this, trc->runtime, UnmarkGrayChildren);
|
JS_TracerInit(this, trc->runtime, UnmarkGrayChildren);
|
||||||
eagerlyTraceWeakMaps = DoNotTraceWeakMaps;
|
eagerlyTraceWeakMaps = DoNotTraceWeakMaps;
|
||||||
|
@ -1596,6 +1601,9 @@ struct UnmarkGrayTracer : public JSTracer
|
||||||
|
|
||||||
/* If tracingShape, shape child or NULL. Otherwise, NULL. */
|
/* If tracingShape, shape child or NULL. Otherwise, NULL. */
|
||||||
void *previousShape;
|
void *previousShape;
|
||||||
|
|
||||||
|
/* Whether we unmarked anything. */
|
||||||
|
bool unmarkedAny;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1642,10 +1650,14 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS::GCThingIsMarkedGray(thing))
|
UnmarkGrayTracer *tracer = static_cast<UnmarkGrayTracer *>(trc);
|
||||||
return;
|
if (!IsInsideNursery(trc->runtime, thing)) {
|
||||||
|
if (!JS::GCThingIsMarkedGray(thing))
|
||||||
|
return;
|
||||||
|
|
||||||
UnmarkGrayGCThing(thing);
|
UnmarkGrayGCThing(thing);
|
||||||
|
tracer->unmarkedAny = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trace children of |thing|. If |thing| and its parent are both shapes,
|
* Trace children of |thing|. If |thing| and its parent are both shapes,
|
||||||
|
@ -1654,12 +1666,12 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||||
* depth during shape tracing. It is safe to do because a shape can only
|
* depth during shape tracing. It is safe to do because a shape can only
|
||||||
* have one child that is a shape.
|
* have one child that is a shape.
|
||||||
*/
|
*/
|
||||||
UnmarkGrayTracer *tracer = static_cast<UnmarkGrayTracer *>(trc);
|
|
||||||
UnmarkGrayTracer childTracer(tracer, kind == JSTRACE_SHAPE);
|
UnmarkGrayTracer childTracer(tracer, kind == JSTRACE_SHAPE);
|
||||||
|
|
||||||
if (kind != JSTRACE_SHAPE) {
|
if (kind != JSTRACE_SHAPE) {
|
||||||
JS_TraceChildren(&childTracer, thing, kind);
|
JS_TraceChildren(&childTracer, thing, kind);
|
||||||
JS_ASSERT(!childTracer.previousShape);
|
JS_ASSERT(!childTracer.previousShape);
|
||||||
|
tracer->unmarkedAny |= childTracer.unmarkedAny;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1675,19 +1687,27 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||||
thing = childTracer.previousShape;
|
thing = childTracer.previousShape;
|
||||||
childTracer.previousShape = NULL;
|
childTracer.previousShape = NULL;
|
||||||
} while (thing);
|
} while (thing);
|
||||||
|
tracer->unmarkedAny |= childTracer.unmarkedAny;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(bool)
|
||||||
JS::UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind)
|
JS::UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind)
|
||||||
{
|
{
|
||||||
JS_ASSERT(kind != JSTRACE_SHAPE);
|
JS_ASSERT(kind != JSTRACE_SHAPE);
|
||||||
|
|
||||||
if (!JS::GCThingIsMarkedGray(thing))
|
|
||||||
return;
|
|
||||||
|
|
||||||
UnmarkGrayGCThing(thing);
|
|
||||||
|
|
||||||
JSRuntime *rt = static_cast<Cell *>(thing)->runtimeFromMainThread();
|
JSRuntime *rt = static_cast<Cell *>(thing)->runtimeFromMainThread();
|
||||||
|
|
||||||
|
bool unmarkedArg = false;
|
||||||
|
if (!IsInsideNursery(rt, thing)) {
|
||||||
|
if (!JS::GCThingIsMarkedGray(thing))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UnmarkGrayGCThing(thing);
|
||||||
|
unmarkedArg = true;
|
||||||
|
}
|
||||||
|
|
||||||
UnmarkGrayTracer trc(rt);
|
UnmarkGrayTracer trc(rt);
|
||||||
JS_TraceChildren(&trc, thing, kind);
|
JS_TraceChildren(&trc, thing, kind);
|
||||||
|
|
||||||
|
return unmarkedArg || trc.unmarkedAny;
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,10 +591,11 @@ js::GCThingTraceKind(void *thing)
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
js::VisitGrayWrapperTargets(Zone *zone, GCThingCallback callback, void *closure)
|
js::VisitGrayWrapperTargets(Zone *zone, GCThingCallback callback, void *closure)
|
||||||
{
|
{
|
||||||
|
JSRuntime *rt = zone->runtimeFromMainThread();
|
||||||
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
|
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
|
||||||
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
|
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
|
||||||
gc::Cell *thing = e.front().key.wrapped;
|
gc::Cell *thing = e.front().key.wrapped;
|
||||||
if (thing->isMarked(gc::GRAY))
|
if (!IsInsideNursery(rt, thing) && thing->isMarked(gc::GRAY))
|
||||||
callback(closure, thing);
|
callback(closure, thing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,8 +258,9 @@ private:
|
||||||
if (delegateMightNeedMarking && kkind == JSTRACE_OBJECT) {
|
if (delegateMightNeedMarking && kkind == JSTRACE_OBJECT) {
|
||||||
JSObject* kdelegate = js::GetWeakmapKeyDelegate((JSObject*)k);
|
JSObject* kdelegate = js::GetWeakmapKeyDelegate((JSObject*)k);
|
||||||
if (kdelegate && !xpc_IsGrayGCThing(kdelegate)) {
|
if (kdelegate && !xpc_IsGrayGCThing(kdelegate)) {
|
||||||
JS::UnmarkGrayGCThingRecursively(k, JSTRACE_OBJECT);
|
if (JS::UnmarkGrayGCThingRecursively(k, JSTRACE_OBJECT)) {
|
||||||
tracer->mAnyMarked = true;
|
tracer->mAnyMarked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,8 +268,9 @@ private:
|
||||||
(!k || !xpc_IsGrayGCThing(k)) &&
|
(!k || !xpc_IsGrayGCThing(k)) &&
|
||||||
(!m || !xpc_IsGrayGCThing(m)) &&
|
(!m || !xpc_IsGrayGCThing(m)) &&
|
||||||
vkind != JSTRACE_SHAPE) {
|
vkind != JSTRACE_SHAPE) {
|
||||||
JS::UnmarkGrayGCThingRecursively(v, vkind);
|
if (JS::UnmarkGrayGCThingRecursively(v, vkind)) {
|
||||||
tracer->mAnyMarked = true;
|
tracer->mAnyMarked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче