Chromium Code Reviews| 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 |