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 | |
92 // The slot offsets specify a range of slots at addresses: | 83 // The slot offsets specify a range of slots at addresses: |
93 // [page_start_ + start_offset ... page_start_ + end_offset). | 84 // [page_start_ + start_offset ... page_start_ + end_offset). |
94 void RemoveRange(int start_offset, int end_offset, EmptyBucketMode mode) { | 85 void RemoveRange(int start_offset, int end_offset, EmptyBucketMode mode) { |
95 CHECK_LE(end_offset, 1 << kPageSizeBits); | 86 CHECK_LE(end_offset, 1 << kPageSizeBits); |
96 DCHECK_LE(start_offset, end_offset); | 87 DCHECK_LE(start_offset, end_offset); |
97 int start_bucket, start_cell, start_bit; | 88 int start_bucket, start_cell, start_bit; |
98 SlotToIndices(start_offset, &start_bucket, &start_cell, &start_bit); | 89 SlotToIndices(start_offset, &start_bucket, &start_cell, &start_bit); |
99 int end_bucket, end_cell, end_bit; | 90 int end_bucket, end_cell, end_bit; |
100 SlotToIndices(end_offset, &end_bucket, &end_cell, &end_bit); | 91 SlotToIndices(end_offset, &end_bucket, &end_cell, &end_bit); |
101 uint32_t start_mask = (1u << start_bit) - 1; | 92 uint32_t start_mask = (1u << start_bit) - 1; |
102 uint32_t end_mask = ~((1u << end_bit) - 1); | 93 uint32_t end_mask = ~((1u << end_bit) - 1); |
103 if (start_bucket == end_bucket && start_cell == end_cell) { | 94 if (start_bucket == end_bucket && start_cell == end_cell) { |
104 ClearCell(start_bucket, start_cell, ~(start_mask | end_mask)); | 95 ClearCell(start_bucket, start_cell, ~(start_mask | end_mask)); |
105 return; | 96 return; |
106 } | 97 } |
107 int current_bucket = start_bucket; | 98 int current_bucket = start_bucket; |
108 int current_cell = start_cell; | 99 int current_cell = start_cell; |
109 ClearCell(current_bucket, current_cell, ~start_mask); | 100 ClearCell(current_bucket, current_cell, ~start_mask); |
110 current_cell++; | 101 current_cell++; |
| 102 base::AtomicValue<uint32_t>* bucket_ptr = bucket[current_bucket].Value(); |
111 if (current_bucket < end_bucket) { | 103 if (current_bucket < end_bucket) { |
112 if (bucket[current_bucket].Value() != nullptr) { | 104 if (bucket_ptr != nullptr) { |
113 while (current_cell < kCellsPerBucket) { | 105 ClearBucket(bucket_ptr, current_cell, kCellsPerBucket); |
114 bucket[current_bucket].Value()[current_cell].SetValue(0); | |
115 current_cell++; | |
116 } | |
117 } | 106 } |
118 // The rest of the current bucket is cleared. | 107 // The rest of the current bucket is cleared. |
119 // Move on to the next bucket. | 108 // Move on to the next bucket. |
120 current_bucket++; | 109 current_bucket++; |
121 current_cell = 0; | 110 current_cell = 0; |
122 } | 111 } |
123 DCHECK(current_bucket == end_bucket || | 112 DCHECK(current_bucket == end_bucket || |
124 (current_bucket < end_bucket && current_cell == 0)); | 113 (current_bucket < end_bucket && current_cell == 0)); |
125 while (current_bucket < end_bucket) { | 114 while (current_bucket < end_bucket) { |
126 if (mode == PREFREE_EMPTY_BUCKETS) { | 115 if (mode == PREFREE_EMPTY_BUCKETS) { |
127 PreFreeEmptyBucket(current_bucket); | 116 PreFreeEmptyBucket(current_bucket); |
128 } else if (mode == FREE_EMPTY_BUCKETS) { | 117 } else if (mode == FREE_EMPTY_BUCKETS) { |
129 ReleaseBucket(current_bucket); | 118 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 } |
130 } | 125 } |
131 current_bucket++; | 126 current_bucket++; |
132 } | 127 } |
133 // All buckets between start_bucket and end_bucket are cleared. | 128 // All buckets between start_bucket and end_bucket are cleared. |
| 129 bucket_ptr = bucket[current_bucket].Value(); |
134 DCHECK(current_bucket == end_bucket && current_cell <= end_cell); | 130 DCHECK(current_bucket == end_bucket && current_cell <= end_cell); |
135 if (current_bucket == kBuckets || | 131 if (current_bucket == kBuckets || bucket_ptr == nullptr) { |
136 bucket[current_bucket].Value() == nullptr) { | |
137 return; | 132 return; |
138 } | 133 } |
139 while (current_cell < end_cell) { | 134 while (current_cell < end_cell) { |
140 bucket[current_bucket].Value()[current_cell].SetValue(0); | 135 bucket_ptr[current_cell].SetValue(0); |
141 current_cell++; | 136 current_cell++; |
142 } | 137 } |
143 // All cells between start_cell and end_cell are cleared. | 138 // All cells between start_cell and end_cell are cleared. |
144 DCHECK(current_bucket == end_bucket && current_cell == end_cell); | 139 DCHECK(current_bucket == end_bucket && current_cell == end_cell); |
145 ClearCell(end_bucket, end_cell, ~end_mask); | 140 ClearCell(end_bucket, end_cell, ~end_mask); |
146 } | 141 } |
147 | 142 |
148 // The slot offset specifies a slot at address page_start_ + slot_offset. | 143 // The slot offset specifies a slot at address page_start_ + slot_offset. |
149 bool Lookup(int slot_offset) { | 144 bool Lookup(int slot_offset) { |
150 int bucket_index, cell_index, bit_index; | 145 int bucket_index, cell_index, bit_index; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 | 230 |
236 base::AtomicValue<uint32_t>* AllocateBucket() { | 231 base::AtomicValue<uint32_t>* AllocateBucket() { |
237 base::AtomicValue<uint32_t>* result = | 232 base::AtomicValue<uint32_t>* result = |
238 NewArray<base::AtomicValue<uint32_t>>(kCellsPerBucket); | 233 NewArray<base::AtomicValue<uint32_t>>(kCellsPerBucket); |
239 for (int i = 0; i < kCellsPerBucket; i++) { | 234 for (int i = 0; i < kCellsPerBucket; i++) { |
240 result[i].SetValue(0); | 235 result[i].SetValue(0); |
241 } | 236 } |
242 return result; | 237 return result; |
243 } | 238 } |
244 | 239 |
| 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 |
245 void ReleaseBucket(int bucket_index) { | 260 void ReleaseBucket(int bucket_index) { |
246 DeleteArray<base::AtomicValue<uint32_t>>(bucket[bucket_index].Value()); | 261 DeleteArray<base::AtomicValue<uint32_t>>(bucket[bucket_index].Value()); |
247 bucket[bucket_index].SetValue(nullptr); | 262 bucket[bucket_index].SetValue(nullptr); |
248 } | 263 } |
249 | 264 |
250 void ClearCell(int bucket_index, int cell_index, uint32_t mask) { | 265 void ClearCell(int bucket_index, int cell_index, uint32_t mask) { |
251 if (bucket_index < kBuckets) { | 266 if (bucket_index < kBuckets) { |
252 base::AtomicValue<uint32_t>* cells = bucket[bucket_index].Value(); | 267 base::AtomicValue<uint32_t>* cells = bucket[bucket_index].Value(); |
253 if (cells != nullptr) { | 268 if (cells != nullptr) { |
254 uint32_t cell = cells[cell_index].Value(); | 269 uint32_t cell = cells[cell_index].Value(); |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 Address page_start_; | 499 Address page_start_; |
485 base::AtomicValue<Chunk*> chunk_; | 500 base::AtomicValue<Chunk*> chunk_; |
486 base::Mutex to_be_freed_chunks_mutex_; | 501 base::Mutex to_be_freed_chunks_mutex_; |
487 std::stack<Chunk*> to_be_freed_chunks_; | 502 std::stack<Chunk*> to_be_freed_chunks_; |
488 }; | 503 }; |
489 | 504 |
490 } // namespace internal | 505 } // namespace internal |
491 } // namespace v8 | 506 } // namespace v8 |
492 | 507 |
493 #endif // V8_SLOT_SET_H | 508 #endif // V8_SLOT_SET_H |
OLD | NEW |