Commit af4888de authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Fix stale end_ pointer in FreeListCategory::EvictFreeListItemsInList

During eviction of FreeSpace nodes that reside on eviction pages we iterate
throug the list node-by-node, unlinking only those that reside on eviction
pages. We failed to properly update end_ if nodes were evicted are encountering
nodes that that are left as is.

BUG=chromium:539356
LOG=N
R=hpayer@chromium.org

Review URL: https://codereview.chromium.org/1411263002

Cr-Commit-Position: refs/heads/master@{#31383}
parent 66b0fbee
...@@ -2092,22 +2092,31 @@ void FreeListCategory::Reset() { ...@@ -2092,22 +2092,31 @@ void FreeListCategory::Reset() {
intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) {
int sum = 0; intptr_t sum = 0;
FreeSpace* t = top(); FreeSpace* prev_node = nullptr;
FreeSpace** n = &t; for (FreeSpace* cur_node = top(); cur_node != nullptr;
while (*n != NULL) { cur_node = cur_node->next()) {
if (Page::FromAddress((*n)->address()) == p) { Page* page_for_node = Page::FromAddress(cur_node->address());
FreeSpace* free_space = *n; if (page_for_node == p) {
sum += free_space->Size(); // FreeSpace node on eviction page found, unlink it.
*n = (*n)->next(); int size = cur_node->size();
} else { sum += size;
n = (*n)->next_address(); DCHECK((prev_node != nullptr) || (top() == cur_node));
if (cur_node == top()) {
set_top(cur_node->next());
}
if (cur_node == end()) {
set_end(prev_node);
}
if (prev_node != nullptr) {
prev_node->set_next(cur_node->next());
}
continue;
} }
prev_node = cur_node;
} }
set_top(t); DCHECK_EQ(p->available_in_free_list(type_), sum);
if (top() == NULL) { p->add_available_in_free_list(type_, -sum);
set_end(NULL);
}
available_ -= sum; available_ -= sum;
return sum; return sum;
} }
...@@ -2446,17 +2455,11 @@ HeapObject* FreeList::Allocate(int size_in_bytes) { ...@@ -2446,17 +2455,11 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
intptr_t FreeList::EvictFreeListItems(Page* p) { intptr_t FreeList::EvictFreeListItems(Page* p) {
intptr_t sum = huge_list_.EvictFreeListItemsInList(p); intptr_t sum = huge_list_.EvictFreeListItemsInList(p);
p->set_available_in_huge_free_list(0);
if (sum < p->area_size()) { if (sum < p->area_size()) {
sum += small_list_.EvictFreeListItemsInList(p) + sum += small_list_.EvictFreeListItemsInList(p) +
medium_list_.EvictFreeListItemsInList(p) + medium_list_.EvictFreeListItemsInList(p) +
large_list_.EvictFreeListItemsInList(p); large_list_.EvictFreeListItemsInList(p);
p->set_available_in_small_free_list(0);
p->set_available_in_medium_free_list(0);
p->set_available_in_large_free_list(0);
} }
return sum; return sum;
} }
......
...@@ -904,6 +904,23 @@ class Page : public MemoryChunk { ...@@ -904,6 +904,23 @@ class Page : public MemoryChunk {
} }
} }
intptr_t available_in_free_list(FreeListCategoryType type) {
switch (type) {
case kSmall:
return available_in_small_free_list();
case kMedium:
return available_in_medium_free_list();
case kLarge:
return available_in_large_free_list();
case kHuge:
return available_in_huge_free_list();
default:
UNREACHABLE();
}
UNREACHABLE();
return 0;
}
#ifdef DEBUG #ifdef DEBUG
void Print(); void Print();
#endif // DEBUG #endif // DEBUG
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment