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 |