#ifndef gc_Zone_inl_h
#define gc_Zone_inl_h
#include "gc/Zone.h"
#ifdef DEBUG
inline bool JS::Zone::requireGCTracer() const {
JSRuntime* rt = runtimeFromAnyThread();
return RuntimeHeapIsMajorCollecting() && !rt->gc.isHeapCompacting() &&
gcState_ != NoGC;
}
#endif
inline void JS::Zone::updateAllGCMallocCountersOnGCStart() {
gcMallocCounter.updateOnGCStart();
jitCodeCounter.updateOnGCStart();
}
inline void JS::Zone::updateAllGCMallocCountersOnGCEnd(
const js::AutoLockGC& lock) {
auto& gc = runtimeFromAnyThread()->gc;
gcMallocCounter.updateOnGCEnd(gc.tunables, lock);
jitCodeCounter.updateOnGCEnd(gc.tunables, lock);
}
inline js::gc::TriggerKind JS::Zone::shouldTriggerGCForTooMuchMalloc() {
auto& gc = runtimeFromAnyThread()->gc;
return std::max(gcMallocCounter.shouldTriggerGC(gc.tunables),
jitCodeCounter.shouldTriggerGC(gc.tunables));
}
inline js::HashNumber JS::Zone::UniqueIdToHash(uint64_t uid) {
return mozilla::HashGeneric(uid);
}
inline bool JS::Zone::getHashCode(js::gc::Cell* cell, js::HashNumber* hashp) {
uint64_t uid;
if (!getOrCreateUniqueId(cell, &uid)) {
return false;
}
*hashp = UniqueIdToHash(uid);
return true;
}
inline bool JS::Zone::maybeGetUniqueId(js::gc::Cell* cell, uint64_t* uidp) {
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
auto p = uniqueIds().lookup(cell);
if (p) {
*uidp = p->value();
}
return p.found();
}
inline bool JS::Zone::getOrCreateUniqueId(js::gc::Cell* cell, uint64_t* uidp) {
MOZ_ASSERT(uidp);
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) ||
js::CurrentThreadIsPerformingGC());
auto p = uniqueIds().lookupForAdd(cell);
if (p) {
*uidp = p->value();
return true;
}
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
*uidp = js::gc::NextCellUniqueId(runtimeFromAnyThread());
if (!uniqueIds().add(p, cell, *uidp)) {
return false;
}
if (IsInsideNursery(cell) &&
!runtimeFromMainThread()->gc.nursery().addedUniqueIdToCell(cell)) {
uniqueIds().remove(cell);
return false;
}
return true;
}
inline js::HashNumber JS::Zone::getHashCodeInfallible(js::gc::Cell* cell) {
return UniqueIdToHash(getUniqueIdInfallible(cell));
}
inline uint64_t JS::Zone::getUniqueIdInfallible(js::gc::Cell* cell) {
uint64_t uid;
js::AutoEnterOOMUnsafeRegion oomUnsafe;
if (!getOrCreateUniqueId(cell, &uid)) {
oomUnsafe.crash("failed to allocate uid");
}
return uid;
}
inline bool JS::Zone::hasUniqueId(js::gc::Cell* cell) {
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this) ||
js::CurrentThreadIsPerformingGC());
return uniqueIds().has(cell);
}
inline void JS::Zone::transferUniqueId(js::gc::Cell* tgt, js::gc::Cell* src) {
MOZ_ASSERT(src != tgt);
MOZ_ASSERT(!IsInsideNursery(tgt));
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtimeFromMainThread()));
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
MOZ_ASSERT(!uniqueIds().has(tgt));
uniqueIds().rekeyIfMoved(src, tgt);
}
inline void JS::Zone::removeUniqueId(js::gc::Cell* cell) {
MOZ_ASSERT(js::CurrentThreadCanAccessZone(this));
uniqueIds().remove(cell);
}
inline void JS::Zone::adoptUniqueIds(JS::Zone* source) {
js::AutoEnterOOMUnsafeRegion oomUnsafe;
for (js::gc::UniqueIdMap::Enum e(source->uniqueIds()); !e.empty();
e.popFront()) {
MOZ_ASSERT(!uniqueIds().has(e.front().key()));
if (!uniqueIds().put(e.front().key(), e.front().value())) {
oomUnsafe.crash("failed to transfer unique ids from off-thread");
}
}
source->uniqueIds().clear();
}
#endif