@@ -63,11 +63,9 @@ class CardTable {
63
63
static constexpr size_t kCardSize = 1 << kLogCardSize ; // ==> 512-byte cards.
64
64
static constexpr size_t kSegmentSize = 1 << HERMESVM_LOG_HEAP_SEGMENT_SIZE;
65
65
66
- // / The number of valid indices into the card table.
67
- static constexpr size_t kValidIndices = kSegmentSize >> kLogCardSize ;
68
-
69
- // / The size of the card table.
70
- static constexpr size_t kCardTableSize = kValidIndices ;
66
+ // / The size of the maximum inline card table. CardStatus array and boundary
67
+ // / array for larger segment has larger size and is stored separately.
68
+ static constexpr size_t kInlineCardTableSize = kSegmentSize >> kLogCardSize ;
71
69
72
70
// / For convenience, this is a conversion factor to determine how many bytes
73
71
// / in the heap correspond to a single byte in the card table. This is
@@ -93,10 +91,15 @@ class CardTable {
93
91
// / since the CardTable contains two byte arrays of that size (cards_ and
94
92
// / boundaries_). And this index must be larger than the size of SHSegmentInfo
95
93
// / to avoid corrupting it when clearing/dirtying bits.
96
- static constexpr size_t kFirstUsedIndex =
97
- std::max (sizeof (SHSegmentInfo), (2 * kCardTableSize ) >> kLogCardSize );
98
-
99
- CardTable () = default ;
94
+ static constexpr size_t kFirstUsedIndex = std::max(
95
+ sizeof (SHSegmentInfo),
96
+ (2 * kInlineCardTableSize ) >> kLogCardSize );
97
+
98
+ CardTable () {
99
+ // Preserve the segment size.
100
+ segmentInfo_.shiftedSegmentSize =
101
+ kSegmentSize >> HERMESVM_LOG_HEAP_SEGMENT_SIZE;
102
+ }
100
103
// / CardTable is not copyable or movable: It must be constructed in-place.
101
104
CardTable (const CardTable &) = delete;
102
105
CardTable (CardTable &&) = delete;
@@ -187,6 +190,18 @@ class CardTable {
187
190
// / is the first object.)
188
191
GCCell *firstObjForCard (unsigned index) const ;
189
192
193
+ // / Get the segment size from SHSegmentInfo. This is only used in debug code
194
+ // / or when clearing the entire card table.
195
+ size_t getSegmentSize () const {
196
+ return (size_t )segmentInfo_.shiftedSegmentSize
197
+ << HERMESVM_LOG_HEAP_SEGMENT_SIZE;
198
+ }
199
+
200
+ // / The end index of the card table (all valid indices should be smaller).
201
+ size_t getEndIndex () const {
202
+ return getSegmentSize () >> kLogCardSize ;
203
+ }
204
+
190
205
#ifdef HERMES_EXTRA_DEBUG
191
206
// / Temporary debugging hack: yield the numeric value of the boundaries_ array
192
207
// / for the given \p index.
@@ -218,9 +233,11 @@ class CardTable {
218
233
219
234
private:
220
235
#ifndef NDEBUG
221
- // / Returns the pointer to the end of the storage containing \p ptr
222
- // / (exclusive).
223
- static void *storageEnd (const void *ptr);
236
+ // / Returns the pointer to the end of the storage starting at \p lowLim.
237
+ void *storageEnd (const void *lowLim) const {
238
+ return reinterpret_cast <char *>(
239
+ reinterpret_cast <uintptr_t >(lowLim) + getSegmentSize ());
240
+ }
224
241
#endif
225
242
226
243
enum class CardStatus : char { Clean = 0 , Dirty = 1 };
@@ -264,7 +281,7 @@ class CardTable {
264
281
SHSegmentInfo segmentInfo_;
265
282
// / This needs to be atomic so that the background thread in Hades can
266
283
// / safely dirty cards when compacting.
267
- std::array<AtomicIfConcurrentGC<CardStatus>, kCardTableSize > cards_{};
284
+ std::array<AtomicIfConcurrentGC<CardStatus>, kInlineCardTableSize > cards_{};
268
285
};
269
286
270
287
// / See the comment at kHeapBytesPerCardByte above to see why this is
@@ -283,7 +300,7 @@ class CardTable {
283
300
// / time: If we allocate a large object that crosses many cards, the first
284
301
// / crossed cards gets a non-negative value, and each subsequent one uses the
285
302
// / maximum exponent that stays within the card range for the object.
286
- int8_t boundaries_[kCardTableSize ];
303
+ int8_t boundaries_[kInlineCardTableSize ];
287
304
};
288
305
289
306
// / Implementations of inlines.
@@ -313,7 +330,7 @@ inline size_t CardTable::addressToIndex(const void *addr) const {
313
330
}
314
331
315
332
inline const char *CardTable::indexToAddress (size_t index) const {
316
- assert (index <= kValidIndices && " index must be within the index range" );
333
+ assert (index <= getEndIndex () && " index must be within the index range" );
317
334
const char *res = base () + (index << kLogCardSize );
318
335
assert (
319
336
base () <= res && res <= storageEnd (base ()) &&
@@ -331,7 +348,7 @@ inline bool CardTable::isCardForAddressDirty(const void *addr) const {
331
348
}
332
349
333
350
inline bool CardTable::isCardForIndexDirty (size_t index) const {
334
- assert (index < kValidIndices && " index is required to be in range." );
351
+ assert (index < getEndIndex () && " index is required to be in range." );
335
352
return cards_[index ].load (std::memory_order_relaxed) == CardStatus::Dirty;
336
353
}
337
354
0 commit comments