5#ifndef V8_HEAP_BASE_BASIC_SLOT_SET_H_
6#define V8_HEAP_BASE_BASIC_SLOT_SET_H_
16class WriteBarrierCodeStubAssembler;
30template <
size_t SlotGranularity>
78 if (slot_set ==
nullptr) {
108 template <AccessMode access_mode>
111 int cell_index, bit_index;
112 SlotToIndices(slot_offset, &bucket_index, &cell_index, &bit_index);
125 uint32_t
mask = 1u << bit_index;
126 if ((
bucket->template LoadCell<access_mode>(cell_index) &
mask) == 0) {
127 bucket->template SetCellBits<access_mode>(cell_index,
mask);
135 int cell_index, bit_index;
136 SlotToIndices(slot_offset, &bucket_index, &cell_index, &bit_index);
138 if (
bucket ==
nullptr)
return false;
145 int cell_index, bit_index;
146 SlotToIndices(slot_offset, &bucket_index, &cell_index, &bit_index);
150 uint32_t bit_mask = 1u << bit_index;
151 if (cell & bit_mask) {
164 int start_cell, start_bit;
165 SlotToIndices(start_offset, &start_bucket, &start_cell, &start_bit);
167 int end_cell, end_bit;
171 SlotToIndices(end_offset - SlotGranularity, &end_bucket, &end_cell,
180 uint32_t start_mask = (1u << start_bit) - 1;
181 uint32_t end_mask = ~((1u << end_bit) - 1);
183 if (start_bucket == end_bucket && start_cell == end_cell) {
190 size_t current_bucket = start_bucket;
191 int current_cell = start_cell;
197 if (current_bucket < end_bucket) {
206 DCHECK(current_bucket == end_bucket ||
207 (current_bucket < end_bucket && current_cell == 0));
208 while (current_bucket < end_bucket) {
221 DCHECK(current_bucket == end_bucket);
222 if (current_bucket ==
buckets)
return;
224 DCHECK(current_cell <= end_cell);
225 if (
bucket ==
nullptr)
return;
226 while (current_cell < end_cell) {
231 DCHECK(current_bucket == end_bucket && current_cell == end_cell);
238 int cell_index, bit_index;
239 SlotToIndices(slot_offset, &bucket_index, &cell_index, &bit_index);
241 if (
bucket ==
nullptr)
return false;
260 template <AccessMode access_mode = AccessMode::ATOMIC,
typename Callback>
264 chunk_start, start_bucket, end_bucket,
callback,
265 [
this, mode](
size_t bucket_index) {
288 uint32_t*
cell(
int cell_index) {
return cells_ + cell_index; }
289 const uint32_t*
cell(
int cell_index)
const {
return cells_ + cell_index; }
291 template <AccessMode access_mode = AccessMode::ATOMIC>
296 return *(
cell(cell_index));
299 template <AccessMode access_mode = AccessMode::ATOMIC>
304 uint32_t* c =
cell(cell_index);
305 *c = (*c & ~mask) |
mask;
309 template <AccessMode access_mode = AccessMode::ATOMIC>
314 *
cell(cell_index) &= ~mask;
336 return *(
reinterpret_cast<const size_t*
>(
this) - 1);
341 typename EmptyBucketCallback>
343 Callback
callback, EmptyBucketCallback empty_bucket_callback) {
344 size_t new_count = 0;
345 for (
size_t bucket_index = start_bucket; bucket_index < end_bucket;
349 size_t in_bucket_count = 0;
352 uint32_t cell =
bucket->template LoadCell<access_mode>(
i);
354 uint32_t old_cell = cell;
358 uint32_t bit_mask = 1u << bit_offset;
359 Address slot = (cell_offset + bit_offset) * SlotGranularity;
367 uint32_t new_cell = old_cell & ~mask;
368 if (old_cell != new_cell) {
369 bucket->template ClearCellBits<access_mode>(
i,
mask);
373 if (in_bucket_count == 0) {
374 empty_bucket_callback(bucket_index);
376 new_count += in_bucket_count;
398 int current_cell = start_cell;
405 template <AccessMode access_mode = AccessMode::ATOMIC>
412 template <AccessMode access_mode = AccessMode::ATOMIC>
419 template <AccessMode access_mode = AccessMode::ATOMIC>
424 template <AccessMode access_mode = AccessMode::ATOMIC>
433 template <AccessMode access_mode = AccessMode::ATOMIC>
438 template <AccessMode access_mode = AccessMode::ATOMIC>
443 b,
nullptr, value) ==
nullptr;
452 void SlotToIndices(
size_t slot_offset,
size_t* bucket_index,
int* cell_index,
455 size_t slot = slot_offset / SlotGranularity;
461 *bit_index =
static_cast<int>(slot & (
kBitsPerCell - 1));
468 *(
reinterpret_cast<size_t*
>(
this) - 1) =
num_buckets;
const uint32_t * cell(int cell_index) const
void SetCellBits(int cell_index, uint32_t mask)
uint32_t * cell(int cell_index)
void ClearCellBits(int cell_index, uint32_t mask)
uint32_t LoadCell(int cell_index)
const uint32_t * cells() const
void StoreCell(int cell_index, uint32_t value)
uint32_t cells_[kCellsPerBucket]
static constexpr int kBitsPerCell
bool Lookup(size_t slot_offset)
void ReleaseBucket(size_t bucket_index)
static constexpr int kCellSizeBytesLog2
static constexpr size_t BucketsForSize(size_t size)
static constexpr int kCellsPerBucketLog2
static void Delete(BasicSlotSet *slot_set)
Bucket * LoadBucket(size_t bucket_index)
void StoreBucket(Bucket **bucket, Bucket *value)
size_t Iterate(Address chunk_start, size_t start_bucket, size_t end_bucket, Callback callback, EmptyBucketMode mode)
static constexpr int kBitsPerCellLog2
static constexpr size_t BucketForSlot(size_t slot_offset)
Bucket ** bucket(size_t bucket_index)
void Insert(size_t slot_offset)
bool FreeBucketIfEmpty(size_t bucket_index)
size_t Iterate(Address chunk_start, size_t start_bucket, size_t end_bucket, Callback callback, EmptyBucketCallback empty_bucket_callback)
static constexpr auto kSystemPointerSize
void RemoveRange(size_t start_offset, size_t end_offset, size_t buckets, EmptyBucketMode mode)
void StoreBucket(size_t bucket_index, Bucket *value)
static constexpr int kCellsPerBucket
void set_num_buckets(size_t num_buckets)
static constexpr int kBitsPerBucket
void SlotToIndices(size_t slot_offset, size_t *bucket_index, int *cell_index, int *bit_index)
Bucket * LoadBucket(Bucket **bucket)
size_t num_buckets() const
static BasicSlotSet * Allocate(size_t buckets)
static constexpr int kCellSizeBytes
bool Contains(size_t slot_offset)
static constexpr size_t OffsetForBucket(size_t bucket_index)
void ClearBucket(Bucket *bucket, int start_cell, int end_cell)
static constexpr int kBitsPerBucketLog2
static constexpr int kNumBucketsSize
bool SwapInNewBucket(size_t bucket_index, Bucket *value)
void Remove(size_t slot_offset)
static void Release_Store(T *addr, typename std::remove_reference< T >::type new_value)
static T Acquire_Load(T *addr)
static T Release_CompareAndSwap(T *addr, typename std::remove_reference< T >::type old_value, typename std::remove_reference< T >::type new_value)
static bool Release_SetBits(T *addr, T bits, T mask)
constexpr unsigned CountTrailingZeros(T value)
void AlignedFree(void *ptr)
void * AlignedAlloc(size_t size, size_t alignment)
#define DCHECK_LE(v1, v2)
#define CHECK_LE(lhs, rhs)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
constexpr bool IsAligned(T value, U alignment)
std::unique_ptr< ValueMirror > value