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