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 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 |