| 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/pages.h" | 11 #include "vm/pages.h" |
| 12 #include "vm/raw_object.h" | 12 #include "vm/raw_object.h" |
| 13 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
| 14 #include "vm/store_buffer.h" | 14 #include "vm/store_buffer.h" |
| 15 #include "vm/thread_barrier.h" | 15 #include "vm/thread_barrier.h" |
| 16 #include "vm/thread_pool.h" | 16 #include "vm/thread_pool.h" |
| 17 #include "vm/thread_registry.h" | 17 #include "vm/thread_registry.h" |
| 18 #include "vm/timeline.h" | 18 #include "vm/timeline.h" |
| 19 #include "vm/visitor.h" | 19 #include "vm/visitor.h" |
| 20 #include "vm/object_id_ring.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) { | 28 void Add(RawFunction* func) { skipped_code_functions_.Add(func); } |
| 29 skipped_code_functions_.Add(func); | |
| 30 } | |
| 31 | 29 |
| 32 void DetachCode() { | 30 void DetachCode() { |
| 33 #if defined(DART_PRECOMPILED_RUNTIME) | 31 #if defined(DART_PRECOMPILED_RUNTIME) |
| 34 UNREACHABLE(); | 32 UNREACHABLE(); |
| 35 #else | 33 #else |
| 36 intptr_t unoptimized_code_count = 0; | 34 intptr_t unoptimized_code_count = 0; |
| 37 intptr_t current_code_count = 0; | 35 intptr_t current_code_count = 0; |
| 38 for (int i = 0; i < skipped_code_functions_.length(); i++) { | 36 for (int i = 0; i < skipped_code_functions_.length(); i++) { |
| 39 RawFunction* func = skipped_code_functions_[i]; | 37 RawFunction* func = skipped_code_functions_[i]; |
| 40 RawCode* code = func->ptr()->code_; | 38 RawCode* code = func->ptr()->code_; |
| 41 if (!code->IsMarked()) { | 39 if (!code->IsMarked()) { |
| 42 // If the code wasn't strongly visited through other references | 40 // If the code wasn't strongly visited through other references |
| 43 // after skipping the function's code pointer, then we disconnect the | 41 // after skipping the function's code pointer, then we disconnect the |
| 44 // code from the function. | 42 // code from the function. |
| 45 func->StorePointer( | 43 func->StorePointer(&(func->ptr()->code_), |
| 46 &(func->ptr()->code_), | 44 StubCode::LazyCompile_entry()->code()); |
| 47 StubCode::LazyCompile_entry()->code()); | |
| 48 uword entry_point = StubCode::LazyCompile_entry()->EntryPoint(); | 45 uword entry_point = StubCode::LazyCompile_entry()->EntryPoint(); |
| 49 func->ptr()->entry_point_ = entry_point; | 46 func->ptr()->entry_point_ = entry_point; |
| 50 if (FLAG_log_code_drop) { | 47 if (FLAG_log_code_drop) { |
| 51 // NOTE: This code runs while GC is in progress and runs within | 48 // NOTE: This code runs while GC is in progress and runs within |
| 52 // a NoHandleScope block. Hence it is not okay to use a regular Zone | 49 // a NoHandleScope block. Hence it is not okay to use a regular Zone |
| 53 // or Scope handle. We use a direct stack handle so the raw pointer in | 50 // or Scope handle. We use a direct stack handle so the raw pointer in |
| 54 // this handle is not traversed. The use of a handle is mainly to | 51 // this handle is not traversed. The use of a handle is mainly to |
| 55 // be able to reuse the handle based code and avoid having to add | 52 // be able to reuse the handle based code and avoid having to add |
| 56 // helper functions to the raw object interface. | 53 // helper functions to the raw object interface. |
| 57 String name; | 54 String name; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // Fail fast on attempts to mark after finalizing. | 131 // Fail fast on attempts to mark after finalizing. |
| 135 marking_stack_ = NULL; | 132 marking_stack_ = NULL; |
| 136 } | 133 } |
| 137 | 134 |
| 138 private: | 135 private: |
| 139 MarkingStack::Block* work_; | 136 MarkingStack::Block* work_; |
| 140 MarkingStack* marking_stack_; | 137 MarkingStack* marking_stack_; |
| 141 }; | 138 }; |
| 142 | 139 |
| 143 | 140 |
| 144 template<bool sync> | 141 template <bool sync> |
| 145 class MarkingVisitorBase : public ObjectPointerVisitor { | 142 class MarkingVisitorBase : public ObjectPointerVisitor { |
| 146 public: | 143 public: |
| 147 MarkingVisitorBase(Isolate* isolate, | 144 MarkingVisitorBase(Isolate* isolate, |
| 148 Heap* heap, | 145 Heap* heap, |
| 149 PageSpace* page_space, | 146 PageSpace* page_space, |
| 150 MarkingStack* marking_stack, | 147 MarkingStack* marking_stack, |
| 151 SkippedCodeFunctions* skipped_code_functions) | 148 SkippedCodeFunctions* skipped_code_functions) |
| 152 : ObjectPointerVisitor(isolate), | 149 : ObjectPointerVisitor(isolate), |
| 153 thread_(Thread::Current()), | 150 thread_(Thread::Current()), |
| 154 heap_(heap), | 151 heap_(heap), |
| 155 vm_heap_(Dart::vm_isolate()->heap()), | 152 vm_heap_(Dart::vm_isolate()->heap()), |
| 156 class_stats_count_(isolate->class_table()->NumCids()), | 153 class_stats_count_(isolate->class_table()->NumCids()), |
| 157 class_stats_size_(isolate->class_table()->NumCids()), | 154 class_stats_size_(isolate->class_table()->NumCids()), |
| 158 page_space_(page_space), | 155 page_space_(page_space), |
| 159 work_list_(marking_stack), | 156 work_list_(marking_stack), |
| 160 delayed_weak_properties_(NULL), | 157 delayed_weak_properties_(NULL), |
| 161 visiting_old_object_(NULL), | 158 visiting_old_object_(NULL), |
| 162 skipped_code_functions_(skipped_code_functions), | 159 skipped_code_functions_(skipped_code_functions), |
| 163 marked_bytes_(0) { | 160 marked_bytes_(0) { |
| 164 ASSERT(heap_ != vm_heap_); | 161 ASSERT(heap_ != vm_heap_); |
| 165 ASSERT(thread_->isolate() == isolate); | 162 ASSERT(thread_->isolate() == isolate); |
| 166 class_stats_count_.SetLength(isolate->class_table()->NumCids()); | 163 class_stats_count_.SetLength(isolate->class_table()->NumCids()); |
| 167 class_stats_size_.SetLength(isolate->class_table()->NumCids()); | 164 class_stats_size_.SetLength(isolate->class_table()->NumCids()); |
| 168 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { | 165 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { |
| 169 class_stats_count_[i] = 0; | 166 class_stats_count_[i] = 0; |
| 170 class_stats_size_[i] = 0; | 167 class_stats_size_[i] = 0; |
| 171 } | 168 } |
| 172 } | 169 } |
| 173 | 170 |
| 174 uintptr_t marked_bytes() const { return marked_bytes_; } | 171 uintptr_t marked_bytes() const { return marked_bytes_; } |
| 175 | 172 |
| 176 intptr_t live_count(intptr_t class_id) { | 173 intptr_t live_count(intptr_t class_id) { |
| 177 return class_stats_count_[class_id]; | 174 return class_stats_count_[class_id]; |
| 178 } | 175 } |
| 179 | 176 |
| 180 intptr_t live_size(intptr_t class_id) { | 177 intptr_t live_size(intptr_t class_id) { return class_stats_size_[class_id]; } |
| 181 return class_stats_size_[class_id]; | |
| 182 } | |
| 183 | 178 |
| 184 bool ProcessPendingWeakProperties() { | 179 bool ProcessPendingWeakProperties() { |
| 185 bool marked = false; | 180 bool marked = false; |
| 186 RawWeakProperty* cur_weak = delayed_weak_properties_; | 181 RawWeakProperty* cur_weak = delayed_weak_properties_; |
| 187 delayed_weak_properties_ = NULL; | 182 delayed_weak_properties_ = NULL; |
| 188 while (cur_weak != NULL) { | 183 while (cur_weak != NULL) { |
| 189 uword next_weak = cur_weak->ptr()->next_; | 184 uword next_weak = cur_weak->ptr()->next_; |
| 190 RawObject* raw_key = cur_weak->ptr()->key_; | 185 RawObject* raw_key = cur_weak->ptr()->key_; |
| 191 // Reset the next pointer in the weak property. | 186 // Reset the next pointer in the weak property. |
| 192 cur_weak->ptr()->next_ = 0; | 187 cur_weak->ptr()->next_ = 0; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 } while (raw_obj != NULL); | 238 } while (raw_obj != NULL); |
| 244 VisitingOldObject(NULL); | 239 VisitingOldObject(NULL); |
| 245 } | 240 } |
| 246 | 241 |
| 247 void VisitPointers(RawObject** first, RawObject** last) { | 242 void VisitPointers(RawObject** first, RawObject** last) { |
| 248 for (RawObject** current = first; current <= last; current++) { | 243 for (RawObject** current = first; current <= last; current++) { |
| 249 MarkObject(*current, current); | 244 MarkObject(*current, current); |
| 250 } | 245 } |
| 251 } | 246 } |
| 252 | 247 |
| 253 bool visit_function_code() const { | 248 bool visit_function_code() const { return skipped_code_functions_ == NULL; } |
| 254 return skipped_code_functions_ == NULL; | |
| 255 } | |
| 256 | 249 |
| 257 virtual void add_skipped_code_function(RawFunction* func) { | 250 virtual void add_skipped_code_function(RawFunction* func) { |
| 258 ASSERT(!visit_function_code()); | 251 ASSERT(!visit_function_code()); |
| 259 skipped_code_functions_->Add(func); | 252 skipped_code_functions_->Add(func); |
| 260 } | 253 } |
| 261 | 254 |
| 262 void EnqueueWeakProperty(RawWeakProperty* raw_weak) { | 255 void EnqueueWeakProperty(RawWeakProperty* raw_weak) { |
| 263 ASSERT(raw_weak->IsHeapObject()); | 256 ASSERT(raw_weak->IsHeapObject()); |
| 264 ASSERT(raw_weak->IsOldObject()); | 257 ASSERT(raw_weak->IsOldObject()); |
| 265 ASSERT(raw_weak->IsWeakProperty()); | 258 ASSERT(raw_weak->IsWeakProperty()); |
| 266 ASSERT(raw_weak->IsMarked()); | 259 ASSERT(raw_weak->IsMarked()); |
| 267 ASSERT(raw_weak->ptr()->next_ == 0); | 260 ASSERT(raw_weak->ptr()->next_ == 0); |
| 268 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_); | 261 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_); |
| 269 delayed_weak_properties_ = raw_weak; | 262 delayed_weak_properties_ = raw_weak; |
| 270 } | 263 } |
| 271 | 264 |
| 272 intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) { | 265 intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) { |
| 273 // The fate of the weak property is determined by its key. | 266 // The fate of the weak property is determined by its key. |
| 274 RawObject* raw_key = raw_weak->ptr()->key_; | 267 RawObject* raw_key = raw_weak->ptr()->key_; |
| 275 if (raw_key->IsHeapObject() && | 268 if (raw_key->IsHeapObject() && raw_key->IsOldObject() && |
| 276 raw_key->IsOldObject() && | |
| 277 !raw_key->IsMarked()) { | 269 !raw_key->IsMarked()) { |
| 278 // Key was white. Enqueue the weak property. | 270 // Key was white. Enqueue the weak property. |
| 279 EnqueueWeakProperty(raw_weak); | 271 EnqueueWeakProperty(raw_weak); |
| 280 return raw_weak->Size(); | 272 return raw_weak->Size(); |
| 281 } | 273 } |
| 282 // Key is gray or black. Make the weak property black. | 274 // Key is gray or black. Make the weak property black. |
| 283 return raw_weak->VisitPointers(this); | 275 return raw_weak->VisitPointers(this); |
| 284 } | 276 } |
| 285 | 277 |
| 286 // Called when all marking is complete. | 278 // Called when all marking is complete. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 306 } | 298 } |
| 307 | 299 |
| 308 void VisitingOldObject(RawObject* obj) { | 300 void VisitingOldObject(RawObject* obj) { |
| 309 ASSERT((obj == NULL) || obj->IsOldObject()); | 301 ASSERT((obj == NULL) || obj->IsOldObject()); |
| 310 visiting_old_object_ = obj; | 302 visiting_old_object_ = obj; |
| 311 } | 303 } |
| 312 | 304 |
| 313 private: | 305 private: |
| 314 void PushMarked(RawObject* raw_obj) { | 306 void PushMarked(RawObject* raw_obj) { |
| 315 ASSERT(raw_obj->IsHeapObject()); | 307 ASSERT(raw_obj->IsHeapObject()); |
| 316 ASSERT((FLAG_verify_before_gc || FLAG_verify_before_gc) ? | 308 ASSERT((FLAG_verify_before_gc || FLAG_verify_before_gc) |
| 317 page_space_->Contains(RawObject::ToAddr(raw_obj)) : | 309 ? page_space_->Contains(RawObject::ToAddr(raw_obj)) |
| 318 true); | 310 : true); |
| 319 | 311 |
| 320 // Push the marked object on the marking stack. | 312 // Push the marked object on the marking stack. |
| 321 ASSERT(raw_obj->IsMarked()); | 313 ASSERT(raw_obj->IsMarked()); |
| 322 // We acquired the mark bit => no other task is modifying the header. | 314 // We acquired the mark bit => no other task is modifying the header. |
| 323 // TODO(koda): For concurrent mutator, this needs synchronization. Consider | 315 // TODO(koda): For concurrent mutator, this needs synchronization. Consider |
| 324 // clearing these bits already in the CAS for the mark bit. | 316 // clearing these bits already in the CAS for the mark bit. |
| 325 raw_obj->ClearRememberedBitUnsynchronized(); | 317 raw_obj->ClearRememberedBitUnsynchronized(); |
| 326 work_list_.Push(raw_obj); | 318 work_list_.Push(raw_obj); |
| 327 } | 319 } |
| 328 | 320 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 423 } |
| 432 if (!raw_obj->IsOldObject()) { | 424 if (!raw_obj->IsOldObject()) { |
| 433 return false; | 425 return false; |
| 434 } | 426 } |
| 435 return !raw_obj->IsMarked(); | 427 return !raw_obj->IsMarked(); |
| 436 } | 428 } |
| 437 | 429 |
| 438 | 430 |
| 439 class MarkingWeakVisitor : public HandleVisitor { | 431 class MarkingWeakVisitor : public HandleVisitor { |
| 440 public: | 432 public: |
| 441 MarkingWeakVisitor(Thread* thread, FinalizationQueue* queue) : | 433 MarkingWeakVisitor(Thread* thread, FinalizationQueue* queue) |
| 442 HandleVisitor(thread), queue_(queue) { } | 434 : HandleVisitor(thread), queue_(queue) {} |
| 443 | 435 |
| 444 void VisitHandle(uword addr) { | 436 void VisitHandle(uword addr) { |
| 445 FinalizablePersistentHandle* handle = | 437 FinalizablePersistentHandle* handle = |
| 446 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 438 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
| 447 RawObject* raw_obj = handle->raw(); | 439 RawObject* raw_obj = handle->raw(); |
| 448 if (IsUnreachable(raw_obj)) { | 440 if (IsUnreachable(raw_obj)) { |
| 449 handle->UpdateUnreachable(thread()->isolate(), queue_); | 441 handle->UpdateUnreachable(thread()->isolate(), queue_); |
| 450 } | 442 } |
| 451 } | 443 } |
| 452 | 444 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 469 | 461 |
| 470 void GCMarker::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { | 462 void GCMarker::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { |
| 471 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { | 463 if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) { |
| 472 (isolate->gc_epilogue_callback())(); | 464 (isolate->gc_epilogue_callback())(); |
| 473 } | 465 } |
| 474 } | 466 } |
| 475 | 467 |
| 476 | 468 |
| 477 void GCMarker::IterateRoots(Isolate* isolate, | 469 void GCMarker::IterateRoots(Isolate* isolate, |
| 478 ObjectPointerVisitor* visitor, | 470 ObjectPointerVisitor* visitor, |
| 479 intptr_t slice_index, intptr_t num_slices) { | 471 intptr_t slice_index, |
| 472 intptr_t num_slices) { |
| 480 ASSERT(0 <= slice_index && slice_index < num_slices); | 473 ASSERT(0 <= slice_index && slice_index < num_slices); |
| 481 if ((slice_index == 0) || (num_slices <= 1)) { | 474 if ((slice_index == 0) || (num_slices <= 1)) { |
| 482 isolate->VisitObjectPointers(visitor, | 475 isolate->VisitObjectPointers(visitor, |
| 483 StackFrameIterator::kDontValidateFrames); | 476 StackFrameIterator::kDontValidateFrames); |
| 484 } | 477 } |
| 485 if ((slice_index == 1) || (num_slices <= 1)) { | 478 if ((slice_index == 1) || (num_slices <= 1)) { |
| 486 heap_->new_space()->VisitObjectPointers(visitor); | 479 heap_->new_space()->VisitObjectPointers(visitor); |
| 487 } | 480 } |
| 488 | 481 |
| 489 // For now, we just distinguish two parts of the root set, so any remaining | 482 // For now, we just distinguish two parts of the root set, so any remaining |
| 490 // slices are empty. | 483 // slices are empty. |
| 491 } | 484 } |
| 492 | 485 |
| 493 | 486 |
| 494 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { | 487 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { |
| 495 ApiState* state = isolate->api_state(); | 488 ApiState* state = isolate->api_state(); |
| 496 ASSERT(state != NULL); | 489 ASSERT(state != NULL); |
| 497 isolate->VisitWeakPersistentHandles(visitor); | 490 isolate->VisitWeakPersistentHandles(visitor); |
| 498 } | 491 } |
| 499 | 492 |
| 500 | 493 |
| 501 void GCMarker::ProcessWeakTables(PageSpace* page_space) { | 494 void GCMarker::ProcessWeakTables(PageSpace* page_space) { |
| 502 for (int sel = 0; | 495 for (int sel = 0; sel < Heap::kNumWeakSelectors; sel++) { |
| 503 sel < Heap::kNumWeakSelectors; | 496 WeakTable* table = |
| 504 sel++) { | 497 heap_->GetWeakTable(Heap::kOld, static_cast<Heap::WeakSelector>(sel)); |
| 505 WeakTable* table = heap_->GetWeakTable( | |
| 506 Heap::kOld, static_cast<Heap::WeakSelector>(sel)); | |
| 507 intptr_t size = table->size(); | 498 intptr_t size = table->size(); |
| 508 for (intptr_t i = 0; i < size; i++) { | 499 for (intptr_t i = 0; i < size; i++) { |
| 509 if (table->IsValidEntryAt(i)) { | 500 if (table->IsValidEntryAt(i)) { |
| 510 RawObject* raw_obj = table->ObjectAt(i); | 501 RawObject* raw_obj = table->ObjectAt(i); |
| 511 ASSERT(raw_obj->IsHeapObject()); | 502 ASSERT(raw_obj->IsHeapObject()); |
| 512 if (!raw_obj->IsMarked()) { | 503 if (!raw_obj->IsMarked()) { |
| 513 table->InvalidateAt(i); | 504 table->InvalidateAt(i); |
| 514 } | 505 } |
| 515 } | 506 } |
| 516 } | 507 } |
| 517 } | 508 } |
| 518 } | 509 } |
| 519 | 510 |
| 520 | 511 |
| 521 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor { | 512 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor { |
| 522 public: | 513 public: |
| 523 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) : | 514 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) |
| 524 ObjectPointerVisitor(isolate) {} | 515 : ObjectPointerVisitor(isolate) {} |
| 525 | 516 |
| 526 | 517 |
| 527 void VisitPointers(RawObject** first, RawObject** last) { | 518 void VisitPointers(RawObject** first, RawObject** last) { |
| 528 for (RawObject** current = first; current <= last; current++) { | 519 for (RawObject** current = first; current <= last; current++) { |
| 529 RawObject* raw_obj = *current; | 520 RawObject* raw_obj = *current; |
| 530 ASSERT(raw_obj->IsHeapObject()); | 521 ASSERT(raw_obj->IsHeapObject()); |
| 531 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) { | 522 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) { |
| 532 // Object has become garbage. Replace it will null. | 523 // Object has become garbage. Replace it will null. |
| 533 *current = Object::null(); | 524 *current = Object::null(); |
| 534 } | 525 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 564 uintptr_t* num_busy) | 555 uintptr_t* num_busy) |
| 565 : marker_(marker), | 556 : marker_(marker), |
| 566 isolate_(isolate), | 557 isolate_(isolate), |
| 567 heap_(heap), | 558 heap_(heap), |
| 568 page_space_(page_space), | 559 page_space_(page_space), |
| 569 marking_stack_(marking_stack), | 560 marking_stack_(marking_stack), |
| 570 barrier_(barrier), | 561 barrier_(barrier), |
| 571 collect_code_(collect_code), | 562 collect_code_(collect_code), |
| 572 task_index_(task_index), | 563 task_index_(task_index), |
| 573 num_tasks_(num_tasks), | 564 num_tasks_(num_tasks), |
| 574 num_busy_(num_busy) { | 565 num_busy_(num_busy) {} |
| 575 } | |
| 576 | 566 |
| 577 virtual void Run() { | 567 virtual void Run() { |
| 578 bool result = | 568 bool result = |
| 579 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); | 569 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); |
| 580 ASSERT(result); | 570 ASSERT(result); |
| 581 { | 571 { |
| 582 Thread* thread = Thread::Current(); | 572 Thread* thread = Thread::Current(); |
| 583 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); | 573 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); |
| 584 StackZone stack_zone(thread); | 574 StackZone stack_zone(thread); |
| 585 Zone* zone = stack_zone.GetZone(); | 575 Zone* zone = stack_zone.GetZone(); |
| 586 SkippedCodeFunctions* skipped_code_functions = | 576 SkippedCodeFunctions* skipped_code_functions = |
| 587 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL; | 577 collect_code_ ? new (zone) SkippedCodeFunctions() : NULL; |
| 588 SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, | 578 SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, |
| 589 skipped_code_functions); | 579 skipped_code_functions); |
| 590 // Phase 1: Iterate over roots and drain marking stack in tasks. | 580 // Phase 1: Iterate over roots and drain marking stack in tasks. |
| 591 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); | 581 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); |
| 592 | 582 |
| 593 bool more_to_mark = false; | 583 bool more_to_mark = false; |
| 594 do { | 584 do { |
| 595 do { | 585 do { |
| 596 visitor.DrainMarkingStack(); | 586 visitor.DrainMarkingStack(); |
| 597 | 587 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 more_to_mark = true; | 631 more_to_mark = true; |
| 642 } | 632 } |
| 643 barrier_->Sync(); | 633 barrier_->Sync(); |
| 644 } while (more_to_mark); | 634 } while (more_to_mark); |
| 645 | 635 |
| 646 // Phase 2: Weak processing and follow-up marking on main thread. | 636 // Phase 2: Weak processing and follow-up marking on main thread. |
| 647 barrier_->Sync(); | 637 barrier_->Sync(); |
| 648 | 638 |
| 649 // Phase 3: Finalize results from all markers (detach code, etc.). | 639 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 650 if (FLAG_log_marker_tasks) { | 640 if (FLAG_log_marker_tasks) { |
| 651 THR_Print("Task %" Pd " marked %" Pd " bytes.\n", | 641 THR_Print("Task %" Pd " marked %" Pd " bytes.\n", task_index_, |
| 652 task_index_, visitor.marked_bytes()); | 642 visitor.marked_bytes()); |
| 653 } | 643 } |
| 654 marker_->FinalizeResultsFrom(&visitor); | 644 marker_->FinalizeResultsFrom(&visitor); |
| 655 } | 645 } |
| 656 Thread::ExitIsolateAsHelper(true); | 646 Thread::ExitIsolateAsHelper(true); |
| 657 | 647 |
| 658 // This task is done. Notify the original thread. | 648 // This task is done. Notify the original thread. |
| 659 barrier_->Exit(); | 649 barrier_->Exit(); |
| 660 } | 650 } |
| 661 | 651 |
| 662 private: | 652 private: |
| 663 GCMarker* marker_; | 653 GCMarker* marker_; |
| 664 Isolate* isolate_; | 654 Isolate* isolate_; |
| 665 Heap* heap_; | 655 Heap* heap_; |
| 666 PageSpace* page_space_; | 656 PageSpace* page_space_; |
| 667 MarkingStack* marking_stack_; | 657 MarkingStack* marking_stack_; |
| 668 ThreadBarrier* barrier_; | 658 ThreadBarrier* barrier_; |
| 669 bool collect_code_; | 659 bool collect_code_; |
| 670 const intptr_t task_index_; | 660 const intptr_t task_index_; |
| 671 const intptr_t num_tasks_; | 661 const intptr_t num_tasks_; |
| 672 uintptr_t* num_busy_; | 662 uintptr_t* num_busy_; |
| 673 | 663 |
| 674 DISALLOW_COPY_AND_ASSIGN(MarkTask); | 664 DISALLOW_COPY_AND_ASSIGN(MarkTask); |
| 675 }; | 665 }; |
| 676 | 666 |
| 677 | 667 |
| 678 template<class MarkingVisitorType> | 668 template <class MarkingVisitorType> |
| 679 void GCMarker::FinalizeResultsFrom(MarkingVisitorType* visitor) { | 669 void GCMarker::FinalizeResultsFrom(MarkingVisitorType* visitor) { |
| 680 { | 670 { |
| 681 MutexLocker ml(&stats_mutex_); | 671 MutexLocker ml(&stats_mutex_); |
| 682 marked_bytes_ += visitor->marked_bytes(); | 672 marked_bytes_ += visitor->marked_bytes(); |
| 683 #ifndef PRODUCT | 673 #ifndef PRODUCT |
| 684 // Class heap stats are not themselves thread-safe yet, so we update the | 674 // Class heap stats are not themselves thread-safe yet, so we update the |
| 685 // stats while holding stats_mutex_. | 675 // stats while holding stats_mutex_. |
| 686 ClassTable* table = heap_->isolate()->class_table(); | 676 ClassTable* table = heap_->isolate()->class_table(); |
| 687 for (intptr_t i = 0; i < table->NumCids(); ++i) { | 677 for (intptr_t i = 0; i < table->NumCids(); ++i) { |
| 688 const intptr_t count = visitor->live_count(i); | 678 const intptr_t count = visitor->live_count(i); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 707 { | 697 { |
| 708 Thread* thread = Thread::Current(); | 698 Thread* thread = Thread::Current(); |
| 709 StackZone stack_zone(thread); | 699 StackZone stack_zone(thread); |
| 710 Zone* zone = stack_zone.GetZone(); | 700 Zone* zone = stack_zone.GetZone(); |
| 711 MarkingStack marking_stack; | 701 MarkingStack marking_stack; |
| 712 marked_bytes_ = 0; | 702 marked_bytes_ = 0; |
| 713 const int num_tasks = FLAG_marker_tasks; | 703 const int num_tasks = FLAG_marker_tasks; |
| 714 if (num_tasks == 0) { | 704 if (num_tasks == 0) { |
| 715 // Mark everything on main thread. | 705 // Mark everything on main thread. |
| 716 SkippedCodeFunctions* skipped_code_functions = | 706 SkippedCodeFunctions* skipped_code_functions = |
| 717 collect_code ? new(zone) SkippedCodeFunctions() : NULL; | 707 collect_code ? new (zone) SkippedCodeFunctions() : NULL; |
| 718 UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, | 708 UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, |
| 719 skipped_code_functions); | 709 skipped_code_functions); |
| 720 IterateRoots(isolate, &mark, 0, 1); | 710 IterateRoots(isolate, &mark, 0, 1); |
| 721 mark.DrainMarkingStack(); | 711 mark.DrainMarkingStack(); |
| 722 { | 712 { |
| 723 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); | 713 TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing"); |
| 724 if (FLAG_background_finalization) { | 714 if (FLAG_background_finalization) { |
| 725 FinalizationQueue* queue = new FinalizationQueue(); | 715 FinalizationQueue* queue = new FinalizationQueue(); |
| 726 MarkingWeakVisitor mark_weak(thread, queue); | 716 MarkingWeakVisitor mark_weak(thread, queue); |
| 727 IterateWeakRoots(isolate, &mark_weak); | 717 IterateWeakRoots(isolate, &mark_weak); |
| 728 if (queue->length() > 0) { | 718 if (queue->length() > 0) { |
| 729 Dart::thread_pool()->Run(new BackgroundFinalizer(isolate, queue)); | 719 Dart::thread_pool()->Run(new BackgroundFinalizer(isolate, queue)); |
| 730 } else { | 720 } else { |
| 731 delete queue; | 721 delete queue; |
| 732 } | 722 } |
| 733 } else { | 723 } else { |
| 734 MarkingWeakVisitor mark_weak(thread, NULL); | 724 MarkingWeakVisitor mark_weak(thread, NULL); |
| 735 IterateWeakRoots(isolate, &mark_weak); | 725 IterateWeakRoots(isolate, &mark_weak); |
| 736 } | 726 } |
| 737 } | 727 } |
| 738 // All marking done; detach code, etc. | 728 // All marking done; detach code, etc. |
| 739 FinalizeResultsFrom(&mark); | 729 FinalizeResultsFrom(&mark); |
| 740 } else { | 730 } else { |
| 741 ThreadBarrier barrier(num_tasks + 1, | 731 ThreadBarrier barrier(num_tasks + 1, heap_->barrier(), |
| 742 heap_->barrier(), | |
| 743 heap_->barrier_done()); | 732 heap_->barrier_done()); |
| 744 // Used to coordinate draining among tasks; all start out as 'busy'. | 733 // Used to coordinate draining among tasks; all start out as 'busy'. |
| 745 uintptr_t num_busy = num_tasks; | 734 uintptr_t num_busy = num_tasks; |
| 746 // Phase 1: Iterate over roots and drain marking stack in tasks. | 735 // Phase 1: Iterate over roots and drain marking stack in tasks. |
| 747 for (intptr_t i = 0; i < num_tasks; ++i) { | 736 for (intptr_t i = 0; i < num_tasks; ++i) { |
| 748 MarkTask* mark_task = | 737 MarkTask* mark_task = |
| 749 new MarkTask(this, isolate, heap_, page_space, &marking_stack, | 738 new MarkTask(this, isolate, heap_, page_space, &marking_stack, |
| 750 &barrier, collect_code, | 739 &barrier, collect_code, i, num_tasks, &num_busy); |
| 751 i, num_tasks, &num_busy); | |
| 752 ThreadPool* pool = Dart::thread_pool(); | 740 ThreadPool* pool = Dart::thread_pool(); |
| 753 pool->Run(mark_task); | 741 pool->Run(mark_task); |
| 754 } | 742 } |
| 755 bool more_to_mark = false; | 743 bool more_to_mark = false; |
| 756 do { | 744 do { |
| 757 // Wait for all markers to stop. | 745 // Wait for all markers to stop. |
| 758 barrier.Sync(); | 746 barrier.Sync(); |
| 759 #if defined(DEBUG) | 747 #if defined(DEBUG) |
| 760 ASSERT(AtomicOperations::LoadRelaxed(&num_busy) == 0); | 748 ASSERT(AtomicOperations::LoadRelaxed(&num_busy) == 0); |
| 761 // Caveat: must not allow any marker to continue past the barrier | 749 // Caveat: must not allow any marker to continue past the barrier |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 // Phase 3: Finalize results from all markers (detach code, etc.). | 783 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 796 barrier.Exit(); | 784 barrier.Exit(); |
| 797 } | 785 } |
| 798 ProcessWeakTables(page_space); | 786 ProcessWeakTables(page_space); |
| 799 ProcessObjectIdTable(isolate); | 787 ProcessObjectIdTable(isolate); |
| 800 } | 788 } |
| 801 Epilogue(isolate, invoke_api_callbacks); | 789 Epilogue(isolate, invoke_api_callbacks); |
| 802 } | 790 } |
| 803 | 791 |
| 804 } // namespace dart | 792 } // namespace dart |
| OLD | NEW |