| Index: src/mark-compact.cc
|
| ===================================================================
|
| --- src/mark-compact.cc (revision 4449)
|
| +++ src/mark-compact.cc (working copy)
|
| @@ -1055,15 +1055,22 @@
|
| PageIterator it(space, PageIterator::PAGES_IN_USE);
|
| while (it.has_next()) {
|
| Page* p = it.next();
|
| - // The offset of each live object in the page from the first live object
|
| - // in the page.
|
| - int offset = 0;
|
| - EncodeForwardingAddressesInRange<Alloc,
|
| - EncodeForwardingAddressInPagedSpace,
|
| - ProcessNonLive>(
|
| - p->ObjectAreaStart(),
|
| - p->AllocationTop(),
|
| - &offset);
|
| +
|
| + if (p->WasInUseBeforeMC()) {
|
| + // The offset of each live object in the page from the first live object
|
| + // in the page.
|
| + int offset = 0;
|
| + EncodeForwardingAddressesInRange<Alloc,
|
| + EncodeForwardingAddressInPagedSpace,
|
| + ProcessNonLive>(
|
| + p->ObjectAreaStart(),
|
| + p->AllocationTop(),
|
| + &offset);
|
| + } else {
|
| + // Mark whole unused page as a free region.
|
| + EncodeFreeRegion(p->ObjectAreaStart(),
|
| + p->AllocationTop() - p->ObjectAreaStart());
|
| + }
|
| }
|
| }
|
|
|
| @@ -1277,6 +1284,23 @@
|
|
|
| static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
|
| PageIterator it(space, PageIterator::PAGES_IN_USE);
|
| +
|
| + // During sweeping of paged space we are trying to find longest sequences
|
| + // of pages without live objects and free them (instead of putting them on
|
| + // the free list).
|
| + Page* prev = NULL; // Page preceding current.
|
| + Page* first_empty_page = NULL; // First empty page in a sequence.
|
| + Page* prec_first_empty_page = NULL; // Page preceding first empty page.
|
| +
|
| + // If last used page of space ends with a sequence of dead objects
|
| + // we can adjust allocation top instead of puting this free area into
|
| + // the free list. Thus during sweeping we keep track of such areas
|
| + // and defer their deallocation until the sweeping of the next page
|
| + // is done: if one of the next pages contains live objects we have
|
| + // to put such area into the free list.
|
| + Address last_free_start = NULL;
|
| + int last_free_size = 0;
|
| +
|
| while (it.has_next()) {
|
| Page* p = it.next();
|
|
|
| @@ -1291,8 +1315,9 @@
|
| if (object->IsMarked()) {
|
| object->ClearMark();
|
| MarkCompactCollector::tracer()->decrement_marked_count();
|
| +
|
| if (!is_previous_alive) { // Transition from free to live.
|
| - dealloc(free_start, static_cast<int>(current - free_start));
|
| + dealloc(free_start, static_cast<int>(current - free_start), true);
|
| is_previous_alive = true;
|
| }
|
| } else {
|
| @@ -1306,39 +1331,112 @@
|
| // loop.
|
| }
|
|
|
| - // If the last region was not live we need to deallocate from
|
| - // free_start to the allocation top in the page.
|
| - if (!is_previous_alive) {
|
| - int free_size = static_cast<int>(p->AllocationTop() - free_start);
|
| - if (free_size > 0) {
|
| - dealloc(free_start, free_size);
|
| + bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop())
|
| + || (!is_previous_alive && free_start == p->ObjectAreaStart());
|
| +
|
| + if (page_is_empty) {
|
| + // This page is empty. Check whether we are in the middle of
|
| + // sequence of empty pages and start one if not.
|
| + if (first_empty_page == NULL) {
|
| + first_empty_page = p;
|
| + prec_first_empty_page = prev;
|
| }
|
| +
|
| + if (!is_previous_alive) {
|
| + // There are dead objects on this page. Update space accounting stats
|
| + // without putting anything into free list.
|
| + int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start);
|
| + if (size_in_bytes > 0) {
|
| + dealloc(free_start, size_in_bytes, false);
|
| + }
|
| + }
|
| + } else {
|
| + // This page is not empty. Sequence of empty pages ended on the previous
|
| + // one.
|
| + if (first_empty_page != NULL) {
|
| + space->FreePages(prec_first_empty_page, prev);
|
| + prec_first_empty_page = first_empty_page = NULL;
|
| + }
|
| +
|
| + // If there is a free ending area on one of the previous pages we have
|
| + // deallocate that area and put it on the free list.
|
| + if (last_free_size > 0) {
|
| + dealloc(last_free_start, last_free_size, true);
|
| + last_free_start = NULL;
|
| + last_free_size = 0;
|
| + }
|
| +
|
| + // If the last region of this page was not live we remember it.
|
| + if (!is_previous_alive) {
|
| + ASSERT(last_free_size == 0);
|
| + last_free_size = static_cast<int>(p->AllocationTop() - free_start);
|
| + last_free_start = free_start;
|
| + }
|
| }
|
| +
|
| + prev = p;
|
| }
|
| +
|
| + // We reached end of space. See if we need to adjust allocation top.
|
| + Address new_allocation_top = NULL;
|
| +
|
| + if (first_empty_page != NULL) {
|
| + // Last used pages in space are empty. We can move allocation top backwards
|
| + // to the beginning of first empty page.
|
| + ASSERT(prev == space->AllocationTopPage());
|
| +
|
| + new_allocation_top = first_empty_page->ObjectAreaStart();
|
| + }
|
| +
|
| + if (last_free_size > 0) {
|
| + // There was a free ending area on the previous page.
|
| + // Deallocate it without putting it into freelist and move allocation
|
| + // top to the beginning of this free area.
|
| + dealloc(last_free_start, last_free_size, false);
|
| + new_allocation_top = last_free_start;
|
| + }
|
| +
|
| + if (new_allocation_top != NULL) {
|
| + Page* new_allocation_top_page = Page::FromAllocationTop(new_allocation_top);
|
| +
|
| + ASSERT(((first_empty_page == NULL) &&
|
| + (new_allocation_top_page == space->AllocationTopPage())) ||
|
| + ((first_empty_page != NULL) && (last_free_size > 0) &&
|
| + (new_allocation_top_page == prec_first_empty_page)) ||
|
| + ((first_empty_page != NULL) && (last_free_size == 0) &&
|
| + (new_allocation_top_page == first_empty_page)));
|
| +
|
| + space->SetTop(new_allocation_top,
|
| + new_allocation_top_page->ObjectAreaEnd());
|
| + }
|
| }
|
|
|
|
|
| void MarkCompactCollector::DeallocateOldPointerBlock(Address start,
|
| - int size_in_bytes) {
|
| + int size_in_bytes,
|
| + bool add_to_freelist) {
|
| Heap::ClearRSetRange(start, size_in_bytes);
|
| - Heap::old_pointer_space()->Free(start, size_in_bytes);
|
| + Heap::old_pointer_space()->Free(start, size_in_bytes, add_to_freelist);
|
| }
|
|
|
|
|
| void MarkCompactCollector::DeallocateOldDataBlock(Address start,
|
| - int size_in_bytes) {
|
| - Heap::old_data_space()->Free(start, size_in_bytes);
|
| + int size_in_bytes,
|
| + bool add_to_freelist) {
|
| + Heap::old_data_space()->Free(start, size_in_bytes, add_to_freelist);
|
| }
|
|
|
|
|
| void MarkCompactCollector::DeallocateCodeBlock(Address start,
|
| - int size_in_bytes) {
|
| - Heap::code_space()->Free(start, size_in_bytes);
|
| + int size_in_bytes,
|
| + bool add_to_freelist) {
|
| + Heap::code_space()->Free(start, size_in_bytes, add_to_freelist);
|
| }
|
|
|
|
|
| void MarkCompactCollector::DeallocateMapBlock(Address start,
|
| - int size_in_bytes) {
|
| + int size_in_bytes,
|
| + bool add_to_freelist) {
|
| // Objects in map space are assumed to have size Map::kSize and a
|
| // valid map in their first word. Thus, we break the free block up into
|
| // chunks and free them separately.
|
| @@ -1346,13 +1444,14 @@
|
| Heap::ClearRSetRange(start, size_in_bytes);
|
| Address end = start + size_in_bytes;
|
| for (Address a = start; a < end; a += Map::kSize) {
|
| - Heap::map_space()->Free(a);
|
| + Heap::map_space()->Free(a, add_to_freelist);
|
| }
|
| }
|
|
|
|
|
| void MarkCompactCollector::DeallocateCellBlock(Address start,
|
| - int size_in_bytes) {
|
| + int size_in_bytes,
|
| + bool add_to_freelist) {
|
| // Free-list elements in cell space are assumed to have a fixed size.
|
| // We break the free block into chunks and add them to the free list
|
| // individually.
|
| @@ -1361,7 +1460,7 @@
|
| Heap::ClearRSetRange(start, size_in_bytes);
|
| Address end = start + size_in_bytes;
|
| for (Address a = start; a < end; a += size) {
|
| - Heap::cell_space()->Free(a);
|
| + Heap::cell_space()->Free(a, add_to_freelist);
|
| }
|
| }
|
|
|
|
|