| 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 112 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 113 CHECK(current >= next_object_must_be_here_or_later); | 113 CHECK(current >= next_object_must_be_here_or_later); |
| 114 object->Iterate(&visitor); | 114 object->Iterate(&visitor); |
| 115 next_object_must_be_here_or_later = current + object->Size(); | 115 next_object_must_be_here_or_later = current + object->Size(); |
| 116 // The next word for sure belongs to the current object, jump over it. | 116 // The next word for sure belongs to the current object, jump over it. |
| 117 current += kPointerSize; | 117 current += kPointerSize; |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 static void VerifyMarkingBlackPage(Heap* heap, Page* page) { |
| 123 CHECK(page->IsFlagSet(Page::BLACK_PAGE)); |
| 124 VerifyMarkingVisitor visitor(heap); |
| 125 HeapObjectIterator it(page); |
| 126 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
| 127 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 128 object->Iterate(&visitor); |
| 129 } |
| 130 } |
| 122 | 131 |
| 123 static void VerifyMarking(NewSpace* space) { | 132 static void VerifyMarking(NewSpace* space) { |
| 124 Address end = space->top(); | 133 Address end = space->top(); |
| 125 NewSpacePageIterator it(space->bottom(), end); | 134 NewSpacePageIterator it(space->bottom(), end); |
| 126 // The bottom position is at the start of its page. Allows us to use | 135 // The bottom position is at the start of its page. Allows us to use |
| 127 // page->area_start() as start of range on all pages. | 136 // page->area_start() as start of range on all pages. |
| 128 CHECK_EQ(space->bottom(), | 137 CHECK_EQ(space->bottom(), |
| 129 NewSpacePage::FromAddress(space->bottom())->area_start()); | 138 NewSpacePage::FromAddress(space->bottom())->area_start()); |
| 130 while (it.has_next()) { | 139 while (it.has_next()) { |
| 131 NewSpacePage* page = it.next(); | 140 NewSpacePage* page = it.next(); |
| 132 Address limit = it.has_next() ? page->area_end() : end; | 141 Address limit = it.has_next() ? page->area_end() : end; |
| 133 CHECK(limit == end || !page->Contains(end)); | 142 CHECK(limit == end || !page->Contains(end)); |
| 134 VerifyMarking(space->heap(), page->area_start(), limit); | 143 VerifyMarking(space->heap(), page->area_start(), limit); |
| 135 } | 144 } |
| 136 } | 145 } |
| 137 | 146 |
| 138 | 147 |
| 139 static void VerifyMarking(PagedSpace* space) { | 148 static void VerifyMarking(PagedSpace* space) { |
| 140 PageIterator it(space); | 149 PageIterator it(space); |
| 141 | 150 |
| 142 while (it.has_next()) { | 151 while (it.has_next()) { |
| 143 Page* p = it.next(); | 152 Page* p = it.next(); |
| 144 VerifyMarking(space->heap(), p->area_start(), p->area_end()); | 153 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 154 VerifyMarkingBlackPage(space->heap(), p); |
| 155 } else { |
| 156 VerifyMarking(space->heap(), p->area_start(), p->area_end()); |
| 157 } |
| 145 } | 158 } |
| 146 } | 159 } |
| 147 | 160 |
| 148 | 161 |
| 149 static void VerifyMarking(Heap* heap) { | 162 static void VerifyMarking(Heap* heap) { |
| 150 VerifyMarking(heap->old_space()); | 163 VerifyMarking(heap->old_space()); |
| 151 VerifyMarking(heap->code_space()); | 164 VerifyMarking(heap->code_space()); |
| 152 VerifyMarking(heap->map_space()); | 165 VerifyMarking(heap->map_space()); |
| 153 VerifyMarking(heap->new_space()); | 166 VerifyMarking(heap->new_space()); |
| 154 | 167 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 map->VerifyOmittedMapChecks(); | 420 map->VerifyOmittedMapChecks(); |
| 408 } | 421 } |
| 409 } | 422 } |
| 410 #endif // VERIFY_HEAP | 423 #endif // VERIFY_HEAP |
| 411 | 424 |
| 412 | 425 |
| 413 static void ClearMarkbitsInPagedSpace(PagedSpace* space) { | 426 static void ClearMarkbitsInPagedSpace(PagedSpace* space) { |
| 414 PageIterator it(space); | 427 PageIterator it(space); |
| 415 | 428 |
| 416 while (it.has_next()) { | 429 while (it.has_next()) { |
| 417 Bitmap::Clear(it.next()); | 430 Page* p = it.next(); |
| 431 Bitmap::Clear(p); |
| 432 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 433 p->ClearFlag(Page::BLACK_PAGE); |
| 434 } |
| 418 } | 435 } |
| 419 } | 436 } |
| 420 | 437 |
| 421 | 438 |
| 422 static void ClearMarkbitsInNewSpace(NewSpace* space) { | 439 static void ClearMarkbitsInNewSpace(NewSpace* space) { |
| 423 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); | 440 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); |
| 424 | 441 |
| 425 while (it.has_next()) { | 442 while (it.has_next()) { |
| 426 Bitmap::Clear(it.next()); | 443 Bitmap::Clear(it.next()); |
| 427 } | 444 } |
| 428 } | 445 } |
| 429 | 446 |
| 430 | 447 |
| 431 void MarkCompactCollector::ClearMarkbits() { | 448 void MarkCompactCollector::ClearMarkbits() { |
| 432 ClearMarkbitsInPagedSpace(heap_->code_space()); | 449 ClearMarkbitsInPagedSpace(heap_->code_space()); |
| 433 ClearMarkbitsInPagedSpace(heap_->map_space()); | 450 ClearMarkbitsInPagedSpace(heap_->map_space()); |
| 434 ClearMarkbitsInPagedSpace(heap_->old_space()); | 451 ClearMarkbitsInPagedSpace(heap_->old_space()); |
| 435 ClearMarkbitsInNewSpace(heap_->new_space()); | 452 ClearMarkbitsInNewSpace(heap_->new_space()); |
| 436 | 453 |
| 437 LargeObjectIterator it(heap_->lo_space()); | 454 LargeObjectIterator it(heap_->lo_space()); |
| 438 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 455 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 439 Marking::MarkWhite(Marking::MarkBitFrom(obj)); | 456 Marking::MarkWhite(Marking::MarkBitFrom(obj)); |
| 440 Page::FromAddress(obj->address())->ResetProgressBar(); | 457 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 441 Page::FromAddress(obj->address())->ResetLiveBytes(); | 458 chunk->ResetProgressBar(); |
| 459 chunk->ResetLiveBytes(); |
| 460 if (chunk->IsFlagSet(Page::BLACK_PAGE)) { |
| 461 chunk->ClearFlag(Page::BLACK_PAGE); |
| 462 } |
| 442 } | 463 } |
| 443 } | 464 } |
| 444 | 465 |
| 445 | 466 |
| 446 class MarkCompactCollector::SweeperTask : public v8::Task { | 467 class MarkCompactCollector::SweeperTask : public v8::Task { |
| 447 public: | 468 public: |
| 448 SweeperTask(Heap* heap, AllocationSpace space_to_start) | 469 SweeperTask(Heap* heap, AllocationSpace space_to_start) |
| 449 : heap_(heap), space_to_start_(space_to_start) {} | 470 : heap_(heap), space_to_start_(space_to_start) {} |
| 450 | 471 |
| 451 virtual ~SweeperTask() {} | 472 virtual ~SweeperTask() {} |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 pending_sweeper_tasks_semaphore_.Signal(); | 569 pending_sweeper_tasks_semaphore_.Signal(); |
| 549 return true; | 570 return true; |
| 550 } | 571 } |
| 551 | 572 |
| 552 | 573 |
| 553 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { | 574 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { |
| 554 // This is only used when resizing an object. | 575 // This is only used when resizing an object. |
| 555 DCHECK(MemoryChunk::FromAddress(old_start) == | 576 DCHECK(MemoryChunk::FromAddress(old_start) == |
| 556 MemoryChunk::FromAddress(new_start)); | 577 MemoryChunk::FromAddress(new_start)); |
| 557 | 578 |
| 558 if (!heap->incremental_marking()->IsMarking()) return; | 579 if (!heap->incremental_marking()->IsMarking() || |
| 580 Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE)) |
| 581 return; |
| 559 | 582 |
| 560 // If the mark doesn't move, we don't check the color of the object. | 583 // If the mark doesn't move, we don't check the color of the object. |
| 561 // It doesn't matter whether the object is black, since it hasn't changed | 584 // It doesn't matter whether the object is black, since it hasn't changed |
| 562 // size, so the adjustment to the live data count will be zero anyway. | 585 // size, so the adjustment to the live data count will be zero anyway. |
| 563 if (old_start == new_start) return; | 586 if (old_start == new_start) return; |
| 564 | 587 |
| 565 MarkBit new_mark_bit = MarkBitFrom(new_start); | 588 MarkBit new_mark_bit = MarkBitFrom(new_start); |
| 566 MarkBit old_mark_bit = MarkBitFrom(old_start); | 589 MarkBit old_mark_bit = MarkBitFrom(old_start); |
| 567 | 590 |
| 568 #ifdef DEBUG | 591 #ifdef DEBUG |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 | 680 |
| 658 // Pairs of (live_bytes_in_page, page). | 681 // Pairs of (live_bytes_in_page, page). |
| 659 typedef std::pair<int, Page*> LiveBytesPagePair; | 682 typedef std::pair<int, Page*> LiveBytesPagePair; |
| 660 std::vector<LiveBytesPagePair> pages; | 683 std::vector<LiveBytesPagePair> pages; |
| 661 pages.reserve(number_of_pages); | 684 pages.reserve(number_of_pages); |
| 662 | 685 |
| 663 PageIterator it(space); | 686 PageIterator it(space); |
| 664 while (it.has_next()) { | 687 while (it.has_next()) { |
| 665 Page* p = it.next(); | 688 Page* p = it.next(); |
| 666 if (p->NeverEvacuate()) continue; | 689 if (p->NeverEvacuate()) continue; |
| 690 if (p->IsFlagSet(Page::BLACK_PAGE)) continue; |
| 667 // Invariant: Evacuation candidates are just created when marking is | 691 // Invariant: Evacuation candidates are just created when marking is |
| 668 // started. This means that sweeping has finished. Furthermore, at the end | 692 // started. This means that sweeping has finished. Furthermore, at the end |
| 669 // of a GC all evacuation candidates are cleared and their slot buffers are | 693 // of a GC all evacuation candidates are cleared and their slot buffers are |
| 670 // released. | 694 // released. |
| 671 CHECK(!p->IsEvacuationCandidate()); | 695 CHECK(!p->IsEvacuationCandidate()); |
| 672 CHECK_NULL(p->old_to_old_slots()); | 696 CHECK_NULL(p->old_to_old_slots()); |
| 673 CHECK_NULL(p->typed_old_to_old_slots()); | 697 CHECK_NULL(p->typed_old_to_old_slots()); |
| 674 CHECK(p->SweepingDone()); | 698 CHECK(p->SweepingDone()); |
| 675 DCHECK(p->area_size() == area_size); | 699 DCHECK(p->area_size() == area_size); |
| 676 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); | 700 pages.push_back(std::make_pair(p->LiveBytesFromFreeList(), p)); |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { | 1484 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { |
| 1461 MarkBit markbit = Marking::MarkBitFrom(object); | 1485 MarkBit markbit = Marking::MarkBitFrom(object); |
| 1462 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { | 1486 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { |
| 1463 Marking::GreyToBlack(markbit); | 1487 Marking::GreyToBlack(markbit); |
| 1464 PushBlack(object); | 1488 PushBlack(object); |
| 1465 if (marking_deque()->IsFull()) return; | 1489 if (marking_deque()->IsFull()) return; |
| 1466 } | 1490 } |
| 1467 } | 1491 } |
| 1468 } | 1492 } |
| 1469 | 1493 |
| 1470 | 1494 template <LiveObjectIterationMode T> |
| 1471 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { | 1495 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
| 1472 DCHECK(!marking_deque()->IsFull()); | 1496 DCHECK(!marking_deque()->IsFull()); |
| 1473 LiveObjectIterator<kGreyObjects> it(p); | 1497 DCHECK(T == kGreyObjects || T == kGreyObjectsOnBlackPage); |
| 1498 LiveObjectIterator<T> it(p); |
| 1474 HeapObject* object = NULL; | 1499 HeapObject* object = NULL; |
| 1475 while ((object = it.Next()) != NULL) { | 1500 while ((object = it.Next()) != NULL) { |
| 1476 MarkBit markbit = Marking::MarkBitFrom(object); | 1501 MarkBit markbit = Marking::MarkBitFrom(object); |
| 1477 DCHECK(Marking::IsGrey(markbit)); | 1502 DCHECK(Marking::IsGrey(markbit)); |
| 1478 Marking::GreyToBlack(markbit); | 1503 Marking::GreyToBlack(markbit); |
| 1479 PushBlack(object); | 1504 PushBlack(object); |
| 1480 if (marking_deque()->IsFull()) return; | 1505 if (marking_deque()->IsFull()) return; |
| 1481 } | 1506 } |
| 1482 } | 1507 } |
| 1483 | 1508 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 } | 1722 } |
| 1698 return false; | 1723 return false; |
| 1699 } | 1724 } |
| 1700 }; | 1725 }; |
| 1701 | 1726 |
| 1702 | 1727 |
| 1703 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { | 1728 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { |
| 1704 PageIterator it(space); | 1729 PageIterator it(space); |
| 1705 while (it.has_next()) { | 1730 while (it.has_next()) { |
| 1706 Page* p = it.next(); | 1731 Page* p = it.next(); |
| 1707 DiscoverGreyObjectsOnPage(p); | 1732 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 1733 DiscoverGreyObjectsOnPage<kGreyObjectsOnBlackPage>(p); |
| 1734 } else { |
| 1735 DiscoverGreyObjectsOnPage<kGreyObjects>(p); |
| 1736 } |
| 1708 if (marking_deque()->IsFull()) return; | 1737 if (marking_deque()->IsFull()) return; |
| 1709 } | 1738 } |
| 1710 } | 1739 } |
| 1711 | 1740 |
| 1712 | 1741 |
| 1713 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { | 1742 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { |
| 1714 NewSpace* space = heap()->new_space(); | 1743 NewSpace* space = heap()->new_space(); |
| 1715 NewSpacePageIterator it(space->bottom(), space->top()); | 1744 NewSpacePageIterator it(space->bottom(), space->top()); |
| 1716 while (it.has_next()) { | 1745 while (it.has_next()) { |
| 1717 NewSpacePage* page = it.next(); | 1746 NewSpacePage* page = it.next(); |
| 1718 DiscoverGreyObjectsOnPage(page); | 1747 DiscoverGreyObjectsOnPage<kGreyObjects>(page); |
| 1719 if (marking_deque()->IsFull()) return; | 1748 if (marking_deque()->IsFull()) return; |
| 1720 } | 1749 } |
| 1721 } | 1750 } |
| 1722 | 1751 |
| 1723 | 1752 |
| 1724 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 1753 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 1725 Object* o = *p; | 1754 Object* o = *p; |
| 1726 if (!o->IsHeapObject()) return false; | 1755 if (!o->IsHeapObject()) return false; |
| 1727 HeapObject* heap_object = HeapObject::cast(o); | 1756 HeapObject* heap_object = HeapObject::cast(o); |
| 1728 MarkBit mark = Marking::MarkBitFrom(heap_object); | 1757 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2798 // for it. | 2827 // for it. |
| 2799 CHECK(large_object->IsHeapObject()); | 2828 CHECK(large_object->IsHeapObject()); |
| 2800 HeapObject* large_heap_object = HeapObject::cast(large_object); | 2829 HeapObject* large_heap_object = HeapObject::cast(large_object); |
| 2801 if (IsMarked(large_heap_object)) { | 2830 if (IsMarked(large_heap_object)) { |
| 2802 *out_object = large_heap_object; | 2831 *out_object = large_heap_object; |
| 2803 return true; | 2832 return true; |
| 2804 } | 2833 } |
| 2805 return false; | 2834 return false; |
| 2806 } | 2835 } |
| 2807 | 2836 |
| 2837 // If we are on a black page, we cannot find the actual object start |
| 2838 // easiliy. We just return true but do not set the out_object. |
| 2839 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 2840 return true; |
| 2841 } |
| 2842 |
| 2808 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); | 2843 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); |
| 2809 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; | 2844 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; |
| 2810 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); | 2845 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); |
| 2811 MarkBit::CellType* cells = p->markbits()->cells(); | 2846 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2812 Address base_address = p->area_start(); | 2847 Address base_address = p->area_start(); |
| 2813 unsigned int base_address_cell_index = Bitmap::IndexToCell( | 2848 unsigned int base_address_cell_index = Bitmap::IndexToCell( |
| 2814 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); | 2849 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); |
| 2815 | 2850 |
| 2816 // Check if the slot points to the start of an object. This can happen e.g. | 2851 // Check if the slot points to the start of an object. This can happen e.g. |
| 2817 // when we left trim a fixed array. Such slots are invalid and we can remove | 2852 // 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... |
| 2878 // Slots pointing to the first word of an object are invalid and removed. | 2913 // Slots pointing to the first word of an object are invalid and removed. |
| 2879 // This can happen when we move the object header while left trimming. | 2914 // This can happen when we move the object header while left trimming. |
| 2880 *out_object = object; | 2915 *out_object = object; |
| 2881 return true; | 2916 return true; |
| 2882 } | 2917 } |
| 2883 return false; | 2918 return false; |
| 2884 } | 2919 } |
| 2885 | 2920 |
| 2886 HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { | 2921 HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { |
| 2887 Page* p = Page::FromAddress(slot); | 2922 Page* p = Page::FromAddress(slot); |
| 2888 // This function does not support large objects right now. | |
| 2889 Space* owner = p->owner(); | 2923 Space* owner = p->owner(); |
| 2890 if (owner == heap_->lo_space() || owner == nullptr) { | 2924 if (owner == heap_->lo_space() || owner == nullptr) { |
| 2891 Object* large_object = heap_->lo_space()->FindObject(slot); | 2925 Object* large_object = heap_->lo_space()->FindObject(slot); |
| 2892 // This object has to exist, otherwise we would not have recorded a slot | 2926 // This object has to exist, otherwise we would not have recorded a slot |
| 2893 // for it. | 2927 // for it. |
| 2894 CHECK(large_object->IsHeapObject()); | 2928 CHECK(large_object->IsHeapObject()); |
| 2895 HeapObject* large_heap_object = HeapObject::cast(large_object); | 2929 HeapObject* large_heap_object = HeapObject::cast(large_object); |
| 2896 | 2930 |
| 2897 if (IsMarked(large_heap_object)) { | 2931 if (IsMarked(large_heap_object)) { |
| 2898 return large_heap_object; | 2932 return large_heap_object; |
| 2899 } | 2933 } |
| 2900 return nullptr; | 2934 return nullptr; |
| 2901 } | 2935 } |
| 2902 | 2936 |
| 2903 LiveObjectIterator<kBlackObjects> it(p); | 2937 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 2904 HeapObject* object = nullptr; | 2938 HeapObjectIterator it(p); |
| 2905 while ((object = it.Next()) != nullptr) { | 2939 HeapObject* object = nullptr; |
| 2906 int size = object->Size(); | 2940 while ((object = it.Next()) != nullptr) { |
| 2907 if (object->address() > slot) return nullptr; | 2941 int size = object->Size(); |
| 2908 if (object->address() <= slot && slot < (object->address() + size)) { | 2942 if (object->address() > slot) return nullptr; |
| 2909 return object; | 2943 if (object->address() <= slot && slot < (object->address() + size)) { |
| 2944 return object; |
| 2945 } |
| 2946 } |
| 2947 } else { |
| 2948 LiveObjectIterator<kBlackObjects> it(p); |
| 2949 HeapObject* object = nullptr; |
| 2950 while ((object = it.Next()) != nullptr) { |
| 2951 int size = object->Size(); |
| 2952 if (object->address() > slot) return nullptr; |
| 2953 if (object->address() <= slot && slot < (object->address() + size)) { |
| 2954 return object; |
| 2955 } |
| 2910 } | 2956 } |
| 2911 } | 2957 } |
| 2912 return nullptr; | 2958 return nullptr; |
| 2913 } | 2959 } |
| 2914 | 2960 |
| 2915 | 2961 |
| 2916 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { | 2962 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { |
| 2917 HeapObject* object = NULL; | |
| 2918 // The target object is black but we don't know if the source slot is black. | 2963 // The target object is black but we don't know if the source slot is black. |
| 2919 // The source object could have died and the slot could be part of a free | 2964 // The source object could have died and the slot could be part of a free |
| 2920 // space. Find out based on mark bits if the slot is part of a live object. | 2965 // space. Find out based on mark bits if the slot is part of a live object. |
| 2921 if (!IsSlotInBlackObject(Page::FromAddress(slot), slot, &object)) { | 2966 Page* page = Page::FromAddress(slot); |
| 2967 HeapObject* object = NULL; |
| 2968 if (!IsSlotInBlackObject(page, slot, &object)) { |
| 2922 return false; | 2969 return false; |
| 2923 } | 2970 } |
| 2924 | 2971 |
| 2925 DCHECK(object != NULL); | 2972 // If the slot is on a black page, the object will be live. |
| 2973 DCHECK(object != NULL || page->IsFlagSet(Page::BLACK_PAGE)); |
| 2974 if (page->IsFlagSet(Page::BLACK_PAGE)) { |
| 2975 return true; |
| 2976 } |
| 2977 |
| 2926 int offset = static_cast<int>(slot - object->address()); | 2978 int offset = static_cast<int>(slot - object->address()); |
| 2927 return object->IsValidSlot(offset); | 2979 return object->IsValidSlot(offset); |
| 2928 } | 2980 } |
| 2929 | 2981 |
| 2930 | 2982 |
| 2931 void MarkCompactCollector::EvacuateNewSpacePrologue() { | 2983 void MarkCompactCollector::EvacuateNewSpacePrologue() { |
| 2932 NewSpace* new_space = heap()->new_space(); | 2984 NewSpace* new_space = heap()->new_space(); |
| 2933 NewSpacePageIterator it(new_space->bottom(), new_space->top()); | 2985 NewSpacePageIterator it(new_space->bottom(), new_space->top()); |
| 2934 // Append the list of new space pages to be processed. | 2986 // Append the list of new space pages to be processed. |
| 2935 while (it.has_next()) { | 2987 while (it.has_next()) { |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3219 // Slots in live objects pointing into evacuation candidates are updated | 3271 // Slots in live objects pointing into evacuation candidates are updated |
| 3220 // if requested. | 3272 // if requested. |
| 3221 // 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. |
| 3222 template <SweepingMode sweeping_mode, | 3274 template <SweepingMode sweeping_mode, |
| 3223 MarkCompactCollector::SweepingParallelism parallelism, | 3275 MarkCompactCollector::SweepingParallelism parallelism, |
| 3224 SkipListRebuildingMode skip_list_mode, | 3276 SkipListRebuildingMode skip_list_mode, |
| 3225 FreeSpaceTreatmentMode free_space_mode> | 3277 FreeSpaceTreatmentMode free_space_mode> |
| 3226 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, | 3278 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, |
| 3227 ObjectVisitor* v) { | 3279 ObjectVisitor* v) { |
| 3228 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3280 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3281 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); |
| 3229 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3282 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
| 3230 space->identity() == CODE_SPACE); | 3283 space->identity() == CODE_SPACE); |
| 3231 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3284 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
| 3232 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3285 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
| 3233 sweeping_mode == SWEEP_ONLY); | 3286 sweeping_mode == SWEEP_ONLY); |
| 3234 | 3287 |
| 3235 Address free_start = p->area_start(); | 3288 Address free_start = p->area_start(); |
| 3236 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3289 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3237 | 3290 |
| 3238 // 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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3691 while (it.has_next()) { | 3744 while (it.has_next()) { |
| 3692 Page* p = it.next(); | 3745 Page* p = it.next(); |
| 3693 DCHECK(p->SweepingDone()); | 3746 DCHECK(p->SweepingDone()); |
| 3694 | 3747 |
| 3695 if (p->IsEvacuationCandidate()) { | 3748 if (p->IsEvacuationCandidate()) { |
| 3696 // Will be processed in EvacuateNewSpaceAndCandidates. | 3749 // Will be processed in EvacuateNewSpaceAndCandidates. |
| 3697 DCHECK(evacuation_candidates_.length() > 0); | 3750 DCHECK(evacuation_candidates_.length() > 0); |
| 3698 continue; | 3751 continue; |
| 3699 } | 3752 } |
| 3700 | 3753 |
| 3754 // We can not sweep black pages, since all mark bits are set for these |
| 3755 // pages. |
| 3756 if (p->IsFlagSet(Page::BLACK_PAGE)) { |
| 3757 Bitmap::Clear(p); |
| 3758 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3759 p->ClearFlag(Page::BLACK_PAGE); |
| 3760 // TODO(hpayer): Free unused memory of last black page. |
| 3761 continue; |
| 3762 } |
| 3763 |
| 3701 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3764 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 3702 // We need to sweep the page to get it into an iterable state again. Note | 3765 // We need to sweep the page to get it into an iterable state again. Note |
| 3703 // that this adds unusable memory into the free list that is later on | 3766 // that this adds unusable memory into the free list that is later on |
| 3704 // (in the free list) dropped again. Since we only use the flag for | 3767 // (in the free list) dropped again. Since we only use the flag for |
| 3705 // testing this is fine. | 3768 // testing this is fine. |
| 3706 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3769 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3707 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3770 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
| 3708 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3771 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); |
| 3709 continue; | 3772 continue; |
| 3710 } | 3773 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3814 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3877 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3815 if (Marking::IsBlack(mark_bit)) { | 3878 if (Marking::IsBlack(mark_bit)) { |
| 3816 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3879 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3817 RecordRelocSlot(host, &rinfo, target); | 3880 RecordRelocSlot(host, &rinfo, target); |
| 3818 } | 3881 } |
| 3819 } | 3882 } |
| 3820 } | 3883 } |
| 3821 | 3884 |
| 3822 } // namespace internal | 3885 } // namespace internal |
| 3823 } // namespace v8 | 3886 } // namespace v8 |
| OLD | NEW |