OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 CodeStub::RecordWrite) { | 205 CodeStub::RecordWrite) { |
206 Object* e = stubs->ValueAt(i); | 206 Object* e = stubs->ValueAt(i); |
207 if (e->IsCode()) { | 207 if (e->IsCode()) { |
208 RecordWriteStub::Patch(Code::cast(e), enable); | 208 RecordWriteStub::Patch(Code::cast(e), enable); |
209 } | 209 } |
210 } | 210 } |
211 } | 211 } |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
215 static VirtualMemory* marking_stack_memory = NULL; | 215 static VirtualMemory* marking_deque_memory = NULL; |
216 | 216 |
217 static void EnsureMarkingStackIsCommitted() { | 217 static void EnsureMarkingDequeIsCommitted() { |
218 if (marking_stack_memory == NULL) { | 218 if (marking_deque_memory == NULL) { |
219 marking_stack_memory = new VirtualMemory(4*MB); | 219 marking_deque_memory = new VirtualMemory(4*MB); |
220 marking_stack_memory->Commit( | 220 marking_deque_memory->Commit( |
221 reinterpret_cast<Address>(marking_stack_memory->address()), | 221 reinterpret_cast<Address>(marking_deque_memory->address()), |
222 marking_stack_memory->size(), | 222 marking_deque_memory->size(), |
223 false); // Not executable. | 223 false); // Not executable. |
224 } | 224 } |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 void IncrementalMarking::Start() { | 228 void IncrementalMarking::Start() { |
229 if (FLAG_trace_incremental_marking) { | 229 if (FLAG_trace_incremental_marking) { |
230 PrintF("[IncrementalMarking] Start\n"); | 230 PrintF("[IncrementalMarking] Start\n"); |
231 } | 231 } |
232 ASSERT(FLAG_incremental_marking); | 232 ASSERT(FLAG_incremental_marking); |
233 ASSERT(state_ == STOPPED); | 233 ASSERT(state_ == STOPPED); |
234 state_ = MARKING; | 234 state_ = MARKING; |
235 | 235 |
236 ResetStepCounters(); | 236 ResetStepCounters(); |
237 | 237 |
238 PatchIncrementalMarkingRecordWriteStubs(true); | 238 PatchIncrementalMarkingRecordWriteStubs(true); |
239 | 239 |
240 EnsureMarkingStackIsCommitted(); | 240 EnsureMarkingDequeIsCommitted(); |
241 | 241 |
242 // Initialize marking stack. | 242 // Initialize marking stack. |
243 Address addr = static_cast<Address>(marking_stack_memory->address()); | 243 Address addr = static_cast<Address>(marking_deque_memory->address()); |
244 marking_stack_.Initialize(addr, | 244 marking_deque_.Initialize(addr, |
245 addr + marking_stack_memory->size()); | 245 addr + marking_deque_memory->size()); |
246 | 246 |
247 // Clear markbits. | 247 // Clear markbits. |
248 Address new_space_low = heap_->new_space()->ToSpaceLow(); | 248 Address new_space_low = heap_->new_space()->ToSpaceLow(); |
249 Address new_space_high = heap_->new_space()->ToSpaceHigh(); | 249 Address new_space_high = heap_->new_space()->ToSpaceHigh(); |
250 heap_->marking()->ClearRange( | 250 heap_->marking()->ClearRange( |
251 new_space_low, static_cast<int>(new_space_high - new_space_low)); | 251 new_space_low, static_cast<int>(new_space_high - new_space_low)); |
252 | 252 |
253 ClearMarkbits(); | 253 ClearMarkbits(); |
254 | 254 |
255 #ifdef DEBUG | 255 #ifdef DEBUG |
(...skipping 16 matching lines...) Expand all Loading... |
272 void IncrementalMarking::PrepareForScavenge() { | 272 void IncrementalMarking::PrepareForScavenge() { |
273 if (IsStopped()) return; | 273 if (IsStopped()) return; |
274 | 274 |
275 Address new_space_low = heap_->new_space()->FromSpaceLow(); | 275 Address new_space_low = heap_->new_space()->FromSpaceLow(); |
276 Address new_space_high = heap_->new_space()->FromSpaceHigh(); | 276 Address new_space_high = heap_->new_space()->FromSpaceHigh(); |
277 heap_->marking()->ClearRange( | 277 heap_->marking()->ClearRange( |
278 new_space_low, static_cast<int>(new_space_high - new_space_low)); | 278 new_space_low, static_cast<int>(new_space_high - new_space_low)); |
279 } | 279 } |
280 | 280 |
281 | 281 |
282 void IncrementalMarking::UpdateMarkingStackAfterScavenge() { | 282 void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { |
283 if (IsStopped()) return; | 283 if (IsStopped()) return; |
284 | 284 |
285 HeapObject** current = marking_stack_.low(); | 285 intptr_t current = marking_deque_.bottom(); |
286 HeapObject** top = marking_stack_.top(); | 286 intptr_t mask = marking_deque_.mask(); |
287 HeapObject** new_top = current; | 287 intptr_t limit = marking_deque_.top(); |
| 288 HeapObject** array = marking_deque_.array(); |
| 289 intptr_t new_top = current; |
288 | 290 |
289 while (current < top) { | 291 while (current != limit) { |
290 HeapObject* obj = *current++; | 292 HeapObject* obj = array[current]; |
| 293 current = ((current + 1) & mask); |
291 if (heap_->InNewSpace(obj)) { | 294 if (heap_->InNewSpace(obj)) { |
292 MapWord map_word = obj->map_word(); | 295 MapWord map_word = obj->map_word(); |
293 if (map_word.IsForwardingAddress()) { | 296 if (map_word.IsForwardingAddress()) { |
294 HeapObject* dest = map_word.ToForwardingAddress(); | 297 HeapObject* dest = map_word.ToForwardingAddress(); |
295 WhiteToGrey(dest, heap_->marking()->MarkBitFrom(dest)); | 298 WhiteToGrey(dest, heap_->marking()->MarkBitFrom(dest)); |
296 *new_top++ = dest; | 299 array[new_top] = dest; |
| 300 new_top = ((new_top + 1) & mask); |
297 ASSERT(Color(obj) == Color(dest)); | 301 ASSERT(Color(obj) == Color(dest)); |
298 } | 302 } |
299 } else { | 303 } else { |
300 *new_top++ = obj; | 304 array[new_top] = obj; |
| 305 new_top = ((new_top + 1) & mask); |
301 } | 306 } |
302 } | 307 } |
303 | 308 |
304 marking_stack_.set_top(new_top); | 309 marking_deque_.set_top(new_top); |
305 } | 310 } |
306 | 311 |
307 | 312 |
308 void IncrementalMarking::Hurry() { | 313 void IncrementalMarking::Hurry() { |
309 if (state() == MARKING) { | 314 if (state() == MARKING) { |
310 double start = 0.0; | 315 double start = 0.0; |
311 if (FLAG_trace_incremental_marking) { | 316 if (FLAG_trace_incremental_marking) { |
312 PrintF("[IncrementalMarking] Hurry\n"); | 317 PrintF("[IncrementalMarking] Hurry\n"); |
313 start = OS::TimeCurrentMillis(); | 318 start = OS::TimeCurrentMillis(); |
314 } | 319 } |
315 // TODO(gc) hurry can mark objects it encounters black as mutator | 320 // TODO(gc) hurry can mark objects it encounters black as mutator |
316 // was stopped. | 321 // was stopped. |
317 Map* filler_map = heap_->one_pointer_filler_map(); | 322 Map* filler_map = heap_->one_pointer_filler_map(); |
318 IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 323 IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); |
319 while (!marking_stack_.is_empty()) { | 324 while (!marking_deque_.IsEmpty()) { |
320 HeapObject* obj = marking_stack_.Pop(); | 325 HeapObject* obj = marking_deque_.Pop(); |
321 | 326 |
322 // Explicitly skip one word fillers. Incremental markbit patterns are | 327 // Explicitly skip one word fillers. Incremental markbit patterns are |
323 // correct only for objects that occupy at least two words. | 328 // correct only for objects that occupy at least two words. |
324 if (obj->map() != filler_map) { | 329 if (obj->map() != filler_map) { |
325 obj->Iterate(&marking_visitor); | 330 obj->Iterate(&marking_visitor); |
326 MarkBit mark_bit = heap_->marking()->MarkBitFrom(obj); | 331 MarkBit mark_bit = heap_->marking()->MarkBitFrom(obj); |
327 MarkBlack(mark_bit); | 332 MarkBlack(mark_bit); |
328 } | 333 } |
329 } | 334 } |
330 state_ = COMPLETE; | 335 state_ = COMPLETE; |
331 if (FLAG_trace_incremental_marking) { | 336 if (FLAG_trace_incremental_marking) { |
332 double end = OS::TimeCurrentMillis(); | 337 double end = OS::TimeCurrentMillis(); |
333 PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", | 338 PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", |
334 static_cast<int>(end - start)); | 339 static_cast<int>(end - start)); |
335 } | 340 } |
336 } | 341 } |
337 } | 342 } |
338 | 343 |
339 | 344 |
340 void IncrementalMarking::Finalize() { | 345 void IncrementalMarking::Finalize() { |
341 Hurry(); | 346 Hurry(); |
342 state_ = STOPPED; | 347 state_ = STOPPED; |
343 heap_->new_space()->LowerInlineAllocationLimit(0); | 348 heap_->new_space()->LowerInlineAllocationLimit(0); |
344 IncrementalMarking::set_should_hurry(false); | 349 IncrementalMarking::set_should_hurry(false); |
345 ResetStepCounters(); | 350 ResetStepCounters(); |
346 PatchIncrementalMarkingRecordWriteStubs(false); | 351 PatchIncrementalMarkingRecordWriteStubs(false); |
347 ASSERT(marking_stack_.is_empty()); | 352 ASSERT(marking_deque_.IsEmpty()); |
348 ISOLATE->stack_guard()->Continue(GC_REQUEST); | 353 ISOLATE->stack_guard()->Continue(GC_REQUEST); |
349 } | 354 } |
350 | 355 |
351 | 356 |
352 void IncrementalMarking::MarkingComplete() { | 357 void IncrementalMarking::MarkingComplete() { |
353 state_ = COMPLETE; | 358 state_ = COMPLETE; |
354 // We will set the stack guard to request a GC now. This will mean the rest | 359 // We will set the stack guard to request a GC now. This will mean the rest |
355 // of the GC gets performed as soon as possible (we can't do a GC here in a | 360 // of the GC gets performed as soon as possible (we can't do a GC here in a |
356 // record-write context). If a few things get allocated between now and then | 361 // record-write context). If a few things get allocated between now and then |
357 // that shouldn't make us do a scavenge and keep being incremental, so we set | 362 // that shouldn't make us do a scavenge and keep being incremental, so we set |
(...skipping 19 matching lines...) Expand all Loading... |
377 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 382 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { |
378 start = OS::TimeCurrentMillis(); | 383 start = OS::TimeCurrentMillis(); |
379 } | 384 } |
380 | 385 |
381 intptr_t bytes_to_process = allocated_ * allocation_marking_factor_; | 386 intptr_t bytes_to_process = allocated_ * allocation_marking_factor_; |
382 int count = 0; | 387 int count = 0; |
383 | 388 |
384 Map* filler_map = heap_->one_pointer_filler_map(); | 389 Map* filler_map = heap_->one_pointer_filler_map(); |
385 IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 390 IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); |
386 Marking* marking = heap_->marking(); | 391 Marking* marking = heap_->marking(); |
387 while (!marking_stack_.is_empty() && bytes_to_process > 0) { | 392 while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { |
388 HeapObject* obj = marking_stack_.Pop(); | 393 HeapObject* obj = marking_deque_.Pop(); |
389 | 394 |
390 // Explicitly skip one word fillers. Incremental markbit patterns are | 395 // Explicitly skip one word fillers. Incremental markbit patterns are |
391 // correct only for objects that occupy at least two words. | 396 // correct only for objects that occupy at least two words. |
392 Map* map = obj->map(); | 397 Map* map = obj->map(); |
393 if (map != filler_map) { | 398 if (map != filler_map) { |
394 ASSERT(IsGrey(marking->MarkBitFrom(obj))); | 399 ASSERT(IsGrey(marking->MarkBitFrom(obj))); |
395 int size = obj->SizeFromMap(map); | 400 int size = obj->SizeFromMap(map); |
396 bytes_to_process -= size; | 401 bytes_to_process -= size; |
397 MarkBit map_mark_bit = marking->MarkBitFromOldSpace(map); | 402 MarkBit map_mark_bit = marking->MarkBitFromOldSpace(map); |
398 if (IsWhite(map_mark_bit)) WhiteToGreyAndPush(map, map_mark_bit); | 403 if (IsWhite(map_mark_bit)) WhiteToGreyAndPush(map, map_mark_bit); |
399 // TODO(gc) switch to static visitor instead of normal visitor. | 404 // TODO(gc) switch to static visitor instead of normal visitor. |
400 obj->IterateBody(map->instance_type(), size, &marking_visitor); | 405 obj->IterateBody(map->instance_type(), size, &marking_visitor); |
401 MarkBit obj_mark_bit = marking->MarkBitFrom(obj); | 406 MarkBit obj_mark_bit = marking->MarkBitFrom(obj); |
402 MarkBlack(obj_mark_bit); | 407 MarkBlack(obj_mark_bit); |
403 } | 408 } |
404 count++; | 409 count++; |
405 } | 410 } |
406 allocated_ = 0; | 411 allocated_ = 0; |
407 if (marking_stack_.is_empty()) MarkingComplete(); | 412 if (marking_deque_.IsEmpty()) MarkingComplete(); |
408 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 413 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { |
409 double end = OS::TimeCurrentMillis(); | 414 double end = OS::TimeCurrentMillis(); |
410 steps_took_ += (end - start); | 415 steps_took_ += (end - start); |
411 } | 416 } |
412 | 417 |
413 steps_count_++; | 418 steps_count_++; |
414 | 419 |
415 if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { | 420 if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { |
416 allocation_marking_factor_ += kAllocationMarkingFactorSpeedup; | 421 allocation_marking_factor_ += kAllocationMarkingFactorSpeedup; |
417 allocation_marking_factor_ *= 1.3; | 422 allocation_marking_factor_ *= 1.3; |
418 if (FLAG_trace_gc) { | 423 if (FLAG_trace_gc) { |
419 PrintF("Marking speed increased to %d\n", allocation_marking_factor_); | 424 PrintF("Marking speed increased to %d\n", allocation_marking_factor_); |
420 } | 425 } |
421 } | 426 } |
422 } | 427 } |
423 } | 428 } |
424 } | 429 } |
425 | 430 |
426 | 431 |
427 } } // namespace v8::internal | 432 } } // namespace v8::internal |
OLD | NEW |