| 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 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), | 1562 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), |
| 1563 nullptr, CODE_ENTRY_SLOT, | 1563 nullptr, CODE_ENTRY_SLOT, |
| 1564 code_entry_slot); | 1564 code_entry_slot); |
| 1565 } | 1565 } |
| 1566 } | 1566 } |
| 1567 | 1567 |
| 1568 inline void VisitCodeTarget(RelocInfo* rinfo) final { | 1568 inline void VisitCodeTarget(RelocInfo* rinfo) final { |
| 1569 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 1569 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 1570 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1570 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 1571 Code* host = rinfo->host(); | 1571 Code* host = rinfo->host(); |
| 1572 // The target is always in old space, we don't have to record the slot in | |
| 1573 // the old-to-new remembered set. | |
| 1574 DCHECK(!collector_->heap()->InNewSpace(target)); | |
| 1575 collector_->RecordRelocSlot(host, rinfo, target); | 1572 collector_->RecordRelocSlot(host, rinfo, target); |
| 1576 } | 1573 } |
| 1577 | 1574 |
| 1578 inline void VisitDebugTarget(RelocInfo* rinfo) final { | 1575 inline void VisitDebugTarget(RelocInfo* rinfo) final { |
| 1579 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 1576 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 1580 rinfo->IsPatchedDebugBreakSlotSequence()); | 1577 rinfo->IsPatchedDebugBreakSlotSequence()); |
| 1581 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | 1578 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); |
| 1582 Code* host = rinfo->host(); | 1579 Code* host = rinfo->host(); |
| 1583 // The target is always in old space, we don't have to record the slot in | |
| 1584 // the old-to-new remembered set. | |
| 1585 DCHECK(!collector_->heap()->InNewSpace(target)); | |
| 1586 collector_->RecordRelocSlot(host, rinfo, target); | 1580 collector_->RecordRelocSlot(host, rinfo, target); |
| 1587 } | 1581 } |
| 1588 | 1582 |
| 1589 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { | 1583 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { |
| 1590 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 1584 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 1591 HeapObject* object = HeapObject::cast(rinfo->target_object()); | 1585 HeapObject* object = HeapObject::cast(rinfo->target_object()); |
| 1592 Code* host = rinfo->host(); | 1586 Code* host = rinfo->host(); |
| 1593 collector_->heap()->RecordWriteIntoCode(host, rinfo, object); | |
| 1594 collector_->RecordRelocSlot(host, rinfo, object); | 1587 collector_->RecordRelocSlot(host, rinfo, object); |
| 1595 } | 1588 } |
| 1596 | 1589 |
| 1597 inline void VisitCell(RelocInfo* rinfo) final { | 1590 inline void VisitCell(RelocInfo* rinfo) final { |
| 1598 DCHECK(rinfo->rmode() == RelocInfo::CELL); | 1591 DCHECK(rinfo->rmode() == RelocInfo::CELL); |
| 1599 Cell* cell = rinfo->target_cell(); | 1592 Cell* cell = rinfo->target_cell(); |
| 1600 Code* host = rinfo->host(); | 1593 Code* host = rinfo->host(); |
| 1601 // The cell is always in old space, we don't have to record the slot in | |
| 1602 // the old-to-new remembered set. | |
| 1603 DCHECK(!collector_->heap()->InNewSpace(cell)); | |
| 1604 collector_->RecordRelocSlot(host, rinfo, cell); | 1594 collector_->RecordRelocSlot(host, rinfo, cell); |
| 1605 } | 1595 } |
| 1606 | 1596 |
| 1607 // Entries that will never move. | 1597 // Entries that will never move. |
| 1608 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { | 1598 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { |
| 1609 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 1599 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); |
| 1610 Code* stub = rinfo->code_age_stub(); | 1600 Code* stub = rinfo->code_age_stub(); |
| 1611 USE(stub); | 1601 USE(stub); |
| 1612 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); | 1602 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); |
| 1613 } | 1603 } |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2459 DependentCode* list_head) { | 2449 DependentCode* list_head) { |
| 2460 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 2450 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); |
| 2461 Isolate* isolate = this->isolate(); | 2451 Isolate* isolate = this->isolate(); |
| 2462 DependentCode* current = list_head; | 2452 DependentCode* current = list_head; |
| 2463 while (current->length() > 0) { | 2453 while (current->length() > 0) { |
| 2464 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2454 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( |
| 2465 isolate, DependentCode::kWeakCodeGroup); | 2455 isolate, DependentCode::kWeakCodeGroup); |
| 2466 current = current->next_link(); | 2456 current = current->next_link(); |
| 2467 } | 2457 } |
| 2468 | 2458 |
| 2469 { | |
| 2470 ArrayList* list = heap_->weak_new_space_object_to_code_list(); | |
| 2471 int counter = 0; | |
| 2472 for (int i = 0; i < list->Length(); i += 2) { | |
| 2473 WeakCell* obj = WeakCell::cast(list->Get(i)); | |
| 2474 WeakCell* dep = WeakCell::cast(list->Get(i + 1)); | |
| 2475 if (obj->cleared() || dep->cleared()) { | |
| 2476 if (!dep->cleared()) { | |
| 2477 Code* code = Code::cast(dep->value()); | |
| 2478 if (!code->marked_for_deoptimization()) { | |
| 2479 DependentCode::SetMarkedForDeoptimization( | |
| 2480 code, DependentCode::DependencyGroup::kWeakCodeGroup); | |
| 2481 code->InvalidateEmbeddedObjects(); | |
| 2482 have_code_to_deoptimize_ = true; | |
| 2483 } | |
| 2484 } | |
| 2485 } else { | |
| 2486 // We record the slot manually because marking is finished at this | |
| 2487 // point and the write barrier would bailout. | |
| 2488 list->Set(counter, obj, SKIP_WRITE_BARRIER); | |
| 2489 RecordSlot(list, list->Slot(counter), obj); | |
| 2490 counter++; | |
| 2491 list->Set(counter, dep, SKIP_WRITE_BARRIER); | |
| 2492 RecordSlot(list, list->Slot(counter), dep); | |
| 2493 counter++; | |
| 2494 } | |
| 2495 } | |
| 2496 } | |
| 2497 | |
| 2498 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2459 WeakHashTable* table = heap_->weak_object_to_code_table(); |
| 2499 uint32_t capacity = table->Capacity(); | 2460 uint32_t capacity = table->Capacity(); |
| 2500 for (uint32_t i = 0; i < capacity; i++) { | 2461 for (uint32_t i = 0; i < capacity; i++) { |
| 2501 uint32_t key_index = table->EntryToIndex(i); | 2462 uint32_t key_index = table->EntryToIndex(i); |
| 2502 Object* key = table->get(key_index); | 2463 Object* key = table->get(key_index); |
| 2503 if (!table->IsKey(isolate, key)) continue; | 2464 if (!table->IsKey(isolate, key)) continue; |
| 2504 uint32_t value_index = table->EntryToValueIndex(i); | 2465 uint32_t value_index = table->EntryToValueIndex(i); |
| 2505 Object* value = table->get(value_index); | 2466 Object* value = table->get(value_index); |
| 2506 DCHECK(key->IsWeakCell()); | 2467 DCHECK(key->IsWeakCell()); |
| 2507 if (WeakCell::cast(key)->cleared()) { | 2468 if (WeakCell::cast(key)->cleared()) { |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2832 HeapObject* undefined = heap()->undefined_value(); | 2793 HeapObject* undefined = heap()->undefined_value(); |
| 2833 Object* obj = heap()->encountered_transition_arrays(); | 2794 Object* obj = heap()->encountered_transition_arrays(); |
| 2834 while (obj != Smi::FromInt(0)) { | 2795 while (obj != Smi::FromInt(0)) { |
| 2835 TransitionArray* array = TransitionArray::cast(obj); | 2796 TransitionArray* array = TransitionArray::cast(obj); |
| 2836 obj = array->next_link(); | 2797 obj = array->next_link(); |
| 2837 array->set_next_link(undefined, SKIP_WRITE_BARRIER); | 2798 array->set_next_link(undefined, SKIP_WRITE_BARRIER); |
| 2838 } | 2799 } |
| 2839 heap()->set_encountered_transition_arrays(Smi::FromInt(0)); | 2800 heap()->set_encountered_transition_arrays(Smi::FromInt(0)); |
| 2840 } | 2801 } |
| 2841 | 2802 |
| 2803 static inline SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { |
| 2804 if (RelocInfo::IsCodeTarget(rmode)) { |
| 2805 return CODE_TARGET_SLOT; |
| 2806 } else if (RelocInfo::IsCell(rmode)) { |
| 2807 return CELL_TARGET_SLOT; |
| 2808 } else if (RelocInfo::IsEmbeddedObject(rmode)) { |
| 2809 return EMBEDDED_OBJECT_SLOT; |
| 2810 } else if (RelocInfo::IsDebugBreakSlot(rmode)) { |
| 2811 return DEBUG_TARGET_SLOT; |
| 2812 } |
| 2813 UNREACHABLE(); |
| 2814 return NUMBER_OF_SLOT_TYPES; |
| 2815 } |
| 2816 |
| 2842 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, | 2817 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, |
| 2843 Object* target) { | 2818 Object* target) { |
| 2844 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | 2819 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); |
| 2845 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); | 2820 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); |
| 2821 RelocInfo::Mode rmode = rinfo->rmode(); |
| 2846 if (target_page->IsEvacuationCandidate() && | 2822 if (target_page->IsEvacuationCandidate() && |
| 2847 (rinfo->host() == NULL || | 2823 (rinfo->host() == NULL || |
| 2848 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { | 2824 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { |
| 2849 RelocInfo::Mode rmode = rinfo->rmode(); | |
| 2850 Address addr = rinfo->pc(); | 2825 Address addr = rinfo->pc(); |
| 2851 SlotType slot_type = SlotTypeForRelocInfoMode(rmode); | 2826 SlotType slot_type = SlotTypeForRMode(rmode); |
| 2852 if (rinfo->IsInConstantPool()) { | 2827 if (rinfo->IsInConstantPool()) { |
| 2853 addr = rinfo->constant_pool_entry_address(); | 2828 addr = rinfo->constant_pool_entry_address(); |
| 2854 if (RelocInfo::IsCodeTarget(rmode)) { | 2829 if (RelocInfo::IsCodeTarget(rmode)) { |
| 2855 slot_type = CODE_ENTRY_SLOT; | 2830 slot_type = CODE_ENTRY_SLOT; |
| 2856 } else { | 2831 } else { |
| 2857 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); | 2832 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); |
| 2858 slot_type = OBJECT_SLOT; | 2833 slot_type = OBJECT_SLOT; |
| 2859 } | 2834 } |
| 2860 } | 2835 } |
| 2861 RememberedSet<OLD_TO_OLD>::InsertTyped( | 2836 RememberedSet<OLD_TO_OLD>::InsertTyped( |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3465 p->heap()->CreateFillerObjectAt(free_start, size, | 3440 p->heap()->CreateFillerObjectAt(free_start, size, |
| 3466 ClearRecordedSlots::kNo); | 3441 ClearRecordedSlots::kNo); |
| 3467 } | 3442 } |
| 3468 } | 3443 } |
| 3469 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3444 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3470 if (free_list_mode == IGNORE_FREE_LIST) return 0; | 3445 if (free_list_mode == IGNORE_FREE_LIST) return 0; |
| 3471 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3446 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
| 3472 } | 3447 } |
| 3473 | 3448 |
| 3474 void MarkCompactCollector::InvalidateCode(Code* code) { | 3449 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3475 Page* page = Page::FromAddress(code->address()); | |
| 3476 Address start = code->instruction_start(); | |
| 3477 Address end = code->address() + code->Size(); | |
| 3478 | |
| 3479 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); | |
| 3480 | |
| 3481 if (heap_->incremental_marking()->IsCompacting() && | 3450 if (heap_->incremental_marking()->IsCompacting() && |
| 3482 !ShouldSkipEvacuationSlotRecording(code)) { | 3451 !ShouldSkipEvacuationSlotRecording(code)) { |
| 3483 DCHECK(compacting_); | 3452 DCHECK(compacting_); |
| 3484 | 3453 |
| 3485 // If the object is white than no slots were recorded on it yet. | 3454 // If the object is white than no slots were recorded on it yet. |
| 3486 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3455 MarkBit mark_bit = Marking::MarkBitFrom(code); |
| 3487 if (Marking::IsWhite(mark_bit)) return; | 3456 if (Marking::IsWhite(mark_bit)) return; |
| 3488 | 3457 |
| 3489 // Ignore all slots that might have been recorded in the body of the | 3458 // Ignore all slots that might have been recorded in the body of the |
| 3490 // deoptimized code object. Assumption: no slots will be recorded for | 3459 // deoptimized code object. Assumption: no slots will be recorded for |
| 3491 // this object after invalidating it. | 3460 // this object after invalidating it. |
| 3461 Page* page = Page::FromAddress(code->address()); |
| 3462 Address start = code->instruction_start(); |
| 3463 Address end = code->address() + code->Size(); |
| 3492 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); | 3464 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); |
| 3465 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); |
| 3493 } | 3466 } |
| 3494 } | 3467 } |
| 3495 | 3468 |
| 3496 | 3469 |
| 3497 // Return true if the given code is deoptimized or will be deoptimized. | 3470 // Return true if the given code is deoptimized or will be deoptimized. |
| 3498 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 3471 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { |
| 3499 return code->is_optimized_code() && code->marked_for_deoptimization(); | 3472 return code->is_optimized_code() && code->marked_for_deoptimization(); |
| 3500 } | 3473 } |
| 3501 | 3474 |
| 3502 | 3475 |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4083 | 4056 |
| 4084 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { | 4057 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { |
| 4085 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); | 4058 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); |
| 4086 if (is_compacting()) { | 4059 if (is_compacting()) { |
| 4087 Code* host = | 4060 Code* host = |
| 4088 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( | 4061 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( |
| 4089 pc); | 4062 pc); |
| 4090 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4063 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 4091 if (Marking::IsBlack(mark_bit)) { | 4064 if (Marking::IsBlack(mark_bit)) { |
| 4092 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4065 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 4093 // The target is always in old space, we don't have to record the slot in | |
| 4094 // the old-to-new remembered set. | |
| 4095 DCHECK(!heap()->InNewSpace(target)); | |
| 4096 RecordRelocSlot(host, &rinfo, target); | 4066 RecordRelocSlot(host, &rinfo, target); |
| 4097 } | 4067 } |
| 4098 } | 4068 } |
| 4099 } | 4069 } |
| 4100 | 4070 |
| 4101 } // namespace internal | 4071 } // namespace internal |
| 4102 } // namespace v8 | 4072 } // namespace v8 |
| OLD | NEW |