Index: src/spaces.cc |
diff --git a/src/spaces.cc b/src/spaces.cc |
index 0ac23d279db6d5c13e3d9b0b67206cdd7f983ce0..66307f6c5df0fca8e35019fa1073dfc4f617c2f4 100644 |
--- a/src/spaces.cc |
+++ b/src/spaces.cc |
@@ -1937,10 +1937,67 @@ FreeList::FreeList(PagedSpace* owner) |
void FreeList::Reset() { |
available_ = 0; |
- small_list_ = NULL; |
- medium_list_ = NULL; |
- large_list_ = NULL; |
- huge_list_ = NULL; |
+ Reset(&small_list_); |
+ Reset(&medium_list_); |
+ Reset(&large_list_); |
+ Reset(&huge_list_); |
+} |
+ |
+ |
+void FreeList::Reset(FreeListCategorie *categorie) { |
+ categorie->top = NULL; |
+ categorie->end = NULL; |
+} |
+ |
+ |
+void FreeList::GetList(struct FreeListCategorie *categorie, |
+ FreeListNode** top, |
+ FreeListNode** end) { |
+ *top = categorie->top; |
+ *end = categorie->end; |
+ categorie->top = NULL; |
+ categorie->end = NULL; |
+} |
+ |
+ |
+void AddList(struct FreeListCategorie *categorie, |
+ FreeListNode* top, |
+ FreeListNode* end) { |
+ end->set_next(categorie->top); |
+ categorie->top = top; |
+} |
+ |
+ |
+void FreeList::ConcurrentGetList(struct FreeListCategorie *categorie, |
+ FreeListNode** top, |
+ FreeListNode** end) { |
+ do { |
+ *top = categorie->top; |
+ *end = categorie->end; |
+ } while (*top != categorie->top || |
+ NoBarrier_CompareAndSwap( |
+ reinterpret_cast<AtomicWord*>(&categorie->top), |
+ reinterpret_cast<AtomicWord>(*top), 0) != |
+ reinterpret_cast<AtomicWord>(*top)); |
+ NoBarrier_CompareAndSwap( |
+ reinterpret_cast<AtomicWord*>(&categorie->end), |
+ reinterpret_cast<AtomicWord>(*end), 0); |
+} |
+ |
+ |
+void ConcurrentAddList(struct FreeListCategorie *categorie, |
+ FreeListNode* top, |
+ FreeListNode* end) { |
+ FreeListNode* current_top; |
+ do { |
+ current_top = categorie->top; |
+ end->set_next(current_top); |
+ } while(current_top != categorie->top || |
+ NoBarrier_CompareAndSwap( |
+ reinterpret_cast<AtomicWord*>(&categorie->top), |
+ reinterpret_cast<AtomicWord>(current_top), |
+ reinterpret_cast<AtomicWord>(top)) != |
+ reinterpret_cast<AtomicWord>(current_top)); |
} |
@@ -1955,17 +2012,29 @@ int FreeList::Free(Address start, int size_in_bytes) { |
// Insert other blocks at the head of a free list of the appropriate |
// magnitude. |
if (size_in_bytes <= kSmallListMax) { |
- node->set_next(small_list_); |
- small_list_ = node; |
+ node->set_next(small_list_.top); |
+ small_list_.top = node; |
+ if (small_list_.end == NULL) { |
+ small_list_.end = node; |
+ } |
} else if (size_in_bytes <= kMediumListMax) { |
- node->set_next(medium_list_); |
- medium_list_ = node; |
+ node->set_next(medium_list_.top); |
+ medium_list_.top = node; |
+ if (medium_list_.end == NULL) { |
+ medium_list_.end = node; |
+ } |
} else if (size_in_bytes <= kLargeListMax) { |
- node->set_next(large_list_); |
- large_list_ = node; |
+ node->set_next(large_list_.top); |
+ large_list_.top = node; |
+ if (large_list_.end == NULL) { |
+ large_list_.end = node; |
+ } |
} else { |
- node->set_next(huge_list_); |
- huge_list_ = node; |
+ node->set_next(huge_list_.top); |
+ huge_list_.top = node; |
+ if (huge_list_.end == NULL) { |
+ huge_list_.end = node; |
+ } |
} |
available_ += size_in_bytes; |
ASSERT(IsVeryLong() || available_ == SumFreeLists()); |
@@ -1973,8 +2042,9 @@ int FreeList::Free(Address start, int size_in_bytes) { |
} |
-FreeListNode* FreeList::PickNodeFromList(FreeListNode** list, int* node_size) { |
- FreeListNode* node = *list; |
+FreeListNode* FreeList::PickNodeFromList(FreeListCategorie* categorie, |
+ int* node_size) { |
+ FreeListNode* node = categorie->top; |
if (node == NULL) return NULL; |
@@ -1986,9 +2056,13 @@ FreeListNode* FreeList::PickNodeFromList(FreeListNode** list, int* node_size) { |
if (node != NULL) { |
*node_size = node->Size(); |
- *list = node->next(); |
+ categorie->top = node->next(); |
} else { |
- *list = NULL; |
+ categorie->top = NULL; |
+ } |
+ |
+ if (categorie->top == NULL) { |
+ categorie->end = NULL; |
} |
return node; |
@@ -2013,7 +2087,7 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
if (node != NULL) return node; |
} |
- for (FreeListNode** cur = &huge_list_; |
+ for (FreeListNode** cur = &(huge_list_.top); |
*cur != NULL; |
cur = (*cur)->next_address()) { |
FreeListNode* cur_node = *cur; |
@@ -2024,7 +2098,10 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
} |
*cur = cur_node; |
- if (cur_node == NULL) break; |
+ if (cur_node == NULL) { |
+ huge_list_.end = NULL; |
+ break; |
+ } |
ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map()); |
FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); |
@@ -2116,8 +2193,10 @@ HeapObject* FreeList::Allocate(int size_in_bytes) { |
} |
-static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { |
+static intptr_t CountFreeListItemsInList(FreeListCategorie* categorie, |
Michael Starzinger
2012/11/27 13:51:53
I think the code would be easier to read if the st
Hannes Payer (out of office)
2012/11/29 13:17:42
Done. Now we just call the method on the given obj
|
+ Page* p) { |
intptr_t sum = 0; |
+ FreeListNode* n = categorie->top; |
while (n != NULL) { |
if (Page::FromAddress(n->address()) == p) { |
FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n); |
@@ -2130,11 +2209,11 @@ static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { |
void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { |
- sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); |
+ sizes->huge_size_ = CountFreeListItemsInList(&huge_list_, p); |
if (sizes->huge_size_ < p->area_size()) { |
- sizes->small_size_ = CountFreeListItemsInList(small_list_, p); |
- sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); |
- sizes->large_size_ = CountFreeListItemsInList(large_list_, p); |
+ sizes->small_size_ = CountFreeListItemsInList(&small_list_, p); |
+ sizes->medium_size_ = CountFreeListItemsInList(&medium_list_, p); |
+ sizes->large_size_ = CountFreeListItemsInList(&large_list_, p); |
} else { |
sizes->small_size_ = 0; |
sizes->medium_size_ = 0; |
@@ -2143,8 +2222,10 @@ void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { |
} |
-static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { |
+static intptr_t EvictFreeListItemsInList(FreeListCategorie* categorie, |
+ Page* p) { |
intptr_t sum = 0; |
+ FreeListNode** n = &(categorie->top); |
while (*n != NULL) { |
if (Page::FromAddress((*n)->address()) == p) { |
FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); |
@@ -2174,8 +2255,9 @@ intptr_t FreeList::EvictFreeListItems(Page* p) { |
#ifdef DEBUG |
-intptr_t FreeList::SumFreeList(FreeListNode* cur) { |
+intptr_t FreeList::SumFreeList(FreeListCategorie* categorie) { |
intptr_t sum = 0; |
+ FreeListNode* cur = categorie->top; |
while (cur != NULL) { |
ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map()); |
FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); |
@@ -2189,8 +2271,9 @@ intptr_t FreeList::SumFreeList(FreeListNode* cur) { |
static const int kVeryLongFreeList = 500; |
-int FreeList::FreeListLength(FreeListNode* cur) { |
+int FreeList::FreeListLength(FreeListCategorie* categorie) { |
int length = 0; |
+ FreeListNode* cur = categorie->top; |
while (cur != NULL) { |
length++; |
cur = cur->next(); |
@@ -2201,10 +2284,10 @@ int FreeList::FreeListLength(FreeListNode* cur) { |
bool FreeList::IsVeryLong() { |
- if (FreeListLength(small_list_) == kVeryLongFreeList) return true; |
- if (FreeListLength(medium_list_) == kVeryLongFreeList) return true; |
- if (FreeListLength(large_list_) == kVeryLongFreeList) return true; |
- if (FreeListLength(huge_list_) == kVeryLongFreeList) return true; |
+ if (FreeListLength(&small_list_) == kVeryLongFreeList) return true; |
+ if (FreeListLength(&medium_list_) == kVeryLongFreeList) return true; |
+ if (FreeListLength(&large_list_) == kVeryLongFreeList) return true; |
+ if (FreeListLength(&huge_list_) == kVeryLongFreeList) return true; |
return false; |
} |
@@ -2213,10 +2296,10 @@ bool FreeList::IsVeryLong() { |
// on the free list, so it should not be called if FreeListLength returns |
// kVeryLongFreeList. |
intptr_t FreeList::SumFreeLists() { |
- intptr_t sum = SumFreeList(small_list_); |
- sum += SumFreeList(medium_list_); |
- sum += SumFreeList(large_list_); |
- sum += SumFreeList(huge_list_); |
+ intptr_t sum = SumFreeList(&small_list_); |
+ sum += SumFreeList(&medium_list_); |
+ sum += SumFreeList(&large_list_); |
+ sum += SumFreeList(&huge_list_); |
return sum; |
} |
#endif |
@@ -2318,10 +2401,10 @@ static void RepairFreeList(Heap* heap, FreeListNode* n) { |
void FreeList::RepairLists(Heap* heap) { |
- RepairFreeList(heap, small_list_); |
- RepairFreeList(heap, medium_list_); |
- RepairFreeList(heap, large_list_); |
- RepairFreeList(heap, huge_list_); |
+ RepairFreeList(heap, small_list_.top); |
+ RepairFreeList(heap, medium_list_.top); |
+ RepairFreeList(heap, large_list_.top); |
+ RepairFreeList(heap, huge_list_.top); |
} |