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 |