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 1470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 MarkBit markbit = Marking::MarkBitFrom(object); | 1481 MarkBit markbit = Marking::MarkBitFrom(object); |
1482 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { | 1482 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { |
1483 Marking::GreyToBlack(markbit); | 1483 Marking::GreyToBlack(markbit); |
1484 PushBlack(object); | 1484 PushBlack(object); |
1485 if (marking_deque()->IsFull()) return; | 1485 if (marking_deque()->IsFull()) return; |
1486 } | 1486 } |
1487 } | 1487 } |
1488 } | 1488 } |
1489 | 1489 |
1490 | 1490 |
1491 static inline int MarkWordToObjectStarts(uint32_t mark_bits, Address base, | 1491 static inline int MarkWordToObjectStarts(uint32_t mark_bits, |
| 1492 uint32_t next_mark_bits, Address base, |
1492 Address* starts); | 1493 Address* starts); |
1493 | 1494 |
1494 | 1495 |
1495 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { | 1496 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
1496 DCHECK(!marking_deque()->IsFull()); | 1497 DCHECK(!marking_deque()->IsFull()); |
1497 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 1498 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
1498 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 1499 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
1499 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 1500 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
1500 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 1501 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
1501 | 1502 |
(...skipping 1764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 skip_list->Clear(); | 3267 skip_list->Clear(); |
3267 } | 3268 } |
3268 | 3269 |
3269 intptr_t freed_bytes = 0; | 3270 intptr_t freed_bytes = 0; |
3270 intptr_t max_freed_bytes = 0; | 3271 intptr_t max_freed_bytes = 0; |
3271 int curr_region = -1; | 3272 int curr_region = -1; |
3272 | 3273 |
3273 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { | 3274 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
3274 Address cell_base = it.CurrentCellBase(); | 3275 Address cell_base = it.CurrentCellBase(); |
3275 MarkBit::CellType* cell = it.CurrentCell(); | 3276 MarkBit::CellType* cell = it.CurrentCell(); |
3276 int live_objects = MarkWordToObjectStarts(*cell, cell_base, starts); | 3277 int live_objects = |
| 3278 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); |
3277 int live_index = 0; | 3279 int live_index = 0; |
3278 for (; live_objects != 0; live_objects--) { | 3280 for (; live_objects != 0; live_objects--) { |
3279 Address free_end = starts[live_index++]; | 3281 Address free_end = starts[live_index++]; |
3280 if (free_end != free_start) { | 3282 if (free_end != free_start) { |
3281 int size = static_cast<int>(free_end - free_start); | 3283 int size = static_cast<int>(free_end - free_start); |
3282 if (free_space_mode == ZAP_FREE_SPACE) { | 3284 if (free_space_mode == ZAP_FREE_SPACE) { |
3283 memset(free_start, 0xcc, size); | 3285 memset(free_start, 0xcc, size); |
3284 } | 3286 } |
3285 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3287 freed_bytes = Free<parallelism>(space, free_list, free_start, size); |
3286 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3288 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3369 | 3371 |
3370 | 3372 |
3371 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, | 3373 bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, |
3372 HeapObjectVisitor* visitor, | 3374 HeapObjectVisitor* visitor, |
3373 IterationMode mode) { | 3375 IterationMode mode) { |
3374 Address offsets[16]; | 3376 Address offsets[16]; |
3375 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { | 3377 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { |
3376 Address cell_base = it.CurrentCellBase(); | 3378 Address cell_base = it.CurrentCellBase(); |
3377 MarkBit::CellType* cell = it.CurrentCell(); | 3379 MarkBit::CellType* cell = it.CurrentCell(); |
3378 if (*cell == 0) continue; | 3380 if (*cell == 0) continue; |
3379 int live_objects = MarkWordToObjectStarts(*cell, cell_base, offsets); | 3381 int live_objects = |
| 3382 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, offsets); |
3380 for (int i = 0; i < live_objects; i++) { | 3383 for (int i = 0; i < live_objects; i++) { |
3381 HeapObject* object = HeapObject::FromAddress(offsets[i]); | 3384 HeapObject* object = HeapObject::FromAddress(offsets[i]); |
3382 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 3385 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
3383 if (!visitor->Visit(object)) { | 3386 if (!visitor->Visit(object)) { |
3384 if ((mode == kClearMarkbits) && (i > 0)) { | 3387 if ((mode == kClearMarkbits) && (i > 0)) { |
3385 page->markbits()->ClearRange( | 3388 page->markbits()->ClearRange( |
3386 page->AddressToMarkbitIndex(page->area_start()), | 3389 page->AddressToMarkbitIndex(page->area_start()), |
3387 page->AddressToMarkbitIndex(offsets[i])); | 3390 page->AddressToMarkbitIndex(offsets[i])); |
3388 } | 3391 } |
3389 return false; | 3392 return false; |
3390 } | 3393 } |
3391 } | 3394 } |
3392 if (mode == kClearMarkbits) { | 3395 if (mode == kClearMarkbits) { |
3393 *cell = 0; | 3396 *cell = 0; |
3394 } | 3397 } |
3395 } | 3398 } |
3396 return true; | 3399 return true; |
3397 } | 3400 } |
3398 | 3401 |
3399 | 3402 |
3400 void MarkCompactCollector::VisitLiveObjectsBody(Page* page, | 3403 void MarkCompactCollector::VisitLiveObjectsBody(Page* page, |
3401 ObjectVisitor* visitor) { | 3404 ObjectVisitor* visitor) { |
3402 Address starts[16]; | 3405 Address starts[16]; |
3403 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { | 3406 for (MarkBitCellIterator it(page); !it.Done(); it.Advance()) { |
3404 Address cell_base = it.CurrentCellBase(); | 3407 Address cell_base = it.CurrentCellBase(); |
3405 MarkBit::CellType* cell = it.CurrentCell(); | 3408 MarkBit::CellType* cell = it.CurrentCell(); |
3406 if (*cell == 0) continue; | 3409 if (*cell == 0) continue; |
3407 int live_objects = MarkWordToObjectStarts(*cell, cell_base, starts); | 3410 int live_objects = |
| 3411 MarkWordToObjectStarts(*cell, it.PeekNext(), cell_base, starts); |
3408 for (int i = 0; i < live_objects; i++) { | 3412 for (int i = 0; i < live_objects; i++) { |
3409 HeapObject* live_object = HeapObject::FromAddress(starts[i]); | 3413 HeapObject* live_object = HeapObject::FromAddress(starts[i]); |
3410 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | 3414 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); |
3411 Map* map = live_object->synchronized_map(); | 3415 Map* map = live_object->synchronized_map(); |
3412 int size = live_object->SizeFromMap(map); | 3416 int size = live_object->SizeFromMap(map); |
3413 live_object->IterateBody(map->instance_type(), size, visitor); | 3417 live_object->IterateBody(map->instance_type(), size, visitor); |
3414 } | 3418 } |
3415 } | 3419 } |
3416 } | 3420 } |
3417 | 3421 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3641 CHECK(p->WasSwept()); | 3645 CHECK(p->WasSwept()); |
3642 space->ReleasePage(p); | 3646 space->ReleasePage(p); |
3643 } | 3647 } |
3644 evacuation_candidates_.Rewind(0); | 3648 evacuation_candidates_.Rewind(0); |
3645 compacting_ = false; | 3649 compacting_ = false; |
3646 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); | 3650 heap()->FilterStoreBufferEntriesOnAboutToBeFreedPages(); |
3647 heap()->FreeQueuedChunks(); | 3651 heap()->FreeQueuedChunks(); |
3648 } | 3652 } |
3649 | 3653 |
3650 | 3654 |
| 3655 #ifdef VERIFY_HEAP |
| 3656 static bool VerifyAllBlackObjects(uint32_t mark_bits, uint32_t next_mark_bits) { |
| 3657 // Check for overlapping mark bits. |
| 3658 if ((mark_bits & 0x80000000) && (next_mark_bits & 0x1)) return false; |
| 3659 |
| 3660 unsigned index = 0; |
| 3661 while ((index = base::bits::CountTrailingZeros32(mark_bits)) != 32) { |
| 3662 if (index > 0) mark_bits >>= index; |
| 3663 if ((mark_bits & 0x3) == 0x3) { |
| 3664 // There should not be any grey (11) objects. |
| 3665 return false; |
| 3666 } |
| 3667 mark_bits &= 0xFFFFFFFE; |
| 3668 } |
| 3669 return true; |
| 3670 } |
| 3671 #endif // VERIFY_HEAP |
| 3672 |
| 3673 |
3651 // Takes a word of mark bits and a base address. Returns the number of objects | 3674 // Takes a word of mark bits and a base address. Returns the number of objects |
3652 // that start in the range. Puts the object starts in the supplied array. | 3675 // that start in the range. Puts the object starts in the supplied array. |
3653 static inline int MarkWordToObjectStarts(uint32_t mark_bits, Address base, | 3676 static inline int MarkWordToObjectStarts(uint32_t mark_bits, |
| 3677 uint32_t next_mark_bits, Address base, |
3654 Address* starts) { | 3678 Address* starts) { |
3655 int objects = 0; | 3679 int objects = 0; |
3656 | 3680 |
3657 // No consecutive 1 bits. | 3681 #ifdef VERIFY_HEAP |
3658 DCHECK((mark_bits & 0x180) != 0x180); | 3682 if (FLAG_verify_heap) { |
3659 DCHECK((mark_bits & 0x18000) != 0x18000); | 3683 CHECK(VerifyAllBlackObjects(mark_bits, next_mark_bits)); |
3660 DCHECK((mark_bits & 0x1800000) != 0x1800000); | 3684 } |
| 3685 #endif // VERIFY_HEAP |
3661 | 3686 |
3662 unsigned index = 0; | 3687 unsigned index = 0; |
3663 while ((index = base::bits::CountTrailingZeros32(mark_bits)) != 32) { | 3688 while ((index = base::bits::CountTrailingZeros32(mark_bits)) != 32) { |
3664 starts[objects++] = base + kPointerSize * index; | 3689 starts[objects++] = base + kPointerSize * index; |
3665 mark_bits &= ~(1u << index); | 3690 mark_bits &= ~(1u << index); |
3666 } | 3691 } |
3667 return objects; | 3692 return objects; |
3668 } | 3693 } |
3669 | 3694 |
3670 | 3695 |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3934 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3959 MarkBit mark_bit = Marking::MarkBitFrom(host); |
3935 if (Marking::IsBlack(mark_bit)) { | 3960 if (Marking::IsBlack(mark_bit)) { |
3936 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3961 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
3937 RecordRelocSlot(&rinfo, target); | 3962 RecordRelocSlot(&rinfo, target); |
3938 } | 3963 } |
3939 } | 3964 } |
3940 } | 3965 } |
3941 | 3966 |
3942 } // namespace internal | 3967 } // namespace internal |
3943 } // namespace v8 | 3968 } // namespace v8 |
OLD | NEW |