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 |