Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: src/heap/mark-compact.cc

Issue 1420423009: [heap] Black allocation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 VerifyMarking(space->heap(), page->area_start(), limit); 137 VerifyMarking(space->heap(), page->area_start(), limit);
138 } 138 }
139 } 139 }
140 140
141 141
142 static void VerifyMarking(PagedSpace* space) { 142 static void VerifyMarking(PagedSpace* space) {
143 PageIterator it(space); 143 PageIterator it(space);
144 144
145 while (it.has_next()) { 145 while (it.has_next()) {
146 Page* p = it.next(); 146 Page* p = it.next();
147 VerifyMarking(space->heap(), p->area_start(), p->area_end()); 147 if (!p->IsFlagSet(Page::BLACK_PAGE)) {
148 VerifyMarking(space->heap(), p->area_start(), p->area_end());
149 }
ulan 2016/02/10 10:27:39 It would be great to verify coloring invariant for
Hannes Payer (out of office) 2016/02/11 18:18:07 Done.
148 } 150 }
149 } 151 }
150 152
151 153
152 static void VerifyMarking(Heap* heap) { 154 static void VerifyMarking(Heap* heap) {
153 VerifyMarking(heap->old_space()); 155 VerifyMarking(heap->old_space());
154 VerifyMarking(heap->code_space()); 156 VerifyMarking(heap->code_space());
155 VerifyMarking(heap->map_space()); 157 VerifyMarking(heap->map_space());
156 VerifyMarking(heap->new_space()); 158 VerifyMarking(heap->new_space());
157 159
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 map->VerifyOmittedMapChecks(); 443 map->VerifyOmittedMapChecks();
442 } 444 }
443 } 445 }
444 #endif // VERIFY_HEAP 446 #endif // VERIFY_HEAP
445 447
446 448
447 static void ClearMarkbitsInPagedSpace(PagedSpace* space) { 449 static void ClearMarkbitsInPagedSpace(PagedSpace* space) {
448 PageIterator it(space); 450 PageIterator it(space);
449 451
450 while (it.has_next()) { 452 while (it.has_next()) {
451 Bitmap::Clear(it.next()); 453 Page* p = it.next();
454 Bitmap::Clear(p);
455 if (p->IsFlagSet(Page::BLACK_PAGE)) {
456 p->ClearFlag(Page::BLACK_PAGE);
457 }
452 } 458 }
453 } 459 }
454 460
455 461
456 static void ClearMarkbitsInNewSpace(NewSpace* space) { 462 static void ClearMarkbitsInNewSpace(NewSpace* space) {
457 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); 463 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd());
458 464
459 while (it.has_next()) { 465 while (it.has_next()) {
460 Bitmap::Clear(it.next()); 466 Bitmap::Clear(it.next());
461 } 467 }
462 } 468 }
463 469
464 470
465 void MarkCompactCollector::ClearMarkbits() { 471 void MarkCompactCollector::ClearMarkbits() {
466 ClearMarkbitsInPagedSpace(heap_->code_space()); 472 ClearMarkbitsInPagedSpace(heap_->code_space());
467 ClearMarkbitsInPagedSpace(heap_->map_space()); 473 ClearMarkbitsInPagedSpace(heap_->map_space());
468 ClearMarkbitsInPagedSpace(heap_->old_space()); 474 ClearMarkbitsInPagedSpace(heap_->old_space());
469 ClearMarkbitsInNewSpace(heap_->new_space()); 475 ClearMarkbitsInNewSpace(heap_->new_space());
470 476
471 LargeObjectIterator it(heap_->lo_space()); 477 LargeObjectIterator it(heap_->lo_space());
472 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { 478 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
473 Marking::MarkWhite(Marking::MarkBitFrom(obj)); 479 Marking::MarkWhite(Marking::MarkBitFrom(obj));
474 Page::FromAddress(obj->address())->ResetProgressBar(); 480 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
475 Page::FromAddress(obj->address())->ResetLiveBytes(); 481 chunk->ResetProgressBar();
482 chunk->ResetLiveBytes();
483 if (chunk->IsFlagSet(Page::BLACK_PAGE)) {
484 chunk->ClearFlag(Page::BLACK_PAGE);
485 }
476 } 486 }
477 } 487 }
478 488
479 489
480 class MarkCompactCollector::SweeperTask : public v8::Task { 490 class MarkCompactCollector::SweeperTask : public v8::Task {
481 public: 491 public:
482 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {} 492 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {}
483 493
484 virtual ~SweeperTask() {} 494 virtual ~SweeperTask() {}
485 495
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 pending_sweeper_tasks_semaphore_.Signal(); 584 pending_sweeper_tasks_semaphore_.Signal();
575 return true; 585 return true;
576 } 586 }
577 587
578 588
579 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) { 589 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) {
580 // This is only used when resizing an object. 590 // This is only used when resizing an object.
581 DCHECK(MemoryChunk::FromAddress(old_start) == 591 DCHECK(MemoryChunk::FromAddress(old_start) ==
582 MemoryChunk::FromAddress(new_start)); 592 MemoryChunk::FromAddress(new_start));
583 593
584 if (!heap->incremental_marking()->IsMarking()) return; 594 if (!heap->incremental_marking()->IsMarking() ||
595 Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE))
596 return;
585 597
586 // If the mark doesn't move, we don't check the color of the object. 598 // If the mark doesn't move, we don't check the color of the object.
587 // It doesn't matter whether the object is black, since it hasn't changed 599 // It doesn't matter whether the object is black, since it hasn't changed
588 // size, so the adjustment to the live data count will be zero anyway. 600 // size, so the adjustment to the live data count will be zero anyway.
589 if (old_start == new_start) return; 601 if (old_start == new_start) return;
590 602
591 MarkBit new_mark_bit = MarkBitFrom(new_start); 603 MarkBit new_mark_bit = MarkBitFrom(new_start);
592 MarkBit old_mark_bit = MarkBitFrom(old_start); 604 MarkBit old_mark_bit = MarkBitFrom(old_start);
593 605
594 #ifdef DEBUG 606 #ifdef DEBUG
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 695
684 // Pairs of (live_bytes_in_page, page). 696 // Pairs of (live_bytes_in_page, page).
685 typedef std::pair<int, Page*> LiveBytesPagePair; 697 typedef std::pair<int, Page*> LiveBytesPagePair;
686 std::vector<LiveBytesPagePair> pages; 698 std::vector<LiveBytesPagePair> pages;
687 pages.reserve(number_of_pages); 699 pages.reserve(number_of_pages);
688 700
689 PageIterator it(space); 701 PageIterator it(space);
690 while (it.has_next()) { 702 while (it.has_next()) {
691 Page* p = it.next(); 703 Page* p = it.next();
692 if (p->NeverEvacuate()) continue; 704 if (p->NeverEvacuate()) continue;
705 if (p->IsFlagSet(Page::BLACK_PAGE)) continue;
693 if (p->IsFlagSet(Page::POPULAR_PAGE)) { 706 if (p->IsFlagSet(Page::POPULAR_PAGE)) {
694 // This page had slots buffer overflow on previous GC, skip it. 707 // This page had slots buffer overflow on previous GC, skip it.
695 p->ClearFlag(Page::POPULAR_PAGE); 708 p->ClearFlag(Page::POPULAR_PAGE);
696 continue; 709 continue;
697 } 710 }
698 // Invariant: Evacuation candidates are just created when marking is 711 // Invariant: Evacuation candidates are just created when marking is
699 // started. This means that sweeping has finished. Furthermore, at the end 712 // started. This means that sweeping has finished. Furthermore, at the end
700 // of a GC all evacuation candidates are cleared and their slot buffers are 713 // of a GC all evacuation candidates are cleared and their slot buffers are
701 // released. 714 // released.
702 CHECK(!p->IsEvacuationCandidate()); 715 CHECK(!p->IsEvacuationCandidate());
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 } 1739 }
1727 return false; 1740 return false;
1728 } 1741 }
1729 }; 1742 };
1730 1743
1731 1744
1732 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) { 1745 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) {
1733 PageIterator it(space); 1746 PageIterator it(space);
1734 while (it.has_next()) { 1747 while (it.has_next()) {
1735 Page* p = it.next(); 1748 Page* p = it.next();
1736 DiscoverGreyObjectsOnPage(p); 1749 if (!p->IsFlagSet(Page::BLACK_PAGE)) {
1737 if (marking_deque()->IsFull()) return; 1750 DiscoverGreyObjectsOnPage(p);
1751 if (marking_deque()->IsFull()) return;
1752 }
1738 } 1753 }
1739 } 1754 }
1740 1755
1741 1756
1742 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() { 1757 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() {
1743 NewSpace* space = heap()->new_space(); 1758 NewSpace* space = heap()->new_space();
1744 NewSpacePageIterator it(space->bottom(), space->top()); 1759 NewSpacePageIterator it(space->bottom(), space->top());
1745 while (it.has_next()) { 1760 while (it.has_next()) {
1746 NewSpacePage* page = it.next(); 1761 NewSpacePage* page = it.next();
1747 DiscoverGreyObjectsOnPage(page); 1762 DiscoverGreyObjectsOnPage(page);
(...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 // for it. 2921 // for it.
2907 CHECK(large_object->IsHeapObject()); 2922 CHECK(large_object->IsHeapObject());
2908 HeapObject* large_heap_object = HeapObject::cast(large_object); 2923 HeapObject* large_heap_object = HeapObject::cast(large_object);
2909 if (IsMarked(large_heap_object)) { 2924 if (IsMarked(large_heap_object)) {
2910 *out_object = large_heap_object; 2925 *out_object = large_heap_object;
2911 return true; 2926 return true;
2912 } 2927 }
2913 return false; 2928 return false;
2914 } 2929 }
2915 2930
2931 // If we are on a black page, we cannot find the actual object start
2932 // easiliy. We just return true but do not set the out_object.
2933 if (p->IsFlagSet(Page::BLACK_PAGE)) {
2934 return true;
2935 }
2936
2916 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); 2937 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot);
2917 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; 2938 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2;
2918 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); 2939 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index);
2919 MarkBit::CellType* cells = p->markbits()->cells(); 2940 MarkBit::CellType* cells = p->markbits()->cells();
2920 Address base_address = p->area_start(); 2941 Address base_address = p->area_start();
2921 unsigned int base_address_cell_index = Bitmap::IndexToCell( 2942 unsigned int base_address_cell_index = Bitmap::IndexToCell(
2922 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); 2943 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address)));
2923 2944
2924 // Check if the slot points to the start of an object. This can happen e.g. 2945 // Check if the slot points to the start of an object. This can happen e.g.
2925 // when we left trim a fixed array. Such slots are invalid and we can remove 2946 // 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
2986 // Slots pointing to the first word of an object are invalid and removed. 3007 // Slots pointing to the first word of an object are invalid and removed.
2987 // This can happen when we move the object header while left trimming. 3008 // This can happen when we move the object header while left trimming.
2988 *out_object = object; 3009 *out_object = object;
2989 return true; 3010 return true;
2990 } 3011 }
2991 return false; 3012 return false;
2992 } 3013 }
2993 3014
2994 3015
2995 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) { 3016 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) {
2996 // This function does not support large objects right now.
2997 Space* owner = p->owner(); 3017 Space* owner = p->owner();
2998 if (owner == heap_->lo_space() || owner == NULL) { 3018 if (owner == heap_->lo_space() || owner == NULL) {
2999 Object* large_object = heap_->lo_space()->FindObject(slot); 3019 Object* large_object = heap_->lo_space()->FindObject(slot);
3000 // This object has to exist, otherwise we would not have recorded a slot 3020 // This object has to exist, otherwise we would not have recorded a slot
3001 // for it. 3021 // for it.
3002 CHECK(large_object->IsHeapObject()); 3022 CHECK(large_object->IsHeapObject());
3003 HeapObject* large_heap_object = HeapObject::cast(large_object); 3023 HeapObject* large_heap_object = HeapObject::cast(large_object);
3004 if (IsMarked(large_heap_object)) { 3024 if (IsMarked(large_heap_object)) {
3005 return true; 3025 return true;
3006 } 3026 }
3007 return false; 3027 return false;
3008 } 3028 }
3009 3029
3030 if (p->IsFlagSet(Page::BLACK_PAGE)) return true;
3031
3010 LiveObjectIterator<kBlackObjects> it(p); 3032 LiveObjectIterator<kBlackObjects> it(p);
3011 HeapObject* object = NULL; 3033 HeapObject* object = NULL;
3012 while ((object = it.Next()) != NULL) { 3034 while ((object = it.Next()) != NULL) {
3013 int size = object->Size(); 3035 int size = object->Size();
3014 3036
3015 if (object->address() > slot) return false; 3037 if (object->address() > slot) return false;
3016 if (object->address() <= slot && slot < (object->address() + size)) { 3038 if (object->address() <= slot && slot < (object->address() + size)) {
3017 return true; 3039 return true;
3018 } 3040 }
3019 } 3041 }
3020 return false; 3042 return false;
3021 } 3043 }
3022 3044
3023 3045
3024 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { 3046 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
3025 HeapObject* object = NULL;
3026 // The target object is black but we don't know if the source slot is black. 3047 // The target object is black but we don't know if the source slot is black.
3027 // The source object could have died and the slot could be part of a free 3048 // The source object could have died and the slot could be part of a free
3028 // space. Find out based on mark bits if the slot is part of a live object. 3049 // space. Find out based on mark bits if the slot is part of a live object.
3029 if (!IsSlotInBlackObject(Page::FromAddress(slot), slot, &object)) { 3050 Page* page = Page::FromAddress(slot);
3051 HeapObject* object = NULL;
3052 if (!IsSlotInBlackObject(page, slot, &object)) {
3030 return false; 3053 return false;
3031 } 3054 }
3032 3055
3033 DCHECK(object != NULL); 3056 // If the slot is on a black page, the object will be live.
3057 DCHECK(object != NULL || page->IsFlagSet(Page::BLACK_PAGE));
3058 if (page->IsFlagSet(Page::BLACK_PAGE)) {
3059 return true;
3060 }
3061
3034 int offset = static_cast<int>(slot - object->address()); 3062 int offset = static_cast<int>(slot - object->address());
3035 return object->IsValidSlot(offset); 3063 return object->IsValidSlot(offset);
3036 } 3064 }
3037 3065
3038 3066
3039 void MarkCompactCollector::VerifyIsSlotInLiveObject(Address slot, 3067 void MarkCompactCollector::VerifyIsSlotInLiveObject(Address slot,
3040 HeapObject* object) { 3068 HeapObject* object) {
3041 // The target object has to be black. 3069 // The target object has to be black.
3042 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 3070 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3043 3071
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
3426 // Slots in live objects pointing into evacuation candidates are updated 3454 // Slots in live objects pointing into evacuation candidates are updated
3427 // if requested. 3455 // if requested.
3428 // Returns the size of the biggest continuous freed memory chunk in bytes. 3456 // Returns the size of the biggest continuous freed memory chunk in bytes.
3429 template <SweepingMode sweeping_mode, 3457 template <SweepingMode sweeping_mode,
3430 MarkCompactCollector::SweepingParallelism parallelism, 3458 MarkCompactCollector::SweepingParallelism parallelism,
3431 SkipListRebuildingMode skip_list_mode, 3459 SkipListRebuildingMode skip_list_mode,
3432 FreeSpaceTreatmentMode free_space_mode> 3460 FreeSpaceTreatmentMode free_space_mode>
3433 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, 3461 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p,
3434 ObjectVisitor* v) { 3462 ObjectVisitor* v) {
3435 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); 3463 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone());
3464 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE));
3436 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, 3465 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST,
3437 space->identity() == CODE_SPACE); 3466 space->identity() == CODE_SPACE);
3438 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); 3467 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST));
3439 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || 3468 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD ||
3440 sweeping_mode == SWEEP_ONLY); 3469 sweeping_mode == SWEEP_ONLY);
3441 3470
3442 Address free_start = p->area_start(); 3471 Address free_start = p->area_start();
3443 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); 3472 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
3444 3473
3445 // If we use the skip list for code space pages, we have to lock the skip 3474 // If we use the skip list for code space pages, we have to lock the skip
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
3882 3911
3883 PageIterator it(space); 3912 PageIterator it(space);
3884 3913
3885 int will_be_swept = 0; 3914 int will_be_swept = 0;
3886 bool unused_page_present = false; 3915 bool unused_page_present = false;
3887 3916
3888 while (it.has_next()) { 3917 while (it.has_next()) {
3889 Page* p = it.next(); 3918 Page* p = it.next();
3890 DCHECK(p->SweepingDone()); 3919 DCHECK(p->SweepingDone());
3891 3920
3921 // We can not sweep black pages, since all mark bits are set for these
3922 // pages.
3923 if (p->IsFlagSet(Page::BLACK_PAGE)) {
3924 Bitmap::Clear(p);
3925 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3926 p->ClearFlag(Page::BLACK_PAGE);
3927 // TODO(hpayer): Free unused memory of last black page.
3928 continue;
3929 }
3930
3892 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || 3931 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) ||
3893 p->IsEvacuationCandidate()) { 3932 p->IsEvacuationCandidate()) {
3894 // Will be processed in EvacuateNewSpaceAndCandidates. 3933 // Will be processed in EvacuateNewSpaceAndCandidates.
3895 DCHECK(evacuation_candidates_.length() > 0); 3934 DCHECK(evacuation_candidates_.length() > 0);
3896 continue; 3935 continue;
3897 } 3936 }
3898 3937
3899 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { 3938 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) {
3900 // We need to sweep the page to get it into an iterable state again. Note 3939 // We need to sweep the page to get it into an iterable state again. Note
3901 // that this adds unusable memory into the free list that is later on 3940 // that this adds unusable memory into the free list that is later on
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
4056 MarkBit mark_bit = Marking::MarkBitFrom(host); 4095 MarkBit mark_bit = Marking::MarkBitFrom(host);
4057 if (Marking::IsBlack(mark_bit)) { 4096 if (Marking::IsBlack(mark_bit)) {
4058 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 4097 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
4059 RecordRelocSlot(&rinfo, target); 4098 RecordRelocSlot(&rinfo, target);
4060 } 4099 }
4061 } 4100 }
4062 } 4101 }
4063 4102
4064 } // namespace internal 4103 } // namespace internal
4065 } // namespace v8 4104 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698