blob: f117acee9b12f8a28d0af898eb0bcb04176cf715 [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 Murdoch097c5b22016-05-18 11:27:45 +010015inline std::vector<Page*>& MarkCompactCollector::sweeping_list(Space* space) {
16 if (space == heap()->old_space()) {
17 return sweeping_list_old_space_;
18 } else if (space == heap()->code_space()) {
19 return sweeping_list_code_space_;
20 }
21 DCHECK_EQ(space, heap()->map_space());
22 return sweeping_list_map_space_;
23}
24
25
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026void MarkCompactCollector::PushBlack(HeapObject* obj) {
27 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
28 if (marking_deque_.Push(obj)) {
29 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
30 } else {
31 Marking::BlackToGrey(obj);
32 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033}
34
35
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036void MarkCompactCollector::UnshiftBlack(HeapObject* obj) {
37 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
38 if (!marking_deque_.Unshift(obj)) {
39 MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size());
40 Marking::BlackToGrey(obj);
41 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042}
43
44
45void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
46 DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 if (Marking::IsWhite(mark_bit)) {
48 Marking::WhiteToBlack(mark_bit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 DCHECK(obj->GetIsolate()->heap()->Contains(obj));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 PushBlack(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 }
52}
53
54
55void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 DCHECK(Marking::IsWhite(mark_bit));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 Marking::WhiteToBlack(mark_bit);
59 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060}
61
62
63bool MarkCompactCollector::IsMarked(Object* obj) {
64 DCHECK(obj->IsHeapObject());
65 HeapObject* heap_object = HeapObject::cast(obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067}
68
69
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot,
71 Object* target) {
72 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
73 if (target_page->IsEvacuationCandidate() &&
74 !ShouldSkipEvacuationSlotRecording(object)) {
75 if (!SlotsBuffer::AddTo(slots_buffer_allocator_,
76 target_page->slots_buffer_address(), slot,
77 SlotsBuffer::FAIL_ON_OVERFLOW)) {
78 EvictPopularEvacuationCandidate(target_page);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 }
80 }
81}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082
83
84void MarkCompactCollector::ForceRecordSlot(HeapObject* object, Object** slot,
85 Object* target) {
86 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
87 if (target_page->IsEvacuationCandidate() &&
88 !ShouldSkipEvacuationSlotRecording(object)) {
89 CHECK(SlotsBuffer::AddTo(slots_buffer_allocator_,
90 target_page->slots_buffer_address(), slot,
91 SlotsBuffer::IGNORE_OVERFLOW));
92 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094
95
96void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010097 if (GetNextCandidate(shared_info) == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 SetNextCandidate(shared_info, shared_function_info_candidates_head_);
99 shared_function_info_candidates_head_ = shared_info;
100 }
101}
102
103
104void CodeFlusher::AddCandidate(JSFunction* function) {
105 DCHECK(function->code() == function->shared()->code());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100106 if (function->next_function_link()->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 SetNextCandidate(function, jsfunction_candidates_head_);
108 jsfunction_candidates_head_ = function;
109 }
110}
111
112
113JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
114 return reinterpret_cast<JSFunction**>(
115 HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
116}
117
118
119JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
120 Object* next_candidate = candidate->next_function_link();
121 return reinterpret_cast<JSFunction*>(next_candidate);
122}
123
124
125void CodeFlusher::SetNextCandidate(JSFunction* candidate,
126 JSFunction* next_candidate) {
127 candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
128}
129
130
131void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
132 DCHECK(undefined->IsUndefined());
133 candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
134}
135
136
137SharedFunctionInfo* CodeFlusher::GetNextCandidate(
138 SharedFunctionInfo* candidate) {
139 Object* next_candidate = candidate->code()->gc_metadata();
140 return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
141}
142
143
144void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
145 SharedFunctionInfo* next_candidate) {
146 candidate->code()->set_gc_metadata(next_candidate);
147}
148
149
150void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
151 candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
152}
153
154
155template <LiveObjectIterationMode T>
156HeapObject* LiveObjectIterator<T>::Next() {
157 while (!it_.Done()) {
158 HeapObject* object = nullptr;
159 while (current_cell_ != 0) {
160 uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_);
161 Address addr = cell_base_ + trailing_zeros * kPointerSize;
162
163 // Clear the first bit of the found object..
164 current_cell_ &= ~(1u << trailing_zeros);
165
166 uint32_t second_bit_index = 0;
167 if (trailing_zeros < Bitmap::kBitIndexMask) {
168 second_bit_index = 1u << (trailing_zeros + 1);
169 } else {
170 second_bit_index = 0x1;
171 // The overlapping case; there has to exist a cell after the current
172 // cell.
173 DCHECK(!it_.Done());
174 it_.Advance();
175 cell_base_ = it_.CurrentCellBase();
176 current_cell_ = *it_.CurrentCell();
177 }
178 if (T == kBlackObjects && (current_cell_ & second_bit_index)) {
179 object = HeapObject::FromAddress(addr);
180 } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) {
181 object = HeapObject::FromAddress(addr);
182 } else if (T == kAllLiveObjects) {
183 object = HeapObject::FromAddress(addr);
184 }
185 // Clear the second bit of the found object.
186 current_cell_ &= ~second_bit_index;
187
188 // We found a live object.
189 if (object != nullptr) break;
190 }
191 if (current_cell_ == 0) {
192 if (!it_.Done()) {
193 it_.Advance();
194 cell_base_ = it_.CurrentCellBase();
195 current_cell_ = *it_.CurrentCell();
196 }
197 }
198 if (object != nullptr) return object;
199 }
200 return nullptr;
201}
202
203} // namespace internal
204} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205
206#endif // V8_HEAP_MARK_COMPACT_INL_H_