Skip to content

Commit 99c0510

Browse files
lavenzgfacebook-github-bot
authored andcommitted
Pass the pointer of owning object in constructorWriteBarrierRange (#1511)
Summary: Pull Request resolved: #1511 Add a `GCCell` pointer parameter to `constructorWriteBarrierRange`, which represents the owning object address. It's used to get the correct card table for pointers live in large segment. Differential Revision: D62171114
1 parent b420164 commit 99c0510

10 files changed

+45
-16
lines changed

include/hermes/VM/AlignedHeapSegment.h

+10
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,16 @@ class AlignedHeapSegment {
283283
return (cp - base) >> LogHeapAlign;
284284
}
285285

286+
#ifndef NDEBUG
287+
/// Get the storage end of segment that \p cell resides in.
288+
static char *storageEnd(const GCCell *cell) {
289+
auto *start = alignedStorageStart(cell);
290+
auto *segmentInfo = reinterpret_cast<const SHSegmentInfo *>(start);
291+
return start +
292+
(segmentInfo->shiftedSegmentSize << HERMESVM_LOG_HEAP_SEGMENT_SIZE);
293+
}
294+
#endif
295+
286296
protected:
287297
AlignedHeapSegment() = default;
288298

include/hermes/VM/ArrayStorage.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class ArrayStorageBase final
237237
auto *fromStart = other->data();
238238
auto *fromEnd = fromStart + otherSz;
239239
GCHVType::uninitialized_copy(
240-
fromStart, fromEnd, data() + sz, runtime.getHeap());
240+
fromStart, fromEnd, data() + sz, runtime.getHeap(), this);
241241
size_.store(sz + otherSz, std::memory_order_release);
242242
}
243243

include/hermes/VM/GCBase.h

+1
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,7 @@ class GCBase {
11621162
void constructorWriteBarrier(const GCPointerBase *loc, const GCCell *value);
11631163
template <typename HVType>
11641164
void constructorWriteBarrierRange(
1165+
const GCCell *owningObj,
11651166
const GCHermesValueBase<HVType> *start,
11661167
uint32_t numHVs);
11671168
template <typename HVType>

include/hermes/VM/HadesGC.h

+11-8
Original file line numberDiff line numberDiff line change
@@ -216,27 +216,30 @@ class HadesGC final : public GCBase {
216216

217217
template <typename HVType>
218218
void constructorWriteBarrierRange(
219+
const GCCell *owningObj,
219220
const GCHermesValueBase<HVType> *start,
220221
uint32_t numHVs) {
221222
// A pointer that lives in YG never needs any write barriers.
222223
if (LLVM_UNLIKELY(!inYoungGen(start)))
223-
constructorWriteBarrierRangeSlow(start, numHVs);
224+
constructorWriteBarrierRangeSlow(owningObj, start, numHVs);
224225
}
225226
template <typename HVType>
226227
void constructorWriteBarrierRangeSlow(
228+
const GCCell *owningObj,
227229
const GCHermesValueBase<HVType> *start,
228230
uint32_t numHVs) {
229231
assert(
230-
FixedSizeHeapSegment::containedInSame(start, start + numHVs) &&
232+
reinterpret_cast<const char *>(start + numHVs) <
233+
AlignedHeapSegment::storageEnd(owningObj) &&
231234
"Range must start and end within a heap segment.");
232235

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

239-
FixedSizeHeapSegment::cardTableCovering(start)->dirtyCardsForAddressRange(
242+
AlignedHeapSegment::cardTableCovering(owningObj)->dirtyCardsForAddressRange(
240243
start, start + numHVs);
241244
}
242245

include/hermes/VM/HermesValue-inline.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ inline GCHermesValueBase<HVType> *GCHermesValueBase<HVType>::uninitialized_copy(
182182
GCHermesValueBase<HVType> *first,
183183
GCHermesValueBase<HVType> *last,
184184
GCHermesValueBase<HVType> *result,
185-
GC &gc) {
185+
GC &gc,
186+
const GCCell *owningObj) {
186187
#ifndef NDEBUG
187188
uintptr_t fromFirst = reinterpret_cast<uintptr_t>(first),
188189
fromLast = reinterpret_cast<uintptr_t>(last);
@@ -194,7 +195,7 @@ inline GCHermesValueBase<HVType> *GCHermesValueBase<HVType>::uninitialized_copy(
194195
"Uninitialized range cannot overlap with an initialized one.");
195196
#endif
196197

197-
gc.constructorWriteBarrierRange(result, last - first);
198+
gc.constructorWriteBarrierRange(owningObj, result, last - first);
198199
// memcpy is fine for an uninitialized copy.
199200
std::memcpy(
200201
reinterpret_cast<void *>(result), first, (last - first) * sizeof(HVType));

include/hermes/VM/HermesValue.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,8 @@ class GCHermesValueBase final : public HVType {
589589
GCHermesValueBase<HVType> *first,
590590
GCHermesValueBase<HVType> *last,
591591
GCHermesValueBase<HVType> *result,
592-
GC &gc);
592+
GC &gc,
593+
const GCCell *owningObj);
593594

594595
/// Copies a range of values and performs a write barrier on each.
595596
template <typename InputIt, typename OutputIt>

include/hermes/VM/MallocGC.h

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ class MallocGC final : public GCBase {
243243
void writeBarrierRange(const GCHermesValueBase<HVType> *, uint32_t) {}
244244
template <typename HVType>
245245
void constructorWriteBarrierRange(
246+
const GCCell *,
246247
const GCHermesValueBase<HVType> *,
247248
uint32_t) {}
248249
template <typename HVType>

lib/VM/ArrayStorage.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ ExecutionStatus ArrayStorageBase<HVType>::reallocateToLarger(
104104
{
105105
GCHVType *from = self->data() + fromFirst;
106106
GCHVType *to = newSelf->data() + toFirst;
107-
GCHVType::uninitialized_copy(from, from + copySize, to, runtime.getHeap());
107+
GCHVType::uninitialized_copy(
108+
from, from + copySize, to, runtime.getHeap(), newSelf);
108109
}
109110

110111
// Initialize the elements before the first copied element.

lib/VM/GCBase.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,11 @@ bool GCBase::shouldSanitizeHandles() {
965965
runtimeGCDispatch([&](auto *gc) { gc->name(arg1, arg2); }); \
966966
}
967967

968+
#define GCBASE_BARRIER_3(name, type1, type2, type3) \
969+
void GCBase::name(type1 arg1, type2 arg2, type3 arg3) { \
970+
runtimeGCDispatch([&](auto *gc) { gc->name(arg1, arg2, arg3); }); \
971+
}
972+
968973
GCBASE_BARRIER_2(writeBarrier, const GCHermesValue *, HermesValue);
969974
GCBASE_BARRIER_2(writeBarrier, const GCSmallHermesValue *, SmallHermesValue);
970975
GCBASE_BARRIER_2(writeBarrier, const GCPointerBase *, const GCCell *);
@@ -979,9 +984,14 @@ GCBASE_BARRIER_2(
979984
const GCCell *);
980985
GCBASE_BARRIER_2(writeBarrierRange, const GCHermesValue *, uint32_t);
981986
GCBASE_BARRIER_2(writeBarrierRange, const GCSmallHermesValue *, uint32_t);
982-
GCBASE_BARRIER_2(constructorWriteBarrierRange, const GCHermesValue *, uint32_t);
983-
GCBASE_BARRIER_2(
987+
GCBASE_BARRIER_3(
988+
constructorWriteBarrierRange,
989+
const GCCell *,
990+
const GCHermesValue *,
991+
uint32_t);
992+
GCBASE_BARRIER_3(
984993
constructorWriteBarrierRange,
994+
const GCCell *,
985995
const GCSmallHermesValue *,
986996
uint32_t);
987997
GCBASE_BARRIER_1(snapshotWriteBarrier, const GCHermesValue *);

lib/VM/SegmentedArray.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@ ExecutionStatus SegmentedArrayBase<HVType>::growRight(
294294
self->inlineStorage(),
295295
self->inlineStorage() + numSlotsUsed,
296296
newSegmentedArray->inlineStorage(),
297-
runtime.getHeap());
297+
runtime.getHeap(),
298+
newSegmentedArray.get());
298299
// Set the size of the new array to be the same as the old array's size.
299300
newSegmentedArray->numSlotsUsed_.store(
300301
numSlotsUsed, std::memory_order_release);

0 commit comments

Comments
 (0)