#include "gc/Barrier.h"
#include "builtin/TypedObject.h"
#include "gc/Policy.h"
#include "gc/Zone.h"
#include "js/HashTable.h"
#include "js/Value.h"
#include "vm/EnvironmentObject.h"
#include "vm/JSObject.h"
#include "vm/Realm.h"
#include "vm/SharedArrayObject.h"
#include "vm/SymbolType.h"
#include "wasm/WasmJS.h"
#include "gc/Zone-inl.h"
namespace js {
bool RuntimeFromMainThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone) {
MOZ_ASSERT(
CurrentThreadCanAccessRuntime(shadowZone->runtimeFromMainThread()));
return JS::RuntimeHeapIsMajorCollecting();
}
#ifdef DEBUG
bool IsMarkedBlack(JSObject* obj) { return obj->isMarkedBlack(); }
bool HeapSlot::preconditionForSet(NativeObject* owner, Kind kind,
uint32_t slot) const {
if (kind == Slot) {
return &owner->getSlotRef(slot) == this;
}
uint32_t numShifted = owner->getElementsHeader()->numShiftedElements();
MOZ_ASSERT(slot >= numShifted);
return &owner->getDenseElement(slot - numShifted) == (const Value*)this;
}
void HeapSlot::assertPreconditionForWriteBarrierPost(
NativeObject* obj, Kind kind, uint32_t slot, const Value& target) const {
if (kind == Slot) {
MOZ_ASSERT(obj->getSlotAddressUnchecked(slot)->get() == target);
} else {
uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
MOZ_ASSERT(slot >= numShifted);
MOZ_ASSERT(
static_cast<HeapSlot*>(obj->getDenseElements() + (slot - numShifted))
->get() == target);
}
AssertTargetIsNotGray(obj);
}
bool CurrentThreadIsIonCompiling() { return TlsContext.get()->ionCompiling; }
bool CurrentThreadIsIonCompilingSafeForMinorGC() {
return TlsContext.get()->ionCompilingSafeForMinorGC;
}
bool CurrentThreadIsGCSweeping() { return TlsContext.get()->gcSweeping; }
bool CurrentThreadIsTouchingGrayThings() {
return TlsContext.get()->isTouchingGrayThings;
}
AutoTouchingGrayThings::AutoTouchingGrayThings() {
TlsContext.get()->isTouchingGrayThings++;
}
AutoTouchingGrayThings::~AutoTouchingGrayThings() {
JSContext* cx = TlsContext.get();
MOZ_ASSERT(cx->isTouchingGrayThings);
cx->isTouchingGrayThings--;
}
#endif
void InternalBarrierMethods<Value>::readBarrier(const Value& v) {
ApplyGCThingTyped(v, [](auto t) { t->readBarrier(t); });
}
void InternalBarrierMethods<Value>::preBarrier(const Value& v) {
ApplyGCThingTyped(v, [](auto t) { t->writeBarrierPre(t); });
}
void InternalBarrierMethods<jsid>::preBarrier(jsid id) {
ApplyGCThingTyped(id, [](auto t) { t->writeBarrierPre(t); });
}
template <typename T>
bool MovableCellHasher<T>::hasHash(const Lookup& l) {
if (!l) {
return true;
}
return l->zoneFromAnyThread()->hasUniqueId(l);
}
template <typename T>
bool MovableCellHasher<T>::ensureHash(const Lookup& l) {
if (!l) {
return true;
}
uint64_t unusedId;
return l->zoneFromAnyThread()->getOrCreateUniqueId(l, &unusedId);
}
template <typename T>
HashNumber MovableCellHasher<T>::hash(const Lookup& l) {
if (!l) {
return 0;
}
MOZ_ASSERT(CurrentThreadCanAccessZone(l->zoneFromAnyThread()) ||
l->zoneFromAnyThread()->isSelfHostingZone() ||
CurrentThreadIsPerformingGC());
return l->zoneFromAnyThread()->getHashCodeInfallible(l);
}
template <typename T>
bool MovableCellHasher<T>::match(const Key& k, const Lookup& l) {
if (!k) {
return !l;
}
if (!l) {
return false;
}
MOZ_ASSERT(k);
MOZ_ASSERT(l);
MOZ_ASSERT(CurrentThreadCanAccessZone(l->zoneFromAnyThread()) ||
l->zoneFromAnyThread()->isSelfHostingZone());
Zone* zone = k->zoneFromAnyThread();
if (zone != l->zoneFromAnyThread()) {
return false;
}
#ifdef DEBUG
if (!zone->hasUniqueId(k)) {
Key key = k;
MOZ_ASSERT(IsAboutToBeFinalizedUnbarriered(&key));
}
MOZ_ASSERT(zone->hasUniqueId(l));
#endif
uint64_t keyId;
if (!zone->maybeGetUniqueId(k, &keyId)) {
return false;
}
return keyId == zone->getUniqueIdInfallible(l);
}
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wattributes"
#endif
template struct JS_PUBLIC_API MovableCellHasher<JSObject*>;
template struct JS_PUBLIC_API MovableCellHasher<GlobalObject*>;
template struct JS_PUBLIC_API MovableCellHasher<SavedFrame*>;
template struct JS_PUBLIC_API MovableCellHasher<EnvironmentObject*>;
template struct JS_PUBLIC_API MovableCellHasher<WasmInstanceObject*>;
template struct JS_PUBLIC_API MovableCellHasher<JSScript*>;
template struct JS_PUBLIC_API MovableCellHasher<LazyScript*>;
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
# pragma GCC diagnostic pop
#endif
}
JS_PUBLIC_API void JS::HeapObjectPostBarrier(JSObject** objp, JSObject* prev,
JSObject* next) {
MOZ_ASSERT(objp);
js::InternalBarrierMethods<JSObject*>::postBarrier(objp, prev, next);
}
JS_PUBLIC_API void JS::HeapStringPostBarrier(JSString** strp, JSString* prev,
JSString* next) {
MOZ_ASSERT(strp);
js::InternalBarrierMethods<JSString*>::postBarrier(strp, prev, next);
}
JS_PUBLIC_API void JS::HeapValuePostBarrier(JS::Value* valuep,
const Value& prev,
const Value& next) {
MOZ_ASSERT(valuep);
js::InternalBarrierMethods<JS::Value>::postBarrier(valuep, prev, next);
}