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 12namespace v8 { 13namespace internal { 14 15void 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 25void 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 34void 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 44void 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 52bool 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 59void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot, 60 Object* target) { 61 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); 62 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(object)); 63 if (target_page->IsEvacuationCandidate() && 64 !ShouldSkipEvacuationSlotRecording(object)) { 65 DCHECK(Marking::IsBlackOrGrey(Marking::MarkBitFrom(object))); 66 RememberedSet<OLD_TO_OLD>::Insert(source_page, 67 reinterpret_cast<Address>(slot)); 68 } 69} 70 71 72void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) { 73 if (GetNextCandidate(shared_info) == nullptr) { 74 SetNextCandidate(shared_info, shared_function_info_candidates_head_); 75 shared_function_info_candidates_head_ = shared_info; 76 } 77} 78 79 80void CodeFlusher::AddCandidate(JSFunction* function) { 81 DCHECK(function->code() == function->shared()->code()); 82 if (function->next_function_link()->IsUndefined(isolate_)) { 83 SetNextCandidate(function, jsfunction_candidates_head_); 84 jsfunction_candidates_head_ = function; 85 } 86} 87 88 89JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) { 90 return reinterpret_cast<JSFunction**>( 91 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset)); 92} 93 94 95JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) { 96 Object* next_candidate = candidate->next_function_link(); 97 return reinterpret_cast<JSFunction*>(next_candidate); 98} 99 100 101void CodeFlusher::SetNextCandidate(JSFunction* candidate, 102 JSFunction* next_candidate) { 103 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER); 104} 105 106 107void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) { 108 DCHECK(undefined->IsUndefined(candidate->GetIsolate())); 109 candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER); 110} 111 112 113SharedFunctionInfo* CodeFlusher::GetNextCandidate( 114 SharedFunctionInfo* candidate) { 115 Object* next_candidate = candidate->code()->gc_metadata(); 116 return reinterpret_cast<SharedFunctionInfo*>(next_candidate); 117} 118 119 120void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate, 121 SharedFunctionInfo* next_candidate) { 122 candidate->code()->set_gc_metadata(next_candidate); 123} 124 125 126void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) { 127 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER); 128} 129 130 131template <LiveObjectIterationMode T> 132HeapObject* LiveObjectIterator<T>::Next() { 133 while (!it_.Done()) { 134 HeapObject* object = nullptr; 135 while (current_cell_ != 0) { 136 uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_); 137 Address addr = cell_base_ + trailing_zeros * kPointerSize; 138 139 // Clear the first bit of the found object.. 140 current_cell_ &= ~(1u << trailing_zeros); 141 142 uint32_t second_bit_index = 0; 143 if (trailing_zeros < Bitmap::kBitIndexMask) { 144 second_bit_index = 1u << (trailing_zeros + 1); 145 } else { 146 second_bit_index = 0x1; 147 // The overlapping case; there has to exist a cell after the current 148 // cell. 149 DCHECK(!it_.Done()); 150 it_.Advance(); 151 cell_base_ = it_.CurrentCellBase(); 152 current_cell_ = *it_.CurrentCell(); 153 } 154 if (T == kBlackObjects && (current_cell_ & second_bit_index)) { 155 object = HeapObject::FromAddress(addr); 156 } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) { 157 object = HeapObject::FromAddress(addr); 158 } else if (T == kAllLiveObjects) { 159 object = HeapObject::FromAddress(addr); 160 } 161 162 // Clear the second bit of the found object. 163 current_cell_ &= ~second_bit_index; 164 165 // We found a live object. 166 if (object != nullptr) break; 167 } 168 if (current_cell_ == 0) { 169 if (!it_.Done()) { 170 it_.Advance(); 171 cell_base_ = it_.CurrentCellBase(); 172 current_cell_ = *it_.CurrentCell(); 173 } 174 } 175 if (object != nullptr) return object; 176 } 177 return nullptr; 178} 179 180} // namespace internal 181} // namespace v8 182 183#endif // V8_HEAP_MARK_COMPACT_INL_H_ 184