OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/freelist.h" | 5 #include "vm/freelist.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "vm/bit_set.h" | 9 #include "vm/bit_set.h" |
10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 intptr_t index = IndexForSize(size); | 189 intptr_t index = IndexForSize(size); |
190 FreeListElement* element = FreeListElement::AsElement(addr, size); | 190 FreeListElement* element = FreeListElement::AsElement(addr, size); |
191 EnqueueElement(element, index); | 191 EnqueueElement(element, index); |
192 // Postcondition: the (page containing the) header is left writable. | 192 // Postcondition: the (page containing the) header is left writable. |
193 } | 193 } |
194 | 194 |
195 | 195 |
196 void FreeList::Reset() { | 196 void FreeList::Reset() { |
197 MutexLocker ml(mutex_); | 197 MutexLocker ml(mutex_); |
198 free_map_.Reset(); | 198 free_map_.Reset(); |
199 last_free_small_size_ = -1; | |
199 for (int i = 0; i < (kNumLists + 1); i++) { | 200 for (int i = 0; i < (kNumLists + 1); i++) { |
200 free_lists_[i] = NULL; | 201 free_lists_[i] = NULL; |
201 } | 202 } |
202 } | 203 } |
203 | 204 |
204 | 205 |
205 intptr_t FreeList::IndexForSize(intptr_t size) { | 206 intptr_t FreeList::IndexForSize(intptr_t size) { |
206 ASSERT(size >= kObjectAlignment); | 207 ASSERT(size >= kObjectAlignment); |
207 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 208 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
208 | 209 |
209 intptr_t index = size / kObjectAlignment; | 210 intptr_t index = size >> kObjectAlignmentLog2; |
210 if (index >= kNumLists) { | 211 if (index >= kNumLists) { |
211 index = kNumLists; | 212 index = kNumLists; |
212 } | 213 } |
213 return index; | 214 return index; |
214 } | 215 } |
215 | 216 |
216 | 217 |
217 void FreeList::EnqueueElement(FreeListElement* element, intptr_t index) { | 218 void FreeList::EnqueueElement(FreeListElement* element, intptr_t index) { |
218 FreeListElement* next = free_lists_[index]; | 219 FreeListElement* next = free_lists_[index]; |
219 if (next == NULL && index != kNumLists) { | 220 if (next == NULL && index != kNumLists) { |
220 free_map_.Set(index, true); | 221 free_map_.Set(index, true); |
222 last_free_small_size_ = Utils::Maximum(last_free_small_size_, | |
223 index << kObjectAlignmentLog2); | |
221 } | 224 } |
222 element->set_next(next); | 225 element->set_next(next); |
223 free_lists_[index] = element; | 226 free_lists_[index] = element; |
224 } | 227 } |
225 | 228 |
226 | 229 |
227 FreeListElement* FreeList::DequeueElement(intptr_t index) { | 230 FreeListElement* FreeList::DequeueElement(intptr_t index) { |
228 FreeListElement* result = free_lists_[index]; | 231 FreeListElement* result = free_lists_[index]; |
229 FreeListElement* next = result->next(); | 232 FreeListElement* next = result->next(); |
230 if (next == NULL && index != kNumLists) { | 233 if (next == NULL && index != kNumLists) { |
231 free_map_.Set(index, false); | 234 free_map_.Set(index, false); |
235 intptr_t size = index << kObjectAlignmentLog2; | |
236 if (size == last_free_small_size_) { | |
237 // Note: Last() returns -1 if none are set; avoid shift of negative. | |
238 last_free_small_size_ = free_map_.Last() * kObjectAlignment; | |
239 // TODO(koda): Consider adding BitSet::Previous(i). | |
240 } | |
232 } | 241 } |
233 free_lists_[index] = next; | 242 free_lists_[index] = next; |
234 return result; | 243 return result; |
235 } | 244 } |
236 | 245 |
237 | 246 |
238 intptr_t FreeList::LengthLocked(int index) const { | 247 intptr_t FreeList::LengthLocked(int index) const { |
239 DEBUG_ASSERT(mutex_->Owner() == Isolate::Current()); | 248 DEBUG_ASSERT(mutex_->Owner() == Isolate::Current()); |
240 ASSERT(index >= 0); | 249 ASSERT(index >= 0); |
241 ASSERT(index < kNumLists); | 250 ASSERT(index < kNumLists); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), | 346 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), |
338 remainder_size, | 347 remainder_size, |
339 VirtualMemory::kReadExecute); | 348 VirtualMemory::kReadExecute); |
340 ASSERT(status); | 349 ASSERT(status); |
341 } | 350 } |
342 } | 351 } |
343 | 352 |
344 | 353 |
345 FreeListElement* FreeList::TryAllocateLarge(intptr_t minimum_size) { | 354 FreeListElement* FreeList::TryAllocateLarge(intptr_t minimum_size) { |
346 MutexLocker ml(mutex_); | 355 MutexLocker ml(mutex_); |
356 return TryAllocateLargeLocked(minimum_size); | |
357 } | |
358 | |
359 | |
360 FreeListElement* FreeList::TryAllocateLargeLocked(intptr_t minimum_size) { | |
Ivan Posva
2014/09/04 21:50:46
DEBUG_ASSERT(mutex_->Owner() == Isolate::Current()
koda
2014/09/05 00:24:52
Done.
| |
347 FreeListElement* previous = NULL; | 361 FreeListElement* previous = NULL; |
348 FreeListElement* current = free_lists_[kNumLists]; | 362 FreeListElement* current = free_lists_[kNumLists]; |
349 // TODO(koda): Find largest. | 363 // TODO(koda): Find largest. |
350 while (current != NULL) { | 364 while (current != NULL) { |
351 FreeListElement* next = current->next(); | 365 FreeListElement* next = current->next(); |
352 if (current->Size() >= minimum_size) { | 366 if (current->Size() >= minimum_size) { |
353 if (previous == NULL) { | 367 if (previous == NULL) { |
354 free_lists_[kNumLists] = next; | 368 free_lists_[kNumLists] = next; |
355 } else { | 369 } else { |
356 previous->set_next(next); | 370 previous->set_next(next); |
357 } | 371 } |
358 return current; | 372 return current; |
359 } | 373 } |
360 previous = current; | 374 previous = current; |
361 current = next; | 375 current = next; |
362 } | 376 } |
363 return NULL; | 377 return NULL; |
364 } | 378 } |
365 | 379 |
380 | |
381 uword FreeList::TryAllocateSmall(intptr_t size) { | |
382 int index = IndexForSize(size); | |
Ivan Posva
2014/09/04 21:50:46
FreeList::TryAllocateSmallLocked
and
DEBUG_ASSERT(
koda
2014/09/05 00:24:52
Done.
| |
383 if (index != kNumLists && free_map_.Test(index)) { | |
384 return reinterpret_cast<uword>(DequeueElement(index)); | |
385 } | |
386 if ((index + 1) < kNumLists) { | |
387 intptr_t next_index = free_map_.Next(index + 1); | |
388 if (next_index != -1) { | |
389 FreeListElement* element = DequeueElement(next_index); | |
390 SplitElementAfterAndEnqueue(element, size, false); | |
391 return reinterpret_cast<uword>(element); | |
392 } | |
393 } | |
394 return 0; | |
395 } | |
396 | |
366 } // namespace dart | 397 } // namespace dart |
OLD | NEW |