| 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 |