| 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" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 private: | 135 private: |
| 136 MarkingStack::Block* work_; | 136 MarkingStack::Block* work_; |
| 137 MarkingStack* marking_stack_; | 137 MarkingStack* marking_stack_; |
| 138 }; | 138 }; |
| 139 | 139 |
| 140 | 140 |
| 141 template <bool sync> | 141 template <bool sync> |
| 142 class MarkingVisitorBase : public ObjectPointerVisitor { | 142 class MarkingVisitorBase : public ObjectPointerVisitor { |
| 143 public: | 143 public: |
| 144 MarkingVisitorBase(Isolate* isolate, | 144 MarkingVisitorBase(Isolate* isolate, |
| 145 Heap* heap, | |
| 146 PageSpace* page_space, | 145 PageSpace* page_space, |
| 147 MarkingStack* marking_stack, | 146 MarkingStack* marking_stack, |
| 148 SkippedCodeFunctions* skipped_code_functions) | 147 SkippedCodeFunctions* skipped_code_functions) |
| 149 : ObjectPointerVisitor(isolate), | 148 : ObjectPointerVisitor(isolate), |
| 150 thread_(Thread::Current()), | 149 thread_(Thread::Current()), |
| 151 heap_(heap), | 150 #ifndef PRODUCT |
| 152 vm_heap_(Dart::vm_isolate()->heap()), | |
| 153 class_stats_count_(isolate->class_table()->NumCids()), | 151 class_stats_count_(isolate->class_table()->NumCids()), |
| 154 class_stats_size_(isolate->class_table()->NumCids()), | 152 class_stats_size_(isolate->class_table()->NumCids()), |
| 153 #endif // !PRODUCT |
| 155 page_space_(page_space), | 154 page_space_(page_space), |
| 156 work_list_(marking_stack), | 155 work_list_(marking_stack), |
| 157 delayed_weak_properties_(NULL), | 156 delayed_weak_properties_(NULL), |
| 158 visiting_old_object_(NULL), | 157 visiting_old_object_(NULL), |
| 159 skipped_code_functions_(skipped_code_functions), | 158 skipped_code_functions_(skipped_code_functions), |
| 160 marked_bytes_(0) { | 159 marked_bytes_(0) { |
| 161 ASSERT(heap_ != vm_heap_); | |
| 162 ASSERT(thread_->isolate() == isolate); | 160 ASSERT(thread_->isolate() == isolate); |
| 161 #ifndef PRODUCT |
| 163 class_stats_count_.SetLength(isolate->class_table()->NumCids()); | 162 class_stats_count_.SetLength(isolate->class_table()->NumCids()); |
| 164 class_stats_size_.SetLength(isolate->class_table()->NumCids()); | 163 class_stats_size_.SetLength(isolate->class_table()->NumCids()); |
| 165 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { | 164 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { |
| 166 class_stats_count_[i] = 0; | 165 class_stats_count_[i] = 0; |
| 167 class_stats_size_[i] = 0; | 166 class_stats_size_[i] = 0; |
| 168 } | 167 } |
| 168 #endif // !PRODUCT |
| 169 } | 169 } |
| 170 | 170 |
| 171 uintptr_t marked_bytes() const { return marked_bytes_; } | 171 uintptr_t marked_bytes() const { return marked_bytes_; } |
| 172 | 172 |
| 173 #ifndef PRODUCT |
| 173 intptr_t live_count(intptr_t class_id) { | 174 intptr_t live_count(intptr_t class_id) { |
| 174 return class_stats_count_[class_id]; | 175 return class_stats_count_[class_id]; |
| 175 } | 176 } |
| 176 | 177 |
| 177 intptr_t live_size(intptr_t class_id) { return class_stats_size_[class_id]; } | 178 intptr_t live_size(intptr_t class_id) { return class_stats_size_[class_id]; } |
| 179 #endif // !PRODUCT |
| 178 | 180 |
| 179 bool ProcessPendingWeakProperties() { | 181 bool ProcessPendingWeakProperties() { |
| 180 bool marked = false; | 182 bool marked = false; |
| 181 RawWeakProperty* cur_weak = delayed_weak_properties_; | 183 RawWeakProperty* cur_weak = delayed_weak_properties_; |
| 182 delayed_weak_properties_ = NULL; | 184 delayed_weak_properties_ = NULL; |
| 183 while (cur_weak != NULL) { | 185 while (cur_weak != NULL) { |
| 184 uword next_weak = cur_weak->ptr()->next_; | 186 uword next_weak = cur_weak->ptr()->next_; |
| 185 RawObject* raw_key = cur_weak->ptr()->key_; | 187 RawObject* raw_key = cur_weak->ptr()->key_; |
| 186 // Reset the next pointer in the weak property. | 188 // Reset the next pointer in the weak property. |
| 187 cur_weak->ptr()->next_ = 0; | 189 cur_weak->ptr()->next_ = 0; |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 // ... | 348 // ... |
| 347 if (raw_obj->IsNewObject()) { | 349 if (raw_obj->IsNewObject()) { |
| 348 ProcessNewSpaceObject(raw_obj, p); | 350 ProcessNewSpaceObject(raw_obj, p); |
| 349 return; | 351 return; |
| 350 } | 352 } |
| 351 | 353 |
| 352 if (!TryAcquireMarkBit(raw_obj)) { | 354 if (!TryAcquireMarkBit(raw_obj)) { |
| 353 // Already marked. | 355 // Already marked. |
| 354 return; | 356 return; |
| 355 } | 357 } |
| 358 |
| 359 #ifndef PRODUCT |
| 356 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) { | 360 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) { |
| 357 UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size()); | 361 UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size()); |
| 358 } else { | 362 } else { |
| 359 UpdateLiveOld(raw_obj->GetClassId(), 0); | 363 UpdateLiveOld(raw_obj->GetClassId(), 0); |
| 360 } | 364 } |
| 365 #endif // !PRODUCT |
| 361 | 366 |
| 362 PushMarked(raw_obj); | 367 PushMarked(raw_obj); |
| 363 } | 368 } |
| 364 | 369 |
| 365 static bool TryAcquireRememberedBit(RawObject* raw_obj) { | 370 static bool TryAcquireRememberedBit(RawObject* raw_obj) { |
| 366 if (!sync) { | 371 if (!sync) { |
| 367 if (raw_obj->IsRemembered()) return false; | 372 if (raw_obj->IsRemembered()) return false; |
| 368 raw_obj->SetRememberedBitUnsynchronized(); | 373 raw_obj->SetRememberedBitUnsynchronized(); |
| 369 return true; | 374 return true; |
| 370 } | 375 } |
| 371 return raw_obj->TryAcquireRememberedBit(); | 376 return raw_obj->TryAcquireRememberedBit(); |
| 372 } | 377 } |
| 373 | 378 |
| 374 void ProcessNewSpaceObject(RawObject* raw_obj, RawObject** p) { | 379 void ProcessNewSpaceObject(RawObject* raw_obj, RawObject** p) { |
| 375 // TODO(iposva): Add consistency check. | 380 // TODO(iposva): Add consistency check. |
| 376 if ((visiting_old_object_ != NULL) && | 381 if ((visiting_old_object_ != NULL) && |
| 377 TryAcquireRememberedBit(visiting_old_object_)) { | 382 TryAcquireRememberedBit(visiting_old_object_)) { |
| 378 // NOTE: We pass in the pointer to the address we are visiting | 383 // NOTE: We pass in the pointer to the address we are visiting |
| 379 // allows us to get a distance from the object start. At some | 384 // allows us to get a distance from the object start. At some |
| 380 // point we might want to store exact addresses in store buffers | 385 // point we might want to store exact addresses in store buffers |
| 381 // for locations far enough from the header, so that we do not | 386 // for locations far enough from the header, so that we do not |
| 382 // need to walk big objects only to find the single new | 387 // need to walk big objects only to find the single new |
| 383 // reference in the last word during scavenge. This doesn't seem | 388 // reference in the last word during scavenge. This doesn't seem |
| 384 // to be a problem though currently. | 389 // to be a problem though currently. |
| 385 ASSERT(p != NULL); | 390 ASSERT(p != NULL); |
| 386 thread_->StoreBufferAddObjectGC(visiting_old_object_); | 391 thread_->StoreBufferAddObjectGC(visiting_old_object_); |
| 387 } | 392 } |
| 388 } | 393 } |
| 389 | 394 |
| 395 #ifndef PRODUCT |
| 390 void UpdateLiveOld(intptr_t class_id, intptr_t size) { | 396 void UpdateLiveOld(intptr_t class_id, intptr_t size) { |
| 391 // TODO(koda): Support growing the array once mutator runs concurrently. | 397 // TODO(koda): Support growing the array once mutator runs concurrently. |
| 392 ASSERT(class_id < class_stats_count_.length()); | 398 ASSERT(class_id < class_stats_count_.length()); |
| 393 class_stats_count_[class_id] += 1; | 399 class_stats_count_[class_id] += 1; |
| 394 class_stats_size_[class_id] += size; | 400 class_stats_size_[class_id] += size; |
| 395 } | 401 } |
| 402 #endif // !PRODUCT |
| 396 | 403 |
| 397 Thread* thread_; | 404 Thread* thread_; |
| 398 Heap* heap_; | 405 #ifndef PRODUCT |
| 399 Heap* vm_heap_; | |
| 400 GrowableArray<intptr_t> class_stats_count_; | 406 GrowableArray<intptr_t> class_stats_count_; |
| 401 GrowableArray<intptr_t> class_stats_size_; | 407 GrowableArray<intptr_t> class_stats_size_; |
| 408 #endif // !PRODUCT |
| 402 PageSpace* page_space_; | 409 PageSpace* page_space_; |
| 403 MarkerWorkList work_list_; | 410 MarkerWorkList work_list_; |
| 404 RawWeakProperty* delayed_weak_properties_; | 411 RawWeakProperty* delayed_weak_properties_; |
| 405 RawObject* visiting_old_object_; | 412 RawObject* visiting_old_object_; |
| 406 SkippedCodeFunctions* skipped_code_functions_; | 413 SkippedCodeFunctions* skipped_code_functions_; |
| 407 uintptr_t marked_bytes_; | 414 uintptr_t marked_bytes_; |
| 408 | 415 |
| 409 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); | 416 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); |
| 410 }; | 417 }; |
| 411 | 418 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 bool result = | 572 bool result = |
| 566 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); | 573 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); |
| 567 ASSERT(result); | 574 ASSERT(result); |
| 568 { | 575 { |
| 569 Thread* thread = Thread::Current(); | 576 Thread* thread = Thread::Current(); |
| 570 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); | 577 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); |
| 571 StackZone stack_zone(thread); | 578 StackZone stack_zone(thread); |
| 572 Zone* zone = stack_zone.GetZone(); | 579 Zone* zone = stack_zone.GetZone(); |
| 573 SkippedCodeFunctions* skipped_code_functions = | 580 SkippedCodeFunctions* skipped_code_functions = |
| 574 collect_code_ ? new (zone) SkippedCodeFunctions() : NULL; | 581 collect_code_ ? new (zone) SkippedCodeFunctions() : NULL; |
| 575 SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, | 582 SyncMarkingVisitor visitor(isolate_, page_space_, marking_stack_, |
| 576 skipped_code_functions); | 583 skipped_code_functions); |
| 577 // Phase 1: Iterate over roots and drain marking stack in tasks. | 584 // Phase 1: Iterate over roots and drain marking stack in tasks. |
| 578 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); | 585 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); |
| 579 | 586 |
| 580 bool more_to_mark = false; | 587 bool more_to_mark = false; |
| 581 do { | 588 do { |
| 582 do { | 589 do { |
| 583 visitor.DrainMarkingStack(); | 590 visitor.DrainMarkingStack(); |
| 584 | 591 |
| 585 // I can't find more work right now. If no other task is busy, | 592 // I can't find more work right now. If no other task is busy, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 Thread* thread = Thread::Current(); | 702 Thread* thread = Thread::Current(); |
| 696 StackZone stack_zone(thread); | 703 StackZone stack_zone(thread); |
| 697 Zone* zone = stack_zone.GetZone(); | 704 Zone* zone = stack_zone.GetZone(); |
| 698 MarkingStack marking_stack; | 705 MarkingStack marking_stack; |
| 699 marked_bytes_ = 0; | 706 marked_bytes_ = 0; |
| 700 const int num_tasks = FLAG_marker_tasks; | 707 const int num_tasks = FLAG_marker_tasks; |
| 701 if (num_tasks == 0) { | 708 if (num_tasks == 0) { |
| 702 // Mark everything on main thread. | 709 // Mark everything on main thread. |
| 703 SkippedCodeFunctions* skipped_code_functions = | 710 SkippedCodeFunctions* skipped_code_functions = |
| 704 collect_code ? new (zone) SkippedCodeFunctions() : NULL; | 711 collect_code ? new (zone) SkippedCodeFunctions() : NULL; |
| 705 UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, | 712 UnsyncMarkingVisitor mark(isolate, page_space, &marking_stack, |
| 706 skipped_code_functions); | 713 skipped_code_functions); |
| 707 IterateRoots(isolate, &mark, 0, 1); | 714 IterateRoots(isolate, &mark, 0, 1); |
| 708 mark.DrainMarkingStack(); | 715 mark.DrainMarkingStack(); |
| 709 { | 716 { |
| 710 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); | 717 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); |
| 711 MarkingWeakVisitor mark_weak(thread); | 718 MarkingWeakVisitor mark_weak(thread); |
| 712 IterateWeakRoots(isolate, &mark_weak); | 719 IterateWeakRoots(isolate, &mark_weak); |
| 713 } | 720 } |
| 714 // All marking done; detach code, etc. | 721 // All marking done; detach code, etc. |
| 715 FinalizeResultsFrom(&mark); | 722 FinalizeResultsFrom(&mark); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 // Phase 3: Finalize results from all markers (detach code, etc.). | 765 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 759 barrier.Exit(); | 766 barrier.Exit(); |
| 760 } | 767 } |
| 761 ProcessWeakTables(page_space); | 768 ProcessWeakTables(page_space); |
| 762 ProcessObjectIdTable(isolate); | 769 ProcessObjectIdTable(isolate); |
| 763 } | 770 } |
| 764 Epilogue(isolate, invoke_api_callbacks); | 771 Epilogue(isolate, invoke_api_callbacks); |
| 765 } | 772 } |
| 766 | 773 |
| 767 } // namespace dart | 774 } // namespace dart |
| OLD | NEW |