Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: src/incremental-marking.h

Issue 6542047: Basic implementation of incremental marking. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
Erik Corry 2011/02/22 12:27:19 2011
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_INCREMENTAL_MARKING_H_
29 #define V8_INCREMENTAL_MARKING_H_
30
31
32 #include "execution.h"
33 #include "mark-compact.h"
34 #include "objects.h"
35
36 namespace v8 {
37 namespace internal {
38
39
40 class IncrementalMarking : public AllStatic {
41 public:
42 enum State {
43 STOPPED,
44 MARKING,
45 COMPLETE
46 };
47
48 static void Start() {
Erik Corry 2011/02/22 12:27:19 I think it would be cleaner to move largish functi
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
49 if (FLAG_trace_incremental_marking) {
50 PrintF("[IncrementalMarking] Start\n");
51 }
52 ASSERT(FLAG_incremental_marking);
53 ASSERT(state_ == STOPPED);
54 state_ = MARKING;
55
56 // Initialize marking stack.
57 marking_stack_.Initialize(Heap::new_space()->FromSpaceLow(),
58 Heap::new_space()->FromSpaceHigh());
59
60 // Clear markbits.
61 Address new_space_top = Heap::new_space()->top();
62 Address new_space_bottom = Heap::new_space()->bottom();
63
64 Marking::ClearRange(new_space_bottom,
65 static_cast<int>(new_space_top - new_space_bottom));
66
67 ClearMarkbits();
68
69 #ifdef DEBUG
70 VerifyMarkbitsAreClean();
71 #endif
72
73 // Mark strong roots grey.
74 RootMarkingVisitor visitor;
75 Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);
76
77 // Ready to start incremental marking.
78 if (FLAG_trace_incremental_marking) {
79 PrintF("[IncrementalMarking] Running\n");
80 }
81 }
82
83 static State state() {
84 ASSERT(state_ == STOPPED || FLAG_incremental_marking);
85 return state_;
86 }
87
88 static void Stop() {
89 state_ = STOPPED;
Erik Corry 2011/02/22 12:27:19 Fits on one line.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
90 }
91
92 static void Hurry() {
93 if (state() == MARKING) {
94 if (FLAG_trace_incremental_marking) {
95 PrintF("[IncrementalMarking] Hurry\n");
96 }
97 // TODO(gc) hurry can mark objects it encounters black as mutator
98 // was stopped.
99 while (!marking_stack_.is_empty()) {
100 HeapObject* obj = marking_stack_.Pop();
101 obj->Iterate(&visitor_);
102 MarkBlack(obj);
103 }
104 state_ = COMPLETE;
105 if (FLAG_trace_incremental_marking) {
106 PrintF("[IncrementalMarking] Complete (hurry)\n");
107 }
108 }
109 }
110
111 static void Finalize() {
112 Hurry();
113 state_ = STOPPED;
114 ASSERT(marking_stack_.is_empty());
115 }
116
117
118 static void MarkingComplete() {
119 state_ = COMPLETE;
120 // We completed marking.
121 if (FLAG_trace_incremental_marking) {
122 PrintF("[IncrementalMarking] Complete (normal)\n");
123 }
124 StackGuard::RequestGC();
125 }
126
127
128 static const intptr_t kAllocatedThreshold = 1024;
129 static const intptr_t kFactor = 8;
Erik Corry 2011/02/22 12:27:19 Perhaps call this kAllocationMarkingFactor.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
130
131 static void Step(intptr_t allocated) {
132 if (state_ == MARKING) {
133 allocated_ += allocated;
134
135 if (allocated_ >= kAllocatedThreshold) {
136 intptr_t bytes_to_process = allocated_ * kFactor;
137 int count = 0;
138 double start = 0;
139 if (FLAG_trace_incremental_marking) {
140 PrintF("[IncrementalMarking] Marking %d bytes\n", bytes_to_process);
141 start = OS::TimeCurrentMillis();
142 }
143 while (!marking_stack_.is_empty() && bytes_to_process > 0) {
144 HeapObject* obj = marking_stack_.Pop();
145 ASSERT(IsGrey(obj));
146 Map* map = obj->map();
147 int size = obj->SizeFromMap(map);
148 bytes_to_process -= size;
149 if (IsWhite(map)) WhiteToGrey(map);
150 obj->IterateBody(map->instance_type(), size, &visitor_);
151 MarkBlack(obj);
152 count++;
153 }
154 if (FLAG_trace_incremental_marking) {
155 double end = OS::TimeCurrentMillis();
156 PrintF("[IncrementalMarking] %d objects marked, spent %d ms\n",
157 count,
158 static_cast<int>(end - start));
159 }
160 allocated_ = 0;
161 if (marking_stack_.is_empty()) MarkingComplete();
162 }
163 }
164 }
165
166 static void RecordWrite(HeapObject* obj, Object* value) {
167 if (state_ != STOPPED && value->IsHeapObject()) {
168 if (IsBlack(obj) && IsWhite(HeapObject::cast(value))) {
169 BlackToGrey(obj);
170 if (state_ == COMPLETE) {
171 state_ = MARKING;
172 if (FLAG_trace_incremental_marking) {
173 PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
174 }
175 }
176 }
177 }
178 }
179
180 static void RecordWriteOf(HeapObject* value) {
181 if (state_ != STOPPED) {
182 if (IsWhite(value)) {
183 WhiteToGrey(value);
184 if (state_ == COMPLETE) {
185 state_ = MARKING;
186 if (FLAG_trace_incremental_marking) {
187 PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
188 }
189 }
190 }
191 }
192 }
193
194
195 static void RecordWrites(HeapObject* obj) {
196 if (state_ != STOPPED) {
197 if (IsBlack(obj)) {
198 BlackToGrey(obj);
199 if (state_ == COMPLETE) {
200 state_ = MARKING;
201 if (FLAG_trace_incremental_marking) {
202 PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
203 }
204 }
205 }
206 }
207 }
208
209
210 // Black markbits: 10
211 static inline bool IsBlack(HeapObject* obj) {
212 return Marking::IsMarked(obj->address());
Erik Corry 2011/02/22 12:27:19 Assert that the other bit is not marked?
213 }
214
215 // White markbits: 00
216 static inline bool IsWhite(HeapObject* obj) {
217 return !Marking::IsMarked(obj->address()) &&
218 !Marking::IsMarked(obj->address() + kPointerSize);
219 }
220
221 // Grey markbits: 01
Erik Corry 2011/02/22 12:27:19 Probably should be 11 when we handle overflow.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Yes. Will investigate when we start handling overf
222 static inline bool IsGrey(HeapObject* obj) {
223 return Marking::IsMarked(obj->address() + kPointerSize);
Erik Corry 2011/02/22 12:27:19 Assert that the other bit is not marked?
224 }
225
226 static inline void BlackToGrey(HeapObject* obj) {
227 ASSERT(IsBlack(obj));
228 Marking::ClearMark(obj->address());
229 Marking::SetMark(obj->address() + kPointerSize);
230 ASSERT(IsGrey(obj));
231
232 marking_stack_.Push(obj);
233 ASSERT(!marking_stack_.overflowed());
234 }
235
236 static inline void WhiteToGrey(HeapObject* obj) {
237 ASSERT(IsWhite(obj));
238 Marking::SetMark(obj->address() + kPointerSize);
239 ASSERT(IsGrey(obj));
240
241 marking_stack_.Push(obj);
242 ASSERT(!marking_stack_.overflowed());
243 }
244
245 static inline void MarkBlack(HeapObject* obj) {
246 Marking::SetMark(obj->address());
247 Marking::ClearMark(obj->address() + kPointerSize);
248 ASSERT(IsBlack(obj));
249 }
250
251 static inline const char* ColorStr(HeapObject* obj) {
252 if (IsBlack(obj)) return "black";
253 if (IsWhite(obj)) return "white";
254 if (IsGrey(obj)) return "grey";
255 return "???";
Erik Corry 2011/02/22 12:27:19 UNREACHABLE()?
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
256 }
257
258 private:
259 static intptr_t allocated_;
260 static State state_;
261 static MarkingStack marking_stack_;
262
263 class MarkingVisitor : public ObjectVisitor {
264 public:
265 void VisitPointer(Object** p) {
266 MarkObjectByPointer(p);
267 }
268
269 void VisitPointers(Object** start, Object** end) {
270 for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
271 }
272
273 private:
274 // Mark object pointed to by p.
275 INLINE(static void MarkObjectByPointer(Object** p)) {
276 if ((*p)->IsHeapObject()) {
277 HeapObject* object = HeapObject::cast(*p);
278 if (IsWhite(object)) WhiteToGrey(object);
279 }
280 }
281 };
282
283
284 class RootMarkingVisitor : public ObjectVisitor {
285 public:
286 void VisitPointer(Object** p) {
287 MarkObjectByPointer(p);
288 }
289
290 void VisitPointers(Object** start, Object** end) {
291 for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
292 }
293
294 private:
295 void MarkObjectByPointer(Object** p) {
296 if (!(*p)->IsHeapObject()) return;
297
298 HeapObject* object = HeapObject::cast(*p);
299 if (!IsWhite(object)) return;
300
301 Map* map = object->map();
302
303 WhiteToGrey(object);
Erik Corry 2011/02/22 12:27:19 This pushes the object onto the stack. When it is
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
304
305 if (IsWhite(map)) WhiteToGrey(map);
Erik Corry 2011/02/22 12:27:19 Here we also mark the map. Aren't we doing it twi
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
306 }
307 };
308
309
310 static void ClearMarkbits(PagedSpace* space) {
311 PageIterator it(space, PageIterator::PAGES_IN_USE);
312
313 while (it.has_next()) {
314 Page* p = it.next();
315 p->markbits()->Clear();
316 }
317 }
318
319
320 static void ClearMarkbits() {
321 // We are sweeping code and map spaces precisely so clearing is not required .
Erik Corry 2011/02/22 12:27:19 lint?
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
322 ClearMarkbits(Heap::old_pointer_space());
323 ClearMarkbits(Heap::old_data_space());
324 ClearMarkbits(Heap::cell_space());
325 }
326
327
328 #ifdef DEBUG
329 static void VerifyMarkbitsAreClean(PagedSpace* space) {
330 PageIterator it(space, PageIterator::PAGES_IN_USE);
331
332 while (it.has_next()) {
333 Page* p = it.next();
334 ASSERT(p->markbits()->IsClean());
335 }
336 }
337
338 static void VerifyMarkbitsAreClean() {
339 VerifyMarkbitsAreClean(Heap::old_pointer_space());
340 VerifyMarkbitsAreClean(Heap::old_data_space());
341 VerifyMarkbitsAreClean(Heap::code_space());
342 VerifyMarkbitsAreClean(Heap::cell_space());
343 VerifyMarkbitsAreClean(Heap::map_space());
344 }
345 #endif
346
347 static MarkingVisitor visitor_;
348 };
349
350 } } // namespace v8::internal
351
352 #endif // V8_INCREMENTAL_MARKING_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698