Bug 1626322 - Add an API to get the zone of a possibly-nursery allocated GC thing and use it in CheckZoneTracer r=sfink,mccr8

Previously CheckZoneTracer didn't take account of the fact that BigInts can be nursery allocated.

Differential Revision: https://phabricator.services.mozilla.com/D72891
This commit is contained in:
Jon Coppeard 2020-04-28 22:26:59 +00:00
parent 7fd1c1c349
commit 24c9e5618f
3 changed files with 36 additions and 11 deletions

View File

@ -465,7 +465,7 @@ static MOZ_ALWAYS_INLINE void GetGCThingMarkWordAndMask(const uintptr_t addr,
*wordp = &bitmap[bit / nbits];
}
static MOZ_ALWAYS_INLINE JS::Zone* GetGCThingZone(const uintptr_t addr) {
static MOZ_ALWAYS_INLINE JS::Zone* GetTenuredGCThingZone(const uintptr_t addr) {
MOZ_ASSERT(addr);
const uintptr_t zone_addr = (addr & ~ArenaMask) | ArenaZoneOffset;
return *reinterpret_cast<JS::Zone**>(zone_addr);
@ -550,7 +550,7 @@ MOZ_ALWAYS_INLINE bool IsCellPointerValid(const void* cell) {
}
auto location = detail::GetCellLocation(cell);
if (location == ChunkLocation::TenuredHeap) {
return !!detail::GetGCThingZone(addr);
return !!detail::GetTenuredGCThingZone(addr);
}
if (location == ChunkLocation::Nursery) {
return detail::NurseryCellHasStoreBuffer(cell);
@ -572,14 +572,25 @@ namespace JS {
static MOZ_ALWAYS_INLINE Zone* GetTenuredGCThingZone(GCCellPtr thing) {
MOZ_ASSERT(!js::gc::IsInsideNursery(thing.asCell()));
return js::gc::detail::GetGCThingZone(thing.unsafeAsUIntPtr());
return js::gc::detail::GetTenuredGCThingZone(thing.unsafeAsUIntPtr());
}
extern JS_PUBLIC_API Zone* GetNurseryGCThingZone(GCCellPtr thing);
static MOZ_ALWAYS_INLINE Zone* GetGCThingZone(GCCellPtr thing) {
if (!js::gc::IsInsideNursery(thing.asCell())) {
return js::gc::detail::GetTenuredGCThingZone(thing.unsafeAsUIntPtr());
}
return GetNurseryGCThingZone(thing);
}
extern JS_PUBLIC_API Zone* GetNurseryStringZone(JSString* str);
static MOZ_ALWAYS_INLINE Zone* GetStringZone(JSString* str) {
if (!js::gc::IsInsideNursery(str)) {
return js::gc::detail::GetGCThingZone(reinterpret_cast<uintptr_t>(str));
return js::gc::detail::GetTenuredGCThingZone(
reinterpret_cast<uintptr_t>(str));
}
return GetNurseryStringZone(str);
}
@ -686,7 +697,8 @@ static MOZ_ALWAYS_INLINE bool EdgeNeedsSweepUnbarriered(JSObject** objp) {
return false;
}
auto zone = JS::shadow::Zone::from(detail::GetGCThingZone(uintptr_t(*objp)));
auto zone =
JS::shadow::Zone::from(detail::GetTenuredGCThingZone(uintptr_t(*objp)));
if (!zone->isGCSweepingOrCompacting()) {
return false;
}

View File

@ -5868,6 +5868,23 @@ JS_PUBLIC_API bool JS::CopyAsyncStack(JSContext* cx,
JS_PUBLIC_API Zone* JS::GetObjectZone(JSObject* obj) { return obj->zone(); }
JS_PUBLIC_API Zone* JS::GetNurseryGCThingZone(GCCellPtr thing) {
MOZ_ASSERT(!thing.asCell()->isTenured());
if (thing.is<JSObject>()) {
return thing.as<JSObject>().zone();
}
if (thing.is<JSString>()) {
return Nursery::getStringZone(&thing.as<JSString>());
}
if (thing.is<BigInt>()) {
return Nursery::getBigIntZone(&thing.as<BigInt>());
}
MOZ_CRASH("Unexpected GC thing kind");
}
JS_PUBLIC_API Zone* JS::GetNurseryStringZone(JSString* str) {
MOZ_ASSERT(!str->isTenured());
return str->zone();

View File

@ -1209,12 +1209,8 @@ struct CheckZoneTracer : public TraceCallbacks {
virtual void Trace(JS::Heap<JS::Value>* aPtr, const char* aName,
void* aClosure) const override {
JS::Value value = aPtr->unbarrieredGet();
if (value.isObject()) {
checkZone(js::GetObjectZoneFromAnyThread(&value.toObject()), aName);
} else if (value.isString()) {
checkZone(JS::GetStringZone(value.toString()), aName);
} else if (value.isGCThing()) {
checkZone(JS::GetTenuredGCThingZone(value.toGCCellPtr()), aName);
if (value.isGCThing()) {
checkZone(JS::GetGCThingZone(value.toGCCellPtr()), aName);
}
}
virtual void Trace(JS::Heap<jsid>* aPtr, const char* aName,