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

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

Issue 1517993003: [heap] Black is encoded with 11, grey with 10. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 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 15 matching lines...) Expand all
26 #include "src/ic/ic.h" 26 #include "src/ic/ic.h"
27 #include "src/ic/stub-cache.h" 27 #include "src/ic/stub-cache.h"
28 #include "src/profiler/cpu-profiler.h" 28 #include "src/profiler/cpu-profiler.h"
29 #include "src/v8.h" 29 #include "src/v8.h"
30 30
31 namespace v8 { 31 namespace v8 {
32 namespace internal { 32 namespace internal {
33 33
34 34
35 const char* Marking::kWhiteBitPattern = "00"; 35 const char* Marking::kWhiteBitPattern = "00";
36 const char* Marking::kBlackBitPattern = "10"; 36 const char* Marking::kBlackBitPattern = "11";
37 const char* Marking::kGreyBitPattern = "11"; 37 const char* Marking::kGreyBitPattern = "10";
38 const char* Marking::kImpossibleBitPattern = "01"; 38 const char* Marking::kImpossibleBitPattern = "01";
39 39
40 40
41 // The following has to hold in order for {Marking::MarkBitFrom} to not produce 41 // The following has to hold in order for {Marking::MarkBitFrom} to not produce
42 // invalid {kImpossibleBitPattern} in the marking bitmap by overlapping. 42 // invalid {kImpossibleBitPattern} in the marking bitmap by overlapping.
43 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2); 43 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2);
44 44
45 45
46 // ------------------------------------------------------------------------- 46 // -------------------------------------------------------------------------
47 // MarkCompactCollector 47 // MarkCompactCollector
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 HeapObject* object; 108 HeapObject* object;
109 Address next_object_must_be_here_or_later = bottom; 109 Address next_object_must_be_here_or_later = bottom;
110 110
111 for (Address current = bottom; current < top; current += kPointerSize) { 111 for (Address current = bottom; current < top; current += kPointerSize) {
112 object = HeapObject::FromAddress(current); 112 object = HeapObject::FromAddress(current);
113 if (MarkCompactCollector::IsMarked(object)) { 113 if (MarkCompactCollector::IsMarked(object)) {
114 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 114 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
115 CHECK(current >= next_object_must_be_here_or_later); 115 CHECK(current >= next_object_must_be_here_or_later);
116 object->Iterate(&visitor); 116 object->Iterate(&visitor);
117 next_object_must_be_here_or_later = current + object->Size(); 117 next_object_must_be_here_or_later = current + object->Size();
118 // The next word for sure belongs to the current object, jump over it.
119 current += kPointerSize;
118 } 120 }
119 } 121 }
120 } 122 }
121 123
122 124
123 static void VerifyMarking(NewSpace* space) { 125 static void VerifyMarking(NewSpace* space) {
124 Address end = space->top(); 126 Address end = space->top();
125 NewSpacePageIterator it(space->bottom(), end); 127 NewSpacePageIterator it(space->bottom(), end);
126 // The bottom position is at the start of its page. Allows us to use 128 // 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. 129 // page->area_start() as start of range on all pages.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 VerifyEvacuation(heap->new_space()); 232 VerifyEvacuation(heap->new_space());
231 233
232 VerifyEvacuationVisitor visitor; 234 VerifyEvacuationVisitor visitor;
233 heap->IterateStrongRoots(&visitor, VISIT_ALL); 235 heap->IterateStrongRoots(&visitor, VISIT_ALL);
234 } 236 }
235 #endif // VERIFY_HEAP 237 #endif // VERIFY_HEAP
236 238
237 239
238 void MarkCompactCollector::SetUp() { 240 void MarkCompactCollector::SetUp() {
239 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); 241 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
240 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); 242 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
241 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); 243 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
242 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 244 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
243 245
244 free_list_old_space_.Reset(new FreeList(heap_->old_space())); 246 free_list_old_space_.Reset(new FreeList(heap_->old_space()));
245 free_list_code_space_.Reset(new FreeList(heap_->code_space())); 247 free_list_code_space_.Reset(new FreeList(heap_->code_space()));
246 free_list_map_space_.Reset(new FreeList(heap_->map_space())); 248 free_list_map_space_.Reset(new FreeList(heap_->map_space()));
247 EnsureMarkingDequeIsReserved(); 249 EnsureMarkingDequeIsReserved();
248 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); 250 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize);
249 slots_buffer_allocator_ = new SlotsBufferAllocator(); 251 slots_buffer_allocator_ = new SlotsBufferAllocator();
250 252
251 if (FLAG_flush_code) { 253 if (FLAG_flush_code) {
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after
1518 MarkBit markbit = Marking::MarkBitFrom(object); 1520 MarkBit markbit = Marking::MarkBitFrom(object);
1519 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { 1521 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) {
1520 Marking::GreyToBlack(markbit); 1522 Marking::GreyToBlack(markbit);
1521 PushBlack(object); 1523 PushBlack(object);
1522 if (marking_deque()->IsFull()) return; 1524 if (marking_deque()->IsFull()) return;
1523 } 1525 }
1524 } 1526 }
1525 } 1527 }
1526 1528
1527 1529
1528 static inline int MarkWordToObjectStarts(uint32_t mark_bits,
1529 uint32_t next_mark_bits, Address base,
1530 Address* starts);
1531
1532
1533 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { 1530 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) {
1534 DCHECK(!marking_deque()->IsFull()); 1531 DCHECK(!marking_deque()->IsFull());
1535 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); 1532 LiveObjectIterator it(p);
1536 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); 1533 HeapObject* object = NULL;
1537 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); 1534 while ((object = it.Next<LiveObjectIterator::kGreyObjects>()) != NULL) {
1538 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); 1535 MarkBit markbit = Marking::MarkBitFrom(object);
1539 1536 DCHECK(Marking::IsGrey(markbit));
1540 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { 1537 Marking::GreyToBlack(markbit);
1541 Address cell_base = it.CurrentCellBase(); 1538 PushBlack(object);
1542 MarkBit::CellType* cell = it.CurrentCell(); 1539 if (marking_deque()->IsFull()) return;
1543
1544 const MarkBit::CellType current_cell = *cell;
1545 if (current_cell == 0) continue;
1546
1547 MarkBit::CellType grey_objects;
1548 if (it.HasNext()) {
1549 const MarkBit::CellType next_cell = *(cell + 1);
1550 grey_objects = current_cell & ((current_cell >> 1) |
1551 (next_cell << (Bitmap::kBitsPerCell - 1)));
1552 } else {
1553 grey_objects = current_cell & (current_cell >> 1);
1554 }
1555
1556 int offset = 0;
1557 while (grey_objects != 0) {
1558 int trailing_zeros = base::bits::CountTrailingZeros32(grey_objects);
1559 grey_objects >>= trailing_zeros;
1560 offset += trailing_zeros;
1561 MarkBit markbit(cell, 1 << offset);
1562 DCHECK(Marking::IsGrey(markbit));
1563 Marking::GreyToBlack(markbit);
1564 Address addr = cell_base + offset * kPointerSize;
1565 HeapObject* object = HeapObject::FromAddress(addr);
1566 PushBlack(object);
1567 if (marking_deque()->IsFull()) return;
1568 offset += 2;
1569 grey_objects >>= 2;
1570 }
1571
1572 grey_objects >>= (Bitmap::kBitsPerCell - 1);
1573 } 1540 }
1574 } 1541 }
1575 1542
1576 1543
1577 class MarkCompactCollector::HeapObjectVisitor { 1544 class MarkCompactCollector::HeapObjectVisitor {
1578 public: 1545 public:
1579 virtual ~HeapObjectVisitor() {} 1546 virtual ~HeapObjectVisitor() {}
1580 virtual bool Visit(HeapObject* object) = 0; 1547 virtual bool Visit(HeapObject* object) = 0;
1581 }; 1548 };
1582 1549
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after
2952 MarkBit::CellType index_in_cell = 1U 2919 MarkBit::CellType index_in_cell = 1U
2953 << (mark_bit_index & Bitmap::kBitIndexMask); 2920 << (mark_bit_index & Bitmap::kBitIndexMask);
2954 MarkBit::CellType* cells = p->markbits()->cells(); 2921 MarkBit::CellType* cells = p->markbits()->cells();
2955 Address cell_base = p->area_start(); 2922 Address cell_base = p->area_start();
2956 unsigned int cell_base_start_index = Bitmap::IndexToCell( 2923 unsigned int cell_base_start_index = Bitmap::IndexToCell(
2957 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(cell_base))); 2924 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(cell_base)));
2958 2925
2959 // Check if the slot points to the start of an object. This can happen e.g. 2926 // Check if the slot points to the start of an object. This can happen e.g.
2960 // when we left trim a fixed array. Such slots are invalid and we can remove 2927 // when we left trim a fixed array. Such slots are invalid and we can remove
2961 // them. 2928 // them.
2962 if ((cells[start_index] & index_in_cell) != 0) { 2929 if (index_in_cell > 1) {
2963 return false; 2930 if ((cells[start_index] & index_in_cell) != 0 &&
ulan 2016/01/07 16:39:11 Let's make the two parts consistent (either treat
Hannes Payer (out of office) 2016/01/11 13:37:34 Done.
2931 !(cells[start_index] & (index_in_cell >> 1))) {
2932 return false;
2933 }
2934 } else {
2935 // Left trimming moves the mark bits so we cannot be in the very first cell.
2936 DCHECK(start_index != cell_base_start_index);
2937 if ((cells[start_index] & index_in_cell) != 0 &&
2938 !(cells[start_index - 1] & 0x80000000)) {
ulan 2016/01/07 16:39:11 Use Bitmap::kBitsPerCell instead of the constant o
Hannes Payer (out of office) 2016/01/11 13:37:34 Done.
2939 return false;
2940 }
2964 } 2941 }
2965 2942
2966 // Check if the object is in the current cell. 2943 // Check if the object is in the current cell.
2967 MarkBit::CellType slot_mask; 2944 MarkBit::CellType slot_mask;
2968 if ((cells[start_index] == 0) || 2945 if ((cells[start_index] == 0) ||
2969 (base::bits::CountTrailingZeros32(cells[start_index]) > 2946 (base::bits::CountTrailingZeros32(cells[start_index]) >
2970 base::bits::CountTrailingZeros32(cells[start_index] | index_in_cell))) { 2947 base::bits::CountTrailingZeros32(cells[start_index] | index_in_cell))) {
2971 // If we are already in the first cell, there is no live object. 2948 // If we are already in the first cell, there is no live object.
2972 if (start_index == cell_base_start_index) return false; 2949 if (start_index == cell_base_start_index) return false;
2973 2950
2974 // If not, find a cell in a preceding cell slot that has a mark bit set. 2951 // If not, find a cell in a preceding cell slot that has a mark bit set.
2975 do { 2952 do {
2976 start_index--; 2953 start_index--;
2977 } while (start_index > cell_base_start_index && cells[start_index] == 0); 2954 } while (start_index > cell_base_start_index && cells[start_index] == 0);
2978 2955
2979 // The slot must be in a dead object if there are no preceding cells that 2956 // The slot must be in a dead object if there are no preceding cells that
2980 // have mark bits set. 2957 // have mark bits set.
2981 if (cells[start_index] == 0) { 2958 if (cells[start_index] == 0) {
2982 return false; 2959 return false;
2983 } 2960 }
2984 2961
2985 // The object is in a preceding cell. Set the mask to find any object. 2962 // The object is in a preceding cell. Set the mask to find any object.
2986 slot_mask = 0xffffffff; 2963 slot_mask = 0xffffffff;
2987 } else { 2964 } else {
2988 // The object start is before the the slot index. Hence, in this case the
2989 // slot index can not be at the beginning of the cell.
2990 CHECK(index_in_cell > 1);
2991 // We are interested in object mark bits right before the slot. 2965 // We are interested in object mark bits right before the slot.
2992 slot_mask = index_in_cell - 1; 2966 slot_mask = index_in_cell + (index_in_cell - 1);
2993 } 2967 }
2994 2968
2995 MarkBit::CellType current_cell = cells[start_index]; 2969 MarkBit::CellType current_cell = cells[start_index];
2996 CHECK(current_cell != 0); 2970 CHECK(current_cell != 0);
2997 2971
2998 // Find the last live object in the cell. 2972 // Find the last live object in the cell.
2999 unsigned int leading_zeros = 2973 unsigned int leading_zeros =
3000 base::bits::CountLeadingZeros32(current_cell & slot_mask); 2974 base::bits::CountLeadingZeros32(current_cell & slot_mask);
3001 CHECK(leading_zeros != 32); 2975 CHECK(leading_zeros != Bitmap::kBitsPerCell);
3002 unsigned int offset = Bitmap::kBitIndexMask - leading_zeros;
3003 2976
3004 cell_base += (start_index - cell_base_start_index) * 32 * kPointerSize; 2977 unsigned int offset;
2978 if (leading_zeros == Bitmap::kBitIndexMask) {
ulan 2016/01/07 16:39:11 Making offset a signed int, would allow to simply
Hannes Payer (out of office) 2016/01/11 13:37:34 Done.
2979 start_index -= 1;
2980 current_cell = cells[start_index];
2981 slot_mask = 0xffffffff;
2982 CHECK(base::bits::CountLeadingZeros32(current_cell & slot_mask) == 0);
ulan 2016/01/07 16:39:11 This check is subsumed by CHECK(Marking::IsBlack(M
Hannes Payer (out of office) 2016/01/11 13:37:34 Done.
2983 offset = Bitmap::kBitIndexMask;
2984 } else {
2985 offset = Bitmap::kBitIndexMask - leading_zeros - 1;
2986 }
2987
2988 cell_base += (start_index - cell_base_start_index) * Bitmap::kBitsPerCell *
2989 kPointerSize;
3005 Address address = cell_base + offset * kPointerSize; 2990 Address address = cell_base + offset * kPointerSize;
3006 HeapObject* object = HeapObject::FromAddress(address); 2991 HeapObject* object = HeapObject::FromAddress(address);
3007 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 2992 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3008 CHECK(object->address() < reinterpret_cast<Address>(slot)); 2993 CHECK(object->address() < reinterpret_cast<Address>(slot));
3009 if (object->address() <= slot && 2994 if ((object->address() + kPointerSize) <= slot &&
3010 (object->address() + object->Size()) > slot) { 2995 (object->address() + object->Size()) > slot) {
3011 // If the slot is within the last found object in the cell, the slot is 2996 // If the slot is within the last found object in the cell, the slot is
3012 // in a live object. 2997 // in a live object.
2998 // Slots pointing to the first word of an object are invalid and removed.
2999 // This can happen when we move the object header while left trimming.
3013 *out_object = object; 3000 *out_object = object;
3014 return true; 3001 return true;
3015 } 3002 }
3016 return false; 3003 return false;
3017 } 3004 }
3018 3005
3019 3006
3020 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) { 3007 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) {
3021 // This function does not support large objects right now. 3008 // This function does not support large objects right now.
3022 Space* owner = p->owner(); 3009 Space* owner = p->owner();
3023 if (owner == heap_->lo_space() || owner == NULL) return true; 3010 if (owner == heap_->lo_space() || owner == NULL) {
3011 Object* large_object = heap_->lo_space()->FindObject(slot);
3012 // This object has to exist, otherwise we would not have recorded a slot
3013 // for it.
3014 CHECK(large_object->IsHeapObject());
3015 HeapObject* large_heap_object = HeapObject::cast(large_object);
3016 if (IsMarked(large_heap_object)) {
3017 return true;
3018 }
3019 return false;
3020 }
3024 3021
3025 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { 3022 LiveObjectIterator it(p);
3026 Address cell_base = it.CurrentCellBase(); 3023 HeapObject* object = NULL;
3027 MarkBit::CellType* cell = it.CurrentCell(); 3024 while ((object = it.Next<LiveObjectIterator::kBlackObjects>()) != NULL) {
3025 int size = object->Size();
3028 3026
3029 MarkBit::CellType current_cell = *cell; 3027 if (object->address() > slot) return false;
3030 if (current_cell == 0) continue; 3028 if (object->address() <= slot && slot < (object->address() + size)) {
3031 3029 return true;
3032 int offset = 0;
3033 while (current_cell != 0) {
3034 int trailing_zeros = base::bits::CountTrailingZeros32(current_cell);
3035 current_cell >>= trailing_zeros;
3036 offset += trailing_zeros;
3037 Address address = cell_base + offset * kPointerSize;
3038
3039 HeapObject* object = HeapObject::FromAddress(address);
3040 int size = object->Size();
3041
3042 if (object->address() > slot) return false;
3043 if (object->address() <= slot && slot < (object->address() + size)) {
3044 return true;
3045 }
3046
3047 offset++;
3048 current_cell >>= 1;
3049 } 3030 }
3050 } 3031 }
3051 return false; 3032 return false;
3052 } 3033 }
3053 3034
3054 3035
3055 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { 3036 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
3056 HeapObject* object = NULL; 3037 HeapObject* object = NULL;
3057 // The target object is black but we don't know if the source slot is black. 3038 // The target object is black but we don't know if the source slot is black.
3058 // The source object could have died and the slot could be part of a free 3039 // The source object could have died and the slot could be part of a free
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 ObjectVisitor* v) { 3358 ObjectVisitor* v) {
3378 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); 3359 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept());
3379 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, 3360 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST,
3380 space->identity() == CODE_SPACE); 3361 space->identity() == CODE_SPACE);
3381 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); 3362 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST));
3382 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || 3363 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD ||
3383 sweeping_mode == SWEEP_ONLY); 3364 sweeping_mode == SWEEP_ONLY);
3384 3365
3385 Address free_start = p->area_start(); 3366 Address free_start = p->area_start();
3386 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); 3367 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
3387 Address starts[16];
3388 3368
3389 // If we use the skip list for code space pages, we have to lock the skip 3369 // If we use the skip list for code space pages, we have to lock the skip
3390 // list because it could be accessed concurrently by the runtime or the 3370 // list because it could be accessed concurrently by the runtime or the
3391 // deoptimizer. 3371 // deoptimizer.
3392 SkipList* skip_list = p->skip_list(); 3372 SkipList* skip_list = p->skip_list();
3393 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { 3373 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) {
3394 skip_list->Clear(); 3374 skip_list->Clear();
3395 } 3375 }
3396 3376
3397 intptr_t freed_bytes = 0; 3377 intptr_t freed_bytes = 0;
3398 intptr_t max_freed_bytes = 0; 3378 intptr_t max_freed_bytes = 0;
3399 int curr_region = -1; 3379 int curr_region = -1;
3400 3380
3401 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { 3381 LiveObjectIterator it(p);
3402 Address cell_base = it.CurrentCellBase(); 3382 HeapObject* object = NULL;
3403 MarkBit::CellType* cell = it.CurrentCell(); 3383 while ((object = it.Next<LiveObjectIterator::kBlackObjects>()) != NULL) {
3404 int live_objects = 3384 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3405 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); 3385 Address free_end = object->address();
3406 int live_index = 0; 3386 if (free_end != free_start) {
3407 for (; live_objects != 0; live_objects--) { 3387 int size = static_cast<int>(free_end - free_start);
3408 Address free_end = starts[live_index++]; 3388 if (free_space_mode == ZAP_FREE_SPACE) {
3409 if (free_end != free_start) { 3389 memset(free_start, 0xcc, size);
3410 int size = static_cast<int>(free_end - free_start);
3411 if (free_space_mode == ZAP_FREE_SPACE) {
3412 memset(free_start, 0xcc, size);
3413 }
3414 freed_bytes = Free<parallelism>(space, free_list, free_start, size);
3415 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3416 } 3390 }
3417 HeapObject* live_object = HeapObject::FromAddress(free_end); 3391 freed_bytes = Free<parallelism>(space, free_list, free_start, size);
3418 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); 3392 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3419 Map* map = live_object->synchronized_map(); 3393 }
3420 int size = live_object->SizeFromMap(map); 3394 Map* map = object->synchronized_map();
3421 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { 3395 int size = object->SizeFromMap(map);
3422 live_object->IterateBody(map->instance_type(), size, v); 3396 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) {
3397 object->IterateBody(map->instance_type(), size, v);
3398 }
3399 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) {
3400 int new_region_start = SkipList::RegionNumber(free_end);
3401 int new_region_end =
3402 SkipList::RegionNumber(free_end + size - kPointerSize);
3403 if (new_region_start != curr_region || new_region_end != curr_region) {
3404 skip_list->AddObject(free_end, size);
3405 curr_region = new_region_end;
3423 } 3406 }
3424 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) {
3425 int new_region_start = SkipList::RegionNumber(free_end);
3426 int new_region_end =
3427 SkipList::RegionNumber(free_end + size - kPointerSize);
3428 if (new_region_start != curr_region || new_region_end != curr_region) {
3429 skip_list->AddObject(free_end, size);
3430 curr_region = new_region_end;
3431 }
3432 }
3433 free_start = free_end + size;
3434 } 3407 }
3435 // Clear marking bits for current cell. 3408 free_start = free_end + size;
3436 *cell = 0;
3437 } 3409 }
3410
3411 // Clear the mark bits of that page and reset live bytes count.
3412 Bitmap::Clear(p);
3413
3438 if (free_start != p->area_end()) { 3414 if (free_start != p->area_end()) {
3439 int size = static_cast<int>(p->area_end() - free_start); 3415 int size = static_cast<int>(p->area_end() - free_start);
3440 if (free_space_mode == ZAP_FREE_SPACE) { 3416 if (free_space_mode == ZAP_FREE_SPACE) {
3441 memset(free_start, 0xcc, size); 3417 memset(free_start, 0xcc, size);
3442 } 3418 }
3443 freed_bytes = Free<parallelism>(space, free_list, free_start, size); 3419 freed_bytes = Free<parallelism>(space, free_list, free_start, size);
3444 max_freed_bytes = Max(freed_bytes, max_freed_bytes); 3420 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3445 } 3421 }
3446 p->ResetLiveBytes();
3447 3422
3448 if (parallelism == MarkCompactCollector::SWEEP_IN_PARALLEL) { 3423 if (parallelism == MarkCompactCollector::SWEEP_IN_PARALLEL) {
3449 // When concurrent sweeping is active, the page will be marked after 3424 // When concurrent sweeping is active, the page will be marked after
3450 // sweeping by the main thread. 3425 // sweeping by the main thread.
3451 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingFinalize); 3426 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingFinalize);
3452 } else { 3427 } else {
3453 p->SetWasSwept(); 3428 p->SetWasSwept();
3454 } 3429 }
3455 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3430 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3456 } 3431 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3489 Page* p = evacuation_candidates_[i]; 3464 Page* p = evacuation_candidates_[i];
3490 DCHECK(p->IsEvacuationCandidate() || 3465 DCHECK(p->IsEvacuationCandidate() ||
3491 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3466 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3492 if (p->IsEvacuationCandidate()) { 3467 if (p->IsEvacuationCandidate()) {
3493 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot, 3468 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot,
3494 end_slot); 3469 end_slot);
3495 } 3470 }
3496 } 3471 }
3497 } 3472 }
3498 3473
3474 #ifdef VERIFY_HEAP
3475 static void VerifyAllBlackObjects(MemoryChunk* page) {
3476 LiveObjectIterator it(page);
3477 HeapObject* object = NULL;
3478 while ((object = it.Next<LiveObjectIterator::kAllLiveObjects>()) != NULL) {
3479 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3480 }
3481 }
3482 #endif // VERIFY_HEAP
3499 3483
3500 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, 3484 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page,
3501 HeapObjectVisitor* visitor, 3485 HeapObjectVisitor* visitor,
3502 IterationMode mode) { 3486 IterationMode mode) {
3503 Address offsets[16]; 3487 #ifdef VERIFY_HEAP
3504 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { 3488 VerifyAllBlackObjects(page);
3505 Address cell_base = it.CurrentCellBase(); 3489 #endif // VERIFY_HEAP
3506 MarkBit::CellType* cell = it.CurrentCell(); 3490
3507 if (*cell == 0) continue; 3491 LiveObjectIterator it(page);
3508 int live_objects = 3492 HeapObject* object = NULL;
3509 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, offsets); 3493 while ((object = it.Next<LiveObjectIterator::kBlackObjects>()) != NULL) {
3510 for (int i = 0; i < live_objects; i++) { 3494 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3511 HeapObject* object = HeapObject::FromAddress(offsets[i]); 3495 if (!visitor->Visit(object)) {
3512 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 3496 if (mode == kClearMarkbits) {
3513 if (!visitor->Visit(object)) { 3497 page->markbits()->ClearRange(
3514 if ((mode == kClearMarkbits) && (i > 0)) { 3498 page->AddressToMarkbitIndex(page->area_start()),
3515 page->markbits()->ClearRange( 3499 page->AddressToMarkbitIndex(object->address()));
3516 page->AddressToMarkbitIndex(page->area_start()),
3517 page->AddressToMarkbitIndex(offsets[i]));
3518 }
3519 return false;
3520 } 3500 }
3501 return false;
3521 } 3502 }
3522 if (mode == kClearMarkbits) { 3503 }
3523 *cell = 0; 3504 if (mode == kClearMarkbits) {
3524 } 3505 Bitmap::Clear(page);
3525 } 3506 }
3526 return true; 3507 return true;
3527 } 3508 }
3528 3509
3529 3510
3530 void MarkCompactCollector::VisitLiveObjectsBody(Page* page, 3511 void MarkCompactCollector::VisitLiveObjectsBody(Page* page,
3531 ObjectVisitor* visitor) { 3512 ObjectVisitor* visitor) {
3532 Address starts[16]; 3513 #ifdef VERIFY_HEAP
3533 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { 3514 VerifyAllBlackObjects(page);
3534 Address cell_base = it.CurrentCellBase(); 3515 #endif // VERIFY_HEAP
3535 MarkBit::CellType* cell = it.CurrentCell(); 3516
3536 if (*cell == 0) continue; 3517 LiveObjectIterator it(page);
3537 int live_objects = 3518 HeapObject* object = NULL;
3538 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); 3519 while ((object = it.Next<LiveObjectIterator::kBlackObjects>()) != NULL) {
3539 for (int i = 0; i < live_objects; i++) { 3520 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3540 HeapObject* live_object = HeapObject::FromAddress(starts[i]); 3521 Map* map = object->synchronized_map();
3541 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); 3522 int size = object->SizeFromMap(map);
3542 Map* map = live_object->synchronized_map(); 3523 object->IterateBody(map->instance_type(), size, visitor);
3543 int size = live_object->SizeFromMap(map);
3544 live_object->IterateBody(map->instance_type(), size, visitor);
3545 }
3546 } 3524 }
3547 } 3525 }
3548 3526
3549 3527
3550 void MarkCompactCollector::SweepAbortedPages() { 3528 void MarkCompactCollector::SweepAbortedPages() {
3551 // Second pass on aborted pages. 3529 // Second pass on aborted pages.
3552 for (int i = 0; i < evacuation_candidates_.length(); i++) { 3530 for (int i = 0; i < evacuation_candidates_.length(); i++) {
3553 Page* p = evacuation_candidates_[i]; 3531 Page* p = evacuation_candidates_[i];
3554 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { 3532 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3555 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); 3533 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
3772 CHECK(p->WasSwept()); 3750 CHECK(p->WasSwept());
3773 space->ReleasePage(p); 3751 space->ReleasePage(p);
3774 } 3752 }
3775 evacuation_candidates_.Rewind(0); 3753 evacuation_candidates_.Rewind(0);
3776 compacting_ = false; 3754 compacting_ = false;
3777 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); 3755 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages();
3778 heap()->FreeQueuedChunks(); 3756 heap()->FreeQueuedChunks();
3779 } 3757 }
3780 3758
3781 3759
3782 #ifdef VERIFY_HEAP
3783 static bool VerifyAllBlackObjects(uint32_t mark_bits, uint32_t next_mark_bits) {
3784 // Check for overlapping mark bits.
3785 if ((mark_bits & 0x80000000) && (next_mark_bits & 0x1)) return false;
3786
3787 unsigned index = 0;
3788 while ((index = base::bits::CountTrailingZeros32(mark_bits)) != 32) {
3789 if (index > 0) mark_bits >>= index;
3790 if ((mark_bits & 0x3) == 0x3) {
3791 // There should not be any grey (11) objects.
3792 return false;
3793 }
3794 mark_bits &= 0xFFFFFFFE;
3795 }
3796 return true;
3797 }
3798 #endif // VERIFY_HEAP
3799
3800
3801 // Takes a word of mark bits and a base address. Returns the number of objects
3802 // that start in the range. Puts the object starts in the supplied array.
3803 static inline int MarkWordToObjectStarts(uint32_t mark_bits,
3804 uint32_t next_mark_bits, Address base,
3805 Address* starts) {
3806 int objects = 0;
3807
3808 #ifdef VERIFY_HEAP
3809 if (FLAG_verify_heap) {
3810 CHECK(VerifyAllBlackObjects(mark_bits, next_mark_bits));
3811 }
3812 #endif // VERIFY_HEAP
3813
3814 unsigned index = 0;
3815 while ((index = base::bits::CountTrailingZeros32(mark_bits)) != 32) {
3816 starts[objects++] = base + kPointerSize * index;
3817 mark_bits &= ~(1u << index);
3818 }
3819 return objects;
3820 }
3821
3822
3823 int MarkCompactCollector::SweepInParallel(PagedSpace* space, 3760 int MarkCompactCollector::SweepInParallel(PagedSpace* space,
3824 int required_freed_bytes) { 3761 int required_freed_bytes) {
3825 int max_freed = 0; 3762 int max_freed = 0;
3826 int max_freed_overall = 0; 3763 int max_freed_overall = 0;
3827 PageIterator it(space); 3764 PageIterator it(space);
3828 while (it.has_next()) { 3765 while (it.has_next()) {
3829 Page* p = it.next(); 3766 Page* p = it.next();
3830 max_freed = SweepInParallel(p, space); 3767 max_freed = SweepInParallel(p, space);
3831 DCHECK(max_freed >= 0); 3768 DCHECK(max_freed >= 0);
3832 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { 3769 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
4096 MarkBit mark_bit = Marking::MarkBitFrom(host); 4033 MarkBit mark_bit = Marking::MarkBitFrom(host);
4097 if (Marking::IsBlack(mark_bit)) { 4034 if (Marking::IsBlack(mark_bit)) {
4098 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 4035 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
4099 RecordRelocSlot(&rinfo, target); 4036 RecordRelocSlot(&rinfo, target);
4100 } 4037 }
4101 } 4038 }
4102 } 4039 }
4103 4040
4104 } // namespace internal 4041 } // namespace internal
4105 } // namespace v8 4042 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698