Skip to content

Commit

Permalink
Update constructorWriteBarrierRange
Browse files Browse the repository at this point in the history
Differential Revision: D62171114
  • Loading branch information
lavenzg authored and facebook-github-bot committed Dec 2, 2024
1 parent f4b85df commit e8d567f
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 15 deletions.
2 changes: 1 addition & 1 deletion include/hermes/VM/ArrayStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class ArrayStorageBase final
auto *fromStart = other->data();
auto *fromEnd = fromStart + otherSz;
GCHVType::uninitialized_copy(
fromStart, fromEnd, data() + sz, runtime.getHeap());
fromStart, fromEnd, data() + sz, this, runtime.getHeap());
size_.store(sz + otherSz, std::memory_order_release);
}

Expand Down
2 changes: 2 additions & 0 deletions include/hermes/VM/GCBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1163,9 +1163,11 @@ class GCBase {
void writeBarrierRange(const GCHermesValue *start, uint32_t numHVs);
void writeBarrierRange(const GCSmallHermesValue *start, uint32_t numHVs);
void constructorWriteBarrierRange(
const GCCell *owningObj,
const GCHermesValue *start,
uint32_t numHVs);
void constructorWriteBarrierRange(
const GCCell *owningObj,
const GCSmallHermesValue *start,
uint32_t numHVs);
void snapshotWriteBarrier(const GCHermesValue *loc);
Expand Down
8 changes: 6 additions & 2 deletions include/hermes/VM/HadesGC.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,24 +213,28 @@ class HadesGC final : public GCBase {
}

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

void constructorWriteBarrierRange(
const GCCell *owningObj,
const GCSmallHermesValue *start,
uint32_t numHVs) {
// A pointer that lives in YG never needs any write barriers.
if (LLVM_UNLIKELY(!inYoungGen(start)))
constructorWriteBarrierRangeSlow(start, numHVs);
constructorWriteBarrierRangeSlow(owningObj, start, numHVs);
}
void constructorWriteBarrierRangeSlow(
const GCCell *owningObj,
const GCSmallHermesValue *start,
uint32_t numHVs);

Expand Down
3 changes: 2 additions & 1 deletion include/hermes/VM/HermesValue-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ inline GCHermesValueBase<HVType> *GCHermesValueBase<HVType>::uninitialized_copy(
GCHermesValueBase<HVType> *first,
GCHermesValueBase<HVType> *last,
GCHermesValueBase<HVType> *result,
const GCCell *owningObj,
GC &gc) {
#ifndef NDEBUG
uintptr_t fromFirst = reinterpret_cast<uintptr_t>(first),
Expand All @@ -194,7 +195,7 @@ inline GCHermesValueBase<HVType> *GCHermesValueBase<HVType>::uninitialized_copy(
"Uninitialized range cannot overlap with an initialized one.");
#endif

gc.constructorWriteBarrierRange(result, last - first);
gc.constructorWriteBarrierRange(owningObj, result, last - first);
// memcpy is fine for an uninitialized copy.
std::memcpy(
reinterpret_cast<void *>(result), first, (last - first) * sizeof(HVType));
Expand Down
1 change: 1 addition & 0 deletions include/hermes/VM/HermesValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ class GCHermesValueBase final : public HVType {
GCHermesValueBase<HVType> *first,
GCHermesValueBase<HVType> *last,
GCHermesValueBase<HVType> *result,
const GCCell *owningObj,
GC &gc);

/// Copies a range of values and performs a write barrier on each.
Expand Down
10 changes: 8 additions & 2 deletions include/hermes/VM/MallocGC.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,14 @@ class MallocGC final : public GCBase {
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 constructorWriteBarrierRange(
const GCCell *,
const GCHermesValue *,
uint32_t) {}
void constructorWriteBarrierRange(
const GCCell *,
const GCSmallHermesValue *,
uint32_t) {}
void snapshotWriteBarrier(const GCHermesValue *) {}
void snapshotWriteBarrier(const GCSmallHermesValue *) {}
void snapshotWriteBarrier(const GCPointerBase *) {}
Expand Down
3 changes: 2 additions & 1 deletion lib/VM/ArrayStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ ExecutionStatus ArrayStorageBase<HVType>::reallocateToLarger(
{
GCHVType *from = self->data() + fromFirst;
GCHVType *to = newSelf->data() + toFirst;
GCHVType::uninitialized_copy(from, from + copySize, to, runtime.getHeap());
GCHVType::uninitialized_copy(
from, from + copySize, to, newSelf, runtime.getHeap());
}

// Initialize the elements before the first copied element.
Expand Down
14 changes: 12 additions & 2 deletions lib/VM/GCBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,11 @@ bool GCBase::shouldSanitizeHandles() {
runtimeGCDispatch([&](auto *gc) { gc->name(arg1, arg2); }); \
}

#define GCBASE_BARRIER_3(name, type1, type2, type3) \
void GCBase::name(type1 arg1, type2 arg2, type3 arg3) { \
runtimeGCDispatch([&](auto *gc) { gc->name(arg1, arg2, arg3); }); \
}

GCBASE_BARRIER_2(writeBarrier, const GCHermesValue *, HermesValue);
GCBASE_BARRIER_2(writeBarrier, const GCSmallHermesValue *, SmallHermesValue);
GCBASE_BARRIER_2(writeBarrier, const GCPointerBase *, const GCCell *);
Expand All @@ -979,9 +984,14 @@ GCBASE_BARRIER_2(
const GCCell *);
GCBASE_BARRIER_2(writeBarrierRange, const GCHermesValue *, uint32_t);
GCBASE_BARRIER_2(writeBarrierRange, const GCSmallHermesValue *, uint32_t);
GCBASE_BARRIER_2(constructorWriteBarrierRange, const GCHermesValue *, uint32_t);
GCBASE_BARRIER_2(
GCBASE_BARRIER_3(
constructorWriteBarrierRange,
const GCCell *,
const GCHermesValue *,
uint32_t);
GCBASE_BARRIER_3(
constructorWriteBarrierRange,
const GCCell *,
const GCSmallHermesValue *,
uint32_t);
GCBASE_BARRIER_1(snapshotWriteBarrier, const GCHermesValue *);
Expand Down
1 change: 1 addition & 0 deletions lib/VM/SegmentedArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ ExecutionStatus SegmentedArrayBase<HVType>::growRight(
self->inlineStorage(),
self->inlineStorage() + numSlotsUsed,
newSegmentedArray->inlineStorage(),
newSegmentedArray.get(),
runtime.getHeap());
// Set the size of the new array to be the same as the old array's size.
newSegmentedArray->numSlotsUsed_.store(
Expand Down
23 changes: 17 additions & 6 deletions lib/VM/gcs/HadesGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1992,28 +1992,39 @@ void HadesGC::constructorWriteBarrierSlow(
}

void HadesGC::constructorWriteBarrierRangeSlow(
const GCCell *owningObj,
const GCHermesValue *start,
uint32_t numHVs) {
assert(
FixedSizeHeapSegment::containedInSame(start, start + numHVs) &&
"Range must start and end within a heap segment.");
reinterpret_cast<const char *>(owningObj) <=
reinterpret_cast<const char *>(start) &&
reinterpret_cast<const char *>(start + numHVs) <=
(reinterpret_cast<const char *>(owningObj) +
owningObj->getAllocatedSize()) &&
"Range must start and end within the owning object.");

// 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.

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

void HadesGC::constructorWriteBarrierRangeSlow(
const GCCell *owningObj,
const GCSmallHermesValue *start,
uint32_t numHVs) {
assert(
FixedSizeHeapSegment::containedInSame(start, start + numHVs) &&
"Range must start and end within a heap segment.");
FixedSizeHeapSegment::cardTableCovering(start)->dirtyCardsForAddressRange(
reinterpret_cast<const char *>(owningObj) <=
reinterpret_cast<const char *>(start) &&
reinterpret_cast<const char *>(start + numHVs) <=
(reinterpret_cast<const char *>(owningObj) +
owningObj->getAllocatedSize()) &&
"Range must start and end within the owning object.");

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

Expand Down

0 comments on commit e8d567f

Please sign in to comment.