| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 113 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 114 CHECK(current >= next_object_must_be_here_or_later); | 114 CHECK(current >= next_object_must_be_here_or_later); |
| 115 object->Iterate(&visitor); | 115 object->Iterate(&visitor); |
| 116 next_object_must_be_here_or_later = current + object->Size(); | 116 next_object_must_be_here_or_later = current + object->Size(); |
| 117 // The next word for sure belongs to the current object, jump over it. | 117 // The next word for sure belongs to the current object, jump over it. |
| 118 current += kPointerSize; | 118 current += kPointerSize; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 } | 121 } |
| 122 | 122 |
| 123 static void VerifyMarkingBlackPage(Heap* heap, Page* page) { |
| 124 CHECK(page->IsFlagSet(Page::BLACK_PAGE)); |
| 125 VerifyMarkingVisitor visitor(heap); |
| 126 HeapObjectIterator it(page); |
| 127 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
| 128 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 129 object->Iterate(&visitor); |
| 130 } |
| 131 } |
| 123 | 132 |
| 124 static void VerifyMarking(NewSpace* space) { | 133 static void VerifyMarking(NewSpace* space) { |
| 125 Address end = space->top(); | 134 Address end = space->top(); |
| 126 NewSpacePageIterator it(space->bottom(), end); | 135 NewSpacePageIterator it(space->bottom(), end); |
| 127 // The bottom position is at the start of its page. Allows us to use | 136 // The bottom position is at the start of its page. Allows us to use |
| 128 // page->area_start() as start of range on all pages. | 137 // page->area_start() as start of range on all pages. |
| 129 CHECK_EQ(space->bottom(), | 138 CHECK_EQ(space->bottom(), |
| 130 NewSpacePage::FromAddress(space->bottom())->area_start()); | 139 NewSpacePage::FromAddress(space->bottom())->area_start()); |
| 131 while (it.has_next()) { | 140 while (it.has_next()) { |
| 132 NewSpacePage* page = it.next(); | 141 NewSpacePage* page = it.next(); |
| 133 Address limit = it.has_next() ? page->area_end() : end; | 142 Address limit = it.has_next() ? page->area_end() : end; |
| 134 CHECK(limit == end || !page->Contains(end)); | 143 CHECK(limit == end || !page->Contains(end)); |
| 135 VerifyMarking(space->heap(), page->area_start(), limit); | 144 VerifyMarking(space->heap(), page->area_start(), limit); |
| 136 } | 145 } |
| 137 } | 146 } |
| 138 | 147 |
| 139 | 148 |
| 140 static void VerifyMarking(PagedSpace* space) { | 149 static void VerifyMarking(PagedSpace* space) { |
| 141 PageIterator it(space); | 150 PageIterator it(space); |
| 142 | 151 |
| 143 while (it.has_next()) { | 152 while (it.has_next()) { |
| 144 Page* p = it.next(); | 153 Page* p = it.next(); |
| 145 VerifyMarking(space->heap(), p->area_start(), p->area_end()); | 154 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 155 VerifyMarkingBlackPage(space->heap(), p); |
| 156 } else { |
| 157 VerifyMarking(space->heap(), p->area_start(), p->area_end()); |
| 158 } |
| 146 } | 159 } |
| 147 } | 160 } |
| 148 | 161 |
| 149 | 162 |
| 150 static void VerifyMarking(Heap* heap) { | 163 static void VerifyMarking(Heap* heap) { |
| 151 VerifyMarking(heap->old_space()); | 164 VerifyMarking(heap->old_space()); |
| 152 VerifyMarking(heap->code_space()); | 165 VerifyMarking(heap->code_space()); |
| 153 VerifyMarking(heap->map_space()); | 166 VerifyMarking(heap->map_space()); |
| 154 VerifyMarking(heap->new_space()); | 167 VerifyMarking(heap->new_space()); |
| 155 | 168 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 map->VerifyOmittedMapChecks(); | 421 map->VerifyOmittedMapChecks(); |
| 409 } | 422 } |
| 410 } | 423 } |
| 411 #endif // VERIFY_HEAP | 424 #endif // VERIFY_HEAP |
| 412 | 425 |
| 413 | 426 |
| 414 static void ClearMarkbitsInPagedSpace(PagedSpace* space) { | 427 static void ClearMarkbitsInPagedSpace(PagedSpace* space) { |
| 415 PageIterator it(space); | 428 PageIterator it(space); |
| 416 | 429 |
| 417 while (it.has_next()) { | 430 while (it.has_next()) { |
| 418 Bitmap::Clear(it.next()); | 431 Page* p = it.next(); |
| 432 Bitmap::Clear(p); |
| 433 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 434 p->ClearFlag(Page::BLACK_PAGE); |
| 435 } |
| 419 } | 436 } |
| 420 } | 437 } |
| 421 | 438 |
| 422 | 439 |
| 423 static void ClearMarkbitsInNewSpace(NewSpace* space) { | 440 static void ClearMarkbitsInNewSpace(NewSpace* space) { |
| 424 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); | 441 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); |
| 425 | 442 |
| 426 while (it.has_next()) { | 443 while (it.has_next()) { |
| 427 Bitmap::Clear(it.next()); | 444 Bitmap::Clear(it.next()); |
| 428 } | 445 } |
| 429 } | 446 } |
| 430 | 447 |
| 431 | 448 |
| 432 void MarkCompactCollector::ClearMarkbits() { | 449 void MarkCompactCollector::ClearMarkbits() { |
| 433 ClearMarkbitsInPagedSpace(heap_->code_space()); | 450 ClearMarkbitsInPagedSpace(heap_->code_space()); |
| 434 ClearMarkbitsInPagedSpace(heap_->map_space()); | 451 ClearMarkbitsInPagedSpace(heap_->map_space()); |
| 435 ClearMarkbitsInPagedSpace(heap_->old_space()); | 452 ClearMarkbitsInPagedSpace(heap_->old_space()); |
| 436 ClearMarkbitsInNewSpace(heap_->new_space()); | 453 ClearMarkbitsInNewSpace(heap_->new_space()); |
| 437 | 454 |
| 438 LargeObjectIterator it(heap_->lo_space()); | 455 LargeObjectIterator it(heap_->lo_space()); |
| 439 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 456 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 440 Marking::MarkWhite(Marking::MarkBitFrom(obj)); | 457 Marking::MarkWhite(Marking::MarkBitFrom(obj)); |
| 441 Page::FromAddress(obj->address())->ResetProgressBar(); | 458 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 442 Page::FromAddress(obj->address())->ResetLiveBytes(); | 459 chunk->ResetProgressBar(); |
| 460 chunk->ResetLiveBytes(); |
| 461 if (chunk->IsFlagSet(Page::BLACK_PAGE)) { |
| 462 chunk->ClearFlag(Page::BLACK_PAGE); |
| 463 } |
| 443 } | 464 } |
| 444 } | 465 } |
| 445 | 466 |
| 446 | 467 |
| 447 class MarkCompactCollector::SweeperTask : public v8::Task { | 468 class MarkCompactCollector::SweeperTask : public v8::Task { |
| 448 public: | 469 public: |
| 449 SweeperTask(Heap* heap, AllocationSpace space_to_start) | 470 SweeperTask(Heap* heap, AllocationSpace space_to_start) |
| 450 : heap_(heap), space_to_start_(space_to_start) {} | 471 : heap_(heap), space_to_start_(space_to_start) {} |
| 451 | 472 |
| 452 virtual ~SweeperTask() {} | 473 virtual ~SweeperTask() {} |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 pending_sweeper_tasks_semaphore_.Signal(); | 570 pending_sweeper_tasks_semaphore_.Signal(); |
| 550 return true; | 571 return true; |
| 551 } | 572 } |
| 552 | 573 |
| 553 | 574 |
| 554 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { | 575 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { |
| 555 // This is only used when resizing an object. | 576 // This is only used when resizing an object. |
| 556 DCHECK(MemoryChunk::FromAddress(old_start) == | 577 DCHECK(MemoryChunk::FromAddress(old_start) == |
| 557 MemoryChunk::FromAddress(new_start)); | 578 MemoryChunk::FromAddress(new_start)); |
| 558 | 579 |
| 559 if (!heap->incremental_marking()->IsMarking()) return; | 580 if (!heap->incremental_marking()->IsMarking() || |
| 581 Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE)) |
| 582 return; |
| 560 | 583 |
| 561 // If the mark doesn't move, we don't check the color of the object. | 584 // If the mark doesn't move, we don't check the color of the object. |
| 562 // It doesn't matter whether the object is black, since it hasn't changed | 585 // It doesn't matter whether the object is black, since it hasn't changed |
| 563 // size, so the adjustment to the live data count will be zero anyway. | 586 // size, so the adjustment to the live data count will be zero anyway. |
| 564 if (old_start == new_start) return; | 587 if (old_start == new_start) return; |
| 565 | 588 |
| 566 MarkBit new_mark_bit = MarkBitFrom(new_start); | 589 MarkBit new_mark_bit = MarkBitFrom(new_start); |
| 567 MarkBit old_mark_bit = MarkBitFrom(old_start); | 590 MarkBit old_mark_bit = MarkBitFrom(old_start); |
| 568 | 591 |
| 569 #ifdef DEBUG | 592 #ifdef DEBUG |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 | 681 |
| 659 // Pairs of (live_bytes_in_page, page). | 682 // Pairs of (live_bytes_in_page, page). |
| 660 typedef std::pair<int, Page*> LiveBytesPagePair; | 683 typedef std::pair<int, Page*> LiveBytesPagePair; |
| 661 std::vector<LiveBytesPagePair> pages; | 684 std::vector<LiveBytesPagePair> pages; |
| 662 pages.reserve(number_of_pages); | 685 pages.reserve(number_of_pages); |
| 663 | 686 |
| 664 PageIterator it(space); | 687 PageIterator it(space); |
| 665 while (it.has_next()) { | 688 while (it.has_next()) { |
| 666 Page* p = it.next(); | 689 Page* p = it.next(); |
| 667 if (p->NeverEvacuate()) continue; | 690 if (p->NeverEvacuate()) continue; |
| 691 if (p->IsFlagSet(Page::BLACK_PAGE)) continue; |
| 668 // Invariant: Evacuation candidates are just created when marking is | 692 // Invariant: Evacuation candidates are just created when marking is |
| 669 // started. This means that sweeping has finished. Furthermore, at the end | 693 // started. This means that sweeping has finished. Furthermore, at the end |
| 670 // of a GC all evacuation candidates are cleared and their slot buffers are | 694 // of a GC all evacuation candidates are cleared and their slot buffers are |
| 671 // released. | 695 // released. |
| 672 CHECK(!p->IsEvacuationCandidate()); | 696 CHECK(!p->IsEvacuationCandidate()); |
| 673 CHECK_NULL(p->old_to_old_slots()); | 697 CHECK_NULL(p->old_to_old_slots()); |
| 674 CHECK_NULL(p->typed_old_to_old_slots()); | 698 CHECK_NULL(p->typed_old_to_old_slots()); |
| 675 CHECK(p->SweepingDone()); | 699 CHECK(p->SweepingDone()); |
| 676 DCHECK(p->area_size() == area_size); | 700 DCHECK(p->area_size() == area_size); |
| 677 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); | 701 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { | 1486 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { |
| 1463 MarkBit markbit = Marking::MarkBitFrom(object); | 1487 MarkBit markbit = Marking::MarkBitFrom(object); |
| 1464 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { | 1488 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { |
| 1465 Marking::GreyToBlack(markbit); | 1489 Marking::GreyToBlack(markbit); |
| 1466 PushBlack(object); | 1490 PushBlack(object); |
| 1467 if (marking_deque()->IsFull()) return; | 1491 if (marking_deque()->IsFull()) return; |
| 1468 } | 1492 } |
| 1469 } | 1493 } |
| 1470 } | 1494 } |
| 1471 | 1495 |
| 1472 | 1496 template <LiveObjectIterationMode T> |
| 1473 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { | 1497 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
| 1474 DCHECK(!marking_deque()->IsFull()); | 1498 DCHECK(!marking_deque()->IsFull()); |
| 1475 LiveObjectIterator<kGreyObjects> it(p); | 1499 DCHECK(T == kGreyObjects || T == kGreyObjectsOnBlackPage); |
| 1500 LiveObjectIterator<T> it(p); |
| 1476 HeapObject* object = NULL; | 1501 HeapObject* object = NULL; |
| 1477 while ((object = it.Next()) != NULL) { | 1502 while ((object = it.Next()) != NULL) { |
| 1478 MarkBit markbit = Marking::MarkBitFrom(object); | 1503 MarkBit markbit = Marking::MarkBitFrom(object); |
| 1479 DCHECK(Marking::IsGrey(markbit)); | 1504 DCHECK(Marking::IsGrey(markbit)); |
| 1480 Marking::GreyToBlack(markbit); | 1505 Marking::GreyToBlack(markbit); |
| 1481 PushBlack(object); | 1506 PushBlack(object); |
| 1482 if (marking_deque()->IsFull()) return; | 1507 if (marking_deque()->IsFull()) return; |
| 1483 } | 1508 } |
| 1484 } | 1509 } |
| 1485 | 1510 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 } | 1724 } |
| 1700 return false; | 1725 return false; |
| 1701 } | 1726 } |
| 1702 }; | 1727 }; |
| 1703 | 1728 |
| 1704 | 1729 |
| 1705 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { | 1730 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { |
| 1706 PageIterator it(space); | 1731 PageIterator it(space); |
| 1707 while (it.has_next()) { | 1732 while (it.has_next()) { |
| 1708 Page* p = it.next(); | 1733 Page* p = it.next(); |
| 1709 DiscoverGreyObjectsOnPage(p); | 1734 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 1735 DiscoverGreyObjectsOnPage<kGreyObjectsOnBlackPage>(p); |
| 1736 } else { |
| 1737 DiscoverGreyObjectsOnPage<kGreyObjects>(p); |
| 1738 } |
| 1710 if (marking_deque()->IsFull()) return; | 1739 if (marking_deque()->IsFull()) return; |
| 1711 } | 1740 } |
| 1712 } | 1741 } |
| 1713 | 1742 |
| 1714 | 1743 |
| 1715 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { | 1744 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { |
| 1716 NewSpace* space = heap()->new_space(); | 1745 NewSpace* space = heap()->new_space(); |
| 1717 NewSpacePageIterator it(space->bottom(), space->top()); | 1746 NewSpacePageIterator it(space->bottom(), space->top()); |
| 1718 while (it.has_next()) { | 1747 while (it.has_next()) { |
| 1719 NewSpacePage* page = it.next(); | 1748 NewSpacePage* page = it.next(); |
| 1720 DiscoverGreyObjectsOnPage(page); | 1749 DiscoverGreyObjectsOnPage<kGreyObjects>(page); |
| 1721 if (marking_deque()->IsFull()) return; | 1750 if (marking_deque()->IsFull()) return; |
| 1722 } | 1751 } |
| 1723 } | 1752 } |
| 1724 | 1753 |
| 1725 | 1754 |
| 1726 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 1755 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 1727 Object* o = *p; | 1756 Object* o = *p; |
| 1728 if (!o->IsHeapObject()) return false; | 1757 if (!o->IsHeapObject()) return false; |
| 1729 HeapObject* heap_object = HeapObject::cast(o); | 1758 HeapObject* heap_object = HeapObject::cast(o); |
| 1730 MarkBit mark = Marking::MarkBitFrom(heap_object); | 1759 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| (...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2805 // for it. | 2834 // for it. |
| 2806 CHECK(large_object->IsHeapObject()); | 2835 CHECK(large_object->IsHeapObject()); |
| 2807 HeapObject* large_heap_object = HeapObject::cast(large_object); | 2836 HeapObject* large_heap_object = HeapObject::cast(large_object); |
| 2808 if (IsMarked(large_heap_object)) { | 2837 if (IsMarked(large_heap_object)) { |
| 2809 *out_object = large_heap_object; | 2838 *out_object = large_heap_object; |
| 2810 return true; | 2839 return true; |
| 2811 } | 2840 } |
| 2812 return false; | 2841 return false; |
| 2813 } | 2842 } |
| 2814 | 2843 |
| 2844 // If we are on a black page, we cannot find the actual object start |
| 2845 // easiliy. We just return true but do not set the out_object. |
| 2846 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 2847 return true; |
| 2848 } |
| 2849 |
| 2815 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); | 2850 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); |
| 2816 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; | 2851 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; |
| 2817 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); | 2852 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); |
| 2818 MarkBit::CellType* cells = p->markbits()->cells(); | 2853 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2819 Address base_address = p->area_start(); | 2854 Address base_address = p->area_start(); |
| 2820 unsigned int base_address_cell_index = Bitmap::IndexToCell( | 2855 unsigned int base_address_cell_index = Bitmap::IndexToCell( |
| 2821 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); | 2856 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); |
| 2822 | 2857 |
| 2823 // Check if the slot points to the start of an object. This can happen e.g. | 2858 // Check if the slot points to the start of an object. This can happen e.g. |
| 2824 // when we left trim a fixed array. Such slots are invalid and we can remove | 2859 // when we left trim a fixed array. Such slots are invalid and we can remove |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2885 // Slots pointing to the first word of an object are invalid and removed. | 2920 // Slots pointing to the first word of an object are invalid and removed. |
| 2886 // This can happen when we move the object header while left trimming. | 2921 // This can happen when we move the object header while left trimming. |
| 2887 *out_object = object; | 2922 *out_object = object; |
| 2888 return true; | 2923 return true; |
| 2889 } | 2924 } |
| 2890 return false; | 2925 return false; |
| 2891 } | 2926 } |
| 2892 | 2927 |
| 2893 HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { | 2928 HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { |
| 2894 Page* p = Page::FromAddress(slot); | 2929 Page* p = Page::FromAddress(slot); |
| 2895 // This function does not support large objects right now. | |
| 2896 Space* owner = p->owner(); | 2930 Space* owner = p->owner(); |
| 2897 if (owner == heap_->lo_space() || owner == nullptr) { | 2931 if (owner == heap_->lo_space() || owner == nullptr) { |
| 2898 Object* large_object = heap_->lo_space()->FindObject(slot); | 2932 Object* large_object = heap_->lo_space()->FindObject(slot); |
| 2899 // This object has to exist, otherwise we would not have recorded a slot | 2933 // This object has to exist, otherwise we would not have recorded a slot |
| 2900 // for it. | 2934 // for it. |
| 2901 CHECK(large_object->IsHeapObject()); | 2935 CHECK(large_object->IsHeapObject()); |
| 2902 HeapObject* large_heap_object = HeapObject::cast(large_object); | 2936 HeapObject* large_heap_object = HeapObject::cast(large_object); |
| 2903 | 2937 |
| 2904 if (IsMarked(large_heap_object)) { | 2938 if (IsMarked(large_heap_object)) { |
| 2905 return large_heap_object; | 2939 return large_heap_object; |
| 2906 } | 2940 } |
| 2907 return nullptr; | 2941 return nullptr; |
| 2908 } | 2942 } |
| 2909 | 2943 |
| 2944 // The LiveObjectIterator does not work on black pages. Hence, we cannot call |
| 2945 // this function black pages. |
| 2946 DCHECK(!Page::FromAddress(slot)->IsFlagSet(Page::BLACK_PAGE)); |
| 2947 |
| 2910 LiveObjectIterator<kBlackObjects> it(p); | 2948 LiveObjectIterator<kBlackObjects> it(p); |
| 2911 HeapObject* object = nullptr; | 2949 HeapObject* object = nullptr; |
| 2912 while ((object = it.Next()) != nullptr) { | 2950 while ((object = it.Next()) != nullptr) { |
| 2913 int size = object->Size(); | 2951 int size = object->Size(); |
| 2914 if (object->address() > slot) return nullptr; | 2952 if (object->address() > slot) return nullptr; |
| 2915 if (object->address() <= slot && slot < (object->address() + size)) { | 2953 if (object->address() <= slot && slot < (object->address() + size)) { |
| 2916 return object; | 2954 return object; |
| 2917 } | 2955 } |
| 2918 } | 2956 } |
| 2919 return nullptr; | 2957 return nullptr; |
| 2920 } | 2958 } |
| 2921 | 2959 |
| 2922 | 2960 |
| 2923 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { | 2961 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { |
| 2924 HeapObject* object = NULL; | |
| 2925 // The target object is black but we don't know if the source slot is black. | 2962 // The target object is black but we don't know if the source slot is black. |
| 2926 // The source object could have died and the slot could be part of a free | 2963 // The source object could have died and the slot could be part of a free |
| 2927 // space. Find out based on mark bits if the slot is part of a live object. | 2964 // space. Find out based on mark bits if the slot is part of a live object. |
| 2928 if (!IsSlotInBlackObject(Page::FromAddress(slot), slot, &object)) { | 2965 Page* page = Page::FromAddress(slot); |
| 2966 HeapObject* object = NULL; |
| 2967 if (!IsSlotInBlackObject(page, slot, &object)) { |
| 2929 return false; | 2968 return false; |
| 2930 } | 2969 } |
| 2931 | 2970 |
| 2932 DCHECK(object != NULL); | 2971 // If the slot is on a black page, the object will be live. |
| 2972 DCHECK(object != NULL || page->IsFlagSet(Page::BLACK_PAGE)); |
| 2973 if (page->IsFlagSet(Page::BLACK_PAGE)) { |
| 2974 return true; |
| 2975 } |
| 2976 |
| 2933 int offset = static_cast<int>(slot - object->address()); | 2977 int offset = static_cast<int>(slot - object->address()); |
| 2934 return object->IsValidSlot(offset); | 2978 return object->IsValidSlot(offset); |
| 2935 } | 2979 } |
| 2936 | 2980 |
| 2937 | 2981 |
| 2938 void MarkCompactCollector::EvacuateNewSpacePrologue() { | 2982 void MarkCompactCollector::EvacuateNewSpacePrologue() { |
| 2939 NewSpace* new_space = heap()->new_space(); | 2983 NewSpace* new_space = heap()->new_space(); |
| 2940 NewSpacePageIterator it(new_space->bottom(), new_space->top()); | 2984 NewSpacePageIterator it(new_space->bottom(), new_space->top()); |
| 2941 // Append the list of new space pages to be processed. | 2985 // Append the list of new space pages to be processed. |
| 2942 while (it.has_next()) { | 2986 while (it.has_next()) { |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3227 // Slots in live objects pointing into evacuation candidates are updated | 3271 // Slots in live objects pointing into evacuation candidates are updated |
| 3228 // if requested. | 3272 // if requested. |
| 3229 // Returns the size of the biggest continuous freed memory chunk in bytes. | 3273 // Returns the size of the biggest continuous freed memory chunk in bytes. |
| 3230 template <SweepingMode sweeping_mode, | 3274 template <SweepingMode sweeping_mode, |
| 3231 MarkCompactCollector::SweepingParallelism parallelism, | 3275 MarkCompactCollector::SweepingParallelism parallelism, |
| 3232 SkipListRebuildingMode skip_list_mode, | 3276 SkipListRebuildingMode skip_list_mode, |
| 3233 FreeSpaceTreatmentMode free_space_mode> | 3277 FreeSpaceTreatmentMode free_space_mode> |
| 3234 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, | 3278 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, |
| 3235 ObjectVisitor* v) { | 3279 ObjectVisitor* v) { |
| 3236 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3280 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3281 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); |
| 3237 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3282 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
| 3238 space->identity() == CODE_SPACE); | 3283 space->identity() == CODE_SPACE); |
| 3239 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3284 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
| 3240 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3285 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
| 3241 sweeping_mode == SWEEP_ONLY); | 3286 sweeping_mode == SWEEP_ONLY); |
| 3242 | 3287 |
| 3243 Address free_start = p->area_start(); | 3288 Address free_start = p->area_start(); |
| 3244 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3289 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3245 | 3290 |
| 3246 // If we use the skip list for code space pages, we have to lock the skip | 3291 // If we use the skip list for code space pages, we have to lock the skip |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3729 | 3774 |
| 3730 PageIterator it(space); | 3775 PageIterator it(space); |
| 3731 | 3776 |
| 3732 int will_be_swept = 0; | 3777 int will_be_swept = 0; |
| 3733 bool unused_page_present = false; | 3778 bool unused_page_present = false; |
| 3734 | 3779 |
| 3735 while (it.has_next()) { | 3780 while (it.has_next()) { |
| 3736 Page* p = it.next(); | 3781 Page* p = it.next(); |
| 3737 DCHECK(p->SweepingDone()); | 3782 DCHECK(p->SweepingDone()); |
| 3738 | 3783 |
| 3784 // We can not sweep black pages, since all mark bits are set for these |
| 3785 // pages. |
| 3786 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 3787 Bitmap::Clear(p); |
| 3788 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3789 p->ClearFlag(Page::BLACK_PAGE); |
| 3790 // TODO(hpayer): Free unused memory of last black page. |
| 3791 continue; |
| 3792 } |
| 3793 |
| 3739 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || | 3794 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || |
| 3740 p->IsEvacuationCandidate()) { | 3795 p->IsEvacuationCandidate()) { |
| 3741 // Will be processed in EvacuateNewSpaceAndCandidates. | 3796 // Will be processed in EvacuateNewSpaceAndCandidates. |
| 3742 DCHECK(evacuation_candidates_.length() > 0); | 3797 DCHECK(evacuation_candidates_.length() > 0); |
| 3743 continue; | 3798 continue; |
| 3744 } | 3799 } |
| 3745 | 3800 |
| 3746 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3801 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 3747 // We need to sweep the page to get it into an iterable state again. Note | 3802 // We need to sweep the page to get it into an iterable state again. Note |
| 3748 // that this adds unusable memory into the free list that is later on | 3803 // that this adds unusable memory into the free list that is later on |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3859 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3914 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3860 if (Marking::IsBlack(mark_bit)) { | 3915 if (Marking::IsBlack(mark_bit)) { |
| 3861 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3916 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3862 RecordRelocSlot(host, &rinfo, target); | 3917 RecordRelocSlot(host, &rinfo, target); |
| 3863 } | 3918 } |
| 3864 } | 3919 } |
| 3865 } | 3920 } |
| 3866 | 3921 |
| 3867 } // namespace internal | 3922 } // namespace internal |
| 3868 } // namespace v8 | 3923 } // namespace v8 |
| OLD | NEW |