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/remembered-set.h" 10 #include "src/isolate.h" 11 12 namespace v8 { 13 namespace internal { 14 15 void MarkCompactCollector::PushBlack(HeapObject* obj) { 16 DCHECK(ObjectMarking::IsBlack(obj)); 17 if (!marking_deque()->Push(obj)) { 18 ObjectMarking::BlackToGrey(obj); 19 } 20 } 21 22 23 void MarkCompactCollector::UnshiftBlack(HeapObject* obj) { 24 DCHECK(ObjectMarking::IsBlack(obj)); 25 if (!marking_deque()->Unshift(obj)) { 26 ObjectMarking::BlackToGrey(obj); 27 } 28 } 29 30 void MarkCompactCollector::MarkObject(HeapObject* obj) { 31 if (ObjectMarking::IsWhite(obj)) { 32 ObjectMarking::WhiteToBlack(obj); 33 PushBlack(obj); 34 } 35 } 36 37 void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot, 38 Object* target) { 39 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); 40 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(object)); 41 if (target_page->IsEvacuationCandidate() && 42 !ShouldSkipEvacuationSlotRecording(object)) { 43 DCHECK(ObjectMarking::IsBlackOrGrey(object)); 44 RememberedSet<OLD_TO_OLD>::Insert(source_page, 45 reinterpret_cast<Address>(slot)); 46 } 47 } 48 49 50 void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) { 51 if (GetNextCandidate(shared_info) == nullptr) { 52 SetNextCandidate(shared_info, shared_function_info_candidates_head_); 53 shared_function_info_candidates_head_ = shared_info; 54 } 55 } 56 57 58 void CodeFlusher::AddCandidate(JSFunction* function) { 59 DCHECK(function->code() == function->shared()->code()); 60 if (function->next_function_link()->IsUndefined(isolate_)) { 61 SetNextCandidate(function, jsfunction_candidates_head_); 62 jsfunction_candidates_head_ = function; 63 } 64 } 65 66 67 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) { 68 return reinterpret_cast<JSFunction**>( 69 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset)); 70 } 71 72 73 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) { 74 Object* next_candidate = candidate->next_function_link(); 75 return reinterpret_cast<JSFunction*>(next_candidate); 76 } 77 78 79 void CodeFlusher::SetNextCandidate(JSFunction* candidate, 80 JSFunction* next_candidate) { 81 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER); 82 } 83 84 85 void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) { 86 DCHECK(undefined->IsUndefined(candidate->GetIsolate())); 87 candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER); 88 } 89 90 91 SharedFunctionInfo* CodeFlusher::GetNextCandidate( 92 SharedFunctionInfo* candidate) { 93 Object* next_candidate = candidate->code()->gc_metadata(); 94 return reinterpret_cast<SharedFunctionInfo*>(next_candidate); 95 } 96 97 98 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate, 99 SharedFunctionInfo* next_candidate) { 100 candidate->code()->set_gc_metadata(next_candidate); 101 } 102 103 104 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) { 105 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER); 106 } 107 108 109 template <LiveObjectIterationMode T> 110 HeapObject* LiveObjectIterator<T>::Next() { 111 while (!it_.Done()) { 112 HeapObject* object = nullptr; 113 while (current_cell_ != 0) { 114 uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_); 115 Address addr = cell_base_ + trailing_zeros * kPointerSize; 116 117 // Clear the first bit of the found object.. 118 current_cell_ &= ~(1u << trailing_zeros); 119 120 uint32_t second_bit_index = 0; 121 if (trailing_zeros < Bitmap::kBitIndexMask) { 122 second_bit_index = 1u << (trailing_zeros + 1); 123 } else { 124 second_bit_index = 0x1; 125 // The overlapping case; there has to exist a cell after the current 126 // cell. 127 // However, if there is a black area at the end of the page, and the 128 // last word is a one word filler, we are not allowed to advance. In 129 // that case we can return immediately. 130 if (it_.Done()) { 131 DCHECK(HeapObject::FromAddress(addr)->map() == 132 HeapObject::FromAddress(addr) 133 ->GetHeap() 134 ->one_pointer_filler_map()); 135 return nullptr; 136 } 137 it_.Advance(); 138 cell_base_ = it_.CurrentCellBase(); 139 current_cell_ = *it_.CurrentCell(); 140 } 141 142 Map* map = nullptr; 143 if (current_cell_ & second_bit_index) { 144 // We found a black object. If the black object is within a black area, 145 // make sure that we skip all set bits in the black area until the 146 // object ends. 147 HeapObject* black_object = HeapObject::FromAddress(addr); 148 map = base::NoBarrierAtomicValue<Map*>::FromAddress(addr)->Value(); 149 Address end = addr + black_object->SizeFromMap(map) - kPointerSize; 150 // One word filler objects do not borrow the second mark bit. We have 151 // to jump over the advancing and clearing part. 152 // Note that we know that we are at a one word filler when 153 // object_start + object_size - kPointerSize == object_start. 154 if (addr != end) { 155 DCHECK_EQ(chunk_, MemoryChunk::FromAddress(end)); 156 uint32_t end_mark_bit_index = chunk_->AddressToMarkbitIndex(end); 157 unsigned int end_cell_index = 158 end_mark_bit_index >> Bitmap::kBitsPerCellLog2; 159 MarkBit::CellType end_index_mask = 160 1u << Bitmap::IndexInCell(end_mark_bit_index); 161 if (it_.Advance(end_cell_index)) { 162 cell_base_ = it_.CurrentCellBase(); 163 current_cell_ = *it_.CurrentCell(); 164 } 165 166 // Clear all bits in current_cell, including the end index. 167 current_cell_ &= ~(end_index_mask + end_index_mask - 1); 168 } 169 170 if (T == kBlackObjects || T == kAllLiveObjects) { 171 object = black_object; 172 } 173 } else if ((T == kGreyObjects || T == kAllLiveObjects)) { 174 map = base::NoBarrierAtomicValue<Map*>::FromAddress(addr)->Value(); 175 object = HeapObject::FromAddress(addr); 176 } 177 178 // We found a live object. 179 if (object != nullptr) { 180 if (map == heap()->one_pointer_filler_map()) { 181 // Black areas together with slack tracking may result in black one 182 // word filler objects. We filter these objects out in the iterator. 183 object = nullptr; 184 } else { 185 break; 186 } 187 } 188 } 189 190 if (current_cell_ == 0) { 191 if (!it_.Done()) { 192 it_.Advance(); 193 cell_base_ = it_.CurrentCellBase(); 194 current_cell_ = *it_.CurrentCell(); 195 } 196 } 197 if (object != nullptr) return object; 198 } 199 return nullptr; 200 } 201 202 } // namespace internal 203 } // namespace v8 204 205 #endif // V8_HEAP_MARK_COMPACT_INL_H_ 206