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 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_INCREMENTAL_MARKING_INL_H_ 6 #define V8_HEAP_INCREMENTAL_MARKING_INL_H_ 7 8 #include "src/heap/incremental-marking.h" 9 10 namespace v8 { 11 namespace internal { 12 13 14 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object** slot, 15 Object* value) { 16 HeapObject* value_heap_obj = HeapObject::cast(value); 17 MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj); 18 if (Marking::IsWhite(value_bit)) { 19 MarkBit obj_bit = Marking::MarkBitFrom(obj); 20 if (Marking::IsBlack(obj_bit)) { 21 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); 22 if (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR)) { 23 if (chunk->IsLeftOfProgressBar(slot)) { 24 WhiteToGreyAndPush(value_heap_obj, value_bit); 25 RestartIfNotMarking(); 26 } else { 27 return false; 28 } 29 } else { 30 BlackToGreyAndUnshift(obj, obj_bit); 31 RestartIfNotMarking(); 32 return false; 33 } 34 } else { 35 return false; 36 } 37 } 38 if (!is_compacting_) return false; 39 MarkBit obj_bit = Marking::MarkBitFrom(obj); 40 return Marking::IsBlack(obj_bit); 41 } 42 43 44 void IncrementalMarking::RecordWrite(HeapObject* obj, Object** slot, 45 Object* value) { 46 if (IsMarking() && value->IsHeapObject()) { 47 RecordWriteSlow(obj, slot, value); 48 } 49 } 50 51 52 void IncrementalMarking::RecordWriteOfCodeEntry(JSFunction* host, Object** slot, 53 Code* value) { 54 if (IsMarking()) RecordWriteOfCodeEntrySlow(host, slot, value); 55 } 56 57 58 void IncrementalMarking::RecordWriteIntoCode(HeapObject* obj, RelocInfo* rinfo, 59 Object* value) { 60 if (IsMarking() && value->IsHeapObject()) { 61 RecordWriteIntoCodeSlow(obj, rinfo, value); 62 } 63 } 64 65 66 void IncrementalMarking::RecordWrites(HeapObject* obj) { 67 if (IsMarking()) { 68 MarkBit obj_bit = Marking::MarkBitFrom(obj); 69 if (Marking::IsBlack(obj_bit)) { 70 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); 71 if (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR)) { 72 chunk->set_progress_bar(0); 73 } 74 BlackToGreyAndUnshift(obj, obj_bit); 75 RestartIfNotMarking(); 76 } 77 } 78 } 79 80 81 void IncrementalMarking::BlackToGreyAndUnshift(HeapObject* obj, 82 MarkBit mark_bit) { 83 DCHECK(Marking::MarkBitFrom(obj) == mark_bit); 84 DCHECK(obj->Size() >= 2 * kPointerSize); 85 DCHECK(IsMarking()); 86 Marking::BlackToGrey(mark_bit); 87 int obj_size = obj->Size(); 88 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), -obj_size); 89 bytes_scanned_ -= obj_size; 90 int64_t old_bytes_rescanned = bytes_rescanned_; 91 bytes_rescanned_ = old_bytes_rescanned + obj_size; 92 if ((bytes_rescanned_ >> 20) != (old_bytes_rescanned >> 20)) { 93 if (bytes_rescanned_ > 2 * heap_->PromotedSpaceSizeOfObjects()) { 94 // If we have queued twice the heap size for rescanning then we are 95 // going around in circles, scanning the same objects again and again 96 // as the program mutates the heap faster than we can incrementally 97 // trace it. In this case we switch to non-incremental marking in 98 // order to finish off this marking phase. 99 if (FLAG_trace_gc) { 100 PrintPID("Hurrying incremental marking because of lack of progress\n"); 101 } 102 marking_speed_ = kMaxMarkingSpeed; 103 } 104 } 105 106 marking_deque_.UnshiftGrey(obj); 107 } 108 109 110 void IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit) { 111 Marking::WhiteToGrey(mark_bit); 112 marking_deque_.PushGrey(obj); 113 } 114 } 115 } // namespace v8::internal 116 117 #endif // V8_HEAP_INCREMENTAL_MARKING_INL_H_ 118