| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_SLOT_SET_H | 5 #ifndef V8_SLOT_SET_H |
| 6 #define V8_SLOT_SET_H | 6 #define V8_SLOT_SET_H |
| 7 | 7 |
| 8 #include <stack> | 8 #include <stack> |
| 9 | 9 |
| 10 #include "src/allocation.h" | 10 #include "src/allocation.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 uint32_t cell = current_bucket[cell_index].Value(); | 73 uint32_t cell = current_bucket[cell_index].Value(); |
| 74 if (cell) { | 74 if (cell) { |
| 75 uint32_t bit_mask = 1u << bit_index; | 75 uint32_t bit_mask = 1u << bit_index; |
| 76 if (cell & bit_mask) { | 76 if (cell & bit_mask) { |
| 77 current_bucket[cell_index].ClearBit(bit_index); | 77 current_bucket[cell_index].ClearBit(bit_index); |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 void PreFreeEmptyBucket(int bucket_index) { |
| 84 base::AtomicValue<uint32_t>* bucket_ptr = bucket[bucket_index].Value(); |
| 85 if (bucket_ptr != nullptr) { |
| 86 base::LockGuard<base::Mutex> guard(&to_be_freed_buckets_mutex_); |
| 87 to_be_freed_buckets_.push(bucket_ptr); |
| 88 bucket[bucket_index].SetValue(nullptr); |
| 89 } |
| 90 } |
| 91 |
| 83 // The slot offsets specify a range of slots at addresses: | 92 // The slot offsets specify a range of slots at addresses: |
| 84 // [page_start_ + start_offset ... page_start_ + end_offset). | 93 // [page_start_ + start_offset ... page_start_ + end_offset). |
| 85 void RemoveRange(int start_offset, int end_offset, EmptyBucketMode mode) { | 94 void RemoveRange(int start_offset, int end_offset, EmptyBucketMode mode) { |
| 86 CHECK_LE(end_offset, 1 << kPageSizeBits); | 95 CHECK_LE(end_offset, 1 << kPageSizeBits); |
| 87 DCHECK_LE(start_offset, end_offset); | 96 DCHECK_LE(start_offset, end_offset); |
| 88 int start_bucket, start_cell, start_bit; | 97 int start_bucket, start_cell, start_bit; |
| 89 SlotToIndices(start_offset, &start_bucket, &start_cell, &start_bit); | 98 SlotToIndices(start_offset, &start_bucket, &start_cell, &start_bit); |
| 90 int end_bucket, end_cell, end_bit; | 99 int end_bucket, end_cell, end_bit; |
| 91 SlotToIndices(end_offset, &end_bucket, &end_cell, &end_bit); | 100 SlotToIndices(end_offset, &end_bucket, &end_cell, &end_bit); |
| 92 uint32_t start_mask = (1u << start_bit) - 1; | 101 uint32_t start_mask = (1u << start_bit) - 1; |
| 93 uint32_t end_mask = ~((1u << end_bit) - 1); | 102 uint32_t end_mask = ~((1u << end_bit) - 1); |
| 94 if (start_bucket == end_bucket && start_cell == end_cell) { | 103 if (start_bucket == end_bucket && start_cell == end_cell) { |
| 95 ClearCell(start_bucket, start_cell, ~(start_mask | end_mask)); | 104 ClearCell(start_bucket, start_cell, ~(start_mask | end_mask)); |
| 96 return; | 105 return; |
| 97 } | 106 } |
| 98 int current_bucket = start_bucket; | 107 int current_bucket = start_bucket; |
| 99 int current_cell = start_cell; | 108 int current_cell = start_cell; |
| 100 ClearCell(current_bucket, current_cell, ~start_mask); | 109 ClearCell(current_bucket, current_cell, ~start_mask); |
| 101 current_cell++; | 110 current_cell++; |
| 102 base::AtomicValue<uint32_t>* bucket_ptr = bucket[current_bucket].Value(); | |
| 103 if (current_bucket < end_bucket) { | 111 if (current_bucket < end_bucket) { |
| 104 if (bucket_ptr != nullptr) { | 112 if (bucket[current_bucket].Value() != nullptr) { |
| 105 ClearBucket(bucket_ptr, current_cell, kCellsPerBucket); | 113 while (current_cell < kCellsPerBucket) { |
| 114 bucket[current_bucket].Value()[current_cell].SetValue(0); |
| 115 current_cell++; |
| 116 } |
| 106 } | 117 } |
| 107 // The rest of the current bucket is cleared. | 118 // The rest of the current bucket is cleared. |
| 108 // Move on to the next bucket. | 119 // Move on to the next bucket. |
| 109 current_bucket++; | 120 current_bucket++; |
| 110 current_cell = 0; | 121 current_cell = 0; |
| 111 } | 122 } |
| 112 DCHECK(current_bucket == end_bucket || | 123 DCHECK(current_bucket == end_bucket || |
| 113 (current_bucket < end_bucket && current_cell == 0)); | 124 (current_bucket < end_bucket && current_cell == 0)); |
| 114 while (current_bucket < end_bucket) { | 125 while (current_bucket < end_bucket) { |
| 115 if (mode == PREFREE_EMPTY_BUCKETS) { | 126 if (mode == PREFREE_EMPTY_BUCKETS) { |
| 116 PreFreeEmptyBucket(current_bucket); | 127 PreFreeEmptyBucket(current_bucket); |
| 117 } else if (mode == FREE_EMPTY_BUCKETS) { | 128 } else if (mode == FREE_EMPTY_BUCKETS) { |
| 118 ReleaseBucket(current_bucket); | 129 ReleaseBucket(current_bucket); |
| 119 } else { | |
| 120 DCHECK(mode == KEEP_EMPTY_BUCKETS); | |
| 121 bucket_ptr = bucket[current_bucket].Value(); | |
| 122 if (bucket_ptr) { | |
| 123 ClearBucket(bucket_ptr, 0, kCellsPerBucket); | |
| 124 } | |
| 125 } | 130 } |
| 126 current_bucket++; | 131 current_bucket++; |
| 127 } | 132 } |
| 128 // All buckets between start_bucket and end_bucket are cleared. | 133 // All buckets between start_bucket and end_bucket are cleared. |
| 129 bucket_ptr = bucket[current_bucket].Value(); | |
| 130 DCHECK(current_bucket == end_bucket && current_cell <= end_cell); | 134 DCHECK(current_bucket == end_bucket && current_cell <= end_cell); |
| 131 if (current_bucket == kBuckets || bucket_ptr == nullptr) { | 135 if (current_bucket == kBuckets || |
| 136 bucket[current_bucket].Value() == nullptr) { |
| 132 return; | 137 return; |
| 133 } | 138 } |
| 134 while (current_cell < end_cell) { | 139 while (current_cell < end_cell) { |
| 135 bucket_ptr[current_cell].SetValue(0); | 140 bucket[current_bucket].Value()[current_cell].SetValue(0); |
| 136 current_cell++; | 141 current_cell++; |
| 137 } | 142 } |
| 138 // All cells between start_cell and end_cell are cleared. | 143 // All cells between start_cell and end_cell are cleared. |
| 139 DCHECK(current_bucket == end_bucket && current_cell == end_cell); | 144 DCHECK(current_bucket == end_bucket && current_cell == end_cell); |
| 140 ClearCell(end_bucket, end_cell, ~end_mask); | 145 ClearCell(end_bucket, end_cell, ~end_mask); |
| 141 } | 146 } |
| 142 | 147 |
| 143 // The slot offset specifies a slot at address page_start_ + slot_offset. | 148 // The slot offset specifies a slot at address page_start_ + slot_offset. |
| 144 bool Lookup(int slot_offset) { | 149 bool Lookup(int slot_offset) { |
| 145 int bucket_index, cell_index, bit_index; | 150 int bucket_index, cell_index, bit_index; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 | 235 |
| 231 base::AtomicValue<uint32_t>* AllocateBucket() { | 236 base::AtomicValue<uint32_t>* AllocateBucket() { |
| 232 base::AtomicValue<uint32_t>* result = | 237 base::AtomicValue<uint32_t>* result = |
| 233 NewArray<base::AtomicValue<uint32_t>>(kCellsPerBucket); | 238 NewArray<base::AtomicValue<uint32_t>>(kCellsPerBucket); |
| 234 for (int i = 0; i < kCellsPerBucket; i++) { | 239 for (int i = 0; i < kCellsPerBucket; i++) { |
| 235 result[i].SetValue(0); | 240 result[i].SetValue(0); |
| 236 } | 241 } |
| 237 return result; | 242 return result; |
| 238 } | 243 } |
| 239 | 244 |
| 240 void ClearBucket(base::AtomicValue<uint32_t>* bucket, int start_cell, | |
| 241 int end_cell) { | |
| 242 DCHECK_GE(start_cell, 0); | |
| 243 DCHECK_LE(end_cell, kCellsPerBucket); | |
| 244 int current_cell = start_cell; | |
| 245 while (current_cell < kCellsPerBucket) { | |
| 246 bucket[current_cell].SetValue(0); | |
| 247 current_cell++; | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 void PreFreeEmptyBucket(int bucket_index) { | |
| 252 base::AtomicValue<uint32_t>* bucket_ptr = bucket[bucket_index].Value(); | |
| 253 if (bucket_ptr != nullptr) { | |
| 254 base::LockGuard<base::Mutex> guard(&to_be_freed_buckets_mutex_); | |
| 255 to_be_freed_buckets_.push(bucket_ptr); | |
| 256 bucket[bucket_index].SetValue(nullptr); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 void ReleaseBucket(int bucket_index) { | 245 void ReleaseBucket(int bucket_index) { |
| 261 DeleteArray<base::AtomicValue<uint32_t>>(bucket[bucket_index].Value()); | 246 DeleteArray<base::AtomicValue<uint32_t>>(bucket[bucket_index].Value()); |
| 262 bucket[bucket_index].SetValue(nullptr); | 247 bucket[bucket_index].SetValue(nullptr); |
| 263 } | 248 } |
| 264 | 249 |
| 265 void ClearCell(int bucket_index, int cell_index, uint32_t mask) { | 250 void ClearCell(int bucket_index, int cell_index, uint32_t mask) { |
| 266 if (bucket_index < kBuckets) { | 251 if (bucket_index < kBuckets) { |
| 267 base::AtomicValue<uint32_t>* cells = bucket[bucket_index].Value(); | 252 base::AtomicValue<uint32_t>* cells = bucket[bucket_index].Value(); |
| 268 if (cells != nullptr) { | 253 if (cells != nullptr) { |
| 269 uint32_t cell = cells[cell_index].Value(); | 254 uint32_t cell = cells[cell_index].Value(); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 Address page_start_; | 484 Address page_start_; |
| 500 base::AtomicValue<Chunk*> chunk_; | 485 base::AtomicValue<Chunk*> chunk_; |
| 501 base::Mutex to_be_freed_chunks_mutex_; | 486 base::Mutex to_be_freed_chunks_mutex_; |
| 502 std::stack<Chunk*> to_be_freed_chunks_; | 487 std::stack<Chunk*> to_be_freed_chunks_; |
| 503 }; | 488 }; |
| 504 | 489 |
| 505 } // namespace internal | 490 } // namespace internal |
| 506 } // namespace v8 | 491 } // namespace v8 |
| 507 | 492 |
| 508 #endif // V8_SLOT_SET_H | 493 #endif // V8_SLOT_SET_H |
| OLD | NEW |