Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(700)

Side by Side Diff: src/heap/mark-compact.cc

Issue 2097023002: Reland [heap] Avoid the use of cells to point from code to new-space objects. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/heap-inl.h ('k') | src/heap/remembered-set.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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));
1572 collector_->RecordRelocSlot(host, rinfo, target); 1575 collector_->RecordRelocSlot(host, rinfo, target);
1573 } 1576 }
1574 1577
1575 inline void VisitDebugTarget(RelocInfo* rinfo) final { 1578 inline void VisitDebugTarget(RelocInfo* rinfo) final {
1576 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && 1579 DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
1577 rinfo->IsPatchedDebugBreakSlotSequence()); 1580 rinfo->IsPatchedDebugBreakSlotSequence());
1578 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); 1581 Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
1579 Code* host = rinfo->host(); 1582 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));
1580 collector_->RecordRelocSlot(host, rinfo, target); 1586 collector_->RecordRelocSlot(host, rinfo, target);
1581 } 1587 }
1582 1588
1583 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final { 1589 inline void VisitEmbeddedPointer(RelocInfo* rinfo) final {
1584 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); 1590 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
1585 HeapObject* object = HeapObject::cast(rinfo->target_object()); 1591 HeapObject* object = HeapObject::cast(rinfo->target_object());
1586 Code* host = rinfo->host(); 1592 Code* host = rinfo->host();
1593 collector_->heap()->RecordWriteIntoCode(host, rinfo, object);
1587 collector_->RecordRelocSlot(host, rinfo, object); 1594 collector_->RecordRelocSlot(host, rinfo, object);
1588 } 1595 }
1589 1596
1590 inline void VisitCell(RelocInfo* rinfo) final { 1597 inline void VisitCell(RelocInfo* rinfo) final {
1591 DCHECK(rinfo->rmode() == RelocInfo::CELL); 1598 DCHECK(rinfo->rmode() == RelocInfo::CELL);
1592 Cell* cell = rinfo->target_cell(); 1599 Cell* cell = rinfo->target_cell();
1593 Code* host = rinfo->host(); 1600 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));
1594 collector_->RecordRelocSlot(host, rinfo, cell); 1604 collector_->RecordRelocSlot(host, rinfo, cell);
1595 } 1605 }
1596 1606
1597 // Entries that will never move. 1607 // Entries that will never move.
1598 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final { 1608 inline void VisitCodeAgeSequence(RelocInfo* rinfo) final {
1599 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); 1609 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
1600 Code* stub = rinfo->code_age_stub(); 1610 Code* stub = rinfo->code_age_stub();
1601 USE(stub); 1611 USE(stub);
1602 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate()); 1612 DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate());
1603 } 1613 }
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after
2449 DependentCode* list_head) { 2459 DependentCode* list_head) {
2450 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); 2460 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE);
2451 Isolate* isolate = this->isolate(); 2461 Isolate* isolate = this->isolate();
2452 DependentCode* current = list_head; 2462 DependentCode* current = list_head;
2453 while (current->length() > 0) { 2463 while (current->length() > 0) {
2454 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( 2464 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization(
2455 isolate, DependentCode::kWeakCodeGroup); 2465 isolate, DependentCode::kWeakCodeGroup);
2456 current = current->next_link(); 2466 current = current->next_link();
2457 } 2467 }
2458 2468
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
2459 WeakHashTable* table = heap_->weak_object_to_code_table(); 2498 WeakHashTable* table = heap_->weak_object_to_code_table();
2460 uint32_t capacity = table->Capacity(); 2499 uint32_t capacity = table->Capacity();
2461 for (uint32_t i = 0; i < capacity; i++) { 2500 for (uint32_t i = 0; i < capacity; i++) {
2462 uint32_t key_index = table->EntryToIndex(i); 2501 uint32_t key_index = table->EntryToIndex(i);
2463 Object* key = table->get(key_index); 2502 Object* key = table->get(key_index);
2464 if (!table->IsKey(isolate, key)) continue; 2503 if (!table->IsKey(isolate, key)) continue;
2465 uint32_t value_index = table->EntryToValueIndex(i); 2504 uint32_t value_index = table->EntryToValueIndex(i);
2466 Object* value = table->get(value_index); 2505 Object* value = table->get(value_index);
2467 DCHECK(key->IsWeakCell()); 2506 DCHECK(key->IsWeakCell());
2468 if (WeakCell::cast(key)->cleared()) { 2507 if (WeakCell::cast(key)->cleared()) {
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
2793 HeapObject* undefined = heap()->undefined_value(); 2832 HeapObject* undefined = heap()->undefined_value();
2794 Object* obj = heap()->encountered_transition_arrays(); 2833 Object* obj = heap()->encountered_transition_arrays();
2795 while (obj != Smi::FromInt(0)) { 2834 while (obj != Smi::FromInt(0)) {
2796 TransitionArray* array = TransitionArray::cast(obj); 2835 TransitionArray* array = TransitionArray::cast(obj);
2797 obj = array->next_link(); 2836 obj = array->next_link();
2798 array->set_next_link(undefined, SKIP_WRITE_BARRIER); 2837 array->set_next_link(undefined, SKIP_WRITE_BARRIER);
2799 } 2838 }
2800 heap()->set_encountered_transition_arrays(Smi::FromInt(0)); 2839 heap()->set_encountered_transition_arrays(Smi::FromInt(0));
2801 } 2840 }
2802 2841
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
2817 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, 2842 void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo,
2818 Object* target) { 2843 Object* target) {
2819 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); 2844 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
2820 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); 2845 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
2821 RelocInfo::Mode rmode = rinfo->rmode();
2822 if (target_page->IsEvacuationCandidate() && 2846 if (target_page->IsEvacuationCandidate() &&
2823 (rinfo->host() == NULL || 2847 (rinfo->host() == NULL ||
2824 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) { 2848 !ShouldSkipEvacuationSlotRecording(rinfo->host()))) {
2849 RelocInfo::Mode rmode = rinfo->rmode();
2825 Address addr = rinfo->pc(); 2850 Address addr = rinfo->pc();
2826 SlotType slot_type = SlotTypeForRMode(rmode); 2851 SlotType slot_type = SlotTypeForRelocInfoMode(rmode);
2827 if (rinfo->IsInConstantPool()) { 2852 if (rinfo->IsInConstantPool()) {
2828 addr = rinfo->constant_pool_entry_address(); 2853 addr = rinfo->constant_pool_entry_address();
2829 if (RelocInfo::IsCodeTarget(rmode)) { 2854 if (RelocInfo::IsCodeTarget(rmode)) {
2830 slot_type = CODE_ENTRY_SLOT; 2855 slot_type = CODE_ENTRY_SLOT;
2831 } else { 2856 } else {
2832 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); 2857 DCHECK(RelocInfo::IsEmbeddedObject(rmode));
2833 slot_type = OBJECT_SLOT; 2858 slot_type = OBJECT_SLOT;
2834 } 2859 }
2835 } 2860 }
2836 RememberedSet<OLD_TO_OLD>::InsertTyped( 2861 RememberedSet<OLD_TO_OLD>::InsertTyped(
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
3440 p->heap()->CreateFillerObjectAt(free_start, size, 3465 p->heap()->CreateFillerObjectAt(free_start, size,
3441 ClearRecordedSlots::kNo); 3466 ClearRecordedSlots::kNo);
3442 } 3467 }
3443 } 3468 }
3444 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); 3469 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
3445 if (free_list_mode == IGNORE_FREE_LIST) return 0; 3470 if (free_list_mode == IGNORE_FREE_LIST) return 0;
3446 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3471 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3447 } 3472 }
3448 3473
3449 void MarkCompactCollector::InvalidateCode(Code* code) { 3474 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
3450 if (heap_->incremental_marking()->IsCompacting() && 3481 if (heap_->incremental_marking()->IsCompacting() &&
3451 !ShouldSkipEvacuationSlotRecording(code)) { 3482 !ShouldSkipEvacuationSlotRecording(code)) {
3452 DCHECK(compacting_); 3483 DCHECK(compacting_);
3453 3484
3454 // If the object is white than no slots were recorded on it yet. 3485 // If the object is white than no slots were recorded on it yet.
3455 MarkBit mark_bit = Marking::MarkBitFrom(code); 3486 MarkBit mark_bit = Marking::MarkBitFrom(code);
3456 if (Marking::IsWhite(mark_bit)) return; 3487 if (Marking::IsWhite(mark_bit)) return;
3457 3488
3458 // Ignore all slots that might have been recorded in the body of the 3489 // Ignore all slots that might have been recorded in the body of the
3459 // deoptimized code object. Assumption: no slots will be recorded for 3490 // deoptimized code object. Assumption: no slots will be recorded for
3460 // this object after invalidating it. 3491 // 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();
3464 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end); 3492 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end);
3465 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end);
3466 } 3493 }
3467 } 3494 }
3468 3495
3469 3496
3470 // Return true if the given code is deoptimized or will be deoptimized. 3497 // Return true if the given code is deoptimized or will be deoptimized.
3471 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { 3498 bool MarkCompactCollector::WillBeDeoptimized(Code* code) {
3472 return code->is_optimized_code() && code->marked_for_deoptimization(); 3499 return code->is_optimized_code() && code->marked_for_deoptimization();
3473 } 3500 }
3474 3501
3475 3502
(...skipping 20 matching lines...) Expand all
3496 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); 3523 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
3497 if (!visitor->Visit(object)) { 3524 if (!visitor->Visit(object)) {
3498 if (mode == kClearMarkbits) { 3525 if (mode == kClearMarkbits) {
3499 page->markbits()->ClearRange( 3526 page->markbits()->ClearRange(
3500 page->AddressToMarkbitIndex(page->area_start()), 3527 page->AddressToMarkbitIndex(page->area_start()),
3501 page->AddressToMarkbitIndex(object->address())); 3528 page->AddressToMarkbitIndex(object->address()));
3502 if (page->old_to_new_slots() != nullptr) { 3529 if (page->old_to_new_slots() != nullptr) {
3503 page->old_to_new_slots()->RemoveRange( 3530 page->old_to_new_slots()->RemoveRange(
3504 0, static_cast<int>(object->address() - page->address())); 3531 0, static_cast<int>(object->address() - page->address()));
3505 } 3532 }
3533 if (page->typed_old_to_new_slots() != nullptr) {
3534 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, page->address(),
3535 object->address());
3536 }
3506 RecomputeLiveBytes(page); 3537 RecomputeLiveBytes(page);
3507 } 3538 }
3508 return false; 3539 return false;
3509 } 3540 }
3510 } 3541 }
3511 if (mode == kClearMarkbits) { 3542 if (mode == kClearMarkbits) {
3512 Bitmap::Clear(page); 3543 Bitmap::Clear(page);
3513 } 3544 }
3514 return true; 3545 return true;
3515 } 3546 }
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
3677 *slot = map_word.ToForwardingAddress(); 3708 *slot = map_word.ToForwardingAddress();
3678 } 3709 }
3679 // If the object was in from space before and is after executing the 3710 // If the object was in from space before and is after executing the
3680 // callback in to space, the object is still live. 3711 // callback in to space, the object is still live.
3681 // Unfortunately, we do not know about the slot. It could be in a 3712 // Unfortunately, we do not know about the slot. It could be in a
3682 // just freed free space object. 3713 // just freed free space object.
3683 if (heap->InToSpace(*slot)) { 3714 if (heap->InToSpace(*slot)) {
3684 return KEEP_SLOT; 3715 return KEEP_SLOT;
3685 } 3716 }
3686 } else if (heap->InToSpace(*slot)) { 3717 } else if (heap->InToSpace(*slot)) {
3687 DCHECK(Page::FromAddress(reinterpret_cast<HeapObject*>(*slot)->address()) 3718 // Slots can point to "to" space if the page has been moved, or if the
3688 ->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)); 3719 // slot has been recorded multiple times in the remembered set. Since
3689 // Slots can be in "to" space after a page has been moved. Since there is 3720 // there is no forwarding information present we need to check the
3690 // no forwarding information present we need to check the markbits to 3721 // markbits to determine liveness.
3691 // determine liveness.
3692 if (Marking::IsBlack( 3722 if (Marking::IsBlack(
3693 Marking::MarkBitFrom(reinterpret_cast<HeapObject*>(*slot)))) 3723 Marking::MarkBitFrom(reinterpret_cast<HeapObject*>(*slot))))
3694 return KEEP_SLOT; 3724 return KEEP_SLOT;
3695 } else { 3725 } else {
3696 DCHECK(!heap->InNewSpace(*slot)); 3726 DCHECK(!heap->InNewSpace(*slot));
3697 } 3727 }
3698 return REMOVE_SLOT; 3728 return REMOVE_SLOT;
3699 } 3729 }
3700 }; 3730 };
3701 3731
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
4056 4086
4057 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { 4087 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) {
4058 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); 4088 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT);
4059 if (is_compacting()) { 4089 if (is_compacting()) {
4060 Code* host = 4090 Code* host =
4061 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer( 4091 isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(
4062 pc); 4092 pc);
4063 MarkBit mark_bit = Marking::MarkBitFrom(host); 4093 MarkBit mark_bit = Marking::MarkBitFrom(host);
4064 if (Marking::IsBlack(mark_bit)) { 4094 if (Marking::IsBlack(mark_bit)) {
4065 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 4095 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
4096 // The target is always in old space, we don't have to record the slot in
4097 // the old-to-new remembered set.
4098 DCHECK(!heap()->InNewSpace(target));
4066 RecordRelocSlot(host, &rinfo, target); 4099 RecordRelocSlot(host, &rinfo, target);
4067 } 4100 }
4068 } 4101 }
4069 } 4102 }
4070 4103
4071 } // namespace internal 4104 } // namespace internal
4072 } // namespace v8 4105 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/heap-inl.h ('k') | src/heap/remembered-set.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698