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() {
intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) {
int sum = 0;
FreeSpace* t = top();
FreeSpace** n = &t;
while (*n != NULL) {
if (Page::FromAddress((*n)->address()) == p) {
FreeSpace* free_space = *n;
sum += free_space->Size();
*n = (*n)->next();
} else {
n = (*n)->next_address();
intptr_t sum = 0;
FreeSpace* prev_node = nullptr;
for (FreeSpace* cur_node = top(); cur_node != nullptr;
cur_node = cur_node->next()) {
Page* page_for_node = Page::FromAddress(cur_node->address());
if (page_for_node == p) {
// FreeSpace node on eviction page found, unlink it.
int size = cur_node->size();
sum += size;
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);
if (top() == NULL) {
set_end(NULL);
}
DCHECK_EQ(p->available_in_free_list(type_), sum);
p->add_available_in_free_list(type_, -sum);
available_ -= sum;
return sum;
}
......@@ -2446,17 +2455,11 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
intptr_t FreeList::EvictFreeListItems(Page* p) {
intptr_t sum = huge_list_.EvictFreeListItemsInList(p);
p->set_available_in_huge_free_list(0);
if (sum < p->area_size()) {
sum += small_list_.EvictFreeListItemsInList(p) +
medium_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;
}
......
......@@ -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
void Print();
#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