| 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 1597 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1608       RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), | 1608       RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), | 
| 1609                                              nullptr, CODE_ENTRY_SLOT, | 1609                                              nullptr, CODE_ENTRY_SLOT, | 
| 1610                                              code_entry_slot); | 1610                                              code_entry_slot); | 
| 1611     } | 1611     } | 
| 1612   } | 1612   } | 
| 1613 | 1613 | 
| 1614   inline void VisitCodeTarget(RelocInfo* rinfo) final { | 1614   inline void VisitCodeTarget(RelocInfo* rinfo) final { | 
| 1615     DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 1615     DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 
| 1616     Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1616     Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 
| 1617     Code* host = rinfo->host(); | 1617     Code* host = rinfo->host(); | 
| 1618     // The target is always in old space, we don't have to record the slot in |  | 
| 1619     // the old-to-new remembered set. |  | 
| 1620     DCHECK(!collector_->heap()->InNewSpace(target)); |  | 
| 1621     collector_->RecordRelocSlot(host, rinfo, target); | 1618     collector_->RecordRelocSlot(host, rinfo, target); | 
| 1622   } | 1619   } | 
| 1623 | 1620 | 
| 1624   inline void VisitDebugTarget(RelocInfo* rinfo) final { | 1621   inline void VisitDebugTarget(RelocInfo* rinfo) final { | 
| 1625     DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 1622     DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 
| 1626            rinfo->IsPatchedDebugBreakSlotSequence()); | 1623            rinfo->IsPatchedDebugBreakSlotSequence()); | 
| 1627     Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | 1624     Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | 
| 1628     Code* host = rinfo->host(); | 1625     Code* host = rinfo->host(); | 
| 1629     // The target is always in old space, we don't have to record the slot in |  | 
| 1630     // the old-to-new remembered set. |  | 
| 1631     DCHECK(!collector_->heap()->InNewSpace(target)); |  | 
| 1632     collector_->RecordRelocSlot(host, rinfo, target); | 1626     collector_->RecordRelocSlot(host, rinfo, target); | 
| 1633   } | 1627   } | 
| 1634 | 1628 | 
| 1635   inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { | 1629   inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { | 
| 1636     DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 1630     DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 
| 1637     HeapObject* object = HeapObject::cast(rinfo->target_object()); | 1631     HeapObject* object = HeapObject::cast(rinfo->target_object()); | 
| 1638     Code* host = rinfo->host(); | 1632     Code* host = rinfo->host(); | 
| 1639     collector_->heap()->RecordWriteIntoCode(host, rinfo, object); |  | 
| 1640     collector_->RecordRelocSlot(host, rinfo, object); | 1633     collector_->RecordRelocSlot(host, rinfo, object); | 
| 1641   } | 1634   } | 
| 1642 | 1635 | 
| 1643   inline void VisitCell(RelocInfo* rinfo) final { | 1636   inline void VisitCell(RelocInfo* rinfo) final { | 
| 1644     DCHECK(rinfo->rmode() == RelocInfo::CELL); | 1637     DCHECK(rinfo->rmode() == RelocInfo::CELL); | 
| 1645     Cell* cell = rinfo->target_cell(); | 1638     Cell* cell = rinfo->target_cell(); | 
| 1646     Code* host = rinfo->host(); | 1639     Code* host = rinfo->host(); | 
| 1647     // The cell is always in old space, we don't have to record the slot in |  | 
| 1648     // the old-to-new remembered set. |  | 
| 1649     DCHECK(!collector_->heap()->InNewSpace(cell)); |  | 
| 1650     collector_->RecordRelocSlot(host, rinfo, cell); | 1640     collector_->RecordRelocSlot(host, rinfo, cell); | 
| 1651   } | 1641   } | 
| 1652 | 1642 | 
| 1653   // Entries that will never move. | 1643   // Entries that will never move. | 
| 1654   inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { | 1644   inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { | 
| 1655     DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 1645     DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 
| 1656     Code* stub = rinfo->code_age_stub(); | 1646     Code* stub = rinfo->code_age_stub(); | 
| 1657     USE(stub); | 1647     USE(stub); | 
| 1658     DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); | 1648     DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); | 
| 1659   } | 1649   } | 
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2509     DependentCode* list_head) { | 2499     DependentCode* list_head) { | 
| 2510   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 2500   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 
| 2511   Isolate* isolate = this->isolate(); | 2501   Isolate* isolate = this->isolate(); | 
| 2512   DependentCode* current = list_head; | 2502   DependentCode* current = list_head; | 
| 2513   while (current->length() > 0) { | 2503   while (current->length() > 0) { | 
| 2514     have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2504     have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 
| 2515         isolate, DependentCode::kWeakCodeGroup); | 2505         isolate, DependentCode::kWeakCodeGroup); | 
| 2516     current = current->next_link(); | 2506     current = current->next_link(); | 
| 2517   } | 2507   } | 
| 2518 | 2508 | 
| 2519   { |  | 
| 2520     ArrayList* list = heap_->weak_new_space_object_to_code_list(); |  | 
| 2521     int counter = 0; |  | 
| 2522     for (int i = 0; i < list->Length(); i += 2) { |  | 
| 2523       WeakCell* obj = WeakCell::cast(list->Get(i)); |  | 
| 2524       WeakCell* dep = WeakCell::cast(list->Get(i + 1)); |  | 
| 2525       if (obj->cleared() || dep->cleared()) { |  | 
| 2526         if (!dep->cleared()) { |  | 
| 2527           Code* code = Code::cast(dep->value()); |  | 
| 2528           if (!code->marked_for_deoptimization()) { |  | 
| 2529             DependentCode::SetMarkedForDeoptimization( |  | 
| 2530                 code, DependentCode::DependencyGroup::kWeakCodeGroup); |  | 
| 2531             code->InvalidateEmbeddedObjects(); |  | 
| 2532             have_code_to_deoptimize_ = true; |  | 
| 2533           } |  | 
| 2534         } |  | 
| 2535       } else { |  | 
| 2536         // We record the slot manually because marking is finished at this |  | 
| 2537         // point and the write barrier would bailout. |  | 
| 2538         list->Set(counter, obj, SKIP_WRITE_BARRIER); |  | 
| 2539         RecordSlot(list, list->Slot(counter), obj); |  | 
| 2540         counter++; |  | 
| 2541         list->Set(counter, dep, SKIP_WRITE_BARRIER); |  | 
| 2542         RecordSlot(list, list->Slot(counter), dep); |  | 
| 2543         counter++; |  | 
| 2544       } |  | 
| 2545     } |  | 
| 2546   } |  | 
| 2547 |  | 
| 2548   WeakHashTable* table = heap_->weak_object_to_code_table(); | 2509   WeakHashTable* table = heap_->weak_object_to_code_table(); | 
| 2549   uint32_t capacity = table->Capacity(); | 2510   uint32_t capacity = table->Capacity(); | 
| 2550   for (uint32_t i = 0; i < capacity; i++) { | 2511   for (uint32_t i = 0; i < capacity; i++) { | 
| 2551     uint32_t key_index = table->EntryToIndex(i); | 2512     uint32_t key_index = table->EntryToIndex(i); | 
| 2552     Object* key = table->get(key_index); | 2513     Object* key = table->get(key_index); | 
| 2553     if (!table->IsKey(isolate, key)) continue; | 2514     if (!table->IsKey(isolate, key)) continue; | 
| 2554     uint32_t value_index = table->EntryToValueIndex(i); | 2515     uint32_t value_index = table->EntryToValueIndex(i); | 
| 2555     Object* value = table->get(value_index); | 2516     Object* value = table->get(value_index); | 
| 2556     DCHECK(key->IsWeakCell()); | 2517     DCHECK(key->IsWeakCell()); | 
| 2557     if (WeakCell::cast(key)->cleared()) { | 2518     if (WeakCell::cast(key)->cleared()) { | 
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2882   HeapObject* undefined = heap()->undefined_value(); | 2843   HeapObject* undefined = heap()->undefined_value(); | 
| 2883   Object* obj = heap()->encountered_transition_arrays(); | 2844   Object* obj = heap()->encountered_transition_arrays(); | 
| 2884   while (obj != Smi::FromInt(0)) { | 2845   while (obj != Smi::FromInt(0)) { | 
| 2885     TransitionArray* array = TransitionArray::cast(obj); | 2846     TransitionArray* array = TransitionArray::cast(obj); | 
| 2886     obj = array->next_link(); | 2847     obj = array->next_link(); | 
| 2887     array->set_next_link(undefined, SKIP_WRITE_BARRIER); | 2848     array->set_next_link(undefined, SKIP_WRITE_BARRIER); | 
| 2888   } | 2849   } | 
| 2889   heap()->set_encountered_transition_arrays(Smi::FromInt(0)); | 2850   heap()->set_encountered_transition_arrays(Smi::FromInt(0)); | 
| 2890 } | 2851 } | 
| 2891 | 2852 | 
|  | 2853 static inline SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { | 
|  | 2854   if (RelocInfo::IsCodeTarget(rmode)) { | 
|  | 2855     return CODE_TARGET_SLOT; | 
|  | 2856   } else if (RelocInfo::IsCell(rmode)) { | 
|  | 2857     return CELL_TARGET_SLOT; | 
|  | 2858   } else if (RelocInfo::IsEmbeddedObject(rmode)) { | 
|  | 2859     return EMBEDDED_OBJECT_SLOT; | 
|  | 2860   } else if (RelocInfo::IsDebugBreakSlot(rmode)) { | 
|  | 2861     return DEBUG_TARGET_SLOT; | 
|  | 2862   } | 
|  | 2863   UNREACHABLE(); | 
|  | 2864   return NUMBER_OF_SLOT_TYPES; | 
|  | 2865 } | 
|  | 2866 | 
| 2892 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, | 2867 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, | 
| 2893                                            Object* target) { | 2868                                            Object* target) { | 
| 2894   Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | 2869   Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | 
| 2895   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); | 2870   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); | 
|  | 2871   RelocInfo::Mode rmode = rinfo->rmode(); | 
| 2896   if (target_page->IsEvacuationCandidate() && | 2872   if (target_page->IsEvacuationCandidate() && | 
| 2897       (rinfo->host() == NULL || | 2873       (rinfo->host() == NULL || | 
| 2898        !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { | 2874        !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { | 
| 2899     RelocInfo::Mode rmode = rinfo->rmode(); |  | 
| 2900     Address addr = rinfo->pc(); | 2875     Address addr = rinfo->pc(); | 
| 2901     SlotType slot_type = SlotTypeForRelocInfoMode(rmode); | 2876     SlotType slot_type = SlotTypeForRMode(rmode); | 
| 2902     if (rinfo->IsInConstantPool()) { | 2877     if (rinfo->IsInConstantPool()) { | 
| 2903       addr = rinfo->constant_pool_entry_address(); | 2878       addr = rinfo->constant_pool_entry_address(); | 
| 2904       if (RelocInfo::IsCodeTarget(rmode)) { | 2879       if (RelocInfo::IsCodeTarget(rmode)) { | 
| 2905         slot_type = CODE_ENTRY_SLOT; | 2880         slot_type = CODE_ENTRY_SLOT; | 
| 2906       } else { | 2881       } else { | 
| 2907         DCHECK(RelocInfo::IsEmbeddedObject(rmode)); | 2882         DCHECK(RelocInfo::IsEmbeddedObject(rmode)); | 
| 2908         slot_type = OBJECT_SLOT; | 2883         slot_type = OBJECT_SLOT; | 
| 2909       } | 2884       } | 
| 2910     } | 2885     } | 
| 2911     RememberedSet<OLD_TO_OLD>::InsertTyped( | 2886     RememberedSet<OLD_TO_OLD>::InsertTyped( | 
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3516       p->heap()->CreateFillerObjectAt(free_start, size, | 3491       p->heap()->CreateFillerObjectAt(free_start, size, | 
| 3517                                       ClearRecordedSlots::kNo); | 3492                                       ClearRecordedSlots::kNo); | 
| 3518     } | 3493     } | 
| 3519   } | 3494   } | 
| 3520   p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3495   p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 
| 3521   if (free_list_mode == IGNORE_FREE_LIST) return 0; | 3496   if (free_list_mode == IGNORE_FREE_LIST) return 0; | 
| 3522   return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3497   return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 
| 3523 } | 3498 } | 
| 3524 | 3499 | 
| 3525 void MarkCompactCollector::InvalidateCode(Code* code) { | 3500 void MarkCompactCollector::InvalidateCode(Code* code) { | 
| 3526   Page* page = Page::FromAddress(code->address()); |  | 
| 3527   Address start = code->instruction_start(); |  | 
| 3528   Address end = code->address() + code->Size(); |  | 
| 3529 |  | 
| 3530   RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); |  | 
| 3531 |  | 
| 3532   if (heap_->incremental_marking()->IsCompacting() && | 3501   if (heap_->incremental_marking()->IsCompacting() && | 
| 3533       !ShouldSkipEvacuationSlotRecording(code)) { | 3502       !ShouldSkipEvacuationSlotRecording(code)) { | 
| 3534     DCHECK(compacting_); | 3503     DCHECK(compacting_); | 
| 3535 | 3504 | 
| 3536     // If the object is white than no slots were recorded on it yet. | 3505     // If the object is white than no slots were recorded on it yet. | 
| 3537     MarkBit mark_bit = Marking::MarkBitFrom(code); | 3506     MarkBit mark_bit = Marking::MarkBitFrom(code); | 
| 3538     if (Marking::IsWhite(mark_bit)) return; | 3507     if (Marking::IsWhite(mark_bit)) return; | 
| 3539 | 3508 | 
| 3540     // Ignore all slots that might have been recorded in the body of the | 3509     // Ignore all slots that might have been recorded in the body of the | 
| 3541     // deoptimized code object. Assumption: no slots will be recorded for | 3510     // deoptimized code object. Assumption: no slots will be recorded for | 
| 3542     // this object after invalidating it. | 3511     // this object after invalidating it. | 
|  | 3512     Page* page = Page::FromAddress(code->address()); | 
|  | 3513     Address start = code->instruction_start(); | 
|  | 3514     Address end = code->address() + code->Size(); | 
| 3543     RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); | 3515     RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); | 
|  | 3516     RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end); | 
| 3544   } | 3517   } | 
| 3545 } | 3518 } | 
| 3546 | 3519 | 
| 3547 | 3520 | 
| 3548 // Return true if the given code is deoptimized or will be deoptimized. | 3521 // Return true if the given code is deoptimized or will be deoptimized. | 
| 3549 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 3522 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 
| 3550   return code->is_optimized_code() && code->marked_for_deoptimization(); | 3523   return code->is_optimized_code() && code->marked_for_deoptimization(); | 
| 3551 } | 3524 } | 
| 3552 | 3525 | 
| 3553 | 3526 | 
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4137 | 4110 | 
| 4138 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { | 4111 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { | 
| 4139   DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); | 4112   DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); | 
| 4140   if (is_compacting()) { | 4113   if (is_compacting()) { | 
| 4141     Code* host = | 4114     Code* host = | 
| 4142         isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( | 4115         isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( | 
| 4143             pc); | 4116             pc); | 
| 4144     MarkBit mark_bit = Marking::MarkBitFrom(host); | 4117     MarkBit mark_bit = Marking::MarkBitFrom(host); | 
| 4145     if (Marking::IsBlack(mark_bit)) { | 4118     if (Marking::IsBlack(mark_bit)) { | 
| 4146       RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 4119       RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 
| 4147       // The target is always in old space, we don't have to record the slot in |  | 
| 4148       // the old-to-new remembered set. |  | 
| 4149       DCHECK(!heap()->InNewSpace(target)); |  | 
| 4150       RecordRelocSlot(host, &rinfo, target); | 4120       RecordRelocSlot(host, &rinfo, target); | 
| 4151     } | 4121     } | 
| 4152   } | 4122   } | 
| 4153 } | 4123 } | 
| 4154 | 4124 | 
| 4155 }  // namespace internal | 4125 }  // namespace internal | 
| 4156 }  // namespace v8 | 4126 }  // namespace v8 | 
| OLD | NEW | 
|---|