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 2781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2792 slot_type = CODE_ENTRY_SLOT; | 2792 slot_type = CODE_ENTRY_SLOT; |
2793 } else { | 2793 } else { |
2794 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); | 2794 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); |
2795 slot_type = OBJECT_SLOT; | 2795 slot_type = OBJECT_SLOT; |
2796 } | 2796 } |
2797 } | 2797 } |
2798 RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr); | 2798 RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr); |
2799 } | 2799 } |
2800 } | 2800 } |
2801 | 2801 |
2802 static inline void UpdateTypedSlot(Isolate* isolate, ObjectVisitor* v, | 2802 static inline SlotCallbackResult UpdateSlot(Object** slot) { |
2803 SlotType slot_type, Address addr) { | 2803 Object* obj = reinterpret_cast<Object*>( |
| 2804 base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot))); |
| 2805 |
| 2806 if (obj->IsHeapObject()) { |
| 2807 HeapObject* heap_obj = HeapObject::cast(obj); |
| 2808 MapWord map_word = heap_obj->map_word(); |
| 2809 if (map_word.IsForwardingAddress()) { |
| 2810 DCHECK(heap_obj->GetHeap()->InFromSpace(heap_obj) || |
| 2811 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) || |
| 2812 Page::FromAddress(heap_obj->address()) |
| 2813 ->IsFlagSet(Page::COMPACTION_WAS_ABORTED)); |
| 2814 HeapObject* target = map_word.ToForwardingAddress(); |
| 2815 base::NoBarrier_CompareAndSwap( |
| 2816 reinterpret_cast<base::AtomicWord*>(slot), |
| 2817 reinterpret_cast<base::AtomicWord>(obj), |
| 2818 reinterpret_cast<base::AtomicWord>(target)); |
| 2819 DCHECK(!heap_obj->GetHeap()->InFromSpace(target) && |
| 2820 !MarkCompactCollector::IsOnEvacuationCandidate(target)); |
| 2821 } |
| 2822 } |
| 2823 return REMOVE_SLOT; |
| 2824 } |
| 2825 |
| 2826 // Updates a cell slot using an untyped slot callback. |
| 2827 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2828 template <typename Callback> |
| 2829 static SlotCallbackResult UpdateCell(RelocInfo* rinfo, Callback callback) { |
| 2830 DCHECK(rinfo->rmode() == RelocInfo::CELL); |
| 2831 Object* cell = rinfo->target_cell(); |
| 2832 Object* old_cell = cell; |
| 2833 SlotCallbackResult result = callback(&cell); |
| 2834 if (cell != old_cell) { |
| 2835 rinfo->set_target_cell(reinterpret_cast<Cell*>(cell)); |
| 2836 } |
| 2837 return result; |
| 2838 } |
| 2839 |
| 2840 // Updates a code entry slot using an untyped slot callback. |
| 2841 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2842 template <typename Callback> |
| 2843 static SlotCallbackResult UpdateCodeEntry(Address entry_address, |
| 2844 Callback callback) { |
| 2845 Object* code = Code::GetObjectFromEntryAddress(entry_address); |
| 2846 Object* old_code = code; |
| 2847 SlotCallbackResult result = callback(&code); |
| 2848 if (code != old_code) { |
| 2849 Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry(); |
| 2850 } |
| 2851 return result; |
| 2852 } |
| 2853 |
| 2854 // Updates a code target slot using an untyped slot callback. |
| 2855 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2856 template <typename Callback> |
| 2857 static SlotCallbackResult UpdateCodeTarget(RelocInfo* rinfo, |
| 2858 Callback callback) { |
| 2859 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 2860 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 2861 Object* old_target = target; |
| 2862 SlotCallbackResult result = callback(&target); |
| 2863 if (target != old_target) { |
| 2864 rinfo->set_target_address(Code::cast(target)->instruction_start()); |
| 2865 } |
| 2866 return result; |
| 2867 } |
| 2868 |
| 2869 // Updates an embedded pointer slot using an untyped slot callback. |
| 2870 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2871 template <typename Callback> |
| 2872 static SlotCallbackResult UpdateEmbeddedPointer(RelocInfo* rinfo, |
| 2873 Callback callback) { |
| 2874 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 2875 Object* target = rinfo->target_object(); |
| 2876 Object* old_target = target; |
| 2877 SlotCallbackResult result = callback(&target); |
| 2878 if (target != old_target) { |
| 2879 rinfo->set_target_object(target); |
| 2880 } |
| 2881 return result; |
| 2882 } |
| 2883 |
| 2884 // Updates a debug target slot using an untyped slot callback. |
| 2885 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2886 template <typename Callback> |
| 2887 static SlotCallbackResult UpdateDebugTarget(RelocInfo* rinfo, |
| 2888 Callback callback) { |
| 2889 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 2890 rinfo->IsPatchedDebugBreakSlotSequence()); |
| 2891 Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); |
| 2892 SlotCallbackResult result = callback(&target); |
| 2893 rinfo->set_debug_call_address(Code::cast(target)->instruction_start()); |
| 2894 return result; |
| 2895 } |
| 2896 |
| 2897 // Updates a typed slot using an untyped slot callback. |
| 2898 // The callback accepts (Heap*, Object**) and returns SlotCallbackResult. |
| 2899 template <typename Callback> |
| 2900 static SlotCallbackResult UpdateTypedSlot(Isolate* isolate, SlotType slot_type, |
| 2901 Address addr, Callback callback) { |
2804 switch (slot_type) { | 2902 switch (slot_type) { |
2805 case CODE_TARGET_SLOT: { | 2903 case CODE_TARGET_SLOT: { |
2806 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); | 2904 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); |
2807 rinfo.Visit(isolate, v); | 2905 return UpdateCodeTarget(&rinfo, callback); |
2808 break; | |
2809 } | 2906 } |
2810 case CELL_TARGET_SLOT: { | 2907 case CELL_TARGET_SLOT: { |
2811 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); | 2908 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); |
2812 rinfo.Visit(isolate, v); | 2909 return UpdateCell(&rinfo, callback); |
2813 break; | |
2814 } | 2910 } |
2815 case CODE_ENTRY_SLOT: { | 2911 case CODE_ENTRY_SLOT: { |
2816 v->VisitCodeEntry(addr); | 2912 return UpdateCodeEntry(addr, callback); |
2817 break; | |
2818 } | 2913 } |
2819 case DEBUG_TARGET_SLOT: { | 2914 case DEBUG_TARGET_SLOT: { |
2820 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0, | 2915 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0, |
2821 NULL); | 2916 NULL); |
2822 if (rinfo.IsPatchedDebugBreakSlotSequence()) rinfo.Visit(isolate, v); | 2917 if (rinfo.IsPatchedDebugBreakSlotSequence()) { |
2823 break; | 2918 return UpdateDebugTarget(&rinfo, callback); |
| 2919 } |
| 2920 return REMOVE_SLOT; |
2824 } | 2921 } |
2825 case EMBEDDED_OBJECT_SLOT: { | 2922 case EMBEDDED_OBJECT_SLOT: { |
2826 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL); | 2923 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL); |
2827 rinfo.Visit(isolate, v); | 2924 return UpdateEmbeddedPointer(&rinfo, callback); |
2828 break; | |
2829 } | 2925 } |
2830 case OBJECT_SLOT: { | 2926 case OBJECT_SLOT: { |
2831 v->VisitPointer(reinterpret_cast<Object**>(addr)); | 2927 return callback(reinterpret_cast<Object**>(addr)); |
2832 break; | |
2833 } | 2928 } |
2834 default: | 2929 case NUMBER_OF_SLOT_TYPES: |
2835 UNREACHABLE(); | |
2836 break; | 2930 break; |
2837 } | 2931 } |
| 2932 UNREACHABLE(); |
| 2933 return REMOVE_SLOT; |
2838 } | 2934 } |
2839 | 2935 |
2840 | 2936 |
2841 // Visitor for updating pointers from live objects in old spaces to new space. | 2937 // Visitor for updating pointers from live objects in old spaces to new space. |
2842 // It does not expect to encounter pointers to dead objects. | 2938 // It does not expect to encounter pointers to dead objects. |
2843 class PointersUpdatingVisitor : public ObjectVisitor { | 2939 class PointersUpdatingVisitor : public ObjectVisitor { |
2844 public: | 2940 public: |
2845 explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) {} | 2941 void VisitPointer(Object** p) override { UpdateSlot(p); } |
2846 | |
2847 void VisitPointer(Object** p) override { UpdatePointer(p); } | |
2848 | 2942 |
2849 void VisitPointers(Object** start, Object** end) override { | 2943 void VisitPointers(Object** start, Object** end) override { |
2850 for (Object** p = start; p < end; p++) UpdatePointer(p); | 2944 for (Object** p = start; p < end; p++) UpdateSlot(p); |
2851 } | 2945 } |
2852 | 2946 |
2853 void VisitCell(RelocInfo* rinfo) override { | 2947 void VisitCell(RelocInfo* rinfo) override { UpdateCell(rinfo, UpdateSlot); } |
2854 DCHECK(rinfo->rmode() == RelocInfo::CELL); | |
2855 Object* cell = rinfo->target_cell(); | |
2856 Object* old_cell = cell; | |
2857 VisitPointer(&cell); | |
2858 if (cell != old_cell) { | |
2859 rinfo->set_target_cell(reinterpret_cast<Cell*>(cell)); | |
2860 } | |
2861 } | |
2862 | 2948 |
2863 void VisitEmbeddedPointer(RelocInfo* rinfo) override { | 2949 void VisitEmbeddedPointer(RelocInfo* rinfo) override { |
2864 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 2950 UpdateEmbeddedPointer(rinfo, UpdateSlot); |
2865 Object* target = rinfo->target_object(); | |
2866 Object* old_target = target; | |
2867 VisitPointer(&target); | |
2868 // Avoid unnecessary changes that might unnecessary flush the instruction | |
2869 // cache. | |
2870 if (target != old_target) { | |
2871 rinfo->set_target_object(target); | |
2872 } | |
2873 } | 2951 } |
2874 | 2952 |
2875 void VisitCodeTarget(RelocInfo* rinfo) override { | 2953 void VisitCodeTarget(RelocInfo* rinfo) override { |
2876 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 2954 UpdateCodeTarget(rinfo, UpdateSlot); |
2877 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | |
2878 Object* old_target = target; | |
2879 VisitPointer(&target); | |
2880 if (target != old_target) { | |
2881 rinfo->set_target_address(Code::cast(target)->instruction_start()); | |
2882 } | |
2883 } | |
2884 | |
2885 void VisitCodeAgeSequence(RelocInfo* rinfo) override { | |
2886 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | |
2887 Object* stub = rinfo->code_age_stub(); | |
2888 DCHECK(stub != NULL); | |
2889 VisitPointer(&stub); | |
2890 if (stub != rinfo->code_age_stub()) { | |
2891 rinfo->set_code_age_stub(Code::cast(stub)); | |
2892 } | |
2893 } | 2955 } |
2894 | 2956 |
2895 void VisitCodeEntry(Address entry_address) override { | 2957 void VisitCodeEntry(Address entry_address) override { |
2896 Object* code = Code::GetObjectFromEntryAddress(entry_address); | 2958 UpdateCodeEntry(entry_address, UpdateSlot); |
2897 Object* old_code = code; | |
2898 VisitPointer(&code); | |
2899 if (code != old_code) { | |
2900 Memory::Address_at(entry_address) = | |
2901 reinterpret_cast<Code*>(code)->entry(); | |
2902 } | |
2903 } | 2959 } |
2904 | 2960 |
2905 void VisitDebugTarget(RelocInfo* rinfo) override { | 2961 void VisitDebugTarget(RelocInfo* rinfo) override { |
2906 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 2962 UpdateDebugTarget(rinfo, UpdateSlot); |
2907 rinfo->IsPatchedDebugBreakSlotSequence()); | |
2908 Object* target = | |
2909 Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | |
2910 VisitPointer(&target); | |
2911 rinfo->set_debug_call_address(Code::cast(target)->instruction_start()); | |
2912 } | 2963 } |
2913 | |
2914 static inline void UpdateSlot(Heap* heap, Object** slot) { | |
2915 Object* obj = reinterpret_cast<Object*>( | |
2916 base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot))); | |
2917 | |
2918 if (!obj->IsHeapObject()) return; | |
2919 | |
2920 HeapObject* heap_obj = HeapObject::cast(obj); | |
2921 | |
2922 MapWord map_word = heap_obj->map_word(); | |
2923 if (map_word.IsForwardingAddress()) { | |
2924 DCHECK(heap->InFromSpace(heap_obj) || | |
2925 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) || | |
2926 Page::FromAddress(heap_obj->address()) | |
2927 ->IsFlagSet(Page::COMPACTION_WAS_ABORTED)); | |
2928 HeapObject* target = map_word.ToForwardingAddress(); | |
2929 base::NoBarrier_CompareAndSwap( | |
2930 reinterpret_cast<base::AtomicWord*>(slot), | |
2931 reinterpret_cast<base::AtomicWord>(obj), | |
2932 reinterpret_cast<base::AtomicWord>(target)); | |
2933 DCHECK(!heap->InFromSpace(target) && | |
2934 !MarkCompactCollector::IsOnEvacuationCandidate(target)); | |
2935 } | |
2936 } | |
2937 | |
2938 private: | |
2939 inline void UpdatePointer(Object** p) { UpdateSlot(heap_, p); } | |
2940 | |
2941 Heap* heap_; | |
2942 }; | 2964 }; |
2943 | 2965 |
2944 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, | 2966 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, |
2945 Object** p) { | 2967 Object** p) { |
2946 MapWord map_word = HeapObject::cast(*p)->map_word(); | 2968 MapWord map_word = HeapObject::cast(*p)->map_word(); |
2947 | 2969 |
2948 if (map_word.IsForwardingAddress()) { | 2970 if (map_word.IsForwardingAddress()) { |
2949 return String::cast(map_word.ToForwardingAddress()); | 2971 return String::cast(map_word.ToForwardingAddress()); |
2950 } | 2972 } |
2951 | 2973 |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3622 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { | 3644 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { |
3623 VerifyEvacuation(heap()); | 3645 VerifyEvacuation(heap()); |
3624 } | 3646 } |
3625 #endif | 3647 #endif |
3626 } | 3648 } |
3627 | 3649 |
3628 template <PointerDirection direction> | 3650 template <PointerDirection direction> |
3629 class PointerUpdateJobTraits { | 3651 class PointerUpdateJobTraits { |
3630 public: | 3652 public: |
3631 typedef int PerPageData; // Per page data is not used in this job. | 3653 typedef int PerPageData; // Per page data is not used in this job. |
3632 typedef PointersUpdatingVisitor* PerTaskData; | 3654 typedef int PerTaskData; // Per task data is not used in this job. |
3633 | 3655 |
3634 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, | 3656 static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk, |
3635 MemoryChunk* chunk, PerPageData) { | 3657 PerPageData) { |
3636 UpdateUntypedPointers(heap, chunk); | 3658 UpdateUntypedPointers(heap, chunk); |
3637 UpdateTypedPointers(heap, chunk, visitor); | 3659 UpdateTypedPointers(heap, chunk); |
3638 return true; | 3660 return true; |
3639 } | 3661 } |
3640 static const bool NeedSequentialFinalization = false; | 3662 static const bool NeedSequentialFinalization = false; |
3641 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { | 3663 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { |
3642 } | 3664 } |
3643 | 3665 |
3644 private: | 3666 private: |
3645 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { | 3667 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { |
3646 if (direction == OLD_TO_NEW) { | 3668 if (direction == OLD_TO_NEW) { |
3647 RememberedSet<OLD_TO_NEW>::IterateWithWrapper(heap, chunk, | 3669 RememberedSet<OLD_TO_NEW>::IterateWithWrapper(heap, chunk, |
3648 UpdateOldToNewSlot); | 3670 UpdateOldToNewSlot); |
3649 } else { | 3671 } else { |
3650 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [heap](Address slot) { | 3672 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) { |
3651 PointersUpdatingVisitor::UpdateSlot(heap, | 3673 return UpdateSlot(reinterpret_cast<Object**>(slot)); |
3652 reinterpret_cast<Object**>(slot)); | |
3653 return REMOVE_SLOT; | |
3654 }); | 3674 }); |
3655 } | 3675 } |
3656 } | 3676 } |
3657 | 3677 |
3658 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk, | 3678 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { |
3659 PointersUpdatingVisitor* visitor) { | |
3660 if (direction == OLD_TO_OLD) { | 3679 if (direction == OLD_TO_OLD) { |
3661 Isolate* isolate = heap->isolate(); | 3680 Isolate* isolate = heap->isolate(); |
3662 RememberedSet<OLD_TO_OLD>::IterateTyped( | 3681 RememberedSet<OLD_TO_OLD>::IterateTyped( |
3663 chunk, [isolate, visitor](SlotType type, Address slot) { | 3682 chunk, [isolate](SlotType type, Address slot) { |
3664 UpdateTypedSlot(isolate, visitor, type, slot); | 3683 return UpdateTypedSlot(isolate, type, slot, UpdateSlot); |
3665 return REMOVE_SLOT; | |
3666 }); | 3684 }); |
3667 } | 3685 } |
3668 } | 3686 } |
3669 | 3687 |
3670 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { | 3688 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { |
3671 MapWord map_word = object->map_word(); | 3689 MapWord map_word = object->map_word(); |
3672 // There could still be stale pointers in large object space, map space, | 3690 // There could still be stale pointers in large object space, map space, |
3673 // and old space for pages that have been promoted. | 3691 // and old space for pages that have been promoted. |
3674 if (map_word.IsForwardingAddress()) { | 3692 if (map_word.IsForwardingAddress()) { |
3675 // Update the corresponding slot. | 3693 // Update the corresponding slot. |
3676 *address = map_word.ToForwardingAddress(); | 3694 *address = map_word.ToForwardingAddress(); |
3677 } | 3695 } |
3678 } | 3696 } |
3679 }; | 3697 }; |
3680 | 3698 |
3681 int NumberOfPointerUpdateTasks(int pages) { | 3699 int NumberOfPointerUpdateTasks(int pages) { |
3682 if (!FLAG_parallel_pointer_update) return 1; | 3700 if (!FLAG_parallel_pointer_update) return 1; |
3683 const int kMaxTasks = 4; | 3701 const int kMaxTasks = 4; |
3684 const int kPagesPerTask = 4; | 3702 const int kPagesPerTask = 4; |
3685 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); | 3703 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); |
3686 } | 3704 } |
3687 | 3705 |
3688 template <PointerDirection direction> | 3706 template <PointerDirection direction> |
3689 void UpdatePointersInParallel(Heap* heap) { | 3707 void UpdatePointersInParallel(Heap* heap) { |
3690 PageParallelJob<PointerUpdateJobTraits<direction> > job( | 3708 PageParallelJob<PointerUpdateJobTraits<direction> > job( |
3691 heap, heap->isolate()->cancelable_task_manager()); | 3709 heap, heap->isolate()->cancelable_task_manager()); |
3692 RememberedSet<direction>::IterateMemoryChunks( | 3710 RememberedSet<direction>::IterateMemoryChunks( |
3693 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); | 3711 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); |
3694 PointersUpdatingVisitor visitor(heap); | |
3695 int num_pages = job.NumberOfPages(); | 3712 int num_pages = job.NumberOfPages(); |
3696 int num_tasks = NumberOfPointerUpdateTasks(num_pages); | 3713 int num_tasks = NumberOfPointerUpdateTasks(num_pages); |
3697 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3714 job.Run(num_tasks, [](int i) { return 0; }); |
3698 } | 3715 } |
3699 | 3716 |
3700 class ToSpacePointerUpdateJobTraits { | 3717 class ToSpacePointerUpdateJobTraits { |
3701 public: | 3718 public: |
3702 typedef std::pair<Address, Address> PerPageData; | 3719 typedef std::pair<Address, Address> PerPageData; |
3703 typedef PointersUpdatingVisitor* PerTaskData; | 3720 typedef PointersUpdatingVisitor* PerTaskData; |
3704 | 3721 |
3705 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, | 3722 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, |
3706 MemoryChunk* chunk, PerPageData limits) { | 3723 MemoryChunk* chunk, PerPageData limits) { |
3707 for (Address cur = limits.first; cur < limits.second;) { | 3724 for (Address cur = limits.first; cur < limits.second;) { |
(...skipping 16 matching lines...) Expand all Loading... |
3724 Address space_start = heap->new_space()->bottom(); | 3741 Address space_start = heap->new_space()->bottom(); |
3725 Address space_end = heap->new_space()->top(); | 3742 Address space_end = heap->new_space()->top(); |
3726 NewSpacePageIterator it(space_start, space_end); | 3743 NewSpacePageIterator it(space_start, space_end); |
3727 while (it.has_next()) { | 3744 while (it.has_next()) { |
3728 Page* page = it.next(); | 3745 Page* page = it.next(); |
3729 Address start = | 3746 Address start = |
3730 page->Contains(space_start) ? space_start : page->area_start(); | 3747 page->Contains(space_start) ? space_start : page->area_start(); |
3731 Address end = page->Contains(space_end) ? space_end : page->area_end(); | 3748 Address end = page->Contains(space_end) ? space_end : page->area_end(); |
3732 job.AddPage(page, std::make_pair(start, end)); | 3749 job.AddPage(page, std::make_pair(start, end)); |
3733 } | 3750 } |
3734 PointersUpdatingVisitor visitor(heap); | 3751 PointersUpdatingVisitor visitor; |
3735 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; | 3752 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; |
3736 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3753 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
3737 } | 3754 } |
3738 | 3755 |
3739 void MarkCompactCollector::UpdatePointersAfterEvacuation() { | 3756 void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
3740 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | 3757 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
3741 | 3758 |
3742 PointersUpdatingVisitor updating_visitor(heap()); | 3759 PointersUpdatingVisitor updating_visitor; |
3743 | 3760 |
3744 { | 3761 { |
3745 TRACE_GC(heap()->tracer(), | 3762 TRACE_GC(heap()->tracer(), |
3746 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 3763 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
3747 UpdateToSpacePointersInParallel(heap_); | 3764 UpdateToSpacePointersInParallel(heap_); |
3748 // Update roots. | 3765 // Update roots. |
3749 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3766 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
3750 UpdatePointersInParallel<OLD_TO_NEW>(heap_); | 3767 UpdatePointersInParallel<OLD_TO_NEW>(heap_); |
3751 } | 3768 } |
3752 | 3769 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3999 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4016 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4000 if (Marking::IsBlack(mark_bit)) { | 4017 if (Marking::IsBlack(mark_bit)) { |
4001 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4018 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
4002 RecordRelocSlot(host, &rinfo, target); | 4019 RecordRelocSlot(host, &rinfo, target); |
4003 } | 4020 } |
4004 } | 4021 } |
4005 } | 4022 } |
4006 | 4023 |
4007 } // namespace internal | 4024 } // namespace internal |
4008 } // namespace v8 | 4025 } // namespace v8 |
OLD | NEW |