blob: a59d36bfa1c463a4ecdd23caa683c98ec14dd7d9 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/heap/slots-buffer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/isolate.h"
11
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012namespace v8 {
13namespace internal {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015void 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 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022}
23
24
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025void 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 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031}
32
33
34void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
35 DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 if (Marking::IsWhite(mark_bit)) {
37 Marking::WhiteToBlack(mark_bit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 DCHECK(obj->GetIsolate()->heap()->Contains(obj));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 PushBlack(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040 }
41}
42
43
44void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045 DCHECK(Marking::IsWhite(mark_bit));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 Marking::WhiteToBlack(mark_bit);
48 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049}
50
51
52bool MarkCompactCollector::IsMarked(Object* obj) {
53 DCHECK(obj->IsHeapObject());
54 HeapObject* heap_object = HeapObject::cast(obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056}
57
58
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059void 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 }
69 }
70}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071
72
73void 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 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083
84
85void 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
93void 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
102JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
103 return reinterpret_cast<JSFunction**>(
104 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
105}
106
107
108JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
109 Object* next_candidate = candidate->next_function_link();
110 return reinterpret_cast<JSFunction*>(next_candidate);
111}
112
113
114void CodeFlusher::SetNextCandidate(JSFunction* candidate,
115 JSFunction* next_candidate) {
116 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
117}
118
119
120void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
121 DCHECK(undefined->IsUndefined());
122 candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
123}
124
125
126SharedFunctionInfo* CodeFlusher::GetNextCandidate(
127 SharedFunctionInfo* candidate) {
128 Object* next_candidate = candidate->code()->gc_metadata();
129 return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
130}
131
132
133void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
134 SharedFunctionInfo* next_candidate) {
135 candidate->code()->set_gc_metadata(next_candidate);
136}
137
138
139void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
140 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
141}
142
143
144template <LiveObjectIterationMode T>
145HeapObject* 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194
195#endif // V8_HEAP_MARK_COMPACT_INL_H_