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

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, LiveObjectIterator::kGreyObjects);
1536 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); 1533 HeapObject* object = NULL;
1537 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); 1534 while ((object = it.Next()) != 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;
ulan 2016/01/05 14:45:23 yay!
Hannes Payer (out of office) 2016/01/07 10:30:32 yay!
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 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after
2949 2916
2950 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); 2917 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot);
2951 unsigned int start_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; 2918 unsigned int start_index = mark_bit_index >> Bitmap::kBitsPerCellLog2;
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.
2960 // when we left trim a fixed array. Such slots are invalid and we can remove
2961 // them.
2962 if ((cells[start_index] & index_in_cell) != 0) {
ulan 2016/01/05 14:45:23 As discussed offline, we still need special handli
Hannes Payer (out of office) 2016/01/07 10:30:32 Done.
2963 return false;
2964 }
2965
2966 // Check if the object is in the current cell. 2926 // Check if the object is in the current cell.
2967 MarkBit::CellType slot_mask; 2927 MarkBit::CellType slot_mask;
2968 if ((cells[start_index] == 0) || 2928 if ((cells[start_index] == 0) ||
2969 (base::bits::CountTrailingZeros32(cells[start_index]) > 2929 (base::bits::CountTrailingZeros32(cells[start_index]) >
2970 base::bits::CountTrailingZeros32(cells[start_index] | index_in_cell))) { 2930 base::bits::CountTrailingZeros32(cells[start_index] | index_in_cell))) {
2971 // If we are already in the first cell, there is no live object. 2931 // If we are already in the first cell, there is no live object.
2972 if (start_index == cell_base_start_index) return false; 2932 if (start_index == cell_base_start_index) return false;
2973 2933
2974 // If not, find a cell in a preceding cell slot that has a mark bit set. 2934 // If not, find a cell in a preceding cell slot that has a mark bit set.
2975 do { 2935 do {
2976 start_index--; 2936 start_index--;
2977 } while (start_index > cell_base_start_index && cells[start_index] == 0); 2937 } while (start_index > cell_base_start_index && cells[start_index] == 0);
2978 2938
2979 // The slot must be in a dead object if there are no preceding cells that 2939 // The slot must be in a dead object if there are no preceding cells that
2980 // have mark bits set. 2940 // have mark bits set.
2981 if (cells[start_index] == 0) { 2941 if (cells[start_index] == 0) {
2982 return false; 2942 return false;
2983 } 2943 }
2984 2944
2985 // The object is in a preceding cell. Set the mask to find any object. 2945 // The object is in a preceding cell. Set the mask to find any object.
2986 slot_mask = 0xffffffff; 2946 slot_mask = 0xffffffff;
2987 } else { 2947 } else {
2988 // The object start is before the the slot index. Hence, in this case the 2948 // The object start is before the slot index. Hence, in this case the
ulan 2016/01/05 14:45:23 The comment is obsolete.
Hannes Payer (out of office) 2016/01/07 10:30:32 Done.
2989 // slot index can not be at the beginning of the cell. 2949 // slot index can not be at the beginning of the cell.
2990 CHECK(index_in_cell > 1); 2950 CHECK(index_in_cell > 0);
ulan 2016/01/05 14:45:23 index_in_cell will always be > 0 by definition.
Hannes Payer (out of office) 2016/01/07 10:30:32 Done.
2991 // We are interested in object mark bits right before the slot. 2951 // We are interested in object mark bits right before the slot.
2992 slot_mask = index_in_cell - 1; 2952 slot_mask = index_in_cell + index_in_cell - 1;
ulan 2016/01/05 14:45:23 let's add explicit parens index_in_cell + (index_i
Hannes Payer (out of office) 2016/01/07 10:30:32 Done.
2993 } 2953 }
2994 2954
2995 MarkBit::CellType current_cell = cells[start_index]; 2955 MarkBit::CellType current_cell = cells[start_index];
2996 CHECK(current_cell != 0); 2956 CHECK(current_cell != 0);
2997 2957
2998 // Find the last live object in the cell. 2958 // Find the last live object in the cell.
2999 unsigned int leading_zeros = 2959 unsigned int leading_zeros =
3000 base::bits::CountLeadingZeros32(current_cell & slot_mask); 2960 base::bits::CountLeadingZeros32(current_cell & slot_mask);
3001 CHECK(leading_zeros != 32); 2961 CHECK(leading_zeros != Bitmap::kBitsPerCell);
3002 unsigned int offset = Bitmap::kBitIndexMask - leading_zeros;
3003 2962
3004 cell_base += (start_index - cell_base_start_index) * 32 * kPointerSize; 2963 unsigned int offset;
2964 if (leading_zeros == Bitmap::kBitIndexMask) {
2965 start_index -= 1;
2966 current_cell = cells[start_index];
2967 slot_mask = 0xffffffff;
2968 CHECK(base::bits::CountLeadingZeros32(current_cell & slot_mask) == 0);
2969 offset = Bitmap::kBitIndexMask;
2970 } else {
2971 offset = Bitmap::kBitIndexMask - leading_zeros - 1;
2972 }
2973
2974 cell_base += (start_index - cell_base_start_index) * Bitmap::kBitsPerCell *
2975 kPointerSize;
3005 Address address = cell_base + offset * kPointerSize; 2976 Address address = cell_base + offset * kPointerSize;
3006 HeapObject* object = HeapObject::FromAddress(address); 2977 HeapObject* object = HeapObject::FromAddress(address);
3007 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 2978 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3008 CHECK(object->address() < reinterpret_cast<Address>(slot)); 2979 CHECK(object->address() < reinterpret_cast<Address>(slot));
3009 if (object->address() <= slot && 2980 if ((object->address() + kPointerSize) <= slot &&
3010 (object->address() + object->Size()) > slot) { 2981 (object->address() + object->Size()) > slot) {
3011 // If the slot is within the last found object in the cell, the slot is 2982 // If the slot is within the last found object in the cell, the slot is
3012 // in a live object. 2983 // in a live object.
2984 // Slots pointing to the first word of an object are invalid and removed.
2985 // This can happen when we move the object header while left trimming.
3013 *out_object = object; 2986 *out_object = object;
3014 return true; 2987 return true;
3015 } 2988 }
3016 return false; 2989 return false;
3017 } 2990 }
3018 2991
3019 2992
3020 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) { 2993 bool MarkCompactCollector::IsSlotInBlackObjectSlow(Page* p, Address slot) {
3021 // This function does not support large objects right now. 2994 // This function does not support large objects right now.
3022 Space* owner = p->owner(); 2995 Space* owner = p->owner();
3023 if (owner == heap_->lo_space() || owner == NULL) return true; 2996 if (owner == heap_->lo_space() || owner == NULL) {
2997 Object* large_object = heap_->lo_space()->FindObject(slot);
2998 // This object has to exist, otherwise we would not have recorded a slot
2999 // for it.
3000 CHECK(large_object->IsHeapObject());
3001 HeapObject* large_heap_object = HeapObject::cast(large_object);
3002 if (IsMarked(large_heap_object)) {
3003 return true;
3004 }
3005 return false;
3006 }
3024 3007
3025 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { 3008 LiveObjectIterator it(p, LiveObjectIterator::kBlackObjects);
3026 Address cell_base = it.CurrentCellBase(); 3009 HeapObject* object = NULL;
3027 MarkBit::CellType* cell = it.CurrentCell(); 3010 while ((object = it.Next()) != NULL) {
3011 int size = object->Size();
3028 3012
3029 MarkBit::CellType current_cell = *cell; 3013 if (object->address() > slot) return false;
3030 if (current_cell == 0) continue; 3014 if (object->address() <= slot && slot < (object->address() + size)) {
3031 3015 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 } 3016 }
3050 } 3017 }
3051 return false; 3018 return false;
3052 } 3019 }
3053 3020
3054 3021
3055 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) { 3022 bool MarkCompactCollector::IsSlotInLiveObject(Address slot) {
3056 HeapObject* object = NULL; 3023 HeapObject* object = NULL;
3057 // The target object is black but we don't know if the source slot is black. 3024 // 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 3025 // 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) { 3344 ObjectVisitor* v) {
3378 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); 3345 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept());
3379 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, 3346 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST,
3380 space->identity() == CODE_SPACE); 3347 space->identity() == CODE_SPACE);
3381 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); 3348 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST));
3382 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || 3349 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD ||
3383 sweeping_mode == SWEEP_ONLY); 3350 sweeping_mode == SWEEP_ONLY);
3384 3351
3385 Address free_start = p->area_start(); 3352 Address free_start = p->area_start();
3386 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); 3353 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
3387 Address starts[16];
3388 3354
3389 // If we use the skip list for code space pages, we have to lock the skip 3355 // 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 3356 // list because it could be accessed concurrently by the runtime or the
3391 // deoptimizer. 3357 // deoptimizer.
3392 SkipList* skip_list = p->skip_list(); 3358 SkipList* skip_list = p->skip_list();
3393 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { 3359 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) {
3394 skip_list->Clear(); 3360 skip_list->Clear();
3395 } 3361 }
3396 3362
3397 intptr_t freed_bytes = 0; 3363 intptr_t freed_bytes = 0;
3398 intptr_t max_freed_bytes = 0; 3364 intptr_t max_freed_bytes = 0;
3399 int curr_region = -1; 3365 int curr_region = -1;
3400 3366
3401 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { 3367 LiveObjectIterator it(p, LiveObjectIterator::kBlackObjects);
3402 Address cell_base = it.CurrentCellBase(); 3368 HeapObject* object = NULL;
3403 MarkBit::CellType* cell = it.CurrentCell(); 3369 while ((object = it.Next()) != NULL) {
3404 int live_objects = 3370 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3405 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); 3371 Address free_end = object->address();
3406 int live_index = 0; 3372 if (free_end != free_start) {
3407 for (; live_objects != 0; live_objects--) { 3373 int size = static_cast<int>(free_end - free_start);
3408 Address free_end = starts[live_index++]; 3374 if (free_space_mode == ZAP_FREE_SPACE) {
3409 if (free_end != free_start) { 3375 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 } 3376 }
3417 HeapObject* live_object = HeapObject::FromAddress(free_end); 3377 freed_bytes = Free<parallelism>(space, free_list, free_start, size);
3418 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); 3378 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3419 Map* map = live_object->synchronized_map(); 3379 }
3420 int size = live_object->SizeFromMap(map); 3380 Map* map = object->synchronized_map();
3421 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { 3381 int size = object->SizeFromMap(map);
3422 live_object->IterateBody(map->instance_type(), size, v); 3382 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) {
3383 object->IterateBody(map->instance_type(), size, v);
3384 }
3385 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) {
3386 int new_region_start = SkipList::RegionNumber(free_end);
3387 int new_region_end =
3388 SkipList::RegionNumber(free_end + size - kPointerSize);
3389 if (new_region_start != curr_region || new_region_end != curr_region) {
3390 skip_list->AddObject(free_end, size);
3391 curr_region = new_region_end;
3423 } 3392 }
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 } 3393 }
3435 // Clear marking bits for current cell. 3394 free_start = free_end + size;
3436 *cell = 0;
3437 } 3395 }
3396
3397 // Clear the mark bits of that page and reset live bytes count.
3398 Bitmap::Clear(p);
3399
3438 if (free_start != p->area_end()) { 3400 if (free_start != p->area_end()) {
3439 int size = static_cast<int>(p->area_end() - free_start); 3401 int size = static_cast<int>(p->area_end() - free_start);
3440 if (free_space_mode == ZAP_FREE_SPACE) { 3402 if (free_space_mode == ZAP_FREE_SPACE) {
3441 memset(free_start, 0xcc, size); 3403 memset(free_start, 0xcc, size);
3442 } 3404 }
3443 freed_bytes = Free<parallelism>(space, free_list, free_start, size); 3405 freed_bytes = Free<parallelism>(space, free_list, free_start, size);
3444 max_freed_bytes = Max(freed_bytes, max_freed_bytes); 3406 max_freed_bytes = Max(freed_bytes, max_freed_bytes);
3445 } 3407 }
3446 p->ResetLiveBytes();
3447 3408
3448 if (parallelism == MarkCompactCollector::SWEEP_IN_PARALLEL) { 3409 if (parallelism == MarkCompactCollector::SWEEP_IN_PARALLEL) {
3449 // When concurrent sweeping is active, the page will be marked after 3410 // When concurrent sweeping is active, the page will be marked after
3450 // sweeping by the main thread. 3411 // sweeping by the main thread.
3451 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingFinalize); 3412 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingFinalize);
3452 } else { 3413 } else {
3453 p->SetWasSwept(); 3414 p->SetWasSwept();
3454 } 3415 }
3455 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3416 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3456 } 3417 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3489 Page* p = evacuation_candidates_[i]; 3450 Page* p = evacuation_candidates_[i];
3490 DCHECK(p->IsEvacuationCandidate() || 3451 DCHECK(p->IsEvacuationCandidate() ||
3491 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3452 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3492 if (p->IsEvacuationCandidate()) { 3453 if (p->IsEvacuationCandidate()) {
3493 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot, 3454 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot,
3494 end_slot); 3455 end_slot);
3495 } 3456 }
3496 } 3457 }
3497 } 3458 }
3498 3459
3460 #ifdef VERIFY_HEAP
3461 static void VerifyAllBlackObjects(MemoryChunk* page) {
3462 LiveObjectIterator it(page, LiveObjectIterator::kAllLiveObjects);
3463 HeapObject* object = NULL;
3464 while ((object = it.Next()) != NULL) {
3465 CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3466 }
3467 }
3468 #endif // VERIFY_HEAP
3499 3469
3500 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, 3470 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page,
3501 HeapObjectVisitor* visitor, 3471 HeapObjectVisitor* visitor,
3502 IterationMode mode) { 3472 IterationMode mode) {
3503 Address offsets[16]; 3473 #ifdef VERIFY_HEAP
3504 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { 3474 VerifyAllBlackObjects(page);
3505 Address cell_base = it.CurrentCellBase(); 3475 #endif // VERIFY_HEAP
3506 MarkBit::CellType* cell = it.CurrentCell(); 3476
3507 if (*cell == 0) continue; 3477 LiveObjectIterator it(page, LiveObjectIterator::kBlackObjects);
3508 int live_objects = 3478 HeapObject* object = NULL;
3509 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, offsets); 3479 while ((object = it.Next()) != NULL) {
3510 for (int i = 0; i < live_objects; i++) { 3480 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3511 HeapObject* object = HeapObject::FromAddress(offsets[i]); 3481 if (!visitor->Visit(object)) {
3512 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 3482 if (mode == kClearMarkbits) {
3513 if (!visitor->Visit(object)) { 3483 page->markbits()->ClearRange(
3514 if ((mode == kClearMarkbits) && (i > 0)) { 3484 page->AddressToMarkbitIndex(page->area_start()),
3515 page->markbits()->ClearRange( 3485 page->AddressToMarkbitIndex(object->address()));
3516 page->AddressToMarkbitIndex(page->area_start()),
3517 page->AddressToMarkbitIndex(offsets[i]));
3518 }
3519 return false;
3520 } 3486 }
3487 return false;
3521 } 3488 }
3522 if (mode == kClearMarkbits) { 3489 }
3523 *cell = 0; 3490 if (mode == kClearMarkbits) {
3524 } 3491 Bitmap::Clear(page);
3525 } 3492 }
3526 return true; 3493 return true;
3527 } 3494 }
3528 3495
3529 3496
3530 void MarkCompactCollector::VisitLiveObjectsBody(Page* page, 3497 void MarkCompactCollector::VisitLiveObjectsBody(Page* page,
3531 ObjectVisitor* visitor) { 3498 ObjectVisitor* visitor) {
3532 Address starts[16]; 3499 #ifdef VERIFY_HEAP
3533 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { 3500 VerifyAllBlackObjects(page);
3534 Address cell_base = it.CurrentCellBase(); 3501 #endif // VERIFY_HEAP
3535 MarkBit::CellType* cell = it.CurrentCell(); 3502
3536 if (*cell == 0) continue; 3503 LiveObjectIterator it(page, LiveObjectIterator::kBlackObjects);
3537 int live_objects = 3504 HeapObject* object = NULL;
3538 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); 3505 while ((object = it.Next()) != NULL) {
3539 for (int i = 0; i < live_objects; i++) { 3506 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3540 HeapObject* live_object = HeapObject::FromAddress(starts[i]); 3507 Map* map = object->synchronized_map();
3541 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); 3508 int size = object->SizeFromMap(map);
3542 Map* map = live_object->synchronized_map(); 3509 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 } 3510 }
3547 } 3511 }
3548 3512
3549 3513
3550 void MarkCompactCollector::SweepAbortedPages() { 3514 void MarkCompactCollector::SweepAbortedPages() {
3551 // Second pass on aborted pages. 3515 // Second pass on aborted pages.
3552 for (int i = 0; i < evacuation_candidates_.length(); i++) { 3516 for (int i = 0; i < evacuation_candidates_.length(); i++) {
3553 Page* p = evacuation_candidates_[i]; 3517 Page* p = evacuation_candidates_[i];
3554 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { 3518 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
3555 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); 3519 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
3772 CHECK(p->WasSwept()); 3736 CHECK(p->WasSwept());
3773 space->ReleasePage(p); 3737 space->ReleasePage(p);
3774 } 3738 }
3775 evacuation_candidates_.Rewind(0); 3739 evacuation_candidates_.Rewind(0);
3776 compacting_ = false; 3740 compacting_ = false;
3777 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); 3741 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages();
3778 heap()->FreeQueuedChunks(); 3742 heap()->FreeQueuedChunks();
3779 } 3743 }
3780 3744
3781 3745
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, 3746 int MarkCompactCollector::SweepInParallel(PagedSpace* space,
3824 int required_freed_bytes) { 3747 int required_freed_bytes) {
3825 int max_freed = 0; 3748 int max_freed = 0;
3826 int max_freed_overall = 0; 3749 int max_freed_overall = 0;
3827 PageIterator it(space); 3750 PageIterator it(space);
3828 while (it.has_next()) { 3751 while (it.has_next()) {
3829 Page* p = it.next(); 3752 Page* p = it.next();
3830 max_freed = SweepInParallel(p, space); 3753 max_freed = SweepInParallel(p, space);
3831 DCHECK(max_freed >= 0); 3754 DCHECK(max_freed >= 0);
3832 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { 3755 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); 4019 MarkBit mark_bit = Marking::MarkBitFrom(host);
4097 if (Marking::IsBlack(mark_bit)) { 4020 if (Marking::IsBlack(mark_bit)) {
4098 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 4021 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
4099 RecordRelocSlot(&rinfo, target); 4022 RecordRelocSlot(&rinfo, target);
4100 } 4023 }
4101 } 4024 }
4102 } 4025 }
4103 4026
4104 } // namespace internal 4027 } // namespace internal
4105 } // namespace v8 4028 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698