| 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/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 class MarkCompactCollector::CompactionTask : public v8::Task { | 476 class MarkCompactCollector::CompactionTask : public v8::Task { |
| 477 public: | 477 public: |
| 478 explicit CompactionTask(Heap* heap, CompactionSpaceCollection* spaces) | 478 explicit CompactionTask(Heap* heap, CompactionSpaceCollection* spaces) |
| 479 : heap_(heap), spaces_(spaces) {} | 479 : heap_(heap), spaces_(spaces) {} |
| 480 | 480 |
| 481 virtual ~CompactionTask() {} | 481 virtual ~CompactionTask() {} |
| 482 | 482 |
| 483 private: | 483 private: |
| 484 // v8::Task overrides. | 484 // v8::Task overrides. |
| 485 void Run() override { | 485 void Run() override { |
| 486 heap_->mark_compact_collector()->EvacuatePages(spaces_); | 486 MarkCompactCollector* mark_compact = heap_->mark_compact_collector(); |
| 487 heap_->mark_compact_collector() | 487 SlotsBuffer* evacuation_slots_buffer = nullptr; |
| 488 ->pending_compaction_tasks_semaphore_.Signal(); | 488 mark_compact->EvacuatePages(spaces_, &evacuation_slots_buffer); |
| 489 mark_compact->AddEvacuationSlotsBufferSynchronized(evacuation_slots_buffer); |
| 490 mark_compact->pending_compaction_tasks_semaphore_.Signal(); |
| 489 } | 491 } |
| 490 | 492 |
| 491 Heap* heap_; | 493 Heap* heap_; |
| 492 CompactionSpaceCollection* spaces_; | 494 CompactionSpaceCollection* spaces_; |
| 493 | 495 |
| 494 DISALLOW_COPY_AND_ASSIGN(CompactionTask); | 496 DISALLOW_COPY_AND_ASSIGN(CompactionTask); |
| 495 }; | 497 }; |
| 496 | 498 |
| 497 | 499 |
| 498 class MarkCompactCollector::SweeperTask : public v8::Task { | 500 class MarkCompactCollector::SweeperTask : public v8::Task { |
| (...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 // Shouldn't happen. We are sweeping linearly, and to-space | 1725 // Shouldn't happen. We are sweeping linearly, and to-space |
| 1724 // has the same number of pages as from-space, so there is | 1726 // has the same number of pages as from-space, so there is |
| 1725 // always room. | 1727 // always room. |
| 1726 UNREACHABLE(); | 1728 UNREACHABLE(); |
| 1727 } | 1729 } |
| 1728 allocation = new_space->AllocateRaw(size, alignment); | 1730 allocation = new_space->AllocateRaw(size, alignment); |
| 1729 DCHECK(!allocation.IsRetry()); | 1731 DCHECK(!allocation.IsRetry()); |
| 1730 } | 1732 } |
| 1731 Object* target = allocation.ToObjectChecked(); | 1733 Object* target = allocation.ToObjectChecked(); |
| 1732 | 1734 |
| 1733 MigrateObject(HeapObject::cast(target), object, size, NEW_SPACE); | 1735 MigrateObject(HeapObject::cast(target), object, size, NEW_SPACE, nullptr); |
| 1734 if (V8_UNLIKELY(target->IsJSArrayBuffer())) { | 1736 if (V8_UNLIKELY(target->IsJSArrayBuffer())) { |
| 1735 heap()->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target)); | 1737 heap()->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target)); |
| 1736 } | 1738 } |
| 1737 heap()->IncrementSemiSpaceCopiedObjectSize(size); | 1739 heap()->IncrementSemiSpaceCopiedObjectSize(size); |
| 1738 } | 1740 } |
| 1739 *cells = 0; | 1741 *cells = 0; |
| 1740 } | 1742 } |
| 1741 return survivors_size; | 1743 return survivors_size; |
| 1742 } | 1744 } |
| 1743 | 1745 |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2551 Object* weak_cell_obj = heap()->encountered_weak_cells(); | 2553 Object* weak_cell_obj = heap()->encountered_weak_cells(); |
| 2552 while (weak_cell_obj != Smi::FromInt(0)) { | 2554 while (weak_cell_obj != Smi::FromInt(0)) { |
| 2553 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); | 2555 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); |
| 2554 weak_cell_obj = weak_cell->next(); | 2556 weak_cell_obj = weak_cell->next(); |
| 2555 weak_cell->clear_next(heap()); | 2557 weak_cell->clear_next(heap()); |
| 2556 } | 2558 } |
| 2557 heap()->set_encountered_weak_cells(Smi::FromInt(0)); | 2559 heap()->set_encountered_weak_cells(Smi::FromInt(0)); |
| 2558 } | 2560 } |
| 2559 | 2561 |
| 2560 | 2562 |
| 2561 void MarkCompactCollector::RecordMigratedSlot(Object* value, Address slot) { | 2563 void MarkCompactCollector::RecordMigratedSlot( |
| 2564 Object* value, Address slot, SlotsBuffer** evacuation_slots_buffer) { |
| 2562 // When parallel compaction is in progress, store and slots buffer entries | 2565 // When parallel compaction is in progress, store and slots buffer entries |
| 2563 // require synchronization. | 2566 // require synchronization. |
| 2564 if (heap_->InNewSpace(value)) { | 2567 if (heap_->InNewSpace(value)) { |
| 2565 if (parallel_compaction_in_progress_) { | 2568 if (parallel_compaction_in_progress_) { |
| 2566 heap_->store_buffer()->MarkSynchronized(slot); | 2569 heap_->store_buffer()->MarkSynchronized(slot); |
| 2567 } else { | 2570 } else { |
| 2568 heap_->store_buffer()->Mark(slot); | 2571 heap_->store_buffer()->Mark(slot); |
| 2569 } | 2572 } |
| 2570 } else if (value->IsHeapObject() && IsOnEvacuationCandidate(value)) { | 2573 } else if (value->IsHeapObject() && IsOnEvacuationCandidate(value)) { |
| 2571 if (parallel_compaction_in_progress_) { | 2574 SlotsBuffer::AddTo(slots_buffer_allocator_, evacuation_slots_buffer, |
| 2572 SlotsBuffer::AddToSynchronized( | 2575 reinterpret_cast<Object**>(slot), |
| 2573 slots_buffer_allocator_, &migration_slots_buffer_, | 2576 SlotsBuffer::IGNORE_OVERFLOW); |
| 2574 &migration_slots_buffer_mutex_, reinterpret_cast<Object**>(slot), | |
| 2575 SlotsBuffer::IGNORE_OVERFLOW); | |
| 2576 } else { | |
| 2577 SlotsBuffer::AddTo(slots_buffer_allocator_, &migration_slots_buffer_, | |
| 2578 reinterpret_cast<Object**>(slot), | |
| 2579 SlotsBuffer::IGNORE_OVERFLOW); | |
| 2580 } | |
| 2581 } | 2577 } |
| 2582 } | 2578 } |
| 2583 | 2579 |
| 2584 | 2580 |
| 2585 void MarkCompactCollector::RecordMigratedCodeEntrySlot( | 2581 void MarkCompactCollector::RecordMigratedCodeEntrySlot( |
| 2586 Address code_entry, Address code_entry_slot) { | 2582 Address code_entry, Address code_entry_slot, |
| 2583 SlotsBuffer** evacuation_slots_buffer) { |
| 2587 if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) { | 2584 if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) { |
| 2588 if (parallel_compaction_in_progress_) { | 2585 SlotsBuffer::AddTo(slots_buffer_allocator_, evacuation_slots_buffer, |
| 2589 SlotsBuffer::AddToSynchronized( | 2586 SlotsBuffer::CODE_ENTRY_SLOT, code_entry_slot, |
| 2590 slots_buffer_allocator_, &migration_slots_buffer_, | |
| 2591 &migration_slots_buffer_mutex_, SlotsBuffer::CODE_ENTRY_SLOT, | |
| 2592 code_entry_slot, SlotsBuffer::IGNORE_OVERFLOW); | |
| 2593 } else { | |
| 2594 SlotsBuffer::AddTo(slots_buffer_allocator_, &migration_slots_buffer_, | |
| 2595 SlotsBuffer::CODE_ENTRY_SLOT, code_entry_slot, | |
| 2596 SlotsBuffer::IGNORE_OVERFLOW); | |
| 2597 } | |
| 2598 } | |
| 2599 } | |
| 2600 | |
| 2601 | |
| 2602 void MarkCompactCollector::RecordMigratedCodeObjectSlot(Address code_object) { | |
| 2603 if (parallel_compaction_in_progress_) { | |
| 2604 SlotsBuffer::AddToSynchronized( | |
| 2605 slots_buffer_allocator_, &migration_slots_buffer_, | |
| 2606 &migration_slots_buffer_mutex_, SlotsBuffer::RELOCATED_CODE_OBJECT, | |
| 2607 code_object, SlotsBuffer::IGNORE_OVERFLOW); | |
| 2608 } else { | |
| 2609 SlotsBuffer::AddTo(slots_buffer_allocator_, &migration_slots_buffer_, | |
| 2610 SlotsBuffer::RELOCATED_CODE_OBJECT, code_object, | |
| 2611 SlotsBuffer::IGNORE_OVERFLOW); | 2587 SlotsBuffer::IGNORE_OVERFLOW); |
| 2612 } | 2588 } |
| 2613 } | 2589 } |
| 2614 | 2590 |
| 2615 | 2591 |
| 2592 void MarkCompactCollector::RecordMigratedCodeObjectSlot( |
| 2593 Address code_object, SlotsBuffer** evacuation_slots_buffer) { |
| 2594 SlotsBuffer::AddTo(slots_buffer_allocator_, evacuation_slots_buffer, |
| 2595 SlotsBuffer::RELOCATED_CODE_OBJECT, code_object, |
| 2596 SlotsBuffer::IGNORE_OVERFLOW); |
| 2597 } |
| 2598 |
| 2599 |
| 2616 static inline SlotsBuffer::SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { | 2600 static inline SlotsBuffer::SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { |
| 2617 if (RelocInfo::IsCodeTarget(rmode)) { | 2601 if (RelocInfo::IsCodeTarget(rmode)) { |
| 2618 return SlotsBuffer::CODE_TARGET_SLOT; | 2602 return SlotsBuffer::CODE_TARGET_SLOT; |
| 2619 } else if (RelocInfo::IsCell(rmode)) { | 2603 } else if (RelocInfo::IsCell(rmode)) { |
| 2620 return SlotsBuffer::CELL_TARGET_SLOT; | 2604 return SlotsBuffer::CELL_TARGET_SLOT; |
| 2621 } else if (RelocInfo::IsEmbeddedObject(rmode)) { | 2605 } else if (RelocInfo::IsEmbeddedObject(rmode)) { |
| 2622 return SlotsBuffer::EMBEDDED_OBJECT_SLOT; | 2606 return SlotsBuffer::EMBEDDED_OBJECT_SLOT; |
| 2623 } else if (RelocInfo::IsDebugBreakSlot(rmode)) { | 2607 } else if (RelocInfo::IsDebugBreakSlot(rmode)) { |
| 2624 return SlotsBuffer::DEBUG_TARGET_SLOT; | 2608 return SlotsBuffer::DEBUG_TARGET_SLOT; |
| 2625 } | 2609 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2668 // promotes them to old space. Forwarding address is written directly into | 2652 // promotes them to old space. Forwarding address is written directly into |
| 2669 // first word of object without any encoding. If object is dead we write | 2653 // first word of object without any encoding. If object is dead we write |
| 2670 // NULL as a forwarding address. | 2654 // NULL as a forwarding address. |
| 2671 // | 2655 // |
| 2672 // The second pass updates pointers to new space in all spaces. It is possible | 2656 // The second pass updates pointers to new space in all spaces. It is possible |
| 2673 // to encounter pointers to dead new space objects during traversal of pointers | 2657 // to encounter pointers to dead new space objects during traversal of pointers |
| 2674 // to new space. We should clear them to avoid encountering them during next | 2658 // to new space. We should clear them to avoid encountering them during next |
| 2675 // pointer iteration. This is an issue if the store buffer overflows and we | 2659 // pointer iteration. This is an issue if the store buffer overflows and we |
| 2676 // have to scan the entire old space, including dead objects, looking for | 2660 // have to scan the entire old space, including dead objects, looking for |
| 2677 // pointers to new space. | 2661 // pointers to new space. |
| 2678 void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src, | 2662 void MarkCompactCollector::MigrateObject( |
| 2679 int size, AllocationSpace dest) { | 2663 HeapObject* dst, HeapObject* src, int size, AllocationSpace dest, |
| 2664 SlotsBuffer** evacuation_slots_buffer) { |
| 2680 Address dst_addr = dst->address(); | 2665 Address dst_addr = dst->address(); |
| 2681 Address src_addr = src->address(); | 2666 Address src_addr = src->address(); |
| 2682 DCHECK(heap()->AllowedToBeMigrated(src, dest)); | 2667 DCHECK(heap()->AllowedToBeMigrated(src, dest)); |
| 2683 DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize); | 2668 DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize); |
| 2684 if (dest == OLD_SPACE) { | 2669 if (dest == OLD_SPACE) { |
| 2670 DCHECK(evacuation_slots_buffer != nullptr); |
| 2685 DCHECK(IsAligned(size, kPointerSize)); | 2671 DCHECK(IsAligned(size, kPointerSize)); |
| 2686 switch (src->ContentType()) { | 2672 switch (src->ContentType()) { |
| 2687 case HeapObjectContents::kTaggedValues: | 2673 case HeapObjectContents::kTaggedValues: |
| 2688 MigrateObjectTagged(dst, src, size); | 2674 MigrateObjectTagged(dst, src, size, evacuation_slots_buffer); |
| 2689 break; | 2675 break; |
| 2690 | 2676 |
| 2691 case HeapObjectContents::kMixedValues: | 2677 case HeapObjectContents::kMixedValues: |
| 2692 MigrateObjectMixed(dst, src, size); | 2678 MigrateObjectMixed(dst, src, size, evacuation_slots_buffer); |
| 2693 break; | 2679 break; |
| 2694 | 2680 |
| 2695 case HeapObjectContents::kRawValues: | 2681 case HeapObjectContents::kRawValues: |
| 2696 MigrateObjectRaw(dst, src, size); | 2682 MigrateObjectRaw(dst, src, size); |
| 2697 break; | 2683 break; |
| 2698 } | 2684 } |
| 2699 | 2685 |
| 2700 if (compacting_ && dst->IsJSFunction()) { | 2686 if (compacting_ && dst->IsJSFunction()) { |
| 2701 Address code_entry_slot = dst->address() + JSFunction::kCodeEntryOffset; | 2687 Address code_entry_slot = dst->address() + JSFunction::kCodeEntryOffset; |
| 2702 Address code_entry = Memory::Address_at(code_entry_slot); | 2688 Address code_entry = Memory::Address_at(code_entry_slot); |
| 2703 RecordMigratedCodeEntrySlot(code_entry, code_entry_slot); | 2689 RecordMigratedCodeEntrySlot(code_entry, code_entry_slot, |
| 2690 evacuation_slots_buffer); |
| 2704 } | 2691 } |
| 2705 } else if (dest == CODE_SPACE) { | 2692 } else if (dest == CODE_SPACE) { |
| 2693 DCHECK(evacuation_slots_buffer != nullptr); |
| 2706 PROFILE(isolate(), CodeMoveEvent(src_addr, dst_addr)); | 2694 PROFILE(isolate(), CodeMoveEvent(src_addr, dst_addr)); |
| 2707 heap()->MoveBlock(dst_addr, src_addr, size); | 2695 heap()->MoveBlock(dst_addr, src_addr, size); |
| 2708 RecordMigratedCodeObjectSlot(dst_addr); | 2696 RecordMigratedCodeObjectSlot(dst_addr, evacuation_slots_buffer); |
| 2709 Code::cast(dst)->Relocate(dst_addr - src_addr); | 2697 Code::cast(dst)->Relocate(dst_addr - src_addr); |
| 2710 } else { | 2698 } else { |
| 2699 DCHECK(evacuation_slots_buffer == nullptr); |
| 2711 DCHECK(dest == NEW_SPACE); | 2700 DCHECK(dest == NEW_SPACE); |
| 2712 heap()->MoveBlock(dst_addr, src_addr, size); | 2701 heap()->MoveBlock(dst_addr, src_addr, size); |
| 2713 } | 2702 } |
| 2714 heap()->OnMoveEvent(dst, src, size); | 2703 heap()->OnMoveEvent(dst, src, size); |
| 2715 Memory::Address_at(src_addr) = dst_addr; | 2704 Memory::Address_at(src_addr) = dst_addr; |
| 2716 } | 2705 } |
| 2717 | 2706 |
| 2718 | 2707 |
| 2719 void MarkCompactCollector::MigrateObjectTagged(HeapObject* dst, HeapObject* src, | 2708 void MarkCompactCollector::MigrateObjectTagged( |
| 2720 int size) { | 2709 HeapObject* dst, HeapObject* src, int size, |
| 2710 SlotsBuffer** evacuation_slots_buffer) { |
| 2721 Address src_slot = src->address(); | 2711 Address src_slot = src->address(); |
| 2722 Address dst_slot = dst->address(); | 2712 Address dst_slot = dst->address(); |
| 2723 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { | 2713 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { |
| 2724 Object* value = Memory::Object_at(src_slot); | 2714 Object* value = Memory::Object_at(src_slot); |
| 2725 Memory::Object_at(dst_slot) = value; | 2715 Memory::Object_at(dst_slot) = value; |
| 2726 RecordMigratedSlot(value, dst_slot); | 2716 RecordMigratedSlot(value, dst_slot, evacuation_slots_buffer); |
| 2727 src_slot += kPointerSize; | 2717 src_slot += kPointerSize; |
| 2728 dst_slot += kPointerSize; | 2718 dst_slot += kPointerSize; |
| 2729 } | 2719 } |
| 2730 } | 2720 } |
| 2731 | 2721 |
| 2732 | 2722 |
| 2733 void MarkCompactCollector::MigrateObjectMixed(HeapObject* dst, HeapObject* src, | 2723 void MarkCompactCollector::MigrateObjectMixed( |
| 2734 int size) { | 2724 HeapObject* dst, HeapObject* src, int size, |
| 2725 SlotsBuffer** evacuation_slots_buffer) { |
| 2735 if (src->IsFixedTypedArrayBase()) { | 2726 if (src->IsFixedTypedArrayBase()) { |
| 2736 heap()->MoveBlock(dst->address(), src->address(), size); | 2727 heap()->MoveBlock(dst->address(), src->address(), size); |
| 2737 Address base_pointer_slot = | 2728 Address base_pointer_slot = |
| 2738 dst->address() + FixedTypedArrayBase::kBasePointerOffset; | 2729 dst->address() + FixedTypedArrayBase::kBasePointerOffset; |
| 2739 RecordMigratedSlot(Memory::Object_at(base_pointer_slot), base_pointer_slot); | 2730 RecordMigratedSlot(Memory::Object_at(base_pointer_slot), base_pointer_slot, |
| 2731 evacuation_slots_buffer); |
| 2740 } else if (src->IsBytecodeArray()) { | 2732 } else if (src->IsBytecodeArray()) { |
| 2741 heap()->MoveBlock(dst->address(), src->address(), size); | 2733 heap()->MoveBlock(dst->address(), src->address(), size); |
| 2742 Address constant_pool_slot = | 2734 Address constant_pool_slot = |
| 2743 dst->address() + BytecodeArray::kConstantPoolOffset; | 2735 dst->address() + BytecodeArray::kConstantPoolOffset; |
| 2744 RecordMigratedSlot(Memory::Object_at(constant_pool_slot), | 2736 RecordMigratedSlot(Memory::Object_at(constant_pool_slot), |
| 2745 constant_pool_slot); | 2737 constant_pool_slot, evacuation_slots_buffer); |
| 2746 } else if (src->IsJSArrayBuffer()) { | 2738 } else if (src->IsJSArrayBuffer()) { |
| 2747 heap()->MoveBlock(dst->address(), src->address(), size); | 2739 heap()->MoveBlock(dst->address(), src->address(), size); |
| 2748 | 2740 |
| 2749 // Visit inherited JSObject properties and byte length of ArrayBuffer | 2741 // Visit inherited JSObject properties and byte length of ArrayBuffer |
| 2750 Address regular_slot = | 2742 Address regular_slot = |
| 2751 dst->address() + JSArrayBuffer::BodyDescriptor::kStartOffset; | 2743 dst->address() + JSArrayBuffer::BodyDescriptor::kStartOffset; |
| 2752 Address regular_slots_end = | 2744 Address regular_slots_end = |
| 2753 dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize; | 2745 dst->address() + JSArrayBuffer::kByteLengthOffset + kPointerSize; |
| 2754 while (regular_slot < regular_slots_end) { | 2746 while (regular_slot < regular_slots_end) { |
| 2755 RecordMigratedSlot(Memory::Object_at(regular_slot), regular_slot); | 2747 RecordMigratedSlot(Memory::Object_at(regular_slot), regular_slot, |
| 2748 evacuation_slots_buffer); |
| 2756 regular_slot += kPointerSize; | 2749 regular_slot += kPointerSize; |
| 2757 } | 2750 } |
| 2758 | 2751 |
| 2759 // Skip backing store and visit just internal fields | 2752 // Skip backing store and visit just internal fields |
| 2760 Address internal_field_slot = dst->address() + JSArrayBuffer::kSize; | 2753 Address internal_field_slot = dst->address() + JSArrayBuffer::kSize; |
| 2761 Address internal_fields_end = | 2754 Address internal_fields_end = |
| 2762 dst->address() + JSArrayBuffer::kSizeWithInternalFields; | 2755 dst->address() + JSArrayBuffer::kSizeWithInternalFields; |
| 2763 while (internal_field_slot < internal_fields_end) { | 2756 while (internal_field_slot < internal_fields_end) { |
| 2764 RecordMigratedSlot(Memory::Object_at(internal_field_slot), | 2757 RecordMigratedSlot(Memory::Object_at(internal_field_slot), |
| 2765 internal_field_slot); | 2758 internal_field_slot, evacuation_slots_buffer); |
| 2766 internal_field_slot += kPointerSize; | 2759 internal_field_slot += kPointerSize; |
| 2767 } | 2760 } |
| 2768 } else if (FLAG_unbox_double_fields) { | 2761 } else if (FLAG_unbox_double_fields) { |
| 2769 Address dst_addr = dst->address(); | 2762 Address dst_addr = dst->address(); |
| 2770 Address src_addr = src->address(); | 2763 Address src_addr = src->address(); |
| 2771 Address src_slot = src_addr; | 2764 Address src_slot = src_addr; |
| 2772 Address dst_slot = dst_addr; | 2765 Address dst_slot = dst_addr; |
| 2773 | 2766 |
| 2774 LayoutDescriptorHelper helper(src->map()); | 2767 LayoutDescriptorHelper helper(src->map()); |
| 2775 DCHECK(!helper.all_fields_tagged()); | 2768 DCHECK(!helper.all_fields_tagged()); |
| 2776 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { | 2769 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { |
| 2777 Object* value = Memory::Object_at(src_slot); | 2770 Object* value = Memory::Object_at(src_slot); |
| 2778 | 2771 |
| 2779 Memory::Object_at(dst_slot) = value; | 2772 Memory::Object_at(dst_slot) = value; |
| 2780 | 2773 |
| 2781 if (helper.IsTagged(static_cast<int>(src_slot - src_addr))) { | 2774 if (helper.IsTagged(static_cast<int>(src_slot - src_addr))) { |
| 2782 RecordMigratedSlot(value, dst_slot); | 2775 RecordMigratedSlot(value, dst_slot, evacuation_slots_buffer); |
| 2783 } | 2776 } |
| 2784 | 2777 |
| 2785 src_slot += kPointerSize; | 2778 src_slot += kPointerSize; |
| 2786 dst_slot += kPointerSize; | 2779 dst_slot += kPointerSize; |
| 2787 } | 2780 } |
| 2788 } else { | 2781 } else { |
| 2789 UNREACHABLE(); | 2782 UNREACHABLE(); |
| 2790 } | 2783 } |
| 2791 } | 2784 } |
| 2792 | 2785 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3087 bool MarkCompactCollector::TryPromoteObject(HeapObject* object, | 3080 bool MarkCompactCollector::TryPromoteObject(HeapObject* object, |
| 3088 int object_size) { | 3081 int object_size) { |
| 3089 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | 3082 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
| 3090 | 3083 |
| 3091 OldSpace* old_space = heap()->old_space(); | 3084 OldSpace* old_space = heap()->old_space(); |
| 3092 | 3085 |
| 3093 HeapObject* target = nullptr; | 3086 HeapObject* target = nullptr; |
| 3094 AllocationAlignment alignment = object->RequiredAlignment(); | 3087 AllocationAlignment alignment = object->RequiredAlignment(); |
| 3095 AllocationResult allocation = old_space->AllocateRaw(object_size, alignment); | 3088 AllocationResult allocation = old_space->AllocateRaw(object_size, alignment); |
| 3096 if (allocation.To(&target)) { | 3089 if (allocation.To(&target)) { |
| 3097 MigrateObject(target, object, object_size, old_space->identity()); | 3090 MigrateObject(target, object, object_size, old_space->identity(), |
| 3091 &migration_slots_buffer_); |
| 3098 // If we end up needing more special cases, we should factor this out. | 3092 // If we end up needing more special cases, we should factor this out. |
| 3099 if (V8_UNLIKELY(target->IsJSArrayBuffer())) { | 3093 if (V8_UNLIKELY(target->IsJSArrayBuffer())) { |
| 3100 heap()->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target)); | 3094 heap()->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target)); |
| 3101 } | 3095 } |
| 3102 heap()->IncrementPromotedObjectsSize(object_size); | 3096 heap()->IncrementPromotedObjectsSize(object_size); |
| 3103 return true; | 3097 return true; |
| 3104 } | 3098 } |
| 3105 | 3099 |
| 3106 return false; | 3100 return false; |
| 3107 } | 3101 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3319 while (it.has_next()) { | 3313 while (it.has_next()) { |
| 3320 NewSpacePage* p = it.next(); | 3314 NewSpacePage* p = it.next(); |
| 3321 survivors_size += DiscoverAndEvacuateBlackObjectsOnPage(new_space, p); | 3315 survivors_size += DiscoverAndEvacuateBlackObjectsOnPage(new_space, p); |
| 3322 } | 3316 } |
| 3323 | 3317 |
| 3324 heap_->IncrementYoungSurvivorsCounter(survivors_size); | 3318 heap_->IncrementYoungSurvivorsCounter(survivors_size); |
| 3325 new_space->set_age_mark(new_space->top()); | 3319 new_space->set_age_mark(new_space->top()); |
| 3326 } | 3320 } |
| 3327 | 3321 |
| 3328 | 3322 |
| 3323 void MarkCompactCollector::AddEvacuationSlotsBufferSynchronized( |
| 3324 SlotsBuffer* evacuation_slots_buffer) { |
| 3325 base::LockGuard<base::Mutex> lock_guard(&evacuation_slots_buffers_mutex_); |
| 3326 evacuation_slots_buffers_.Add(evacuation_slots_buffer); |
| 3327 } |
| 3328 |
| 3329 |
| 3329 bool MarkCompactCollector::EvacuateLiveObjectsFromPage( | 3330 bool MarkCompactCollector::EvacuateLiveObjectsFromPage( |
| 3330 Page* p, PagedSpace* target_space) { | 3331 Page* p, PagedSpace* target_space, SlotsBuffer** evacuation_slots_buffer) { |
| 3331 AlwaysAllocateScope always_allocate(isolate()); | 3332 AlwaysAllocateScope always_allocate(isolate()); |
| 3332 DCHECK(p->IsEvacuationCandidate() && !p->WasSwept()); | 3333 DCHECK(p->IsEvacuationCandidate() && !p->WasSwept()); |
| 3333 | 3334 |
| 3334 int offsets[16]; | 3335 int offsets[16]; |
| 3335 | 3336 |
| 3336 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { | 3337 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
| 3337 Address cell_base = it.CurrentCellBase(); | 3338 Address cell_base = it.CurrentCellBase(); |
| 3338 MarkBit::CellType* cell = it.CurrentCell(); | 3339 MarkBit::CellType* cell = it.CurrentCell(); |
| 3339 | 3340 |
| 3340 if (*cell == 0) continue; | 3341 if (*cell == 0) continue; |
| 3341 | 3342 |
| 3342 int live_objects = MarkWordToObjectStarts(*cell, offsets); | 3343 int live_objects = MarkWordToObjectStarts(*cell, offsets); |
| 3343 for (int i = 0; i < live_objects; i++) { | 3344 for (int i = 0; i < live_objects; i++) { |
| 3344 Address object_addr = cell_base + offsets[i] * kPointerSize; | 3345 Address object_addr = cell_base + offsets[i] * kPointerSize; |
| 3345 HeapObject* object = HeapObject::FromAddress(object_addr); | 3346 HeapObject* object = HeapObject::FromAddress(object_addr); |
| 3346 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 3347 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 3347 | 3348 |
| 3348 int size = object->Size(); | 3349 int size = object->Size(); |
| 3349 AllocationAlignment alignment = object->RequiredAlignment(); | 3350 AllocationAlignment alignment = object->RequiredAlignment(); |
| 3350 HeapObject* target_object = nullptr; | 3351 HeapObject* target_object = nullptr; |
| 3351 AllocationResult allocation = target_space->AllocateRaw(size, alignment); | 3352 AllocationResult allocation = target_space->AllocateRaw(size, alignment); |
| 3352 if (!allocation.To(&target_object)) { | 3353 if (!allocation.To(&target_object)) { |
| 3353 return false; | 3354 return false; |
| 3354 } | 3355 } |
| 3355 MigrateObject(target_object, object, size, target_space->identity()); | 3356 |
| 3357 MigrateObject(target_object, object, size, target_space->identity(), |
| 3358 evacuation_slots_buffer); |
| 3356 DCHECK(object->map_word().IsForwardingAddress()); | 3359 DCHECK(object->map_word().IsForwardingAddress()); |
| 3357 } | 3360 } |
| 3358 | 3361 |
| 3359 // Clear marking bits for current cell. | 3362 // Clear marking bits for current cell. |
| 3360 *cell = 0; | 3363 *cell = 0; |
| 3361 } | 3364 } |
| 3362 p->ResetLiveBytes(); | 3365 p->ResetLiveBytes(); |
| 3363 return true; | 3366 return true; |
| 3364 } | 3367 } |
| 3365 | 3368 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3389 // Kick off parallel tasks. | 3392 // Kick off parallel tasks. |
| 3390 for (int i = 1; i < num_tasks; i++) { | 3393 for (int i = 1; i < num_tasks; i++) { |
| 3391 concurrent_compaction_tasks_active_++; | 3394 concurrent_compaction_tasks_active_++; |
| 3392 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 3395 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 3393 new CompactionTask(heap(), compaction_spaces_for_tasks[i]), | 3396 new CompactionTask(heap(), compaction_spaces_for_tasks[i]), |
| 3394 v8::Platform::kShortRunningTask); | 3397 v8::Platform::kShortRunningTask); |
| 3395 } | 3398 } |
| 3396 | 3399 |
| 3397 // Contribute in main thread. Counter and signal are in principal not needed. | 3400 // Contribute in main thread. Counter and signal are in principal not needed. |
| 3398 concurrent_compaction_tasks_active_++; | 3401 concurrent_compaction_tasks_active_++; |
| 3399 EvacuatePages(compaction_spaces_for_tasks[0]); | 3402 EvacuatePages(compaction_spaces_for_tasks[0], &migration_slots_buffer_); |
| 3400 pending_compaction_tasks_semaphore_.Signal(); | 3403 pending_compaction_tasks_semaphore_.Signal(); |
| 3401 | 3404 |
| 3402 WaitUntilCompactionCompleted(); | 3405 WaitUntilCompactionCompleted(); |
| 3403 | 3406 |
| 3404 // Merge back memory (compacted and unused) from compaction spaces. | 3407 // Merge back memory (compacted and unused) from compaction spaces. |
| 3405 for (int i = 0; i < num_tasks; i++) { | 3408 for (int i = 0; i < num_tasks; i++) { |
| 3406 heap()->old_space()->MergeCompactionSpace( | 3409 heap()->old_space()->MergeCompactionSpace( |
| 3407 compaction_spaces_for_tasks[i]->Get(OLD_SPACE)); | 3410 compaction_spaces_for_tasks[i]->Get(OLD_SPACE)); |
| 3408 heap()->code_space()->MergeCompactionSpace( | 3411 heap()->code_space()->MergeCompactionSpace( |
| 3409 compaction_spaces_for_tasks[i]->Get(CODE_SPACE)); | 3412 compaction_spaces_for_tasks[i]->Get(CODE_SPACE)); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3465 | 3468 |
| 3466 void MarkCompactCollector::WaitUntilCompactionCompleted() { | 3469 void MarkCompactCollector::WaitUntilCompactionCompleted() { |
| 3467 while (concurrent_compaction_tasks_active_-- > 0) { | 3470 while (concurrent_compaction_tasks_active_-- > 0) { |
| 3468 pending_compaction_tasks_semaphore_.Wait(); | 3471 pending_compaction_tasks_semaphore_.Wait(); |
| 3469 } | 3472 } |
| 3470 parallel_compaction_in_progress_ = false; | 3473 parallel_compaction_in_progress_ = false; |
| 3471 } | 3474 } |
| 3472 | 3475 |
| 3473 | 3476 |
| 3474 void MarkCompactCollector::EvacuatePages( | 3477 void MarkCompactCollector::EvacuatePages( |
| 3475 CompactionSpaceCollection* compaction_spaces) { | 3478 CompactionSpaceCollection* compaction_spaces, |
| 3479 SlotsBuffer** evacuation_slots_buffer) { |
| 3476 for (int i = 0; i < evacuation_candidates_.length(); i++) { | 3480 for (int i = 0; i < evacuation_candidates_.length(); i++) { |
| 3477 Page* p = evacuation_candidates_[i]; | 3481 Page* p = evacuation_candidates_[i]; |
| 3478 DCHECK(p->IsEvacuationCandidate() || | 3482 DCHECK(p->IsEvacuationCandidate() || |
| 3479 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3483 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
| 3480 DCHECK(static_cast<int>(p->parallel_sweeping()) == | 3484 DCHECK(static_cast<int>(p->parallel_sweeping()) == |
| 3481 MemoryChunk::SWEEPING_DONE); | 3485 MemoryChunk::SWEEPING_DONE); |
| 3482 if (p->parallel_compaction_state().TrySetValue( | 3486 if (p->parallel_compaction_state().TrySetValue( |
| 3483 MemoryChunk::kCompactingDone, MemoryChunk::kCompactingInProgress)) { | 3487 MemoryChunk::kCompactingDone, MemoryChunk::kCompactingInProgress)) { |
| 3484 if (p->IsEvacuationCandidate()) { | 3488 if (p->IsEvacuationCandidate()) { |
| 3485 DCHECK_EQ(p->parallel_compaction_state().Value(), | 3489 DCHECK_EQ(p->parallel_compaction_state().Value(), |
| 3486 MemoryChunk::kCompactingInProgress); | 3490 MemoryChunk::kCompactingInProgress); |
| 3487 if (EvacuateLiveObjectsFromPage( | 3491 if (EvacuateLiveObjectsFromPage( |
| 3488 p, compaction_spaces->Get(p->owner()->identity()))) { | 3492 p, compaction_spaces->Get(p->owner()->identity()), |
| 3493 evacuation_slots_buffer)) { |
| 3489 p->parallel_compaction_state().SetValue( | 3494 p->parallel_compaction_state().SetValue( |
| 3490 MemoryChunk::kCompactingFinalize); | 3495 MemoryChunk::kCompactingFinalize); |
| 3491 } else { | 3496 } else { |
| 3492 p->parallel_compaction_state().SetValue( | 3497 p->parallel_compaction_state().SetValue( |
| 3493 MemoryChunk::kCompactingAborted); | 3498 MemoryChunk::kCompactingAborted); |
| 3494 } | 3499 } |
| 3495 } else { | 3500 } else { |
| 3496 // There could be popular pages in the list of evacuation candidates | 3501 // There could be popular pages in the list of evacuation candidates |
| 3497 // which we do compact. | 3502 // which we do compact. |
| 3498 p->parallel_compaction_state().SetValue(MemoryChunk::kCompactingDone); | 3503 p->parallel_compaction_state().SetValue(MemoryChunk::kCompactingDone); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3680 EvacuateNewSpace(); | 3685 EvacuateNewSpace(); |
| 3681 } | 3686 } |
| 3682 | 3687 |
| 3683 { | 3688 { |
| 3684 GCTracer::Scope gc_scope(heap()->tracer(), | 3689 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3685 GCTracer::Scope::MC_EVACUATE_PAGES); | 3690 GCTracer::Scope::MC_EVACUATE_PAGES); |
| 3686 EvacuationScope evacuation_scope(this); | 3691 EvacuationScope evacuation_scope(this); |
| 3687 EvacuatePagesInParallel(); | 3692 EvacuatePagesInParallel(); |
| 3688 } | 3693 } |
| 3689 | 3694 |
| 3695 { |
| 3696 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3697 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); |
| 3698 UpdateSlotsRecordedIn(migration_slots_buffer_); |
| 3699 if (FLAG_trace_fragmentation_verbose) { |
| 3700 PrintF(" migration slots buffer: %d\n", |
| 3701 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); |
| 3702 } |
| 3703 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); |
| 3704 DCHECK(migration_slots_buffer_ == NULL); |
| 3705 |
| 3706 // TODO(hpayer): Process the slots buffers in parallel. This has to be done |
| 3707 // after evacuation of all pages finishes. |
| 3708 int buffers = evacuation_slots_buffers_.length(); |
| 3709 for (int i = 0; i < buffers; i++) { |
| 3710 SlotsBuffer* buffer = evacuation_slots_buffers_[i]; |
| 3711 UpdateSlotsRecordedIn(buffer); |
| 3712 slots_buffer_allocator_->DeallocateChain(&buffer); |
| 3713 } |
| 3714 evacuation_slots_buffers_.Rewind(0); |
| 3715 } |
| 3716 |
| 3690 // Second pass: find pointers to new space and update them. | 3717 // Second pass: find pointers to new space and update them. |
| 3691 PointersUpdatingVisitor updating_visitor(heap()); | 3718 PointersUpdatingVisitor updating_visitor(heap()); |
| 3692 | 3719 |
| 3693 { | 3720 { |
| 3694 GCTracer::Scope gc_scope(heap()->tracer(), | 3721 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3695 GCTracer::Scope::MC_UPDATE_NEW_TO_NEW_POINTERS); | 3722 GCTracer::Scope::MC_UPDATE_NEW_TO_NEW_POINTERS); |
| 3696 // Update pointers in to space. | 3723 // Update pointers in to space. |
| 3697 SemiSpaceIterator to_it(heap()->new_space()); | 3724 SemiSpaceIterator to_it(heap()->new_space()); |
| 3698 for (HeapObject* object = to_it.Next(); object != NULL; | 3725 for (HeapObject* object = to_it.Next(); object != NULL; |
| 3699 object = to_it.Next()) { | 3726 object = to_it.Next()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3711 } | 3738 } |
| 3712 | 3739 |
| 3713 { | 3740 { |
| 3714 GCTracer::Scope gc_scope(heap()->tracer(), | 3741 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3715 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); | 3742 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); |
| 3716 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), | 3743 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), |
| 3717 &Heap::ScavengeStoreBufferCallback); | 3744 &Heap::ScavengeStoreBufferCallback); |
| 3718 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 3745 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| 3719 } | 3746 } |
| 3720 | 3747 |
| 3721 { | |
| 3722 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3723 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); | |
| 3724 UpdateSlotsRecordedIn(migration_slots_buffer_); | |
| 3725 if (FLAG_trace_fragmentation_verbose) { | |
| 3726 PrintF(" migration slots buffer: %d\n", | |
| 3727 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | |
| 3728 } | |
| 3729 } | |
| 3730 | |
| 3731 int npages = evacuation_candidates_.length(); | 3748 int npages = evacuation_candidates_.length(); |
| 3732 { | 3749 { |
| 3733 GCTracer::Scope gc_scope( | 3750 GCTracer::Scope gc_scope( |
| 3734 heap()->tracer(), | 3751 heap()->tracer(), |
| 3735 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); | 3752 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); |
| 3736 for (int i = 0; i < npages; i++) { | 3753 for (int i = 0; i < npages; i++) { |
| 3737 Page* p = evacuation_candidates_[i]; | 3754 Page* p = evacuation_candidates_[i]; |
| 3738 DCHECK(p->IsEvacuationCandidate() || | 3755 DCHECK(p->IsEvacuationCandidate() || |
| 3739 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3756 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
| 3740 | 3757 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3798 | 3815 |
| 3799 // Update pointers from external string table. | 3816 // Update pointers from external string table. |
| 3800 heap_->UpdateReferencesInExternalStringTable( | 3817 heap_->UpdateReferencesInExternalStringTable( |
| 3801 &UpdateReferenceInExternalStringTableEntry); | 3818 &UpdateReferenceInExternalStringTableEntry); |
| 3802 | 3819 |
| 3803 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3820 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3804 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); | 3821 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); |
| 3805 | 3822 |
| 3806 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); | 3823 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); |
| 3807 | 3824 |
| 3808 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); | |
| 3809 DCHECK(migration_slots_buffer_ == NULL); | |
| 3810 | |
| 3811 // The hashing of weak_object_to_code_table is no longer valid. | 3825 // The hashing of weak_object_to_code_table is no longer valid. |
| 3812 heap()->weak_object_to_code_table()->Rehash( | 3826 heap()->weak_object_to_code_table()->Rehash( |
| 3813 heap()->isolate()->factory()->undefined_value()); | 3827 heap()->isolate()->factory()->undefined_value()); |
| 3814 } | 3828 } |
| 3815 | 3829 |
| 3816 | 3830 |
| 3817 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { | 3831 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { |
| 3818 int npages = evacuation_candidates_.length(); | 3832 int npages = evacuation_candidates_.length(); |
| 3819 for (int i = 0; i < npages; i++) { | 3833 for (int i = 0; i < npages; i++) { |
| 3820 Page* p = evacuation_candidates_[i]; | 3834 Page* p = evacuation_candidates_[i]; |
| (...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4569 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4583 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 4570 if (Marking::IsBlack(mark_bit)) { | 4584 if (Marking::IsBlack(mark_bit)) { |
| 4571 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 4585 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
| 4572 RecordRelocSlot(&rinfo, target); | 4586 RecordRelocSlot(&rinfo, target); |
| 4573 } | 4587 } |
| 4574 } | 4588 } |
| 4575 } | 4589 } |
| 4576 | 4590 |
| 4577 } // namespace internal | 4591 } // namespace internal |
| 4578 } // namespace v8 | 4592 } // namespace v8 |
| OLD | NEW |