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 |