| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/incremental-marking.h" | 7 #include "src/incremental-marking.h" |
| 8 | 8 |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 heap_->mark_compact_collector()->RecordSlot( | 46 heap_->mark_compact_collector()->RecordSlot( |
| 47 HeapObject::RawField(obj, 0), slot, value); | 47 HeapObject::RawField(obj, 0), slot, value); |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 void IncrementalMarking::RecordWriteFromCode(HeapObject* obj, | 53 void IncrementalMarking::RecordWriteFromCode(HeapObject* obj, |
| 54 Object** slot, | 54 Object** slot, |
| 55 Isolate* isolate) { | 55 Isolate* isolate) { |
| 56 ASSERT(obj->IsHeapObject()); | 56 DCHECK(obj->IsHeapObject()); |
| 57 IncrementalMarking* marking = isolate->heap()->incremental_marking(); | 57 IncrementalMarking* marking = isolate->heap()->incremental_marking(); |
| 58 | 58 |
| 59 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 59 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 60 int counter = chunk->write_barrier_counter(); | 60 int counter = chunk->write_barrier_counter(); |
| 61 if (counter < (MemoryChunk::kWriteBarrierCounterGranularity / 2)) { | 61 if (counter < (MemoryChunk::kWriteBarrierCounterGranularity / 2)) { |
| 62 marking->write_barriers_invoked_since_last_step_ += | 62 marking->write_barriers_invoked_since_last_step_ += |
| 63 MemoryChunk::kWriteBarrierCounterGranularity - | 63 MemoryChunk::kWriteBarrierCounterGranularity - |
| 64 chunk->write_barrier_counter(); | 64 chunk->write_barrier_counter(); |
| 65 chunk->set_write_barrier_counter( | 65 chunk->set_write_barrier_counter( |
| 66 MemoryChunk::kWriteBarrierCounterGranularity); | 66 MemoryChunk::kWriteBarrierCounterGranularity); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 87 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 87 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
| 88 RecordWriteIntoCode(host, &rinfo, value); | 88 RecordWriteIntoCode(host, &rinfo, value); |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 void IncrementalMarking::RecordWriteOfCodeEntrySlow(JSFunction* host, | 93 void IncrementalMarking::RecordWriteOfCodeEntrySlow(JSFunction* host, |
| 94 Object** slot, | 94 Object** slot, |
| 95 Code* value) { | 95 Code* value) { |
| 96 if (BaseRecordWrite(host, slot, value)) { | 96 if (BaseRecordWrite(host, slot, value)) { |
| 97 ASSERT(slot != NULL); | 97 DCHECK(slot != NULL); |
| 98 heap_->mark_compact_collector()-> | 98 heap_->mark_compact_collector()-> |
| 99 RecordCodeEntrySlot(reinterpret_cast<Address>(slot), value); | 99 RecordCodeEntrySlot(reinterpret_cast<Address>(slot), value); |
| 100 } | 100 } |
| 101 } | 101 } |
| 102 | 102 |
| 103 | 103 |
| 104 void IncrementalMarking::RecordWriteIntoCodeSlow(HeapObject* obj, | 104 void IncrementalMarking::RecordWriteIntoCodeSlow(HeapObject* obj, |
| 105 RelocInfo* rinfo, | 105 RelocInfo* rinfo, |
| 106 Object* value) { | 106 Object* value) { |
| 107 MarkBit value_bit = Marking::MarkBitFrom(HeapObject::cast(value)); | 107 MarkBit value_bit = Marking::MarkBitFrom(HeapObject::cast(value)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 135 -heap_obj->Size()); | 135 -heap_obj->Size()); |
| 136 } | 136 } |
| 137 Marking::AnyToGrey(mark_bit); | 137 Marking::AnyToGrey(mark_bit); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 | 141 |
| 142 static inline void MarkBlackOrKeepGrey(HeapObject* heap_object, | 142 static inline void MarkBlackOrKeepGrey(HeapObject* heap_object, |
| 143 MarkBit mark_bit, | 143 MarkBit mark_bit, |
| 144 int size) { | 144 int size) { |
| 145 ASSERT(!Marking::IsImpossible(mark_bit)); | 145 DCHECK(!Marking::IsImpossible(mark_bit)); |
| 146 if (mark_bit.Get()) return; | 146 if (mark_bit.Get()) return; |
| 147 mark_bit.Set(); | 147 mark_bit.Set(); |
| 148 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); | 148 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); |
| 149 ASSERT(Marking::IsBlack(mark_bit)); | 149 DCHECK(Marking::IsBlack(mark_bit)); |
| 150 } | 150 } |
| 151 | 151 |
| 152 | 152 |
| 153 static inline void MarkBlackOrKeepBlack(HeapObject* heap_object, | 153 static inline void MarkBlackOrKeepBlack(HeapObject* heap_object, |
| 154 MarkBit mark_bit, | 154 MarkBit mark_bit, |
| 155 int size) { | 155 int size) { |
| 156 ASSERT(!Marking::IsImpossible(mark_bit)); | 156 DCHECK(!Marking::IsImpossible(mark_bit)); |
| 157 if (Marking::IsBlack(mark_bit)) return; | 157 if (Marking::IsBlack(mark_bit)) return; |
| 158 Marking::MarkBlack(mark_bit); | 158 Marking::MarkBlack(mark_bit); |
| 159 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); | 159 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); |
| 160 ASSERT(Marking::IsBlack(mark_bit)); | 160 DCHECK(Marking::IsBlack(mark_bit)); |
| 161 } | 161 } |
| 162 | 162 |
| 163 | 163 |
| 164 class IncrementalMarkingMarkingVisitor | 164 class IncrementalMarkingMarkingVisitor |
| 165 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { | 165 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { |
| 166 public: | 166 public: |
| 167 static void Initialize() { | 167 static void Initialize() { |
| 168 StaticMarkingVisitor<IncrementalMarkingMarkingVisitor>::Initialize(); | 168 StaticMarkingVisitor<IncrementalMarkingMarkingVisitor>::Initialize(); |
| 169 table_.Register(kVisitFixedArray, &VisitFixedArrayIncremental); | 169 table_.Register(kVisitFixedArray, &VisitFixedArrayIncremental); |
| 170 table_.Register(kVisitNativeContext, &VisitNativeContextIncremental); | 170 table_.Register(kVisitNativeContext, &VisitNativeContextIncremental); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 return FLAG_incremental_marking && | 448 return FLAG_incremental_marking && |
| 449 FLAG_incremental_marking_steps && | 449 FLAG_incremental_marking_steps && |
| 450 heap_->gc_state() == Heap::NOT_IN_GC && | 450 heap_->gc_state() == Heap::NOT_IN_GC && |
| 451 !heap_->isolate()->serializer_enabled() && | 451 !heap_->isolate()->serializer_enabled() && |
| 452 heap_->isolate()->IsInitialized() && | 452 heap_->isolate()->IsInitialized() && |
| 453 heap_->PromotedSpaceSizeOfObjects() > kActivationThreshold; | 453 heap_->PromotedSpaceSizeOfObjects() > kActivationThreshold; |
| 454 } | 454 } |
| 455 | 455 |
| 456 | 456 |
| 457 void IncrementalMarking::ActivateGeneratedStub(Code* stub) { | 457 void IncrementalMarking::ActivateGeneratedStub(Code* stub) { |
| 458 ASSERT(RecordWriteStub::GetMode(stub) == | 458 DCHECK(RecordWriteStub::GetMode(stub) == |
| 459 RecordWriteStub::STORE_BUFFER_ONLY); | 459 RecordWriteStub::STORE_BUFFER_ONLY); |
| 460 | 460 |
| 461 if (!IsMarking()) { | 461 if (!IsMarking()) { |
| 462 // Initially stub is generated in STORE_BUFFER_ONLY mode thus | 462 // Initially stub is generated in STORE_BUFFER_ONLY mode thus |
| 463 // we don't need to do anything if incremental marking is | 463 // we don't need to do anything if incremental marking is |
| 464 // not active. | 464 // not active. |
| 465 } else if (IsCompacting()) { | 465 } else if (IsCompacting()) { |
| 466 RecordWriteStub::Patch(stub, RecordWriteStub::INCREMENTAL_COMPACTION); | 466 RecordWriteStub::Patch(stub, RecordWriteStub::INCREMENTAL_COMPACTION); |
| 467 } else { | 467 } else { |
| 468 RecordWriteStub::Patch(stub, RecordWriteStub::INCREMENTAL); | 468 RecordWriteStub::Patch(stub, RecordWriteStub::INCREMENTAL); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 CHECK(success); | 515 CHECK(success); |
| 516 marking_deque_memory_committed_ = false; | 516 marking_deque_memory_committed_ = false; |
| 517 } | 517 } |
| 518 } | 518 } |
| 519 | 519 |
| 520 | 520 |
| 521 void IncrementalMarking::Start(CompactionFlag flag) { | 521 void IncrementalMarking::Start(CompactionFlag flag) { |
| 522 if (FLAG_trace_incremental_marking) { | 522 if (FLAG_trace_incremental_marking) { |
| 523 PrintF("[IncrementalMarking] Start\n"); | 523 PrintF("[IncrementalMarking] Start\n"); |
| 524 } | 524 } |
| 525 ASSERT(FLAG_incremental_marking); | 525 DCHECK(FLAG_incremental_marking); |
| 526 ASSERT(FLAG_incremental_marking_steps); | 526 DCHECK(FLAG_incremental_marking_steps); |
| 527 ASSERT(state_ == STOPPED); | 527 DCHECK(state_ == STOPPED); |
| 528 ASSERT(heap_->gc_state() == Heap::NOT_IN_GC); | 528 DCHECK(heap_->gc_state() == Heap::NOT_IN_GC); |
| 529 ASSERT(!heap_->isolate()->serializer_enabled()); | 529 DCHECK(!heap_->isolate()->serializer_enabled()); |
| 530 ASSERT(heap_->isolate()->IsInitialized()); | 530 DCHECK(heap_->isolate()->IsInitialized()); |
| 531 | 531 |
| 532 ResetStepCounters(); | 532 ResetStepCounters(); |
| 533 | 533 |
| 534 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { | 534 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { |
| 535 StartMarking(flag); | 535 StartMarking(flag); |
| 536 } else { | 536 } else { |
| 537 if (FLAG_trace_incremental_marking) { | 537 if (FLAG_trace_incremental_marking) { |
| 538 PrintF("[IncrementalMarking] Start sweeping.\n"); | 538 PrintF("[IncrementalMarking] Start sweeping.\n"); |
| 539 } | 539 } |
| 540 state_ = SWEEPING; | 540 state_ = SWEEPING; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 int current = marking_deque_.bottom(); | 615 int current = marking_deque_.bottom(); |
| 616 int mask = marking_deque_.mask(); | 616 int mask = marking_deque_.mask(); |
| 617 int limit = marking_deque_.top(); | 617 int limit = marking_deque_.top(); |
| 618 HeapObject** array = marking_deque_.array(); | 618 HeapObject** array = marking_deque_.array(); |
| 619 int new_top = current; | 619 int new_top = current; |
| 620 | 620 |
| 621 Map* filler_map = heap_->one_pointer_filler_map(); | 621 Map* filler_map = heap_->one_pointer_filler_map(); |
| 622 | 622 |
| 623 while (current != limit) { | 623 while (current != limit) { |
| 624 HeapObject* obj = array[current]; | 624 HeapObject* obj = array[current]; |
| 625 ASSERT(obj->IsHeapObject()); | 625 DCHECK(obj->IsHeapObject()); |
| 626 current = ((current + 1) & mask); | 626 current = ((current + 1) & mask); |
| 627 if (heap_->InNewSpace(obj)) { | 627 if (heap_->InNewSpace(obj)) { |
| 628 MapWord map_word = obj->map_word(); | 628 MapWord map_word = obj->map_word(); |
| 629 if (map_word.IsForwardingAddress()) { | 629 if (map_word.IsForwardingAddress()) { |
| 630 HeapObject* dest = map_word.ToForwardingAddress(); | 630 HeapObject* dest = map_word.ToForwardingAddress(); |
| 631 array[new_top] = dest; | 631 array[new_top] = dest; |
| 632 new_top = ((new_top + 1) & mask); | 632 new_top = ((new_top + 1) & mask); |
| 633 ASSERT(new_top != marking_deque_.bottom()); | 633 DCHECK(new_top != marking_deque_.bottom()); |
| 634 #ifdef DEBUG | 634 #ifdef DEBUG |
| 635 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 635 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 636 ASSERT(Marking::IsGrey(mark_bit) || | 636 DCHECK(Marking::IsGrey(mark_bit) || |
| 637 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 637 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
| 638 #endif | 638 #endif |
| 639 } | 639 } |
| 640 } else if (obj->map() != filler_map) { | 640 } else if (obj->map() != filler_map) { |
| 641 // Skip one word filler objects that appear on the | 641 // Skip one word filler objects that appear on the |
| 642 // stack when we perform in place array shift. | 642 // stack when we perform in place array shift. |
| 643 array[new_top] = obj; | 643 array[new_top] = obj; |
| 644 new_top = ((new_top + 1) & mask); | 644 new_top = ((new_top + 1) & mask); |
| 645 ASSERT(new_top != marking_deque_.bottom()); | 645 DCHECK(new_top != marking_deque_.bottom()); |
| 646 #ifdef DEBUG | 646 #ifdef DEBUG |
| 647 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 647 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 648 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 648 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 649 ASSERT(Marking::IsGrey(mark_bit) || | 649 DCHECK(Marking::IsGrey(mark_bit) || |
| 650 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || | 650 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || |
| 651 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | 651 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && |
| 652 Marking::IsBlack(mark_bit))); | 652 Marking::IsBlack(mark_bit))); |
| 653 #endif | 653 #endif |
| 654 } | 654 } |
| 655 } | 655 } |
| 656 marking_deque_.set_top(new_top); | 656 marking_deque_.set_top(new_top); |
| 657 } | 657 } |
| 658 | 658 |
| 659 | 659 |
| 660 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { | 660 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { |
| 661 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | 661 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
| 662 if (Marking::IsWhite(map_mark_bit)) { | 662 if (Marking::IsWhite(map_mark_bit)) { |
| 663 WhiteToGreyAndPush(map, map_mark_bit); | 663 WhiteToGreyAndPush(map, map_mark_bit); |
| 664 } | 664 } |
| 665 | 665 |
| 666 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | 666 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
| 667 | 667 |
| 668 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 668 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 669 #if ENABLE_SLOW_ASSERTS | 669 #if ENABLE_SLOW_DCHECKS |
| 670 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 670 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 671 SLOW_ASSERT(Marking::IsGrey(mark_bit) || | 671 SLOW_DCHECK(Marking::IsGrey(mark_bit) || |
| 672 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || | 672 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || |
| 673 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | 673 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && |
| 674 Marking::IsBlack(mark_bit))); | 674 Marking::IsBlack(mark_bit))); |
| 675 #endif | 675 #endif |
| 676 MarkBlackOrKeepBlack(obj, mark_bit, size); | 676 MarkBlackOrKeepBlack(obj, mark_bit, size); |
| 677 } | 677 } |
| 678 | 678 |
| 679 | 679 |
| 680 intptr_t IncrementalMarking::ProcessMarkingDeque(intptr_t bytes_to_process) { | 680 intptr_t IncrementalMarking::ProcessMarkingDeque(intptr_t bytes_to_process) { |
| 681 intptr_t bytes_processed = 0; | 681 intptr_t bytes_processed = 0; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 void IncrementalMarking::Finalize() { | 796 void IncrementalMarking::Finalize() { |
| 797 Hurry(); | 797 Hurry(); |
| 798 state_ = STOPPED; | 798 state_ = STOPPED; |
| 799 is_compacting_ = false; | 799 is_compacting_ = false; |
| 800 heap_->new_space()->LowerInlineAllocationLimit(0); | 800 heap_->new_space()->LowerInlineAllocationLimit(0); |
| 801 IncrementalMarking::set_should_hurry(false); | 801 IncrementalMarking::set_should_hurry(false); |
| 802 ResetStepCounters(); | 802 ResetStepCounters(); |
| 803 PatchIncrementalMarkingRecordWriteStubs(heap_, | 803 PatchIncrementalMarkingRecordWriteStubs(heap_, |
| 804 RecordWriteStub::STORE_BUFFER_ONLY); | 804 RecordWriteStub::STORE_BUFFER_ONLY); |
| 805 DeactivateIncrementalWriteBarrier(); | 805 DeactivateIncrementalWriteBarrier(); |
| 806 ASSERT(marking_deque_.IsEmpty()); | 806 DCHECK(marking_deque_.IsEmpty()); |
| 807 heap_->isolate()->stack_guard()->ClearGC(); | 807 heap_->isolate()->stack_guard()->ClearGC(); |
| 808 } | 808 } |
| 809 | 809 |
| 810 | 810 |
| 811 void IncrementalMarking::MarkingComplete(CompletionAction action) { | 811 void IncrementalMarking::MarkingComplete(CompletionAction action) { |
| 812 state_ = COMPLETE; | 812 state_ = COMPLETE; |
| 813 // We will set the stack guard to request a GC now. This will mean the rest | 813 // We will set the stack guard to request a GC now. This will mean the rest |
| 814 // of the GC gets performed as soon as possible (we can't do a GC here in a | 814 // of the GC gets performed as soon as possible (we can't do a GC here in a |
| 815 // record-write context). If a few things get allocated between now and then | 815 // record-write context). If a few things get allocated between now and then |
| 816 // that shouldn't make us do a scavenge and keep being incremental, so we set | 816 // that shouldn't make us do a scavenge and keep being incremental, so we set |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 bytes_scanned_ = 0; | 978 bytes_scanned_ = 0; |
| 979 write_barriers_invoked_since_last_step_ = 0; | 979 write_barriers_invoked_since_last_step_ = 0; |
| 980 } | 980 } |
| 981 | 981 |
| 982 | 982 |
| 983 int64_t IncrementalMarking::SpaceLeftInOldSpace() { | 983 int64_t IncrementalMarking::SpaceLeftInOldSpace() { |
| 984 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); | 984 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); |
| 985 } | 985 } |
| 986 | 986 |
| 987 } } // namespace v8::internal | 987 } } // namespace v8::internal |
| OLD | NEW |