Bug 1328251 - Don't mark GC things owned by another runtime r=sfink a=abillings

This commit is contained in:
Jon Coppeard 2017-01-11 10:33:52 +00:00
parent 0cf1eda5de
commit e639e46d9a
4 changed files with 58 additions and 36 deletions

View File

@ -175,6 +175,17 @@ template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JS::Symbol>(JS::Symbol* s
return sym->isWellKnownSymbol();
}
template <typename T>
static inline bool
IsOwnedByOtherRuntime(JSTracer* trc, T thing)
{
bool other = thing->runtimeFromAnyThread() != trc->runtime();
MOZ_ASSERT_IF(other,
ThingIsPermanentAtomOrWellKnownSymbol(thing) ||
thing->zoneFromAnyThread()->isSelfHostingZone());
return other;
}
template<typename T>
void
js::CheckTracedThing(JSTracer* trc, T* thing)
@ -196,10 +207,10 @@ js::CheckTracedThing(JSTracer* trc, T* thing)
MOZ_ASSERT_IF(!IsMovingTracer(trc) && !trc->isTenuringTracer(), !IsForwarded(thing));
/*
* Permanent atoms are not associated with this runtime, but will be
* ignored during marking.
* Permanent atoms and things in the self-hosting zone are not associated
* with this runtime, but will be ignored during marking.
*/
if (ThingIsPermanentAtomOrWellKnownSymbol(thing))
if (IsOwnedByOtherRuntime(trc, thing))
return;
Zone* zone = thing->zoneFromAnyThread();
@ -740,16 +751,24 @@ GCMarker::markImplicitEdges(T* thing)
template <typename T>
static inline bool
MustSkipMarking(T thing)
MustSkipMarking(GCMarker* gcmarker, T thing)
{
// Don't trace things that are owned by another runtime.
if (IsOwnedByOtherRuntime(gcmarker, thing))
return true;
// Don't mark things outside a zone if we are in a per-zone GC.
return !thing->zone()->isGCMarking();
}
template <>
bool
MustSkipMarking<JSObject*>(JSObject* obj)
MustSkipMarking<JSObject*>(GCMarker* gcmarker, JSObject* obj)
{
// Don't trace things that are owned by another runtime.
if (IsOwnedByOtherRuntime(gcmarker, obj))
return true;
// We may mark a Nursery thing outside the context of the
// MinorCollectionTracer because of a pre-barrier. The pre-barrier is not
// needed in this case because we perform a minor collection before each
@ -763,34 +782,12 @@ MustSkipMarking<JSObject*>(JSObject* obj)
return !TenuredCell::fromPointer(obj)->zone()->isGCMarking();
}
template <>
bool
MustSkipMarking<JSString*>(JSString* str)
{
// Don't mark permanent atoms, as they may be associated with another
// runtime. Note that traverse() also checks this, but we need to not
// run the isGCMarking test from off-main-thread, so have to check it here
// too.
return str->isPermanentAtom() ||
!str->zone()->isGCMarking();
}
template <>
bool
MustSkipMarking<JS::Symbol*>(JS::Symbol* sym)
{
// As for JSString, don't touch a globally owned well-known symbol from
// off-main-thread.
return sym->isWellKnownSymbol() ||
!sym->zone()->isGCMarking();
}
template <typename T>
void
DoMarking(GCMarker* gcmarker, T* thing)
{
// Do per-type marking precondition checks.
if (MustSkipMarking(thing))
if (MustSkipMarking(gcmarker, thing))
return;
CheckTracedThing(gcmarker, thing);
@ -817,7 +814,7 @@ void
NoteWeakEdge(GCMarker* gcmarker, T** thingp)
{
// Do per-type marking precondition checks.
if (MustSkipMarking(*thingp))
if (MustSkipMarking(gcmarker, *thingp))
return;
CheckTracedThing(gcmarker, *thingp);

View File

@ -0,0 +1,13 @@
if (helperThreadCount() === 0)
quit();
evalInWorker(`
if (!('gczeal' in this))
quit();
try {
gczeal(2,1);
throw new Error();
} catch (e) {
assertEq("" + e, "Error");
}
`);

View File

@ -0,0 +1,12 @@
if (helperThreadCount() == 0)
quit();
evalInWorker(`
if (!('gczeal' in this))
quit();
gczeal(2);
for (let i = 0; i < 30; i++) {
var a = [1, 2, 3];
a.indexOf(1);
relazifyFunctions(); }
`);

View File

@ -2098,7 +2098,7 @@ void
MovingTracer::onObjectEdge(JSObject** objp)
{
JSObject* obj = *objp;
if (IsForwarded(obj))
if (obj->runtimeFromAnyThread() == runtime() && IsForwarded(obj))
*objp = Forwarded(obj);
}
@ -2106,7 +2106,7 @@ void
MovingTracer::onShapeEdge(Shape** shapep)
{
Shape* shape = *shapep;
if (IsForwarded(shape))
if (shape->runtimeFromAnyThread() == runtime() && IsForwarded(shape))
*shapep = Forwarded(shape);
}
@ -2114,7 +2114,7 @@ void
MovingTracer::onStringEdge(JSString** stringp)
{
JSString* string = *stringp;
if (IsForwarded(string))
if (string->runtimeFromAnyThread() == runtime() && IsForwarded(string))
*stringp = Forwarded(string);
}
@ -2122,7 +2122,7 @@ void
MovingTracer::onScriptEdge(JSScript** scriptp)
{
JSScript* script = *scriptp;
if (IsForwarded(script))
if (script->runtimeFromAnyThread() == runtime() && IsForwarded(script))
*scriptp = Forwarded(script);
}
@ -2130,7 +2130,7 @@ void
MovingTracer::onLazyScriptEdge(LazyScript** lazyp)
{
LazyScript* lazy = *lazyp;
if (IsForwarded(lazy))
if (lazy->runtimeFromAnyThread() == runtime() && IsForwarded(lazy))
*lazyp = Forwarded(lazy);
}
@ -2138,7 +2138,7 @@ void
MovingTracer::onBaseShapeEdge(BaseShape** basep)
{
BaseShape* base = *basep;
if (IsForwarded(base))
if (base->runtimeFromAnyThread() == runtime() && IsForwarded(base))
*basep = Forwarded(base);
}
@ -2146,7 +2146,7 @@ void
MovingTracer::onScopeEdge(Scope** scopep)
{
Scope* scope = *scopep;
if (IsForwarded(scope))
if (scope->runtimeFromAnyThread() == runtime() && IsForwarded(scope))
*scopep = Forwarded(scope);
}