Bug 1666853 - Part 4: Remove use of ApplyGCThingTyped from Value barriers as this doesn't generate good code r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D91311
This commit is contained in:
Jon Coppeard 2020-09-26 10:40:48 +00:00
Родитель 14ae5786a0
Коммит 0bbf0e853e
2 изменённых файлов: 93 добавлений и 5 удалений

Просмотреть файл

@ -92,8 +92,13 @@ struct PropertyKey {
return reinterpret_cast<JS::Symbol*>(asBits ^ JSID_TYPE_SYMBOL); return reinterpret_cast<JS::Symbol*>(asBits ^ JSID_TYPE_SYMBOL);
} }
js::gc::Cell* toGCThing() const {
MOZ_ASSERT(isGCThing());
return reinterpret_cast<js::gc::Cell*>(asBits & ~(size_t)JSID_TYPE_MASK);
}
GCCellPtr toGCCellPtr() const { GCCellPtr toGCCellPtr() const {
void* thing = (void*)(asBits & ~(size_t)JSID_TYPE_MASK); js::gc::Cell* thing = toGCThing();
if (isString()) { if (isString()) {
return JS::GCCellPtr(thing, JS::TraceKind::String); return JS::GCCellPtr(thing, JS::TraceKind::String);
} }

Просмотреть файл

@ -103,20 +103,103 @@ AutoTouchingGrayThings::~AutoTouchingGrayThings() {
#endif // DEBUG #endif // DEBUG
// Tagged pointer barriers
//
// It's tempting to use ApplyGCThingTyped to dispatch to the typed barrier
// functions (e.g. gc::ReadBarrier(JSObject*)) but this does not compile well
// (clang generates 1580 bytes on x64 versus 296 bytes for this implementation
// of ValueReadBarrier).
//
// Instead, check known special cases and call the generic barrier functions.
static MOZ_ALWAYS_INLINE bool ValueIsPermanent(const Value& value) {
gc::Cell* cell = value.toGCThing();
if (value.isString()) {
return cell->as<JSString>()->isPermanentAndMayBeShared();
}
if (value.isSymbol()) {
return cell->as<JS::Symbol>()->isPermanentAndMayBeShared();
}
#ifdef DEBUG
// Using mozilla::DebugOnly here still generated code in opt builds.
bool isPermanent = MapGCThingTyped(value, [](auto t) {
return t->isPermanentAndMayBeShared();
}).value();
MOZ_ASSERT(!isPermanent);
#endif
return false;
}
void gc::ValueReadBarrier(const Value& v) { void gc::ValueReadBarrier(const Value& v) {
ApplyGCThingTyped(v, [](auto t) { gc::ReadBarrier(t); }); MOZ_ASSERT(v.isGCThing());
if (!ValueIsPermanent(v)) {
ReadBarrierImpl(v.toGCThing());
}
} }
void gc::ValuePreWriteBarrier(const Value& v) { void gc::ValuePreWriteBarrier(const Value& v) {
ApplyGCThingTyped(v, [](auto t) { gc::PreWriteBarrier(t); }); MOZ_ASSERT(v.isGCThing());
if (!ValueIsPermanent(v)) {
PreWriteBarrierImpl(v.toGCThing());
}
}
static MOZ_ALWAYS_INLINE bool IdIsPermanent(jsid id) {
gc::Cell* cell = id.toGCThing();
if (id.isString()) {
return cell->as<JSString>()->isPermanentAndMayBeShared();
}
if (id.isSymbol()) {
return cell->as<JS::Symbol>()->isPermanentAndMayBeShared();
}
#ifdef DEBUG
bool isPermanent = MapGCThingTyped(id, [](auto t) {
return t->isPermanentAndMayBeShared();
}).value();
MOZ_ASSERT(!isPermanent);
#endif
return false;
} }
void gc::IdPreWriteBarrier(jsid id) { void gc::IdPreWriteBarrier(jsid id) {
ApplyGCThingTyped(id, [](auto t) { gc::PreWriteBarrier(t); }); MOZ_ASSERT(id.isGCThing());
if (!IdIsPermanent(id)) {
PreWriteBarrierImpl(&id.toGCThing()->asTenured());
}
}
static MOZ_ALWAYS_INLINE bool CellPtrIsPermanent(JS::GCCellPtr thing) {
if (thing.mayBeOwnedByOtherRuntime()) {
return true;
}
#ifdef DEBUG
bool isPermanent = MapGCThingTyped(thing, [](auto t) {
return t->isPermanentAndMayBeShared();
});
MOZ_ASSERT(!isPermanent);
#endif
return false;
} }
void gc::CellPtrPreWriteBarrier(JS::GCCellPtr thing) { void gc::CellPtrPreWriteBarrier(JS::GCCellPtr thing) {
ApplyGCThingTyped(thing, [](auto t) { gc::PreWriteBarrier(t); }); MOZ_ASSERT(thing);
if (!CellPtrIsPermanent(thing)) {
PreWriteBarrierImpl(thing.asCell());
}
} }
template <typename T> template <typename T>