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 1545 matching lines...) Loading... |
1556 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), | 1556 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), |
1557 nullptr, CODE_ENTRY_SLOT, | 1557 nullptr, CODE_ENTRY_SLOT, |
1558 code_entry_slot); | 1558 code_entry_slot); |
1559 } | 1559 } |
1560 } | 1560 } |
1561 | 1561 |
1562 inline void VisitCodeTarget(RelocInfo* rinfo) final { | 1562 inline void VisitCodeTarget(RelocInfo* rinfo) final { |
1563 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 1563 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
1564 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1564 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
1565 Code* host = rinfo->host(); | 1565 Code* host = rinfo->host(); |
| 1566 collector_->RecordRelocSlotToNewSpace(host, rinfo, target); |
1566 collector_->RecordRelocSlot(host, rinfo, target); | 1567 collector_->RecordRelocSlot(host, rinfo, target); |
1567 } | 1568 } |
1568 | 1569 |
1569 inline void VisitDebugTarget(RelocInfo* rinfo) final { | 1570 inline void VisitDebugTarget(RelocInfo* rinfo) final { |
1570 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 1571 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
1571 rinfo->IsPatchedDebugBreakSlotSequence()); | 1572 rinfo->IsPatchedDebugBreakSlotSequence()); |
1572 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | 1573 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); |
1573 Code* host = rinfo->host(); | 1574 Code* host = rinfo->host(); |
| 1575 collector_->RecordRelocSlotToNewSpace(host, rinfo, target); |
1574 collector_->RecordRelocSlot(host, rinfo, target); | 1576 collector_->RecordRelocSlot(host, rinfo, target); |
1575 } | 1577 } |
1576 | 1578 |
1577 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { | 1579 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { |
1578 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 1580 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
1579 HeapObject* object = HeapObject::cast(rinfo->target_object()); | 1581 HeapObject* object = HeapObject::cast(rinfo->target_object()); |
1580 Code* host = rinfo->host(); | 1582 Code* host = rinfo->host(); |
| 1583 collector_->RecordRelocSlotToNewSpace(host, rinfo, object); |
1581 collector_->RecordRelocSlot(host, rinfo, object); | 1584 collector_->RecordRelocSlot(host, rinfo, object); |
1582 } | 1585 } |
1583 | 1586 |
1584 inline void VisitCell(RelocInfo* rinfo) final { | 1587 inline void VisitCell(RelocInfo* rinfo) final { |
1585 DCHECK(rinfo->rmode() == RelocInfo::CELL); | 1588 DCHECK(rinfo->rmode() == RelocInfo::CELL); |
1586 Cell* cell = rinfo->target_cell(); | 1589 Cell* cell = rinfo->target_cell(); |
1587 Code* host = rinfo->host(); | 1590 Code* host = rinfo->host(); |
| 1591 collector_->RecordRelocSlotToNewSpace(host, rinfo, cell); |
1588 collector_->RecordRelocSlot(host, rinfo, cell); | 1592 collector_->RecordRelocSlot(host, rinfo, cell); |
1589 } | 1593 } |
1590 | 1594 |
1591 // Entries that will never move. | 1595 // Entries that will never move. |
1592 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { | 1596 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { |
1593 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 1597 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); |
1594 Code* stub = rinfo->code_age_stub(); | 1598 Code* stub = rinfo->code_age_stub(); |
1595 USE(stub); | 1599 USE(stub); |
1596 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); | 1600 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); |
1597 } | 1601 } |
(...skipping 843 matching lines...) Loading... |
2441 DependentCode* list_head) { | 2445 DependentCode* list_head) { |
2442 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 2446 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); |
2443 Isolate* isolate = this->isolate(); | 2447 Isolate* isolate = this->isolate(); |
2444 DependentCode* current = list_head; | 2448 DependentCode* current = list_head; |
2445 while (current->length() > 0) { | 2449 while (current->length() > 0) { |
2446 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2450 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( |
2447 isolate, DependentCode::kWeakCodeGroup); | 2451 isolate, DependentCode::kWeakCodeGroup); |
2448 current = current->next_link(); | 2452 current = current->next_link(); |
2449 } | 2453 } |
2450 | 2454 |
| 2455 { |
| 2456 ArrayList* list = heap_->weak_code_to_new_space_ref_list(); |
| 2457 int counter = 0; |
| 2458 for (int i = 0; i < list->Length(); i += 2) { |
| 2459 WeakCell* obj = WeakCell::cast(list->Get(i)); |
| 2460 WeakCell* dep = WeakCell::cast(list->Get(i + 1)); |
| 2461 if (obj->cleared() || dep->cleared()) { |
| 2462 if (!dep->cleared()) { |
| 2463 Code* code = Code::cast(dep->value()); |
| 2464 if (!code->marked_for_deoptimization()) { |
| 2465 DependentCode::SetMarkedForDeoptimization( |
| 2466 code, DependentCode::DependencyGroup::kWeakCodeGroup); |
| 2467 code->InvalidateEmbeddedObjects(); |
| 2468 have_code_to_deoptimize_ = true; |
| 2469 } |
| 2470 } |
| 2471 } else { |
| 2472 list->Set(counter, obj, SKIP_WRITE_BARRIER); |
| 2473 RecordSlot(list, list->Slot(counter), obj); |
| 2474 counter++; |
| 2475 list->Set(counter, dep, SKIP_WRITE_BARRIER); |
| 2476 RecordSlot(list, list->Slot(counter), dep); |
| 2477 counter++; |
| 2478 } |
| 2479 } |
| 2480 } |
| 2481 |
2451 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2482 WeakHashTable* table = heap_->weak_object_to_code_table(); |
2452 uint32_t capacity = table->Capacity(); | 2483 uint32_t capacity = table->Capacity(); |
2453 for (uint32_t i = 0; i < capacity; i++) { | 2484 for (uint32_t i = 0; i < capacity; i++) { |
2454 uint32_t key_index = table->EntryToIndex(i); | 2485 uint32_t key_index = table->EntryToIndex(i); |
2455 Object* key = table->get(key_index); | 2486 Object* key = table->get(key_index); |
2456 if (!table->IsKey(isolate, key)) continue; | 2487 if (!table->IsKey(isolate, key)) continue; |
2457 uint32_t value_index = table->EntryToValueIndex(i); | 2488 uint32_t value_index = table->EntryToValueIndex(i); |
2458 Object* value = table->get(value_index); | 2489 Object* value = table->get(value_index); |
2459 DCHECK(key->IsWeakCell()); | 2490 DCHECK(key->IsWeakCell()); |
2460 if (WeakCell::cast(key)->cleared()) { | 2491 if (WeakCell::cast(key)->cleared()) { |
(...skipping 338 matching lines...) Loading... |
2799 return CELL_TARGET_SLOT; | 2830 return CELL_TARGET_SLOT; |
2800 } else if (RelocInfo::IsEmbeddedObject(rmode)) { | 2831 } else if (RelocInfo::IsEmbeddedObject(rmode)) { |
2801 return EMBEDDED_OBJECT_SLOT; | 2832 return EMBEDDED_OBJECT_SLOT; |
2802 } else if (RelocInfo::IsDebugBreakSlot(rmode)) { | 2833 } else if (RelocInfo::IsDebugBreakSlot(rmode)) { |
2803 return DEBUG_TARGET_SLOT; | 2834 return DEBUG_TARGET_SLOT; |
2804 } | 2835 } |
2805 UNREACHABLE(); | 2836 UNREACHABLE(); |
2806 return NUMBER_OF_SLOT_TYPES; | 2837 return NUMBER_OF_SLOT_TYPES; |
2807 } | 2838 } |
2808 | 2839 |
| 2840 namespace { |
| 2841 void GetAddressAndSlotType(RelocInfo::Mode rmode, RelocInfo* rinfo, |
| 2842 Address& addr, SlotType& slot_type) { |
| 2843 addr = rinfo->pc(); |
| 2844 slot_type = SlotTypeForRMode(rmode); |
| 2845 if (rinfo->IsInConstantPool()) { |
| 2846 addr = rinfo->constant_pool_entry_address(); |
| 2847 if (RelocInfo::IsCodeTarget(rmode)) { |
| 2848 slot_type = CODE_ENTRY_SLOT; |
| 2849 } else { |
| 2850 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); |
| 2851 slot_type = OBJECT_SLOT; |
| 2852 } |
| 2853 } |
| 2854 } |
| 2855 } // namespace |
| 2856 |
| 2857 void MarkCompactCollector::RecordRelocSlotToNewSpace(Code* host, |
| 2858 RelocInfo* rinfo, |
| 2859 Object* target) { |
| 2860 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); |
| 2861 RelocInfo::Mode rmode = rinfo->rmode(); |
| 2862 if (heap()->InNewSpace(target)) { |
| 2863 Address addr; |
| 2864 SlotType slot_type; |
| 2865 GetAddressAndSlotType(rmode, rinfo, addr, slot_type); |
| 2866 RememberedSet<OLD_TO_NEW>::InsertTyped( |
| 2867 source_page, reinterpret_cast<Address>(host), slot_type, addr); |
| 2868 } |
| 2869 } |
| 2870 |
2809 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, | 2871 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, |
2810 Object* target) { | 2872 Object* target) { |
2811 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | 2873 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); |
2812 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); | 2874 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); |
2813 RelocInfo::Mode rmode = rinfo->rmode(); | 2875 RelocInfo::Mode rmode = rinfo->rmode(); |
2814 if (target_page->IsEvacuationCandidate() && | 2876 if (target_page->IsEvacuationCandidate() && |
2815 (rinfo->host() == NULL || | 2877 (rinfo->host() == NULL || |
2816 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { | 2878 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { |
2817 Address addr = rinfo->pc(); | 2879 Address addr; |
2818 SlotType slot_type = SlotTypeForRMode(rmode); | 2880 SlotType slot_type; |
2819 if (rinfo->IsInConstantPool()) { | 2881 GetAddressAndSlotType(rmode, rinfo, addr, slot_type); |
2820 addr = rinfo->constant_pool_entry_address(); | |
2821 if (RelocInfo::IsCodeTarget(rmode)) { | |
2822 slot_type = CODE_ENTRY_SLOT; | |
2823 } else { | |
2824 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); | |
2825 slot_type = OBJECT_SLOT; | |
2826 } | |
2827 } | |
2828 RememberedSet<OLD_TO_OLD>::InsertTyped( | 2882 RememberedSet<OLD_TO_OLD>::InsertTyped( |
2829 source_page, reinterpret_cast<Address>(host), slot_type, addr); | 2883 source_page, reinterpret_cast<Address>(host), slot_type, addr); |
2830 } | 2884 } |
2831 } | 2885 } |
2832 | 2886 |
2833 static inline SlotCallbackResult UpdateSlot(Object** slot) { | 2887 static inline SlotCallbackResult UpdateSlot(Object** slot) { |
2834 Object* obj = reinterpret_cast<Object*>( | 2888 Object* obj = reinterpret_cast<Object*>( |
2835 base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot))); | 2889 base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot))); |
2836 | 2890 |
2837 if (obj->IsHeapObject()) { | 2891 if (obj->IsHeapObject()) { |
(...skipping 587 matching lines...) Loading... |
3425 memset(free_start, 0xcc, size); | 3479 memset(free_start, 0xcc, size); |
3426 } | 3480 } |
3427 freed_bytes = space->UnaccountedFree(free_start, size); | 3481 freed_bytes = space->UnaccountedFree(free_start, size); |
3428 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3482 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
3429 } | 3483 } |
3430 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3484 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
3431 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3485 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
3432 } | 3486 } |
3433 | 3487 |
3434 void MarkCompactCollector::InvalidateCode(Code* code) { | 3488 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3489 Page* page = Page::FromAddress(code->address()); |
| 3490 Address start = code->instruction_start(); |
| 3491 Address end = code->address() + code->Size(); |
| 3492 |
| 3493 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); |
| 3494 |
3435 if (heap_->incremental_marking()->IsCompacting() && | 3495 if (heap_->incremental_marking()->IsCompacting() && |
3436 !ShouldSkipEvacuationSlotRecording(code)) { | 3496 !ShouldSkipEvacuationSlotRecording(code)) { |
3437 DCHECK(compacting_); | 3497 DCHECK(compacting_); |
3438 | 3498 |
3439 // If the object is white than no slots were recorded on it yet. | 3499 // If the object is white than no slots were recorded on it yet. |
3440 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3500 MarkBit mark_bit = Marking::MarkBitFrom(code); |
3441 if (Marking::IsWhite(mark_bit)) return; | 3501 if (Marking::IsWhite(mark_bit)) return; |
3442 | 3502 |
3443 // Ignore all slots that might have been recorded in the body of the | 3503 // Ignore all slots that might have been recorded in the body of the |
3444 // deoptimized code object. Assumption: no slots will be recorded for | 3504 // deoptimized code object. Assumption: no slots will be recorded for |
3445 // this object after invalidating it. | 3505 // this object after invalidating it. |
3446 Page* page = Page::FromAddress(code->address()); | |
3447 Address start = code->instruction_start(); | |
3448 Address end = code->address() + code->Size(); | |
3449 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); | 3506 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); |
3450 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); | |
3451 } | 3507 } |
3452 } | 3508 } |
3453 | 3509 |
3454 | 3510 |
3455 // Return true if the given code is deoptimized or will be deoptimized. | 3511 // Return true if the given code is deoptimized or will be deoptimized. |
3456 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 3512 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { |
3457 return code->is_optimized_code() && code->marked_for_deoptimization(); | 3513 return code->is_optimized_code() && code->marked_for_deoptimization(); |
3458 } | 3514 } |
3459 | 3515 |
3460 | 3516 |
(...skipping 525 matching lines...) Loading... |
3986 | 4042 |
3987 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { | 4043 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { |
3988 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); | 4044 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); |
3989 if (is_compacting()) { | 4045 if (is_compacting()) { |
3990 Code* host = | 4046 Code* host = |
3991 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( | 4047 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( |
3992 pc); | 4048 pc); |
3993 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4049 MarkBit mark_bit = Marking::MarkBitFrom(host); |
3994 if (Marking::IsBlack(mark_bit)) { | 4050 if (Marking::IsBlack(mark_bit)) { |
3995 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4051 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 4052 RecordRelocSlotToNewSpace(host, &rinfo, target); |
3996 RecordRelocSlot(host, &rinfo, target); | 4053 RecordRelocSlot(host, &rinfo, target); |
3997 } | 4054 } |
3998 } | 4055 } |
3999 } | 4056 } |
4000 | 4057 |
4001 } // namespace internal | 4058 } // namespace internal |
4002 } // namespace v8 | 4059 } // namespace v8 |
OLD | NEW |