Skip to content

Commit

Permalink
Collapse write barrier function for HV and SHV (facebook#1501)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#1501

Collapse them to `GCHermesValueBase` since the implementation is
exactly the same. This will make future changes to these functions
easier.

Differential Revision: D62158417
  • Loading branch information
lavenzg authored and facebook-github-bot committed Nov 8, 2024
1 parent 34154c4 commit b3db0ce
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 163 deletions.
26 changes: 11 additions & 15 deletions include/hermes/VM/GCBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1152,29 +1152,25 @@ class GCBase {

#ifdef HERMESVM_GC_RUNTIME
/// Default implementations for read and write barriers: do nothing.
void writeBarrier(const GCHermesValue *loc, HermesValue value);
void writeBarrier(const GCSmallHermesValue *loc, SmallHermesValue value);
template <typename HVType>
void writeBarrier(const GCHermesValueBase<HVType> *loc, HVType value);
void writeBarrier(const GCPointerBase *loc, const GCCell *value);
void constructorWriteBarrier(const GCHermesValue *loc, HermesValue value);
template <typename HVType>
void constructorWriteBarrier(
const GCSmallHermesValue *loc,
SmallHermesValue value);
const GCHermesValueBase<HVType> *loc,
HVType value);
void constructorWriteBarrier(const GCPointerBase *loc, const GCCell *value);
void writeBarrierRange(const GCHermesValue *start, uint32_t numHVs);
void writeBarrierRange(const GCSmallHermesValue *start, uint32_t numHVs);
void constructorWriteBarrierRange(
const GCHermesValue *start,
uint32_t numHVs);
template <typename HVType>
void constructorWriteBarrierRange(
const GCSmallHermesValue *start,
const GCHermesValueBase<HVType> *start,
uint32_t numHVs);
void snapshotWriteBarrier(const GCHermesValue *loc);
void snapshotWriteBarrier(const GCSmallHermesValue *loc);
template <typename HVType>
void snapshotWriteBarrier(const GCHermesValueBase<HVType> *loc);
void snapshotWriteBarrier(const GCPointerBase *loc);
void snapshotWriteBarrier(const GCSymbolID *symbol);
void snapshotWriteBarrierRange(const GCHermesValue *start, uint32_t numHVs);
template <typename HVType>
void snapshotWriteBarrierRange(
const GCSmallHermesValue *start,
const GCHermesValueBase<HVType> *start,
uint32_t numHVs);
void weakRefReadBarrier(HermesValue value);
void weakRefReadBarrier(GCCell *value);
Expand Down
101 changes: 51 additions & 50 deletions include/hermes/VM/HadesGC.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,25 +152,25 @@ class HadesGC final : public GCBase {
/// be in the heap). If value is a pointer, execute a write barrier.
/// NOTE: The write barrier call must be placed *before* the write to the
/// pointer, so that the current value can be fetched.
void writeBarrier(const GCHermesValue *loc, HermesValue value) {
template <typename HVType>
void writeBarrier(const GCHermesValueBase<HVType> *loc, HVType value) {
assert(
!calledByBackgroundThread() &&
"Write barrier invoked by background thread.");
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(loc)))
writeBarrierSlow(loc, value);
}
void writeBarrierSlow(const GCHermesValue *loc, HermesValue value);

void writeBarrier(const GCSmallHermesValue *loc, SmallHermesValue value) {
assert(
!calledByBackgroundThread() &&
"Write barrier invoked by background thread.");
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(loc)))
writeBarrierSlow(loc, value);
template <typename HVType>
void writeBarrierSlow(const GCHermesValueBase<HVType> *loc, HVType value) {
if (ogMarkingBarriers_) {
snapshotWriteBarrierInternal(*loc);
}
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer(getPointerBase()));
}
void writeBarrierSlow(const GCSmallHermesValue *loc, SmallHermesValue value);

/// The given pointer value is being written at the given loc (required to
/// be in the heap). The value may be null. Execute a write barrier.
Expand All @@ -188,57 +188,60 @@ class HadesGC final : public GCBase {

/// Special versions of \p writeBarrier for when there was no previous value
/// initialized into the space.
void constructorWriteBarrier(const GCHermesValue *loc, HermesValue value) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(loc)))
constructorWriteBarrierSlow(loc, value);
}
void constructorWriteBarrierSlow(const GCHermesValue *loc, HermesValue value);

template <typename HVType>
void constructorWriteBarrier(
const GCSmallHermesValue *loc,
SmallHermesValue value) {
const GCHermesValueBase<HVType> *loc,
HVType value) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(loc)))
constructorWriteBarrierSlow(loc, value);
}
template <typename HVType>
void constructorWriteBarrierSlow(
const GCSmallHermesValue *loc,
SmallHermesValue value);
const GCHermesValueBase<HVType> *loc,
HVType value) {
// A constructor never needs to execute a SATB write barrier, since its
// previous value was definitely not live.
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer(getPointerBase()));
}

void constructorWriteBarrier(const GCPointerBase *loc, const GCCell *value) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(loc)))
relocationWriteBarrier(loc, value);
}

template <typename HVType>
void constructorWriteBarrierRange(
const GCHermesValue *start,
const GCHermesValueBase<HVType> *start,
uint32_t numHVs) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(start)))
constructorWriteBarrierRangeSlow(start, numHVs);
}
template <typename HVType>
void constructorWriteBarrierRangeSlow(
const GCHermesValue *start,
uint32_t numHVs);

void constructorWriteBarrierRange(
const GCSmallHermesValue *start,
const GCHermesValueBase<HVType> *start,
uint32_t numHVs) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(start)))
constructorWriteBarrierRangeSlow(start, numHVs);
}
void constructorWriteBarrierRangeSlow(
const GCSmallHermesValue *start,
uint32_t numHVs);
assert(
AlignedHeapSegment::containedInSame(start, start + numHVs) &&
"Range must start and end within a heap segment.");

void snapshotWriteBarrier(const GCHermesValue *loc) {
if (LLVM_UNLIKELY(!inYoungGen(loc) && ogMarkingBarriers_))
snapshotWriteBarrierInternal(*loc);
// Most constructors should be running in the YG, so in the common case, we
// can avoid doing anything for the whole range. If the range is in the OG,
// then just dirty all the cards corresponding to it, and we can scan them
// for pointers later. This is less precise but makes the write barrier
// faster.

AlignedHeapSegment::cardTableCovering(start)->dirtyCardsForAddressRange(
start, start + numHVs);
}
void snapshotWriteBarrier(const GCSmallHermesValue *loc) {

template <typename HVType>
void snapshotWriteBarrier(const GCHermesValueBase<HVType> *loc) {
if (LLVM_UNLIKELY(!inYoungGen(loc) && ogMarkingBarriers_))
snapshotWriteBarrierInternal(*loc);
}
Expand All @@ -252,23 +255,21 @@ class HadesGC final : public GCBase {
snapshotWriteBarrierInternal(*loc);
}

void snapshotWriteBarrierRange(const GCHermesValue *start, uint32_t numHVs) {
if (LLVM_UNLIKELY(!inYoungGen(start) && ogMarkingBarriers_))
snapshotWriteBarrierRangeSlow(start, numHVs);
}
void snapshotWriteBarrierRangeSlow(
const GCHermesValue *start,
uint32_t numHVs);

template <typename HVType>
void snapshotWriteBarrierRange(
const GCSmallHermesValue *start,
const GCHermesValueBase<HVType> *start,
uint32_t numHVs) {
if (LLVM_UNLIKELY(!inYoungGen(start) && ogMarkingBarriers_))
snapshotWriteBarrierRangeSlow(start, numHVs);
}
template <typename HVType>
void snapshotWriteBarrierRangeSlow(
const GCSmallHermesValue *start,
uint32_t numHVs);
const GCHermesValueBase<HVType> *start,
uint32_t numHVs) {
for (uint32_t i = 0; i < numHVs; ++i) {
snapshotWriteBarrierInternal(start[i]);
}
}

/// Add read barrier for \p value. This is only used when reading entry
/// value from WeakMap/WeakSet.
Expand Down
26 changes: 14 additions & 12 deletions include/hermes/VM/MallocGC.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,22 +233,24 @@ class MallocGC final : public GCBase {
virtual void creditExternalMemory(GCCell *alloc, uint32_t size) override;
virtual void debitExternalMemory(GCCell *alloc, uint32_t size) override;

void writeBarrier(const GCHermesValue *, HermesValue) {}
void writeBarrier(const GCSmallHermesValue *, SmallHermesValue) {}
template <typename HVType>
void writeBarrier(const GCHermesValueBase<HVType> *, HVType) {}
void writeBarrier(const GCPointerBase *, const GCCell *) {}
void constructorWriteBarrier(const GCHermesValue *, HermesValue) {}
void constructorWriteBarrier(const GCSmallHermesValue *, SmallHermesValue) {}
template <typename HVType>
void constructorWriteBarrier(const GCHermesValueBase<HVType> *, HVType) {}
void constructorWriteBarrier(const GCPointerBase *, const GCCell *) {}
void writeBarrierRange(const GCHermesValue *, uint32_t) {}
void writeBarrierRange(const GCSmallHermesValue *, uint32_t) {}
void constructorWriteBarrierRange(const GCHermesValue *, uint32_t) {}
void constructorWriteBarrierRange(const GCSmallHermesValue *, uint32_t) {}
void snapshotWriteBarrier(const GCHermesValue *) {}
void snapshotWriteBarrier(const GCSmallHermesValue *) {}
template <typename HVType>
void writeBarrierRange(const GCHermesValueBase<HVType> *, uint32_t) {}
template <typename HVType>
void constructorWriteBarrierRange(
const GCHermesValueBase<HVType> *,
uint32_t) {}
template <typename HVType>
void snapshotWriteBarrier(const GCHermesValueBase<HVType> *) {}
void snapshotWriteBarrier(const GCPointerBase *) {}
void snapshotWriteBarrier(const GCSymbolID *) {}
void snapshotWriteBarrierRange(const GCHermesValue *, uint32_t) {}
void snapshotWriteBarrierRange(const GCSmallHermesValue *, uint32_t) {}
template <typename HVType>
void snapshotWriteBarrierRange(const GCHermesValueBase<HVType> *, uint32_t) {}
void weakRefReadBarrier(HermesValue) {}
void weakRefReadBarrier(GCCell *) {}

Expand Down
86 changes: 0 additions & 86 deletions lib/VM/gcs/HadesGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1902,28 +1902,6 @@ void HadesGC::debitExternalMemory(GCCell *cell, uint32_t sz) {
}
}

void HadesGC::writeBarrierSlow(const GCHermesValue *loc, HermesValue value) {
if (ogMarkingBarriers_) {
snapshotWriteBarrierInternal(*loc);
}
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer());
}

void HadesGC::writeBarrierSlow(
const GCSmallHermesValue *loc,
SmallHermesValue value) {
if (ogMarkingBarriers_) {
snapshotWriteBarrierInternal(*loc);
}
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer(getPointerBase()));
}

void HadesGC::writeBarrierSlow(const GCPointerBase *loc, const GCCell *value) {
if (*loc && ogMarkingBarriers_)
snapshotWriteBarrierInternal(*loc);
Expand All @@ -1932,70 +1910,6 @@ void HadesGC::writeBarrierSlow(const GCPointerBase *loc, const GCCell *value) {
relocationWriteBarrier(loc, value);
}

void HadesGC::constructorWriteBarrierSlow(
const GCHermesValue *loc,
HermesValue value) {
// A constructor never needs to execute a SATB write barrier, since its
// previous value was definitely not live.
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer());
}

void HadesGC::constructorWriteBarrierSlow(
const GCSmallHermesValue *loc,
SmallHermesValue value) {
// A constructor never needs to execute a SATB write barrier, since its
// previous value was definitely not live.
if (!value.isPointer()) {
return;
}
relocationWriteBarrier(loc, value.getPointer(getPointerBase()));
}

void HadesGC::constructorWriteBarrierRangeSlow(
const GCHermesValue *start,
uint32_t numHVs) {
assert(
AlignedHeapSegment::containedInSame(start, start + numHVs) &&
"Range must start and end within a heap segment.");

// Most constructors should be running in the YG, so in the common case, we
// can avoid doing anything for the whole range. If the range is in the OG,
// then just dirty all the cards corresponding to it, and we can scan them for
// pointers later. This is less precise but makes the write barrier faster.

AlignedHeapSegment::cardTableCovering(start)->dirtyCardsForAddressRange(
start, start + numHVs);
}

void HadesGC::constructorWriteBarrierRangeSlow(
const GCSmallHermesValue *start,
uint32_t numHVs) {
assert(
AlignedHeapSegment::containedInSame(start, start + numHVs) &&
"Range must start and end within a heap segment.");
AlignedHeapSegment::cardTableCovering(start)->dirtyCardsForAddressRange(
start, start + numHVs);
}

void HadesGC::snapshotWriteBarrierRangeSlow(
const GCHermesValue *start,
uint32_t numHVs) {
for (uint32_t i = 0; i < numHVs; ++i) {
snapshotWriteBarrierInternal(start[i]);
}
}

void HadesGC::snapshotWriteBarrierRangeSlow(
const GCSmallHermesValue *start,
uint32_t numHVs) {
for (uint32_t i = 0; i < numHVs; ++i) {
snapshotWriteBarrierInternal(start[i]);
}
}

void HadesGC::snapshotWriteBarrierInternal(GCCell *oldValue) {
assert(
(oldValue->isValid()) &&
Expand Down

0 comments on commit b3db0ce

Please sign in to comment.