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

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

Issue 1818013002: [heap] Optimize migration of objects (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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/mark-compact.h ('k') | no next file » | 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 1490 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 HeapObject* object = NULL; 1501 HeapObject* object = NULL;
1502 while ((object = it.Next()) != NULL) { 1502 while ((object = it.Next()) != NULL) {
1503 MarkBit markbit = Marking::MarkBitFrom(object); 1503 MarkBit markbit = Marking::MarkBitFrom(object);
1504 DCHECK(Marking::IsGrey(markbit)); 1504 DCHECK(Marking::IsGrey(markbit));
1505 Marking::GreyToBlack(markbit); 1505 Marking::GreyToBlack(markbit);
1506 PushBlack(object); 1506 PushBlack(object);
1507 if (marking_deque()->IsFull()) return; 1507 if (marking_deque()->IsFull()) return;
1508 } 1508 }
1509 } 1509 }
1510 1510
1511 class RecordMigratedSlotVisitor final : public ObjectVisitor {
1512 public:
1513 inline void VisitPointer(Object** p) final {
1514 RecordMigratedSlot(*p, reinterpret_cast<Address>(p));
1515 }
1516
1517 inline void VisitPointers(Object** start, Object** end) final {
1518 while (start < end) {
1519 RecordMigratedSlot(*start, reinterpret_cast<Address>(start));
1520 ++start;
1521 }
1522 }
1523
1524 inline void VisitCodeEntry(Address code_entry_slot) final {
1525 Address code_entry = Memory::Address_at(code_entry_slot);
1526 if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
1527 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot),
1528 CODE_ENTRY_SLOT, code_entry_slot);
1529 }
1530 }
1531
1532 private:
1533 inline void RecordMigratedSlot(Object* value, Address slot) {
1534 if (value->IsHeapObject()) {
1535 Page* p = Page::FromAddress(reinterpret_cast<Address>(value));
1536 if (p->InNewSpace()) {
1537 RememberedSet<OLD_TO_NEW>::Insert(Page::FromAddress(slot), slot);
1538 } else if (p->IsEvacuationCandidate()) {
1539 RememberedSet<OLD_TO_OLD>::Insert(Page::FromAddress(slot), slot);
1540 }
1541 }
1542 }
1543 };
1511 1544
1512 class MarkCompactCollector::HeapObjectVisitor { 1545 class MarkCompactCollector::HeapObjectVisitor {
1513 public: 1546 public:
1514 virtual ~HeapObjectVisitor() {} 1547 virtual ~HeapObjectVisitor() {}
1515 virtual bool Visit(HeapObject* object) = 0; 1548 virtual bool Visit(HeapObject* object) = 0;
1516 }; 1549 };
1517 1550
1518
1519 class MarkCompactCollector::EvacuateVisitorBase 1551 class MarkCompactCollector::EvacuateVisitorBase
1520 : public MarkCompactCollector::HeapObjectVisitor { 1552 : public MarkCompactCollector::HeapObjectVisitor {
1521 public: 1553 public:
1522 EvacuateVisitorBase(Heap* heap, CompactionSpaceCollection* compaction_spaces) 1554 EvacuateVisitorBase(Heap* heap, CompactionSpaceCollection* compaction_spaces)
1523 : heap_(heap), compaction_spaces_(compaction_spaces) {} 1555 : heap_(heap), compaction_spaces_(compaction_spaces) {}
1524 1556
1525 bool TryEvacuateObject(PagedSpace* target_space, HeapObject* object, 1557 inline bool TryEvacuateObject(PagedSpace* target_space, HeapObject* object,
1526 HeapObject** target_object) { 1558 HeapObject** target_object) {
1527 int size = object->Size(); 1559 int size = object->Size();
1528 AllocationAlignment alignment = object->RequiredAlignment(); 1560 AllocationAlignment alignment = object->RequiredAlignment();
1529 AllocationResult allocation = target_space->AllocateRaw(size, alignment); 1561 AllocationResult allocation = target_space->AllocateRaw(size, alignment);
1530 if (allocation.To(target_object)) { 1562 if (allocation.To(target_object)) {
1531 heap_->mark_compact_collector()->MigrateObject( 1563 MigrateObject(*target_object, object, size, target_space->identity());
1532 *target_object, object, size, target_space->identity());
1533 return true; 1564 return true;
1534 } 1565 }
1535 return false; 1566 return false;
1536 } 1567 }
1537 1568
1569 inline void MigrateObject(HeapObject* dst, HeapObject* src, int size,
1570 AllocationSpace dest) {
1571 Address dst_addr = dst->address();
1572 Address src_addr = src->address();
1573 DCHECK(heap_->AllowedToBeMigrated(src, dest));
1574 DCHECK(dest != LO_SPACE);
1575 if (dest == OLD_SPACE) {
1576 DCHECK_OBJECT_SIZE(size);
1577 DCHECK(IsAligned(size, kPointerSize));
1578 heap_->MoveBlock(dst_addr, src_addr, size);
1579 if (FLAG_ignition && dst->IsBytecodeArray()) {
1580 PROFILE(heap_->isolate(),
1581 CodeMoveEvent(AbstractCode::cast(src), dst_addr));
1582 }
1583 RecordMigratedSlotVisitor visitor;
1584 dst->IterateBodyFast(dst->map()->instance_type(), size, &visitor);
1585 } else if (dest == CODE_SPACE) {
1586 DCHECK_CODEOBJECT_SIZE(size, heap_->code_space());
1587 PROFILE(heap_->isolate(),
1588 CodeMoveEvent(AbstractCode::cast(src), dst_addr));
1589 heap_->MoveBlock(dst_addr, src_addr, size);
1590 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(dst_addr),
1591 RELOCATED_CODE_OBJECT, dst_addr);
1592 Code::cast(dst)->Relocate(dst_addr - src_addr);
1593 } else {
1594 DCHECK_OBJECT_SIZE(size);
1595 DCHECK(dest == NEW_SPACE);
1596 heap_->MoveBlock(dst_addr, src_addr, size);
1597 }
1598 heap_->OnMoveEvent(dst, src, size);
1599 Memory::Address_at(src_addr) = dst_addr;
1600 }
1601
1538 protected: 1602 protected:
1539 Heap* heap_; 1603 Heap* heap_;
1540 CompactionSpaceCollection* compaction_spaces_; 1604 CompactionSpaceCollection* compaction_spaces_;
1541 }; 1605 };
1542 1606
1543
1544 class MarkCompactCollector::EvacuateNewSpaceVisitor final 1607 class MarkCompactCollector::EvacuateNewSpaceVisitor final
1545 : public MarkCompactCollector::EvacuateVisitorBase { 1608 : public MarkCompactCollector::EvacuateVisitorBase {
1546 public: 1609 public:
1547 static const intptr_t kLabSize = 4 * KB; 1610 static const intptr_t kLabSize = 4 * KB;
1548 static const intptr_t kMaxLabObjectSize = 256; 1611 static const intptr_t kMaxLabObjectSize = 256;
1549 1612
1550 explicit EvacuateNewSpaceVisitor(Heap* heap, 1613 explicit EvacuateNewSpaceVisitor(Heap* heap,
1551 CompactionSpaceCollection* compaction_spaces, 1614 CompactionSpaceCollection* compaction_spaces,
1552 HashMap* local_pretenuring_feedback) 1615 HashMap* local_pretenuring_feedback)
1553 : EvacuateVisitorBase(heap, compaction_spaces), 1616 : EvacuateVisitorBase(heap, compaction_spaces),
(...skipping 14 matching lines...) Expand all
1568 // If we end up needing more special cases, we should factor this out. 1631 // If we end up needing more special cases, we should factor this out.
1569 if (V8_UNLIKELY(target_object->IsJSArrayBuffer())) { 1632 if (V8_UNLIKELY(target_object->IsJSArrayBuffer())) {
1570 heap_->array_buffer_tracker()->Promote( 1633 heap_->array_buffer_tracker()->Promote(
1571 JSArrayBuffer::cast(target_object)); 1634 JSArrayBuffer::cast(target_object));
1572 } 1635 }
1573 promoted_size_ += size; 1636 promoted_size_ += size;
1574 return true; 1637 return true;
1575 } 1638 }
1576 HeapObject* target = nullptr; 1639 HeapObject* target = nullptr;
1577 AllocationSpace space = AllocateTargetObject(object, &target); 1640 AllocationSpace space = AllocateTargetObject(object, &target);
1578 heap_->mark_compact_collector()->MigrateObject(HeapObject::cast(target), 1641 MigrateObject(HeapObject::cast(target), object, size, space);
1579 object, size, space);
1580 if (V8_UNLIKELY(target->IsJSArrayBuffer())) { 1642 if (V8_UNLIKELY(target->IsJSArrayBuffer())) {
1581 heap_->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target)); 1643 heap_->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target));
1582 } 1644 }
1583 semispace_copied_size_ += size; 1645 semispace_copied_size_ += size;
1584 return true; 1646 return true;
1585 } 1647 }
1586 1648
1587 intptr_t promoted_size() { return promoted_size_; } 1649 intptr_t promoted_size() { return promoted_size_; }
1588 intptr_t semispace_copied_size() { return semispace_copied_size_; } 1650 intptr_t semispace_copied_size() { return semispace_copied_size_; }
1589 1651
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after
2549 slot_type = CODE_ENTRY_SLOT; 2611 slot_type = CODE_ENTRY_SLOT;
2550 } else { 2612 } else {
2551 DCHECK(RelocInfo::IsEmbeddedObject(rmode)); 2613 DCHECK(RelocInfo::IsEmbeddedObject(rmode));
2552 slot_type = OBJECT_SLOT; 2614 slot_type = OBJECT_SLOT;
2553 } 2615 }
2554 } 2616 }
2555 RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr); 2617 RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr);
2556 } 2618 }
2557 } 2619 }
2558 2620
2559
2560 class RecordMigratedSlotVisitor final : public ObjectVisitor {
2561 public:
2562 explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector)
2563 : collector_(collector) {}
2564
2565 V8_INLINE void VisitPointer(Object** p) override {
2566 RecordMigratedSlot(*p, reinterpret_cast<Address>(p));
2567 }
2568
2569 V8_INLINE void VisitPointers(Object** start, Object** end) override {
2570 while (start < end) {
2571 RecordMigratedSlot(*start, reinterpret_cast<Address>(start));
2572 ++start;
2573 }
2574 }
2575
2576 V8_INLINE void VisitCodeEntry(Address code_entry_slot) override {
2577 if (collector_->compacting_) {
2578 Address code_entry = Memory::Address_at(code_entry_slot);
2579 if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
2580 RememberedSet<OLD_TO_OLD>::InsertTyped(
2581 Page::FromAddress(code_entry_slot), CODE_ENTRY_SLOT,
2582 code_entry_slot);
2583 }
2584 }
2585 }
2586
2587 private:
2588 inline void RecordMigratedSlot(Object* value, Address slot) {
2589 if (collector_->heap()->InNewSpace(value)) {
2590 RememberedSet<OLD_TO_NEW>::Insert(Page::FromAddress(slot), slot);
2591 } else if (value->IsHeapObject() &&
2592 Page::FromAddress(reinterpret_cast<Address>(value))
2593 ->IsEvacuationCandidate()) {
2594 RememberedSet<OLD_TO_OLD>::Insert(Page::FromAddress(slot), slot);
2595 }
2596 }
2597
2598 MarkCompactCollector* collector_;
2599 };
2600
2601
2602 // We scavenge new space simultaneously with sweeping. This is done in two
2603 // passes.
2604 //
2605 // The first pass migrates all alive objects from one semispace to another or
2606 // promotes them to old space. Forwarding address is written directly into
2607 // first word of object without any encoding. If object is dead we write
2608 // NULL as a forwarding address.
2609 //
2610 // The second pass updates pointers to new space in all spaces. It is possible
2611 // to encounter pointers to dead new space objects during traversal of pointers
2612 // to new space. We should clear them to avoid encountering them during next
2613 // pointer iteration. This is an issue if the store buffer overflows and we
2614 // have to scan the entire old space, including dead objects, looking for
2615 // pointers to new space.
2616 void MarkCompactCollector::MigrateObject(HeapObject* dst, HeapObject* src,
2617 int size, AllocationSpace dest) {
2618 Address dst_addr = dst->address();
2619 Address src_addr = src->address();
2620 DCHECK(heap()->AllowedToBeMigrated(src, dest));
2621 DCHECK(dest != LO_SPACE);
2622 if (dest == OLD_SPACE) {
2623 DCHECK_OBJECT_SIZE(size);
2624 DCHECK(IsAligned(size, kPointerSize));
2625
2626 heap()->MoveBlock(dst->address(), src->address(), size);
2627 if (FLAG_ignition && dst->IsBytecodeArray()) {
2628 PROFILE(isolate(), CodeMoveEvent(AbstractCode::cast(src), dst_addr));
2629 }
2630 RecordMigratedSlotVisitor visitor(this);
2631 dst->IterateBody(&visitor);
2632 } else if (dest == CODE_SPACE) {
2633 DCHECK_CODEOBJECT_SIZE(size, heap()->code_space());
2634 PROFILE(isolate(), CodeMoveEvent(AbstractCode::cast(src), dst_addr));
2635 heap()->MoveBlock(dst_addr, src_addr, size);
2636 RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(dst_addr),
2637 RELOCATED_CODE_OBJECT, dst_addr);
2638 Code::cast(dst)->Relocate(dst_addr - src_addr);
2639 } else {
2640 DCHECK_OBJECT_SIZE(size);
2641 DCHECK(dest == NEW_SPACE);
2642 heap()->MoveBlock(dst_addr, src_addr, size);
2643 }
2644 heap()->OnMoveEvent(dst, src, size);
2645 Memory::Address_at(src_addr) = dst_addr;
2646 }
2647
2648 static inline void UpdateTypedSlot(Isolate* isolate, ObjectVisitor* v, 2621 static inline void UpdateTypedSlot(Isolate* isolate, ObjectVisitor* v,
2649 SlotType slot_type, Address addr) { 2622 SlotType slot_type, Address addr) {
2650 switch (slot_type) { 2623 switch (slot_type) {
2651 case CODE_TARGET_SLOT: { 2624 case CODE_TARGET_SLOT: {
2652 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL); 2625 RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL);
2653 rinfo.Visit(isolate, v); 2626 rinfo.Visit(isolate, v);
2654 break; 2627 break;
2655 } 2628 }
2656 case CELL_TARGET_SLOT: { 2629 case CELL_TARGET_SLOT: {
2657 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL); 2630 RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL);
(...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3818 MarkBit mark_bit = Marking::MarkBitFrom(host); 3791 MarkBit mark_bit = Marking::MarkBitFrom(host);
3819 if (Marking::IsBlack(mark_bit)) { 3792 if (Marking::IsBlack(mark_bit)) {
3820 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); 3793 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
3821 RecordRelocSlot(host, &rinfo, target); 3794 RecordRelocSlot(host, &rinfo, target);
3822 } 3795 }
3823 } 3796 }
3824 } 3797 }
3825 3798
3826 } // namespace internal 3799 } // namespace internal
3827 } // namespace v8 3800 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698