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