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_MARK_COMPACT_INL_H_ 6 #define V8_HEAP_MARK_COMPACT_INL_H_ 7 8 #include "src/heap/mark-compact.h" 9 #include "src/heap/slots-buffer.h" 10 #include "src/isolate.h" 11 12 namespace v8 { 13 namespace internal { 14 15 void MarkCompactCollector::PushBlack(HeapObject* obj) { 16 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj))); 17 if (marking_deque_.Push(obj)) { 18 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size()); 19 } else { 20 Marking::BlackToGrey(obj); 21 } 22 } 23 24 25 void MarkCompactCollector::UnshiftBlack(HeapObject* obj) { 26 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj))); 27 if (!marking_deque_.Unshift(obj)) { 28 MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size()); 29 Marking::BlackToGrey(obj); 30 } 31 } 32 33 34 void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { 35 DCHECK(Marking::MarkBitFrom(obj) == mark_bit); 36 if (Marking::IsWhite(mark_bit)) { 37 Marking::WhiteToBlack(mark_bit); 38 DCHECK(obj->GetIsolate()->heap()->Contains(obj)); 39 PushBlack(obj); 40 } 41 } 42 43 44 void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) { 45 DCHECK(Marking::IsWhite(mark_bit)); 46 DCHECK(Marking::MarkBitFrom(obj) == mark_bit); 47 Marking::WhiteToBlack(mark_bit); 48 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size()); 49 } 50 51 52 bool MarkCompactCollector::IsMarked(Object* obj) { 53 DCHECK(obj->IsHeapObject()); 54 HeapObject* heap_object = HeapObject::cast(obj); 55 return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object)); 56 } 57 58 59 void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot, 60 Object* target) { 61 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); 62 if (target_page->IsEvacuationCandidate() && 63 !ShouldSkipEvacuationSlotRecording(object)) { 64 if (!SlotsBuffer::AddTo(slots_buffer_allocator_, 65 target_page->slots_buffer_address(), slot, 66 SlotsBuffer::FAIL_ON_OVERFLOW)) { 67 EvictPopularEvacuationCandidate(target_page); 68 } 69 } 70 } 71 72 73 void MarkCompactCollector::ForceRecordSlot(HeapObject* object, Object** slot, 74 Object* target) { 75 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); 76 if (target_page->IsEvacuationCandidate() && 77 !ShouldSkipEvacuationSlotRecording(object)) { 78 CHECK(SlotsBuffer::AddTo(slots_buffer_allocator_, 79 target_page->slots_buffer_address(), slot, 80 SlotsBuffer::IGNORE_OVERFLOW)); 81 } 82 } 83 84 85 void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) { 86 if (GetNextCandidate(shared_info) == NULL) { 87 SetNextCandidate(shared_info, shared_function_info_candidates_head_); 88 shared_function_info_candidates_head_ = shared_info; 89 } 90 } 91 92 93 void CodeFlusher::AddCandidate(JSFunction* function) { 94 DCHECK(function->code() == function->shared()->code()); 95 if (GetNextCandidate(function)->IsUndefined()) { 96 SetNextCandidate(function, jsfunction_candidates_head_); 97 jsfunction_candidates_head_ = function; 98 } 99 } 100 101 102 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) { 103 return reinterpret_cast<JSFunction**>( 104 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset)); 105 } 106 107 108 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) { 109 Object* next_candidate = candidate->next_function_link(); 110 return reinterpret_cast<JSFunction*>(next_candidate); 111 } 112 113 114 void CodeFlusher::SetNextCandidate(JSFunction* candidate, 115 JSFunction* next_candidate) { 116 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER); 117 } 118 119 120 void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) { 121 DCHECK(undefined->IsUndefined()); 122 candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER); 123 } 124 125 126 SharedFunctionInfo* CodeFlusher::GetNextCandidate( 127 SharedFunctionInfo* candidate) { 128 Object* next_candidate = candidate->code()->gc_metadata(); 129 return reinterpret_cast<SharedFunctionInfo*>(next_candidate); 130 } 131 132 133 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate, 134 SharedFunctionInfo* next_candidate) { 135 candidate->code()->set_gc_metadata(next_candidate); 136 } 137 138 139 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) { 140 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER); 141 } 142 143 144 template <LiveObjectIterationMode T> 145 HeapObject* LiveObjectIterator<T>::Next() { 146 while (!it_.Done()) { 147 HeapObject* object = nullptr; 148 while (current_cell_ != 0) { 149 uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_); 150 Address addr = cell_base_ + trailing_zeros * kPointerSize; 151 152 // Clear the first bit of the found object.. 153 current_cell_ &= ~(1u << trailing_zeros); 154 155 uint32_t second_bit_index = 0; 156 if (trailing_zeros < Bitmap::kBitIndexMask) { 157 second_bit_index = 1u << (trailing_zeros + 1); 158 } else { 159 second_bit_index = 0x1; 160 // The overlapping case; there has to exist a cell after the current 161 // cell. 162 DCHECK(!it_.Done()); 163 it_.Advance(); 164 cell_base_ = it_.CurrentCellBase(); 165 current_cell_ = *it_.CurrentCell(); 166 } 167 if (T == kBlackObjects && (current_cell_ & second_bit_index)) { 168 object = HeapObject::FromAddress(addr); 169 } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) { 170 object = HeapObject::FromAddress(addr); 171 } else if (T == kAllLiveObjects) { 172 object = HeapObject::FromAddress(addr); 173 } 174 // Clear the second bit of the found object. 175 current_cell_ &= ~second_bit_index; 176 177 // We found a live object. 178 if (object != nullptr) break; 179 } 180 if (current_cell_ == 0) { 181 if (!it_.Done()) { 182 it_.Advance(); 183 cell_base_ = it_.CurrentCellBase(); 184 current_cell_ = *it_.CurrentCell(); 185 } 186 } 187 if (object != nullptr) return object; 188 } 189 return nullptr; 190 } 191 192 } // namespace internal 193 } // namespace v8 194 195 #endif // V8_HEAP_MARK_COMPACT_INL_H_ 196