Bug 1135100 - Remove Cell* versions of various GC methods forcing callers to use correct type r=terrence

This commit is contained in:
Jon Coppeard 2015-02-24 09:40:02 +00:00
parent 2f9550d600
commit 5e6eee1375
6 changed files with 59 additions and 56 deletions

View File

@ -1007,24 +1007,6 @@ gc::MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
MarkValueInternal(trc, v);
}
bool
gc::IsCellMarked(Cell **thingp)
{
return IsMarked<Cell>(thingp);
}
bool
gc::IsCellAboutToBeFinalized(Cell **thingp)
{
return IsAboutToBeFinalized<Cell>(thingp);
}
bool
gc::IsCellAboutToBeFinalizedFromAnyThread(Cell **thingp)
{
return IsAboutToBeFinalizedFromAnyThread<Cell>(thingp);
}
/*** Push Mark Stack ***/
#define JS_COMPARTMENT_ASSERT(rt, thing) \

View File

@ -320,15 +320,6 @@ Mark(JSTracer *trc, ScopeObject **obj, const char *name)
MarkObjectUnbarriered(trc, obj, name);
}
bool
IsCellMarked(Cell **thingp);
bool
IsCellAboutToBeFinalized(Cell **thing);
bool
IsCellAboutToBeFinalizedFromAnyThread(Cell **thing);
inline bool
IsMarked(BarrieredBase<Value> *v)
{

View File

@ -203,8 +203,15 @@ class WrapperMapRef : public BufferableRef
CrossCompartmentKey prior = key;
if (key.debugger)
Mark(trc, &key.debugger, "CCW debugger");
if (key.kind != CrossCompartmentKey::StringWrapper)
if (key.kind == CrossCompartmentKey::ObjectWrapper ||
key.kind == CrossCompartmentKey::DebuggerObject ||
key.kind == CrossCompartmentKey::DebuggerEnvironment ||
key.kind == CrossCompartmentKey::DebuggerSource)
{
MOZ_ASSERT(IsInsideNursery(key.wrapped) ||
key.wrapped->asTenured().getTraceKind() == JSTRACE_OBJECT);
Mark(trc, reinterpret_cast<JSObject**>(&key.wrapped), "CCW wrapped object");
}
if (key.debugger == prior.debugger && key.wrapped == prior.wrapped)
return;
@ -630,7 +637,30 @@ JSCompartment::sweepCrossCompartmentWrappers()
/* Remove dead wrappers from the table. */
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
CrossCompartmentKey key = e.front().key();
bool keyDying = IsCellAboutToBeFinalizedFromAnyThread(&key.wrapped);
bool keyDying;
switch (key.kind) {
case CrossCompartmentKey::ObjectWrapper:
case CrossCompartmentKey::DebuggerObject:
case CrossCompartmentKey::DebuggerEnvironment:
case CrossCompartmentKey::DebuggerSource:
MOZ_ASSERT(IsInsideNursery(key.wrapped) ||
key.wrapped->asTenured().getTraceKind() == JSTRACE_OBJECT);
keyDying = IsObjectAboutToBeFinalizedFromAnyThread(
reinterpret_cast<JSObject**>(&key.wrapped));
break;
case CrossCompartmentKey::StringWrapper:
MOZ_ASSERT(key.wrapped->asTenured().getTraceKind() == JSTRACE_STRING);
keyDying = IsStringAboutToBeFinalizedFromAnyThread(
reinterpret_cast<JSString**>(&key.wrapped));
break;
case CrossCompartmentKey::DebuggerScript:
MOZ_ASSERT(key.wrapped->asTenured().getTraceKind() == JSTRACE_SCRIPT);
keyDying = IsScriptAboutToBeFinalizedFromAnyThread(
reinterpret_cast<JSScript**>(&key.wrapped));
break;
default:
MOZ_CRASH("Unknown key kind");
}
bool valDying = IsValueAboutToBeFinalizedFromAnyThread(e.front().value().unsafeGet());
bool dbgDying = key.debugger && IsObjectAboutToBeFinalizedFromAnyThread(&key.debugger);
if (keyDying || valDying || dbgDying) {

View File

@ -1935,13 +1935,6 @@ CanRelocateAllocKind(AllocKind kind)
return kind <= FINALIZE_OBJECT_LAST;
}
static bool
CanRelocateTraceKind(JSGCTraceKind kind)
{
return kind == JSTRACE_OBJECT;
}
size_t ArenaHeader::countFreeCells()
{
size_t count = 0;
@ -2255,21 +2248,16 @@ void
MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
{
TenuredCell *thing = TenuredCell::fromPointer(*thingp);
if (!CanRelocateTraceKind(kind)) {
MOZ_ASSERT(!IsForwarded(thing));
// Currently we only relocate objects.
if (kind != JSTRACE_OBJECT) {
MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing));
return;
}
Zone *zone = thing->zoneFromAnyThread();
if (!zone->isGCCompacting()) {
MOZ_ASSERT(!IsForwarded(thing));
return;
}
if (IsForwarded(thing)) {
Cell *dst = Forwarded(thing);
*thingp = dst;
}
JSObject *obj = reinterpret_cast<JSObject*>(thing);
if (IsForwarded(obj))
*thingp = Forwarded(obj);
}
void
@ -5506,7 +5494,7 @@ GCRuntime::compactPhase(bool lastGC, JS::gcreason::Reason reason)
for (ArenaHeader *arena = relocatedList; arena; arena = arena->next) {
for (ArenaCellIterUnderFinalize i(arena); !i.done(); i.next()) {
TenuredCell *src = i.getCell();
MOZ_ASSERT(IsForwarded(src));
MOZ_ASSERT(RelocationOverlay::isCellForwarded(src));
TenuredCell *dest = Forwarded(src);
MOZ_ASSERT(src->isMarked(BLACK) == dest->isMarked(BLACK));
MOZ_ASSERT(src->isMarked(GRAY) == dest->isMarked(GRAY));

View File

@ -1182,6 +1182,10 @@ class RelocationOverlay
RelocationOverlay *next() const {
return next_;
}
static bool isCellForwarded(Cell *cell) {
return fromCell(cell)->isForwarded();
}
};
/* Functions for checking and updating things that might be moved by compacting GC. */
@ -1193,7 +1197,6 @@ class RelocationOverlay
return value; \
} \
TYPE_MIGHT_BE_FORWARDED(Cell, true)
TYPE_MIGHT_BE_FORWARDED(JSObject, true)
TYPE_MIGHT_BE_FORWARDED(JSString, false)
TYPE_MIGHT_BE_FORWARDED(JS::Symbol, false)
@ -1272,7 +1275,7 @@ inline void
CheckGCThingAfterMovingGC(T *t)
{
MOZ_ASSERT_IF(t, !IsInsideNursery(t));
MOZ_ASSERT_IF(t, !IsForwarded(t));
MOZ_ASSERT_IF(t, !RelocationOverlay::isCellForwarded(t));
}
inline void

View File

@ -3073,11 +3073,20 @@ js::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args, b
static inline bool
IsAboutToBeFinalized(TypeSet::ObjectKey **keyp)
{
// Mask out the low bit indicating whether this is a group or JS object.
uintptr_t flagBit = uintptr_t(*keyp) & 1;
gc::Cell *tmp = reinterpret_cast<gc::Cell *>(uintptr_t(*keyp) & ~1);
bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp);
*keyp = reinterpret_cast<TypeSet::ObjectKey *>(uintptr_t(tmp) | flagBit);
TypeSet::ObjectKey *key = *keyp;
bool isAboutToBeFinalized;
if (key->isGroup()) {
ObjectGroup *group = key->groupNoBarrier();
isAboutToBeFinalized = IsObjectGroupAboutToBeFinalized(&group);
if (!isAboutToBeFinalized)
*keyp = TypeSet::ObjectKey::get(group);
} else {
MOZ_ASSERT(key->isSingleton());
JSObject *singleton = key->singletonNoBarrier();
isAboutToBeFinalized = IsObjectAboutToBeFinalized(&singleton);
if (!isAboutToBeFinalized)
*keyp = TypeSet::ObjectKey::get(singleton);
}
return isAboutToBeFinalized;
}