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(Heap* heap, Object** slot) { |
ulan
2016/05/19 08:31:08
I just moved this function and changed its type fr
| |
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->InFromSpace(heap_obj) || | |
ahaas
2016/05/19 08:48:44
you could get the heap from heap_obj->GetHeap()
ulan
2016/05/19 09:01:35
Done :)
| |
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->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 SlotCallbackResult UpdateCell(Heap* heap, 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(heap, &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 SlotCallbackResult UpdateCodeEntry(Heap* heap, Address entry_address, | |
2844 Callback callback) { | |
2845 Object* code = Code::GetObjectFromEntryAddress(entry_address); | |
ahaas
2016/05/19 08:48:44
Why do you not do the DCHECK here?
ulan
2016/05/19 09:01:35
There is not reloc info.
| |
2846 Object* old_code = code; | |
2847 SlotCallbackResult result = callback(heap, &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 SlotCallbackResult UpdateCodeTarget(Heap* heap, 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(heap, &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 SlotCallbackResult UpdateEmbeddedPointer(Heap* heap, 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(heap, &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 SlotCallbackResult UpdateDebugTarget(Heap* heap, 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(heap, &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 inline SlotCallbackResult UpdateTypedSlot(Isolate* isolate, | |
2901 SlotType slot_type, | |
2902 Address addr, | |
2903 Callback callback) { | |
2904 Heap* heap = isolate->heap(); | |
2804 switch (slot_type) { | 2905 switch (slot_type) { |
2805 case CODE_TARGET_SLOT: { | 2906 case CODE_TARGET_SLOT: { |
2806 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); | 2907 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); |
2807 rinfo.Visit(isolate, v); | 2908 return UpdateCodeTarget(heap, &rinfo, callback); |
2808 break; | |
2809 } | 2909 } |
2810 case CELL_TARGET_SLOT: { | 2910 case CELL_TARGET_SLOT: { |
2811 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); | 2911 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); |
2812 rinfo.Visit(isolate, v); | 2912 return UpdateCell(heap, &rinfo, callback); |
2813 break; | |
2814 } | 2913 } |
2815 case CODE_ENTRY_SLOT: { | 2914 case CODE_ENTRY_SLOT: { |
2816 v->VisitCodeEntry(addr); | 2915 return UpdateCodeEntry(heap, addr, callback); |
2817 break; | |
2818 } | 2916 } |
2819 case DEBUG_TARGET_SLOT: { | 2917 case DEBUG_TARGET_SLOT: { |
2820 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0, | 2918 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0, |
2821 NULL); | 2919 NULL); |
2822 if (rinfo.IsPatchedDebugBreakSlotSequence()) rinfo.Visit(isolate, v); | 2920 if (rinfo.IsPatchedDebugBreakSlotSequence()) { |
2823 break; | 2921 return UpdateDebugTarget(heap, &rinfo, callback); |
2922 } | |
2923 return REMOVE_SLOT; | |
2824 } | 2924 } |
2825 case EMBEDDED_OBJECT_SLOT: { | 2925 case EMBEDDED_OBJECT_SLOT: { |
2826 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL); | 2926 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL); |
2827 rinfo.Visit(isolate, v); | 2927 return UpdateEmbeddedPointer(heap, &rinfo, callback); |
2828 break; | |
2829 } | 2928 } |
2830 case OBJECT_SLOT: { | 2929 case OBJECT_SLOT: { |
2831 v->VisitPointer(reinterpret_cast<Object**>(addr)); | 2930 return callback(heap, reinterpret_cast<Object**>(addr)); |
2832 break; | |
2833 } | 2931 } |
2834 default: | 2932 case NUMBER_OF_SLOT_TYPES: |
2835 UNREACHABLE(); | 2933 UNREACHABLE(); |
2836 break; | 2934 break; |
2837 } | 2935 } |
2838 } | 2936 } |
2839 | 2937 |
2840 | 2938 |
2841 // Visitor for updating pointers from live objects in old spaces to new space. | 2939 // Visitor for updating pointers from live objects in old spaces to new space. |
2842 // It does not expect to encounter pointers to dead objects. | 2940 // It does not expect to encounter pointers to dead objects. |
2843 class PointersUpdatingVisitor : public ObjectVisitor { | 2941 class PointersUpdatingVisitor : public ObjectVisitor { |
2844 public: | 2942 public: |
2845 explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) {} | 2943 explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) {} |
2846 | 2944 |
2847 void VisitPointer(Object** p) override { UpdatePointer(p); } | 2945 void VisitPointer(Object** p) override { UpdateSlot(heap_, p); } |
2848 | 2946 |
2849 void VisitPointers(Object** start, Object** end) override { | 2947 void VisitPointers(Object** start, Object** end) override { |
2850 for (Object** p = start; p < end; p++) UpdatePointer(p); | 2948 for (Object** p = start; p < end; p++) UpdateSlot(heap_, p); |
2851 } | 2949 } |
2852 | 2950 |
2853 void VisitCell(RelocInfo* rinfo) override { | 2951 void VisitCell(RelocInfo* rinfo) override { |
2854 DCHECK(rinfo->rmode() == RelocInfo::CELL); | 2952 UpdateCell(heap_, rinfo, UpdateSlot); |
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 } | 2953 } |
2862 | 2954 |
2863 void VisitEmbeddedPointer(RelocInfo* rinfo) override { | 2955 void VisitEmbeddedPointer(RelocInfo* rinfo) override { |
2864 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 2956 UpdateEmbeddedPointer(heap_, 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 } | 2957 } |
2874 | 2958 |
2875 void VisitCodeTarget(RelocInfo* rinfo) override { | 2959 void VisitCodeTarget(RelocInfo* rinfo) override { |
2876 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 2960 UpdateCodeTarget(heap_, 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 } | 2961 } |
2894 | 2962 |
2895 void VisitCodeEntry(Address entry_address) override { | 2963 void VisitCodeEntry(Address entry_address) override { |
2896 Object* code = Code::GetObjectFromEntryAddress(entry_address); | 2964 UpdateCodeEntry(heap_, 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 } | 2965 } |
2904 | 2966 |
2905 void VisitDebugTarget(RelocInfo* rinfo) override { | 2967 void VisitDebugTarget(RelocInfo* rinfo) override { |
2906 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 2968 UpdateDebugTarget(heap_, 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 } | |
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 } | 2969 } |
2937 | 2970 |
2938 private: | 2971 private: |
2939 inline void UpdatePointer(Object** p) { UpdateSlot(heap_, p); } | |
2940 | |
2941 Heap* heap_; | 2972 Heap* heap_; |
2942 }; | 2973 }; |
2943 | 2974 |
2944 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, | 2975 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, |
2945 Object** p) { | 2976 Object** p) { |
2946 MapWord map_word = HeapObject::cast(*p)->map_word(); | 2977 MapWord map_word = HeapObject::cast(*p)->map_word(); |
2947 | 2978 |
2948 if (map_word.IsForwardingAddress()) { | 2979 if (map_word.IsForwardingAddress()) { |
2949 return String::cast(map_word.ToForwardingAddress()); | 2980 return String::cast(map_word.ToForwardingAddress()); |
2950 } | 2981 } |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3622 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { | 3653 if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) { |
3623 VerifyEvacuation(heap()); | 3654 VerifyEvacuation(heap()); |
3624 } | 3655 } |
3625 #endif | 3656 #endif |
3626 } | 3657 } |
3627 | 3658 |
3628 template <PointerDirection direction> | 3659 template <PointerDirection direction> |
3629 class PointerUpdateJobTraits { | 3660 class PointerUpdateJobTraits { |
3630 public: | 3661 public: |
3631 typedef int PerPageData; // Per page data is not used in this job. | 3662 typedef int PerPageData; // Per page data is not used in this job. |
3632 typedef PointersUpdatingVisitor* PerTaskData; | 3663 typedef int PerTaskData; // Per task data is not used in this job. |
3633 | 3664 |
3634 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, | 3665 static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk, |
3635 MemoryChunk* chunk, PerPageData) { | 3666 PerPageData) { |
3636 UpdateUntypedPointers(heap, chunk); | 3667 UpdateUntypedPointers(heap, chunk); |
3637 UpdateTypedPointers(heap, chunk, visitor); | 3668 UpdateTypedPointers(heap, chunk); |
3638 return true; | 3669 return true; |
3639 } | 3670 } |
3640 static const bool NeedSequentialFinalization = false; | 3671 static const bool NeedSequentialFinalization = false; |
3641 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { | 3672 static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) { |
3642 } | 3673 } |
3643 | 3674 |
3644 private: | 3675 private: |
3645 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { | 3676 static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) { |
3646 if (direction == OLD_TO_NEW) { | 3677 if (direction == OLD_TO_NEW) { |
3647 RememberedSet<OLD_TO_NEW>::IterateWithWrapper(heap, chunk, | 3678 RememberedSet<OLD_TO_NEW>::IterateWithWrapper(heap, chunk, |
3648 UpdateOldToNewSlot); | 3679 UpdateOldToNewSlot); |
3649 } else { | 3680 } else { |
3650 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [heap](Address slot) { | 3681 RememberedSet<OLD_TO_OLD>::Iterate(chunk, [heap](Address slot) { |
3651 PointersUpdatingVisitor::UpdateSlot(heap, | 3682 return UpdateSlot(heap, reinterpret_cast<Object**>(slot)); |
3652 reinterpret_cast<Object**>(slot)); | |
3653 return REMOVE_SLOT; | |
3654 }); | 3683 }); |
3655 } | 3684 } |
3656 } | 3685 } |
3657 | 3686 |
3658 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk, | 3687 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { |
3659 PointersUpdatingVisitor* visitor) { | |
3660 if (direction == OLD_TO_OLD) { | 3688 if (direction == OLD_TO_OLD) { |
3661 Isolate* isolate = heap->isolate(); | 3689 Isolate* isolate = heap->isolate(); |
3662 RememberedSet<OLD_TO_OLD>::IterateTyped( | 3690 RememberedSet<OLD_TO_OLD>::IterateTyped( |
3663 chunk, [isolate, visitor](SlotType type, Address slot) { | 3691 chunk, [isolate](SlotType type, Address slot) { |
3664 UpdateTypedSlot(isolate, visitor, type, slot); | 3692 return UpdateTypedSlot(isolate, type, slot, UpdateSlot); |
3665 return REMOVE_SLOT; | |
3666 }); | 3693 }); |
3667 } | 3694 } |
3668 } | 3695 } |
3669 | 3696 |
3670 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { | 3697 static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { |
3671 MapWord map_word = object->map_word(); | 3698 MapWord map_word = object->map_word(); |
3672 // There could still be stale pointers in large object space, map space, | 3699 // There could still be stale pointers in large object space, map space, |
3673 // and old space for pages that have been promoted. | 3700 // and old space for pages that have been promoted. |
3674 if (map_word.IsForwardingAddress()) { | 3701 if (map_word.IsForwardingAddress()) { |
3675 // Update the corresponding slot. | 3702 // Update the corresponding slot. |
3676 *address = map_word.ToForwardingAddress(); | 3703 *address = map_word.ToForwardingAddress(); |
3677 } | 3704 } |
3678 } | 3705 } |
3679 }; | 3706 }; |
3680 | 3707 |
3681 int NumberOfPointerUpdateTasks(int pages) { | 3708 int NumberOfPointerUpdateTasks(int pages) { |
3682 if (!FLAG_parallel_pointer_update) return 1; | 3709 if (!FLAG_parallel_pointer_update) return 1; |
3683 const int kMaxTasks = 4; | 3710 const int kMaxTasks = 4; |
3684 const int kPagesPerTask = 4; | 3711 const int kPagesPerTask = 4; |
3685 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); | 3712 return Min(kMaxTasks, (pages + kPagesPerTask - 1) / kPagesPerTask); |
3686 } | 3713 } |
3687 | 3714 |
3688 template <PointerDirection direction> | 3715 template <PointerDirection direction> |
3689 void UpdatePointersInParallel(Heap* heap) { | 3716 void UpdatePointersInParallel(Heap* heap) { |
3690 PageParallelJob<PointerUpdateJobTraits<direction> > job( | 3717 PageParallelJob<PointerUpdateJobTraits<direction> > job( |
3691 heap, heap->isolate()->cancelable_task_manager()); | 3718 heap, heap->isolate()->cancelable_task_manager()); |
3692 RememberedSet<direction>::IterateMemoryChunks( | 3719 RememberedSet<direction>::IterateMemoryChunks( |
3693 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); | 3720 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); |
3694 PointersUpdatingVisitor visitor(heap); | |
3695 int num_pages = job.NumberOfPages(); | 3721 int num_pages = job.NumberOfPages(); |
3696 int num_tasks = NumberOfPointerUpdateTasks(num_pages); | 3722 int num_tasks = NumberOfPointerUpdateTasks(num_pages); |
3697 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3723 job.Run(num_tasks, [](int i) { return 0; }); |
3698 } | 3724 } |
3699 | 3725 |
3700 class ToSpacePointerUpdateJobTraits { | 3726 class ToSpacePointerUpdateJobTraits { |
3701 public: | 3727 public: |
3702 typedef std::pair<Address, Address> PerPageData; | 3728 typedef std::pair<Address, Address> PerPageData; |
3703 typedef PointersUpdatingVisitor* PerTaskData; | 3729 typedef PointersUpdatingVisitor* PerTaskData; |
3704 | 3730 |
3705 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, | 3731 static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor, |
3706 MemoryChunk* chunk, PerPageData limits) { | 3732 MemoryChunk* chunk, PerPageData limits) { |
3707 for (Address cur = limits.first; cur < limits.second;) { | 3733 for (Address cur = limits.first; cur < limits.second;) { |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3999 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4025 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4000 if (Marking::IsBlack(mark_bit)) { | 4026 if (Marking::IsBlack(mark_bit)) { |
4001 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4027 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
4002 RecordRelocSlot(host, &rinfo, target); | 4028 RecordRelocSlot(host, &rinfo, target); |
4003 } | 4029 } |
4004 } | 4030 } |
4005 } | 4031 } |
4006 | 4032 |
4007 } // namespace internal | 4033 } // namespace internal |
4008 } // namespace v8 | 4034 } // namespace v8 |
OLD | NEW |