| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 | 50 |
| 51 | 51 |
| 52 void IncrementalMarking::TearDown() { | 52 void IncrementalMarking::TearDown() { |
| 53 delete marking_deque_memory_; | 53 delete marking_deque_memory_; |
| 54 } | 54 } |
| 55 | 55 |
| 56 | 56 |
| 57 void IncrementalMarking::RecordWriteFromCode(HeapObject* obj, | 57 void IncrementalMarking::RecordWriteFromCode(HeapObject* obj, |
| 58 Object* value, | 58 Object* value, |
| 59 Isolate* isolate) { | 59 Isolate* isolate) { |
| 60 isolate->heap()->incremental_marking()->RecordWrite(obj, value); | 60 ASSERT(obj->IsHeapObject()); |
| 61 |
| 62 IncrementalMarking* marking = isolate->heap()->incremental_marking(); |
| 63 ASSERT(!marking->is_compacting_); |
| 64 marking->RecordWrite(obj, NULL, value); |
| 61 } | 65 } |
| 62 | 66 |
| 63 | 67 |
| 68 void IncrementalMarking::RecordWriteForEvacuationFromCode(HeapObject* obj, |
| 69 Object** slot, |
| 70 Isolate* isolate) { |
| 71 IncrementalMarking* marking = isolate->heap()->incremental_marking(); |
| 72 ASSERT(marking->is_compacting_); |
| 73 marking->RecordWrite(obj, slot, *slot); |
| 74 } |
| 75 |
| 76 |
| 64 class IncrementalMarkingMarkingVisitor : public ObjectVisitor { | 77 class IncrementalMarkingMarkingVisitor : public ObjectVisitor { |
| 65 public: | 78 public: |
| 66 IncrementalMarkingMarkingVisitor(Heap* heap, | 79 IncrementalMarkingMarkingVisitor(Heap* heap, |
| 67 IncrementalMarking* incremental_marking) | 80 IncrementalMarking* incremental_marking) |
| 68 : heap_(heap), | 81 : heap_(heap), |
| 69 incremental_marking_(incremental_marking) { | 82 incremental_marking_(incremental_marking) { |
| 70 } | 83 } |
| 71 | 84 |
| 72 void VisitPointer(Object** p) { | 85 void VisitPointer(Object** p) { |
| 73 MarkObjectByPointer(p); | 86 MarkObjectByPointer(p, p); |
| 74 } | 87 } |
| 75 | 88 |
| 76 void VisitPointers(Object** start, Object** end) { | 89 void VisitPointers(Object** start, Object** end) { |
| 77 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 90 for (Object** p = start; p < end; p++) MarkObjectByPointer(start, p); |
| 78 } | 91 } |
| 79 | 92 |
| 80 private: | 93 private: |
| 81 // Mark object pointed to by p. | 94 // Mark object pointed to by p. |
| 82 INLINE(void MarkObjectByPointer(Object** p)) { | 95 INLINE(void MarkObjectByPointer(Object** anchor, Object** p)) { |
| 83 Object* obj = *p; | 96 Object* obj = *p; |
| 84 // Since we can be sure that the object is not tagged as a failure we can | 97 // Since we can be sure that the object is not tagged as a failure we can |
| 85 // inline a slightly more efficient tag check here than IsHeapObject() would | 98 // inline a slightly more efficient tag check here than IsHeapObject() would |
| 86 // produce. | 99 // produce. |
| 87 if (obj->NonFailureIsHeapObject()) { | 100 if (obj->NonFailureIsHeapObject()) { |
| 88 HeapObject* heap_object = HeapObject::cast(obj); | 101 HeapObject* heap_object = HeapObject::cast(obj); |
| 102 |
| 103 heap_->mark_compact_collector()->RecordSlot(anchor, p, obj); |
| 89 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 104 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 90 if (mark_bit.data_only()) { | 105 if (mark_bit.data_only()) { |
| 91 incremental_marking_->MarkBlackOrKeepGrey(mark_bit); | 106 incremental_marking_->MarkBlackOrKeepGrey(mark_bit); |
| 92 } else if (Marking::IsWhite(mark_bit)) { | 107 } else if (Marking::IsWhite(mark_bit)) { |
| 93 incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); | 108 incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); |
| 94 } | 109 } |
| 95 } | 110 } |
| 96 } | 111 } |
| 97 | 112 |
| 98 Heap* heap_; | 113 Heap* heap_; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 | 287 |
| 273 bool IncrementalMarking::WorthActivating() { | 288 bool IncrementalMarking::WorthActivating() { |
| 274 #ifndef DEBUG | 289 #ifndef DEBUG |
| 275 static const intptr_t kActivationThreshold = 8 * MB; | 290 static const intptr_t kActivationThreshold = 8 * MB; |
| 276 #else | 291 #else |
| 277 // TODO(gc) consider setting this to some low level so that some | 292 // TODO(gc) consider setting this to some low level so that some |
| 278 // debug tests run with incremental marking and some without. | 293 // debug tests run with incremental marking and some without. |
| 279 static const intptr_t kActivationThreshold = 0; | 294 static const intptr_t kActivationThreshold = 0; |
| 280 #endif | 295 #endif |
| 281 | 296 |
| 282 // TODO(gc) ISOLATES MERGE | |
| 283 return FLAG_incremental_marking && | 297 return FLAG_incremental_marking && |
| 284 heap_->PromotedSpaceSize() > kActivationThreshold; | 298 heap_->PromotedSpaceSize() > kActivationThreshold; |
| 285 } | 299 } |
| 286 | 300 |
| 287 | 301 |
| 288 static void PatchIncrementalMarkingRecordWriteStubs(bool enable) { | 302 static void PatchIncrementalMarkingRecordWriteStubs( |
| 289 NumberDictionary* stubs = HEAP->code_stubs(); | 303 Heap* heap, RecordWriteStub::Mode mode) { |
| 304 NumberDictionary* stubs = heap->code_stubs(); |
| 290 | 305 |
| 291 int capacity = stubs->Capacity(); | 306 int capacity = stubs->Capacity(); |
| 292 for (int i = 0; i < capacity; i++) { | 307 for (int i = 0; i < capacity; i++) { |
| 293 Object* k = stubs->KeyAt(i); | 308 Object* k = stubs->KeyAt(i); |
| 294 if (stubs->IsKey(k)) { | 309 if (stubs->IsKey(k)) { |
| 295 uint32_t key = NumberToUint32(k); | 310 uint32_t key = NumberToUint32(k); |
| 296 | 311 |
| 297 if (CodeStub::MajorKeyFromKey(key) == | 312 if (CodeStub::MajorKeyFromKey(key) == |
| 298 CodeStub::RecordWrite) { | 313 CodeStub::RecordWrite) { |
| 299 Object* e = stubs->ValueAt(i); | 314 Object* e = stubs->ValueAt(i); |
| 300 if (e->IsCode()) { | 315 if (e->IsCode()) { |
| 301 RecordWriteStub::Patch(Code::cast(e), enable); | 316 RecordWriteStub::Patch(Code::cast(e), mode); |
| 302 } | 317 } |
| 303 } | 318 } |
| 304 } | 319 } |
| 305 } | 320 } |
| 306 } | 321 } |
| 307 | 322 |
| 308 | 323 |
| 309 void IncrementalMarking::EnsureMarkingDequeIsCommitted() { | 324 void IncrementalMarking::EnsureMarkingDequeIsCommitted() { |
| 310 if (marking_deque_memory_ == NULL) { | 325 if (marking_deque_memory_ == NULL) { |
| 311 marking_deque_memory_ = new VirtualMemory(4 * MB); | 326 marking_deque_memory_ = new VirtualMemory(4 * MB); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 338 | 353 |
| 339 heap_->new_space()->LowerInlineAllocationLimit(kAllocatedThreshold); | 354 heap_->new_space()->LowerInlineAllocationLimit(kAllocatedThreshold); |
| 340 } | 355 } |
| 341 | 356 |
| 342 | 357 |
| 343 void IncrementalMarking::StartMarking() { | 358 void IncrementalMarking::StartMarking() { |
| 344 if (FLAG_trace_incremental_marking) { | 359 if (FLAG_trace_incremental_marking) { |
| 345 PrintF("[IncrementalMarking] Start marking\n"); | 360 PrintF("[IncrementalMarking] Start marking\n"); |
| 346 } | 361 } |
| 347 | 362 |
| 363 is_compacting_ = !FLAG_never_compact && |
| 364 heap_->mark_compact_collector()->StartCompaction(); |
| 365 |
| 348 state_ = MARKING; | 366 state_ = MARKING; |
| 349 | 367 |
| 350 PatchIncrementalMarkingRecordWriteStubs(true); | 368 RecordWriteStub::Mode mode = is_compacting_ ? |
| 369 RecordWriteStub::INCREMENTAL_COMPACTION : RecordWriteStub::INCREMENTAL; |
| 370 |
| 371 PatchIncrementalMarkingRecordWriteStubs(heap_, mode); |
| 351 | 372 |
| 352 EnsureMarkingDequeIsCommitted(); | 373 EnsureMarkingDequeIsCommitted(); |
| 353 | 374 |
| 354 // Initialize marking stack. | 375 // Initialize marking stack. |
| 355 Address addr = static_cast<Address>(marking_deque_memory_->address()); | 376 Address addr = static_cast<Address>(marking_deque_memory_->address()); |
| 356 int size = marking_deque_memory_->size(); | 377 int size = marking_deque_memory_->size(); |
| 357 if (FLAG_force_marking_deque_overflows) size = 64 * kPointerSize; | 378 if (FLAG_force_marking_deque_overflows) size = 64 * kPointerSize; |
| 358 marking_deque_.Initialize(addr, addr + size); | 379 marking_deque_.Initialize(addr, addr + size); |
| 359 | 380 |
| 360 // Clear markbits. | 381 // Clear markbits. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 391 intptr_t current = marking_deque_.bottom(); | 412 intptr_t current = marking_deque_.bottom(); |
| 392 intptr_t mask = marking_deque_.mask(); | 413 intptr_t mask = marking_deque_.mask(); |
| 393 intptr_t limit = marking_deque_.top(); | 414 intptr_t limit = marking_deque_.top(); |
| 394 HeapObject** array = marking_deque_.array(); | 415 HeapObject** array = marking_deque_.array(); |
| 395 intptr_t new_top = current; | 416 intptr_t new_top = current; |
| 396 | 417 |
| 397 Map* filler_map = heap_->one_pointer_filler_map(); | 418 Map* filler_map = heap_->one_pointer_filler_map(); |
| 398 | 419 |
| 399 while (current != limit) { | 420 while (current != limit) { |
| 400 HeapObject* obj = array[current]; | 421 HeapObject* obj = array[current]; |
| 422 ASSERT(obj->IsHeapObject()); |
| 401 current = ((current + 1) & mask); | 423 current = ((current + 1) & mask); |
| 402 if (heap_->InNewSpace(obj)) { | 424 if (heap_->InNewSpace(obj)) { |
| 403 MapWord map_word = obj->map_word(); | 425 MapWord map_word = obj->map_word(); |
| 404 if (map_word.IsForwardingAddress()) { | 426 if (map_word.IsForwardingAddress()) { |
| 405 HeapObject* dest = map_word.ToForwardingAddress(); | 427 HeapObject* dest = map_word.ToForwardingAddress(); |
| 406 array[new_top] = dest; | 428 array[new_top] = dest; |
| 407 new_top = ((new_top + 1) & mask); | 429 new_top = ((new_top + 1) & mask); |
| 408 ASSERT(new_top != marking_deque_.bottom()); | 430 ASSERT(new_top != marking_deque_.bottom()); |
| 409 ASSERT(Marking::IsGrey(Marking::MarkBitFrom(obj))); | 431 ASSERT(Marking::IsGrey(Marking::MarkBitFrom(obj))); |
| 410 } | 432 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 480 |
| 459 void IncrementalMarking::Abort() { | 481 void IncrementalMarking::Abort() { |
| 460 if (IsStopped()) return; | 482 if (IsStopped()) return; |
| 461 if (FLAG_trace_incremental_marking) { | 483 if (FLAG_trace_incremental_marking) { |
| 462 PrintF("[IncrementalMarking] Aborting.\n"); | 484 PrintF("[IncrementalMarking] Aborting.\n"); |
| 463 } | 485 } |
| 464 heap_->new_space()->LowerInlineAllocationLimit(0); | 486 heap_->new_space()->LowerInlineAllocationLimit(0); |
| 465 IncrementalMarking::set_should_hurry(false); | 487 IncrementalMarking::set_should_hurry(false); |
| 466 ResetStepCounters(); | 488 ResetStepCounters(); |
| 467 if (IsMarking()) { | 489 if (IsMarking()) { |
| 468 PatchIncrementalMarkingRecordWriteStubs(false); | 490 PatchIncrementalMarkingRecordWriteStubs(heap_, |
| 491 RecordWriteStub::STORE_BUFFER_ONLY); |
| 469 DeactivateIncrementalWriteBarrier(); | 492 DeactivateIncrementalWriteBarrier(); |
| 470 } | 493 } |
| 471 heap_->isolate()->stack_guard()->Continue(GC_REQUEST); | 494 heap_->isolate()->stack_guard()->Continue(GC_REQUEST); |
| 472 state_ = STOPPED; | 495 state_ = STOPPED; |
| 496 is_compacting_ = false; |
| 473 } | 497 } |
| 474 | 498 |
| 475 | 499 |
| 476 void IncrementalMarking::Finalize() { | 500 void IncrementalMarking::Finalize() { |
| 477 Hurry(); | 501 Hurry(); |
| 478 state_ = STOPPED; | 502 state_ = STOPPED; |
| 503 is_compacting_ = false; |
| 479 heap_->new_space()->LowerInlineAllocationLimit(0); | 504 heap_->new_space()->LowerInlineAllocationLimit(0); |
| 480 IncrementalMarking::set_should_hurry(false); | 505 IncrementalMarking::set_should_hurry(false); |
| 481 ResetStepCounters(); | 506 ResetStepCounters(); |
| 482 PatchIncrementalMarkingRecordWriteStubs(false); | 507 PatchIncrementalMarkingRecordWriteStubs(heap_, |
| 508 RecordWriteStub::STORE_BUFFER_ONLY); |
| 483 DeactivateIncrementalWriteBarrier(); | 509 DeactivateIncrementalWriteBarrier(); |
| 484 ASSERT(marking_deque_.IsEmpty()); | 510 ASSERT(marking_deque_.IsEmpty()); |
| 485 heap_->isolate()->stack_guard()->Continue(GC_REQUEST); | 511 heap_->isolate()->stack_guard()->Continue(GC_REQUEST); |
| 486 } | 512 } |
| 487 | 513 |
| 488 | 514 |
| 489 void IncrementalMarking::MarkingComplete() { | 515 void IncrementalMarking::MarkingComplete() { |
| 490 state_ = COMPLETE; | 516 state_ = COMPLETE; |
| 491 // We will set the stack guard to request a GC now. This will mean the rest | 517 // We will set the stack guard to request a GC now. This will mean the rest |
| 492 // of the GC gets performed as soon as possible (we can't do a GC here in a | 518 // of the GC gets performed as soon as possible (we can't do a GC here in a |
| 493 // record-write context). If a few things get allocated between now and then | 519 // record-write context). If a few things get allocated between now and then |
| 494 // that shouldn't make us do a scavenge and keep being incremental, so we set | 520 // that shouldn't make us do a scavenge and keep being incremental, so we set |
| 495 // the should-hurry flag to indicate that there can't be much work left to do. | 521 // the should-hurry flag to indicate that there can't be much work left to do. |
| 496 set_should_hurry(true); | 522 set_should_hurry(true); |
| 497 if (FLAG_trace_incremental_marking) { | 523 if (FLAG_trace_incremental_marking) { |
| 498 PrintF("[IncrementalMarking] Complete (normal).\n"); | 524 PrintF("[IncrementalMarking] Complete (normal).\n"); |
| 499 } | 525 } |
| 500 // TODO(gc) ISOLATES | 526 heap_->isolate()->stack_guard()->RequestGC(); |
| 501 ISOLATE->stack_guard()->RequestGC(); | |
| 502 } | 527 } |
| 503 | 528 |
| 504 | 529 |
| 505 void IncrementalMarking::Step(intptr_t allocated_bytes) { | 530 void IncrementalMarking::Step(intptr_t allocated_bytes) { |
| 506 if (heap_->gc_state() != Heap::NOT_IN_GC) return; | 531 if (heap_->gc_state() != Heap::NOT_IN_GC) return; |
| 507 if (!FLAG_incremental_marking) return; | 532 if (!FLAG_incremental_marking) return; |
| 508 if (!FLAG_incremental_marking_steps) return; | 533 if (!FLAG_incremental_marking_steps) return; |
| 509 | 534 |
| 510 allocated_ += allocated_bytes; | 535 allocated_ += allocated_bytes; |
| 511 | 536 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 591 if (FLAG_trace_incremental_marking || FLAG_trace_gc) { |
| 567 double end = OS::TimeCurrentMillis(); | 592 double end = OS::TimeCurrentMillis(); |
| 568 double delta = (end - start); | 593 double delta = (end - start); |
| 569 steps_took_ += delta; | 594 steps_took_ += delta; |
| 570 steps_took_since_last_gc_ += delta; | 595 steps_took_since_last_gc_ += delta; |
| 571 } | 596 } |
| 572 } | 597 } |
| 573 | 598 |
| 574 | 599 |
| 575 } } // namespace v8::internal | 600 } } // namespace v8::internal |
| OLD | NEW |