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
PushBlack(HeapObject * obj)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
UnshiftBlack(HeapObject * obj)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
MarkObject(HeapObject * obj,MarkBit mark_bit)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
SetMark(HeapObject * obj,MarkBit mark_bit)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
IsMarked(Object * obj)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
RecordSlot(HeapObject * object,Object ** slot,Object * target)59 void 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
AddCandidate(SharedFunctionInfo * shared_info)72 void 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
AddCandidate(JSFunction * function)80 void 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
GetNextCandidateSlot(JSFunction * candidate)89 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
90 return reinterpret_cast<JSFunction**>(
91 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
92 }
93
94
GetNextCandidate(JSFunction * candidate)95 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
96 Object* next_candidate = candidate->next_function_link();
97 return reinterpret_cast<JSFunction*>(next_candidate);
98 }
99
100
SetNextCandidate(JSFunction * candidate,JSFunction * next_candidate)101 void CodeFlusher::SetNextCandidate(JSFunction* candidate,
102 JSFunction* next_candidate) {
103 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
104 }
105
106
ClearNextCandidate(JSFunction * candidate,Object * undefined)107 void 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
GetNextCandidate(SharedFunctionInfo * candidate)113 SharedFunctionInfo* CodeFlusher::GetNextCandidate(
114 SharedFunctionInfo* candidate) {
115 Object* next_candidate = candidate->code()->gc_metadata();
116 return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
117 }
118
119
SetNextCandidate(SharedFunctionInfo * candidate,SharedFunctionInfo * next_candidate)120 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
121 SharedFunctionInfo* next_candidate) {
122 candidate->code()->set_gc_metadata(next_candidate);
123 }
124
125
ClearNextCandidate(SharedFunctionInfo * candidate)126 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
127 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
128 }
129
130
131 template <LiveObjectIterationMode T>
Next()132 HeapObject* 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