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 2805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2816 reinterpret_cast<base::AtomicWord*>(slot), | 2816 reinterpret_cast<base::AtomicWord*>(slot), |
2817 reinterpret_cast<base::AtomicWord>(obj), | 2817 reinterpret_cast<base::AtomicWord>(obj), |
2818 reinterpret_cast<base::AtomicWord>(target)); | 2818 reinterpret_cast<base::AtomicWord>(target)); |
2819 DCHECK(!heap_obj->GetHeap()->InFromSpace(target) && | 2819 DCHECK(!heap_obj->GetHeap()->InFromSpace(target) && |
2820 !MarkCompactCollector::IsOnEvacuationCandidate(target)); | 2820 !MarkCompactCollector::IsOnEvacuationCandidate(target)); |
2821 } | 2821 } |
2822 } | 2822 } |
2823 return REMOVE_SLOT; | 2823 return REMOVE_SLOT; |
2824 } | 2824 } |
2825 | 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) { | |
2902 switch (slot_type) { | |
2903 case CODE_TARGET_SLOT: { | |
2904 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); | |
2905 return UpdateCodeTarget(&rinfo, callback); | |
2906 } | |
2907 case CELL_TARGET_SLOT: { | |
2908 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); | |
2909 return UpdateCell(&rinfo, callback); | |
2910 } | |
2911 case CODE_ENTRY_SLOT: { | |
2912 return UpdateCodeEntry(addr, callback); | |
2913 } | |
2914 case DEBUG_TARGET_SLOT: { | |
2915 RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0, | |
2916 NULL); | |
2917 if (rinfo.IsPatchedDebugBreakSlotSequence()) { | |
2918 return UpdateDebugTarget(&rinfo, callback); | |
2919 } | |
2920 return REMOVE_SLOT; | |
2921 } | |
2922 case EMBEDDED_OBJECT_SLOT: { | |
2923 RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL); | |
2924 return UpdateEmbeddedPointer(&rinfo, callback); | |
2925 } | |
2926 case OBJECT_SLOT: { | |
2927 return callback(reinterpret_cast<Object**>(addr)); | |
2928 } | |
2929 case NUMBER_OF_SLOT_TYPES: | |
2930 break; | |
2931 } | |
2932 UNREACHABLE(); | |
2933 return REMOVE_SLOT; | |
2934 } | |
2935 | |
2936 | |
2937 // Visitor for updating pointers from live objects in old spaces to new space. | 2826 // Visitor for updating pointers from live objects in old spaces to new space. |
2938 // It does not expect to encounter pointers to dead objects. | 2827 // It does not expect to encounter pointers to dead objects. |
2939 class PointersUpdatingVisitor : public ObjectVisitor { | 2828 class PointersUpdatingVisitor : public ObjectVisitor { |
2940 public: | 2829 public: |
2941 void VisitPointer(Object** p) override { UpdateSlot(p); } | 2830 void VisitPointer(Object** p) override { UpdateSlot(p); } |
2942 | 2831 |
2943 void VisitPointers(Object** start, Object** end) override { | 2832 void VisitPointers(Object** start, Object** end) override { |
2944 for (Object** p = start; p < end; p++) UpdateSlot(p); | 2833 for (Object** p = start; p < end; p++) UpdateSlot(p); |
2945 } | 2834 } |
2946 | 2835 |
2947 void VisitCell(RelocInfo* rinfo) override { UpdateCell(rinfo, UpdateSlot); } | 2836 void VisitCell(RelocInfo* rinfo) override { |
2837 UpdateTypedSlotHelper::UpdateCell(rinfo, UpdateSlot); | |
2838 } | |
2948 | 2839 |
2949 void VisitEmbeddedPointer(RelocInfo* rinfo) override { | 2840 void VisitEmbeddedPointer(RelocInfo* rinfo) override { |
2950 UpdateEmbeddedPointer(rinfo, UpdateSlot); | 2841 UpdateTypedSlotHelper::UpdateEmbeddedPointer(rinfo, UpdateSlot); |
2951 } | 2842 } |
2952 | 2843 |
2953 void VisitCodeTarget(RelocInfo* rinfo) override { | 2844 void VisitCodeTarget(RelocInfo* rinfo) override { |
2954 UpdateCodeTarget(rinfo, UpdateSlot); | 2845 UpdateTypedSlotHelper::UpdateCodeTarget(rinfo, UpdateSlot); |
2955 } | 2846 } |
2956 | 2847 |
2957 void VisitCodeEntry(Address entry_address) override { | 2848 void VisitCodeEntry(Address entry_address) override { |
2958 UpdateCodeEntry(entry_address, UpdateSlot); | 2849 UpdateTypedSlotHelper::UpdateCodeEntry(entry_address, UpdateSlot); |
2959 } | 2850 } |
2960 | 2851 |
2961 void VisitDebugTarget(RelocInfo* rinfo) override { | 2852 void VisitDebugTarget(RelocInfo* rinfo) override { |
2962 UpdateDebugTarget(rinfo, UpdateSlot); | 2853 UpdateTypedSlotHelper::UpdateDebugTarget(rinfo, UpdateSlot); |
2963 } | 2854 } |
2964 }; | 2855 }; |
2965 | 2856 |
2966 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, | 2857 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, |
2967 Object** p) { | 2858 Object** p) { |
2968 MapWord map_word = HeapObject::cast(*p)->map_word(); | 2859 MapWord map_word = HeapObject::cast(*p)->map_word(); |
2969 | 2860 |
2970 if (map_word.IsForwardingAddress()) { | 2861 if (map_word.IsForwardingAddress()) { |
2971 return String::cast(map_word.ToForwardingAddress()); | 2862 return String::cast(map_word.ToForwardingAddress()); |
2972 } | 2863 } |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3502 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3393 MarkBit mark_bit = Marking::MarkBitFrom(code); |
3503 if (Marking::IsWhite(mark_bit)) return; | 3394 if (Marking::IsWhite(mark_bit)) return; |
3504 | 3395 |
3505 // Ignore all slots that might have been recorded in the body of the | 3396 // Ignore all slots that might have been recorded in the body of the |
3506 // deoptimized code object. Assumption: no slots will be recorded for | 3397 // deoptimized code object. Assumption: no slots will be recorded for |
3507 // this object after invalidating it. | 3398 // this object after invalidating it. |
3508 Page* page = Page::FromAddress(code->address()); | 3399 Page* page = Page::FromAddress(code->address()); |
3509 Address start = code->instruction_start(); | 3400 Address start = code->instruction_start(); |
3510 Address end = code->address() + code->Size(); | 3401 Address end = code->address() + code->Size(); |
3511 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); | 3402 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); |
3403 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); | |
3512 } | 3404 } |
3513 } | 3405 } |
3514 | 3406 |
3515 | 3407 |
3516 // Return true if the given code is deoptimized or will be deoptimized. | 3408 // Return true if the given code is deoptimized or will be deoptimized. |
3517 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 3409 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { |
3518 return code->is_optimized_code() && code->marked_for_deoptimization(); | 3410 return code->is_optimized_code() && code->marked_for_deoptimization(); |
3519 } | 3411 } |
3520 | 3412 |
3521 | 3413 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3674 return UpdateSlot(reinterpret_cast<Object**>(slot)); | 3566 return UpdateSlot(reinterpret_cast<Object**>(slot)); |
3675 }); | 3567 }); |
3676 } | 3568 } |
3677 } | 3569 } |
3678 | 3570 |
3679 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { | 3571 static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) { |
3680 if (direction == OLD_TO_OLD) { | 3572 if (direction == OLD_TO_OLD) { |
3681 Isolate* isolate = heap->isolate(); | 3573 Isolate* isolate = heap->isolate(); |
3682 RememberedSet<OLD_TO_OLD>::IterateTyped( | 3574 RememberedSet<OLD_TO_OLD>::IterateTyped( |
3683 chunk, [isolate](SlotType type, Address slot) { | 3575 chunk, [isolate](SlotType type, Address slot) { |
3684 return UpdateTypedSlot(isolate, type, slot, UpdateSlot); | 3576 return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, type, slot, |
3577 UpdateSlot); | |
3578 }); | |
3579 } else { | |
3580 Isolate* isolate = heap->isolate(); | |
3581 RememberedSet<OLD_TO_NEW>::IterateTyped( | |
3582 chunk, [isolate, heap](SlotType type, Address slot) { | |
3583 return UpdateTypedSlotHelper::UpdateTypedSlot( | |
3584 isolate, type, slot, [heap](Object** slot) { | |
3585 return CheckAndUpdateOldToNewSlot( | |
ulan
2016/05/23 08:40:08
For separate CL: We would need to force promotion
| |
3586 heap, reinterpret_cast<Address>(slot)); | |
3587 }); | |
3685 }); | 3588 }); |
3686 } | 3589 } |
3687 } | 3590 } |
3688 | 3591 |
3689 static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap, | 3592 static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap, |
3690 Address slot_address) { | 3593 Address slot_address) { |
3691 Object** slot = reinterpret_cast<Object**>(slot_address); | 3594 Object** slot = reinterpret_cast<Object**>(slot_address); |
3692 if (heap->InFromSpace(*slot)) { | 3595 if (heap->InFromSpace(*slot)) { |
3693 HeapObject* heap_object = reinterpret_cast<HeapObject*>(*slot); | 3596 HeapObject* heap_object = reinterpret_cast<HeapObject*>(*slot); |
3694 DCHECK(heap_object->IsHeapObject()); | 3597 DCHECK(heap_object->IsHeapObject()); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4033 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3936 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4034 if (Marking::IsBlack(mark_bit)) { | 3937 if (Marking::IsBlack(mark_bit)) { |
4035 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3938 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
4036 RecordRelocSlot(host, &rinfo, target); | 3939 RecordRelocSlot(host, &rinfo, target); |
4037 } | 3940 } |
4038 } | 3941 } |
4039 } | 3942 } |
4040 | 3943 |
4041 } // namespace internal | 3944 } // namespace internal |
4042 } // namespace v8 | 3945 } // namespace v8 |
OLD | NEW |