OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/gc_marker.h" | 5 #include "vm/gc_marker.h" |
6 | 6 |
7 #include "vm/allocation.h" | 7 #include "vm/allocation.h" |
8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/log.h" | 10 #include "vm/log.h" |
| 11 #include "vm/object_id_ring.h" |
11 #include "vm/pages.h" | 12 #include "vm/pages.h" |
12 #include "vm/raw_object.h" | 13 #include "vm/raw_object.h" |
13 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
14 #include "vm/store_buffer.h" | 15 #include "vm/store_buffer.h" |
15 #include "vm/thread_barrier.h" | 16 #include "vm/thread_barrier.h" |
16 #include "vm/thread_pool.h" | 17 #include "vm/thread_pool.h" |
17 #include "vm/thread_registry.h" | 18 #include "vm/thread_registry.h" |
18 #include "vm/timeline.h" | 19 #include "vm/timeline.h" |
19 #include "vm/visitor.h" | 20 #include "vm/visitor.h" |
20 #include "vm/object_id_ring.h" | |
21 | 21 |
22 namespace dart { | 22 namespace dart { |
23 | 23 |
24 class SkippedCodeFunctions : public ZoneAllocated { | 24 class SkippedCodeFunctions : public ZoneAllocated { |
25 public: | 25 public: |
26 SkippedCodeFunctions() {} | 26 SkippedCodeFunctions() {} |
27 | 27 |
28 void Add(RawFunction* func) { skipped_code_functions_.Add(func); } | 28 void Add(RawFunction* func) { skipped_code_functions_.Add(func); } |
29 | 29 |
30 void DetachCode() { | 30 void DetachCode() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 skipped_code_functions_.Clear(); | 78 skipped_code_functions_.Clear(); |
79 #endif // !DART_PRECOMPILED_RUNTIME | 79 #endif // !DART_PRECOMPILED_RUNTIME |
80 } | 80 } |
81 | 81 |
82 private: | 82 private: |
83 GrowableArray<RawFunction*> skipped_code_functions_; | 83 GrowableArray<RawFunction*> skipped_code_functions_; |
84 | 84 |
85 DISALLOW_COPY_AND_ASSIGN(SkippedCodeFunctions); | 85 DISALLOW_COPY_AND_ASSIGN(SkippedCodeFunctions); |
86 }; | 86 }; |
87 | 87 |
88 | |
89 class MarkerWorkList : public ValueObject { | 88 class MarkerWorkList : public ValueObject { |
90 public: | 89 public: |
91 explicit MarkerWorkList(MarkingStack* marking_stack) | 90 explicit MarkerWorkList(MarkingStack* marking_stack) |
92 : marking_stack_(marking_stack) { | 91 : marking_stack_(marking_stack) { |
93 work_ = marking_stack_->PopEmptyBlock(); | 92 work_ = marking_stack_->PopEmptyBlock(); |
94 } | 93 } |
95 | 94 |
96 ~MarkerWorkList() { | 95 ~MarkerWorkList() { |
97 ASSERT(work_ == NULL); | 96 ASSERT(work_ == NULL); |
98 ASSERT(marking_stack_ == NULL); | 97 ASSERT(marking_stack_ == NULL); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 work_ = NULL; | 129 work_ = NULL; |
131 // Fail fast on attempts to mark after finalizing. | 130 // Fail fast on attempts to mark after finalizing. |
132 marking_stack_ = NULL; | 131 marking_stack_ = NULL; |
133 } | 132 } |
134 | 133 |
135 private: | 134 private: |
136 MarkingStack::Block* work_; | 135 MarkingStack::Block* work_; |
137 MarkingStack* marking_stack_; | 136 MarkingStack* marking_stack_; |
138 }; | 137 }; |
139 | 138 |
140 | |
141 template <bool sync> | 139 template <bool sync> |
142 class MarkingVisitorBase : public ObjectPointerVisitor { | 140 class MarkingVisitorBase : public ObjectPointerVisitor { |
143 public: | 141 public: |
144 MarkingVisitorBase(Isolate* isolate, | 142 MarkingVisitorBase(Isolate* isolate, |
145 PageSpace* page_space, | 143 PageSpace* page_space, |
146 MarkingStack* marking_stack, | 144 MarkingStack* marking_stack, |
147 SkippedCodeFunctions* skipped_code_functions) | 145 SkippedCodeFunctions* skipped_code_functions) |
148 : ObjectPointerVisitor(isolate), | 146 : ObjectPointerVisitor(isolate), |
149 thread_(Thread::Current()), | 147 thread_(Thread::Current()), |
150 #ifndef PRODUCT | 148 #ifndef PRODUCT |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 PageSpace* page_space_; | 407 PageSpace* page_space_; |
410 MarkerWorkList work_list_; | 408 MarkerWorkList work_list_; |
411 RawWeakProperty* delayed_weak_properties_; | 409 RawWeakProperty* delayed_weak_properties_; |
412 RawObject* visiting_old_object_; | 410 RawObject* visiting_old_object_; |
413 SkippedCodeFunctions* skipped_code_functions_; | 411 SkippedCodeFunctions* skipped_code_functions_; |
414 uintptr_t marked_bytes_; | 412 uintptr_t marked_bytes_; |
415 | 413 |
416 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); | 414 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); |
417 }; | 415 }; |
418 | 416 |
419 | |
420 typedef MarkingVisitorBase<false> UnsyncMarkingVisitor; | 417 typedef MarkingVisitorBase<false> UnsyncMarkingVisitor; |
421 typedef MarkingVisitorBase<true> SyncMarkingVisitor; | 418 typedef MarkingVisitorBase<true> SyncMarkingVisitor; |
422 | 419 |
423 | |
424 static bool IsUnreachable(const RawObject* raw_obj) { | 420 static bool IsUnreachable(const RawObject* raw_obj) { |
425 if (!raw_obj->IsHeapObject()) { | 421 if (!raw_obj->IsHeapObject()) { |
426 return false; | 422 return false; |
427 } | 423 } |
428 if (raw_obj == Object::null()) { | 424 if (raw_obj == Object::null()) { |
429 return true; | 425 return true; |
430 } | 426 } |
431 if (!raw_obj->IsOldObject()) { | 427 if (!raw_obj->IsOldObject()) { |
432 return false; | 428 return false; |
433 } | 429 } |
434 return !raw_obj->IsMarked(); | 430 return !raw_obj->IsMarked(); |
435 } | 431 } |
436 | 432 |
437 | |
438 class MarkingWeakVisitor : public HandleVisitor { | 433 class MarkingWeakVisitor : public HandleVisitor { |
439 public: | 434 public: |
440 explicit MarkingWeakVisitor(Thread* thread) : HandleVisitor(thread) {} | 435 explicit MarkingWeakVisitor(Thread* thread) : HandleVisitor(thread) {} |
441 | 436 |
442 void VisitHandle(uword addr) { | 437 void VisitHandle(uword addr) { |
443 FinalizablePersistentHandle* handle = | 438 FinalizablePersistentHandle* handle = |
444 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 439 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
445 RawObject* raw_obj = handle->raw(); | 440 RawObject* raw_obj = handle->raw(); |
446 if (IsUnreachable(raw_obj)) { | 441 if (IsUnreachable(raw_obj)) { |
447 handle->UpdateUnreachable(thread()->isolate()); | 442 handle->UpdateUnreachable(thread()->isolate()); |
448 } | 443 } |
449 } | 444 } |
450 | 445 |
451 private: | 446 private: |
452 DISALLOW_COPY_AND_ASSIGN(MarkingWeakVisitor); | 447 DISALLOW_COPY_AND_ASSIGN(MarkingWeakVisitor); |
453 }; | 448 }; |
454 | 449 |
455 | |
456 void GCMarker::Prologue(Isolate* isolate, bool invoke_api_callbacks) { | 450 void GCMarker::Prologue(Isolate* isolate, bool invoke_api_callbacks) { |
457 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { | 451 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { |
458 (isolate->gc_prologue_callback())(); | 452 (isolate->gc_prologue_callback())(); |
459 } | 453 } |
460 isolate->PrepareForGC(); | 454 isolate->PrepareForGC(); |
461 // The store buffers will be rebuilt as part of marking, reset them now. | 455 // The store buffers will be rebuilt as part of marking, reset them now. |
462 isolate->store_buffer()->Reset(); | 456 isolate->store_buffer()->Reset(); |
463 } | 457 } |
464 | 458 |
465 | |
466 void GCMarker::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { | 459 void GCMarker::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { |
467 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { | 460 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { |
468 (isolate->gc_epilogue_callback())(); | 461 (isolate->gc_epilogue_callback())(); |
469 } | 462 } |
470 } | 463 } |
471 | 464 |
472 | |
473 void GCMarker::IterateRoots(Isolate* isolate, | 465 void GCMarker::IterateRoots(Isolate* isolate, |
474 ObjectPointerVisitor* visitor, | 466 ObjectPointerVisitor* visitor, |
475 intptr_t slice_index, | 467 intptr_t slice_index, |
476 intptr_t num_slices) { | 468 intptr_t num_slices) { |
477 ASSERT(0 <= slice_index && slice_index < num_slices); | 469 ASSERT(0 <= slice_index && slice_index < num_slices); |
478 if ((slice_index == 0) || (num_slices <= 1)) { | 470 if ((slice_index == 0) || (num_slices <= 1)) { |
479 isolate->VisitObjectPointers(visitor, | 471 isolate->VisitObjectPointers(visitor, |
480 StackFrameIterator::kDontValidateFrames); | 472 StackFrameIterator::kDontValidateFrames); |
481 } | 473 } |
482 if ((slice_index == 1) || (num_slices <= 1)) { | 474 if ((slice_index == 1) || (num_slices <= 1)) { |
483 heap_->new_space()->VisitObjectPointers(visitor); | 475 heap_->new_space()->VisitObjectPointers(visitor); |
484 } | 476 } |
485 | 477 |
486 // For now, we just distinguish two parts of the root set, so any remaining | 478 // For now, we just distinguish two parts of the root set, so any remaining |
487 // slices are empty. | 479 // slices are empty. |
488 } | 480 } |
489 | 481 |
490 | |
491 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { | 482 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { |
492 ApiState* state = isolate->api_state(); | 483 ApiState* state = isolate->api_state(); |
493 ASSERT(state != NULL); | 484 ASSERT(state != NULL); |
494 isolate->VisitWeakPersistentHandles(visitor); | 485 isolate->VisitWeakPersistentHandles(visitor); |
495 } | 486 } |
496 | 487 |
497 | |
498 void GCMarker::ProcessWeakTables(PageSpace* page_space) { | 488 void GCMarker::ProcessWeakTables(PageSpace* page_space) { |
499 for (int sel = 0; sel < Heap::kNumWeakSelectors; sel++) { | 489 for (int sel = 0; sel < Heap::kNumWeakSelectors; sel++) { |
500 WeakTable* table = | 490 WeakTable* table = |
501 heap_->GetWeakTable(Heap::kOld, static_cast<Heap::WeakSelector>(sel)); | 491 heap_->GetWeakTable(Heap::kOld, static_cast<Heap::WeakSelector>(sel)); |
502 intptr_t size = table->size(); | 492 intptr_t size = table->size(); |
503 for (intptr_t i = 0; i < size; i++) { | 493 for (intptr_t i = 0; i < size; i++) { |
504 if (table->IsValidEntryAt(i)) { | 494 if (table->IsValidEntryAt(i)) { |
505 RawObject* raw_obj = table->ObjectAt(i); | 495 RawObject* raw_obj = table->ObjectAt(i); |
506 ASSERT(raw_obj->IsHeapObject()); | 496 ASSERT(raw_obj->IsHeapObject()); |
507 if (!raw_obj->IsMarked()) { | 497 if (!raw_obj->IsMarked()) { |
508 table->InvalidateAt(i); | 498 table->InvalidateAt(i); |
509 } | 499 } |
510 } | 500 } |
511 } | 501 } |
512 } | 502 } |
513 } | 503 } |
514 | 504 |
515 | |
516 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor { | 505 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor { |
517 public: | 506 public: |
518 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) | 507 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) |
519 : ObjectPointerVisitor(isolate) {} | 508 : ObjectPointerVisitor(isolate) {} |
520 | 509 |
521 | |
522 void VisitPointers(RawObject** first, RawObject** last) { | 510 void VisitPointers(RawObject** first, RawObject** last) { |
523 for (RawObject** current = first; current <= last; current++) { | 511 for (RawObject** current = first; current <= last; current++) { |
524 RawObject* raw_obj = *current; | 512 RawObject* raw_obj = *current; |
525 ASSERT(raw_obj->IsHeapObject()); | 513 ASSERT(raw_obj->IsHeapObject()); |
526 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) { | 514 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) { |
527 // Object has become garbage. Replace it will null. | 515 // Object has become garbage. Replace it will null. |
528 *current = Object::null(); | 516 *current = Object::null(); |
529 } | 517 } |
530 } | 518 } |
531 } | 519 } |
532 }; | 520 }; |
533 | 521 |
534 | |
535 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { | 522 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { |
536 #ifndef PRODUCT | 523 #ifndef PRODUCT |
537 if (!FLAG_support_service) { | 524 if (!FLAG_support_service) { |
538 return; | 525 return; |
539 } | 526 } |
540 ObjectIdRingClearPointerVisitor visitor(isolate); | 527 ObjectIdRingClearPointerVisitor visitor(isolate); |
541 ObjectIdRing* ring = isolate->object_id_ring(); | 528 ObjectIdRing* ring = isolate->object_id_ring(); |
542 ASSERT(ring != NULL); | 529 ASSERT(ring != NULL); |
543 ring->VisitPointers(&visitor); | 530 ring->VisitPointers(&visitor); |
544 #endif // !PRODUCT | 531 #endif // !PRODUCT |
545 } | 532 } |
546 | 533 |
547 | |
548 class MarkTask : public ThreadPool::Task { | 534 class MarkTask : public ThreadPool::Task { |
549 public: | 535 public: |
550 MarkTask(GCMarker* marker, | 536 MarkTask(GCMarker* marker, |
551 Isolate* isolate, | 537 Isolate* isolate, |
552 Heap* heap, | 538 Heap* heap, |
553 PageSpace* page_space, | 539 PageSpace* page_space, |
554 MarkingStack* marking_stack, | 540 MarkingStack* marking_stack, |
555 ThreadBarrier* barrier, | 541 ThreadBarrier* barrier, |
556 bool collect_code, | 542 bool collect_code, |
557 intptr_t task_index, | 543 intptr_t task_index, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 MarkingStack* marking_stack_; | 647 MarkingStack* marking_stack_; |
662 ThreadBarrier* barrier_; | 648 ThreadBarrier* barrier_; |
663 bool collect_code_; | 649 bool collect_code_; |
664 const intptr_t task_index_; | 650 const intptr_t task_index_; |
665 const intptr_t num_tasks_; | 651 const intptr_t num_tasks_; |
666 uintptr_t* num_busy_; | 652 uintptr_t* num_busy_; |
667 | 653 |
668 DISALLOW_COPY_AND_ASSIGN(MarkTask); | 654 DISALLOW_COPY_AND_ASSIGN(MarkTask); |
669 }; | 655 }; |
670 | 656 |
671 | |
672 template <class MarkingVisitorType> | 657 template <class MarkingVisitorType> |
673 void GCMarker::FinalizeResultsFrom(MarkingVisitorType* visitor) { | 658 void GCMarker::FinalizeResultsFrom(MarkingVisitorType* visitor) { |
674 { | 659 { |
675 MutexLocker ml(&stats_mutex_); | 660 MutexLocker ml(&stats_mutex_); |
676 marked_bytes_ += visitor->marked_bytes(); | 661 marked_bytes_ += visitor->marked_bytes(); |
677 #ifndef PRODUCT | 662 #ifndef PRODUCT |
678 // Class heap stats are not themselves thread-safe yet, so we update the | 663 // Class heap stats are not themselves thread-safe yet, so we update the |
679 // stats while holding stats_mutex_. | 664 // stats while holding stats_mutex_. |
680 ClassTable* table = heap_->isolate()->class_table(); | 665 ClassTable* table = heap_->isolate()->class_table(); |
681 for (intptr_t i = 0; i < table->NumCids(); ++i) { | 666 for (intptr_t i = 0; i < table->NumCids(); ++i) { |
682 const intptr_t count = visitor->live_count(i); | 667 const intptr_t count = visitor->live_count(i); |
683 if (count > 0) { | 668 if (count > 0) { |
684 const intptr_t size = visitor->live_size(i); | 669 const intptr_t size = visitor->live_size(i); |
685 table->UpdateLiveOld(i, size, count); | 670 table->UpdateLiveOld(i, size, count); |
686 } | 671 } |
687 } | 672 } |
688 #endif // !PRODUCT | 673 #endif // !PRODUCT |
689 } | 674 } |
690 visitor->Finalize(); | 675 visitor->Finalize(); |
691 } | 676 } |
692 | 677 |
693 | |
694 void GCMarker::MarkObjects(Isolate* isolate, | 678 void GCMarker::MarkObjects(Isolate* isolate, |
695 PageSpace* page_space, | 679 PageSpace* page_space, |
696 bool invoke_api_callbacks, | 680 bool invoke_api_callbacks, |
697 bool collect_code) { | 681 bool collect_code) { |
698 Prologue(isolate, invoke_api_callbacks); | 682 Prologue(isolate, invoke_api_callbacks); |
699 // The API prologue/epilogue may create/destroy zones, so we must not | 683 // The API prologue/epilogue may create/destroy zones, so we must not |
700 // depend on zone allocations surviving beyond the epilogue callback. | 684 // depend on zone allocations surviving beyond the epilogue callback. |
701 { | 685 { |
702 Thread* thread = Thread::Current(); | 686 Thread* thread = Thread::Current(); |
703 StackZone stack_zone(thread); | 687 StackZone stack_zone(thread); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 // Phase 3: Finalize results from all markers (detach code, etc.). | 749 // Phase 3: Finalize results from all markers (detach code, etc.). |
766 barrier.Exit(); | 750 barrier.Exit(); |
767 } | 751 } |
768 ProcessWeakTables(page_space); | 752 ProcessWeakTables(page_space); |
769 ProcessObjectIdTable(isolate); | 753 ProcessObjectIdTable(isolate); |
770 } | 754 } |
771 Epilogue(isolate, invoke_api_callbacks); | 755 Epilogue(isolate, invoke_api_callbacks); |
772 } | 756 } |
773 | 757 |
774 } // namespace dart | 758 } // namespace dart |
OLD | NEW |