Chromium Code Reviews| 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 <map> | |
| 8 #include <utility> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "vm/allocation.h" | 7 #include "vm/allocation.h" |
| 12 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
| 13 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 14 #include "vm/log.h" | 10 #include "vm/log.h" |
| 15 #include "vm/pages.h" | 11 #include "vm/pages.h" |
| 16 #include "vm/raw_object.h" | 12 #include "vm/raw_object.h" |
| 17 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
| 18 #include "vm/store_buffer.h" | 14 #include "vm/store_buffer.h" |
| 19 #include "vm/thread_barrier.h" | 15 #include "vm/thread_barrier.h" |
| 20 #include "vm/thread_pool.h" | 16 #include "vm/thread_pool.h" |
| 21 #include "vm/thread_registry.h" | 17 #include "vm/thread_registry.h" |
| 22 #include "vm/timeline.h" | 18 #include "vm/timeline.h" |
| 23 #include "vm/visitor.h" | 19 #include "vm/visitor.h" |
| 24 #include "vm/object_id_ring.h" | 20 #include "vm/object_id_ring.h" |
| 25 | 21 |
| 26 namespace dart { | 22 namespace dart { |
| 27 | 23 |
| 28 class DelaySet { | |
| 29 private: | |
| 30 typedef std::multimap<RawObject*, RawWeakProperty*> Map; | |
| 31 typedef std::pair<RawObject*, RawWeakProperty*> MapEntry; | |
| 32 | |
| 33 public: | |
| 34 DelaySet() : mutex_(new Mutex()) {} | |
| 35 ~DelaySet() { delete mutex_; } | |
| 36 | |
| 37 // After atomically setting the watched bit on a white key (see | |
| 38 // EnsureWatchedIfWhitewhich; this means the mark bit cannot be set | |
| 39 // without observing the watched bit), this method atomically | |
| 40 // inserts raw_weak if its key is *still* white, so that any future | |
| 41 // call to VisitValuesForKey is guaranteed to include its | |
| 42 // value. Returns true on success, and false if the key is no longer white. | |
| 43 bool InsertIfWhite(RawWeakProperty* raw_weak) { | |
| 44 MutexLocker ml(mutex_); | |
| 45 RawObject* raw_key = raw_weak->ptr()->key_; | |
| 46 if (raw_key->IsMarked()) return false; | |
| 47 // The key was white *after* acquiring the lock. Thus any future call to | |
| 48 // VisitValuesForKey is guaranteed to include the entry inserted below. | |
| 49 delay_set_.insert(std::make_pair(raw_key, raw_weak)); | |
| 50 return true; | |
| 51 } | |
| 52 | |
| 53 void ClearReferences() { | |
| 54 MutexLocker ml(mutex_); | |
| 55 for (Map::iterator it = delay_set_.begin(); it != delay_set_.end(); ++it) { | |
| 56 ASSERT(!it->first->IsMarked()); | |
| 57 WeakProperty::Clear(it->second); | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 // Visit all values with a key equal to raw_obj, which must already be marked. | |
| 62 void VisitValuesForKey(RawObject* raw_obj, ObjectPointerVisitor* visitor) { | |
| 63 ASSERT(raw_obj->IsMarked()); | |
| 64 // Extract the range into a temporary vector to iterate over it | |
| 65 // while delay_set_ may be modified. | |
| 66 std::vector<MapEntry> temp_copy; | |
| 67 { | |
| 68 MutexLocker ml(mutex_); | |
| 69 std::pair<Map::iterator, Map::iterator> ret = | |
| 70 delay_set_.equal_range(raw_obj); | |
| 71 temp_copy.insert(temp_copy.end(), ret.first, ret.second); | |
| 72 delay_set_.erase(ret.first, ret.second); | |
| 73 } | |
| 74 for (std::vector<MapEntry>::iterator it = temp_copy.begin(); | |
| 75 it != temp_copy.end(); ++it) { | |
| 76 it->second->VisitPointers(visitor); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 private: | |
| 81 Map delay_set_; | |
| 82 Mutex* mutex_; | |
| 83 }; | |
| 84 | |
| 85 | |
| 86 class SkippedCodeFunctions : public ZoneAllocated { | 24 class SkippedCodeFunctions : public ZoneAllocated { |
| 87 public: | 25 public: |
| 88 SkippedCodeFunctions() {} | 26 SkippedCodeFunctions() {} |
| 89 | 27 |
| 90 void Add(RawFunction* func) { | 28 void Add(RawFunction* func) { |
| 91 skipped_code_functions_.Add(func); | 29 skipped_code_functions_.Add(func); |
| 92 } | 30 } |
| 93 | 31 |
| 94 void DetachCode() { | 32 void DetachCode() { |
| 95 intptr_t unoptimized_code_count = 0; | 33 intptr_t unoptimized_code_count = 0; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 }; | 137 }; |
| 200 | 138 |
| 201 | 139 |
| 202 template<bool sync> | 140 template<bool sync> |
| 203 class MarkingVisitorBase : public ObjectPointerVisitor { | 141 class MarkingVisitorBase : public ObjectPointerVisitor { |
| 204 public: | 142 public: |
| 205 MarkingVisitorBase(Isolate* isolate, | 143 MarkingVisitorBase(Isolate* isolate, |
| 206 Heap* heap, | 144 Heap* heap, |
| 207 PageSpace* page_space, | 145 PageSpace* page_space, |
| 208 MarkingStack* marking_stack, | 146 MarkingStack* marking_stack, |
| 209 DelaySet* delay_set, | |
| 210 SkippedCodeFunctions* skipped_code_functions) | 147 SkippedCodeFunctions* skipped_code_functions) |
| 211 : ObjectPointerVisitor(isolate), | 148 : ObjectPointerVisitor(isolate), |
| 212 thread_(Thread::Current()), | 149 thread_(Thread::Current()), |
| 213 heap_(heap), | 150 heap_(heap), |
| 214 vm_heap_(Dart::vm_isolate()->heap()), | 151 vm_heap_(Dart::vm_isolate()->heap()), |
| 215 class_stats_count_(isolate->class_table()->NumCids()), | 152 class_stats_count_(isolate->class_table()->NumCids()), |
| 216 class_stats_size_(isolate->class_table()->NumCids()), | 153 class_stats_size_(isolate->class_table()->NumCids()), |
| 217 page_space_(page_space), | 154 page_space_(page_space), |
| 218 work_list_(marking_stack), | 155 work_list_(marking_stack), |
| 219 delay_set_(delay_set), | 156 delayed_weak_properties_(NULL), |
| 220 visiting_old_object_(NULL), | 157 visiting_old_object_(NULL), |
| 221 skipped_code_functions_(skipped_code_functions), | 158 skipped_code_functions_(skipped_code_functions), |
| 222 marked_bytes_(0) { | 159 marked_bytes_(0) { |
| 223 ASSERT(heap_ != vm_heap_); | 160 ASSERT(heap_ != vm_heap_); |
| 224 ASSERT(thread_->isolate() == isolate); | 161 ASSERT(thread_->isolate() == isolate); |
| 225 class_stats_count_.SetLength(isolate->class_table()->NumCids()); | 162 class_stats_count_.SetLength(isolate->class_table()->NumCids()); |
| 226 class_stats_size_.SetLength(isolate->class_table()->NumCids()); | 163 class_stats_size_.SetLength(isolate->class_table()->NumCids()); |
| 227 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { | 164 for (intptr_t i = 0; i < class_stats_count_.length(); ++i) { |
| 228 class_stats_count_[i] = 0; | 165 class_stats_count_[i] = 0; |
| 229 class_stats_size_[i] = 0; | 166 class_stats_size_[i] = 0; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 241 } | 178 } |
| 242 | 179 |
| 243 // Returns true if some non-zero amount of work was performed. | 180 // Returns true if some non-zero amount of work was performed. |
| 244 bool DrainMarkingStack() { | 181 bool DrainMarkingStack() { |
| 245 RawObject* raw_obj = work_list_.Pop(); | 182 RawObject* raw_obj = work_list_.Pop(); |
| 246 if (raw_obj == NULL) { | 183 if (raw_obj == NULL) { |
| 247 ASSERT(visiting_old_object_ == NULL); | 184 ASSERT(visiting_old_object_ == NULL); |
| 248 return false; | 185 return false; |
| 249 } | 186 } |
| 250 do { | 187 do { |
| 251 VisitingOldObject(raw_obj); | 188 do { |
| 252 const intptr_t class_id = raw_obj->GetClassId(); | 189 // First drain the marking stacks. |
| 253 if (class_id != kWeakPropertyCid) { | 190 VisitingOldObject(raw_obj); |
| 254 marked_bytes_ += raw_obj->VisitPointers(this); | 191 const intptr_t class_id = raw_obj->GetClassId(); |
| 255 } else { | 192 if (class_id != kWeakPropertyCid) { |
| 256 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | 193 marked_bytes_ += raw_obj->VisitPointers(this); |
| 257 marked_bytes_ += raw_weak->Size(); | 194 } else { |
| 258 ProcessWeakProperty(raw_weak); | 195 RawWeakProperty* raw_weak = |
| 196 reinterpret_cast<RawWeakProperty*>(raw_obj); | |
| 197 marked_bytes_ += ProcessWeakProperty(raw_weak); | |
| 198 } | |
| 199 raw_obj = work_list_.Pop(); | |
| 200 } while (raw_obj != NULL); | |
| 201 | |
| 202 // Marking stack is empty. | |
| 203 // Process all the pending weak properties in this visitor. | |
| 204 RawWeakProperty* cur_weak = delayed_weak_properties_; | |
| 205 delayed_weak_properties_ = NULL; | |
| 206 while (cur_weak != NULL) { | |
| 207 uword next_weak = cur_weak->ptr()->next_; | |
| 208 RawObject* raw_key = cur_weak->ptr()->key_; | |
| 209 // Reset the next pointer in the weak property. | |
| 210 cur_weak->ptr()->next_ = 0; | |
| 211 if (raw_key->IsMarked()) { | |
| 212 // The key is marked so we make sure to properly visit all pointers | |
| 213 // originating from this weak property. | |
| 214 VisitingOldObject(cur_weak); | |
| 215 cur_weak->VisitPointers(this); | |
| 216 } else { | |
| 217 // Requeue this weak property to be handled later. | |
| 218 EnqueueWeakProperty(cur_weak); | |
| 219 } | |
| 220 // Advance to next weak property in the queue. | |
| 221 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | |
| 259 } | 222 } |
| 223 | |
| 224 // Check whether any further work was pushed either by other markers or | |
| 225 // by the handling of weak properties. | |
| 260 raw_obj = work_list_.Pop(); | 226 raw_obj = work_list_.Pop(); |
| 261 } while (raw_obj != NULL); | 227 } while (raw_obj != NULL); |
| 262 VisitingOldObject(NULL); | 228 VisitingOldObject(NULL); |
| 263 return true; | 229 return true; |
| 264 } | 230 } |
| 265 | 231 |
| 266 void VisitPointers(RawObject** first, RawObject** last) { | 232 void VisitPointers(RawObject** first, RawObject** last) { |
| 267 for (RawObject** current = first; current <= last; current++) { | 233 for (RawObject** current = first; current <= last; current++) { |
| 268 MarkObject(*current, current); | 234 MarkObject(*current, current); |
| 269 } | 235 } |
| 270 } | 236 } |
| 271 | 237 |
| 272 bool visit_function_code() const { | 238 bool visit_function_code() const { |
| 273 return skipped_code_functions_ == NULL; | 239 return skipped_code_functions_ == NULL; |
| 274 } | 240 } |
| 275 | 241 |
| 276 virtual void add_skipped_code_function(RawFunction* func) { | 242 virtual void add_skipped_code_function(RawFunction* func) { |
| 277 ASSERT(!visit_function_code()); | 243 ASSERT(!visit_function_code()); |
| 278 skipped_code_functions_->Add(func); | 244 skipped_code_functions_->Add(func); |
| 279 } | 245 } |
| 280 | 246 |
| 281 // If unmarked, sets the watch bit and returns true. | 247 void EnqueueWeakProperty(RawWeakProperty* raw_weak) { |
| 282 // If marked, does nothing and returns false. | 248 ASSERT(raw_weak->IsHeapObject()); |
| 283 static bool EnsureWatchedIfWhite(RawObject* obj) { | 249 ASSERT(raw_weak->IsOldObject()); |
| 284 if (!sync) { | 250 ASSERT(raw_weak->IsWeakProperty()); |
| 285 if (obj->IsMarked()) return false; | 251 ASSERT(raw_weak->IsMarked()); |
| 286 if (!obj->IsWatched()) obj->SetWatchedBitUnsynchronized(); | 252 ASSERT(raw_weak->ptr()->next_ == 0); |
| 287 return true; | 253 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_); |
| 288 } | 254 delayed_weak_properties_ = raw_weak; |
| 289 uword tags = obj->ptr()->tags_; | |
| 290 uword old_tags; | |
| 291 do { | |
| 292 old_tags = tags; | |
| 293 if (RawObject::MarkBit::decode(tags)) return false; | |
| 294 if (RawObject::WatchedBit::decode(tags)) return true; | |
| 295 uword new_tags = RawObject::WatchedBit::update(true, old_tags); | |
| 296 tags = AtomicOperations::CompareAndSwapWord( | |
| 297 &obj->ptr()->tags_, old_tags, new_tags); | |
| 298 } while (tags != old_tags); | |
| 299 return true; | |
| 300 } | 255 } |
| 301 | 256 |
| 302 void ProcessWeakProperty(RawWeakProperty* raw_weak) { | 257 intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) { |
| 303 // The fate of the weak property is determined by its key. | 258 // The fate of the weak property is determined by its key. |
| 304 RawObject* raw_key = raw_weak->ptr()->key_; | 259 RawObject* raw_key = raw_weak->ptr()->key_; |
| 305 if (raw_key->IsHeapObject() && | 260 if (raw_key->IsHeapObject() && |
| 306 raw_key->IsOldObject() && | 261 raw_key->IsOldObject() && |
| 307 EnsureWatchedIfWhite(raw_key) && | 262 !raw_key->IsMarked()) { |
| 308 delay_set_->InsertIfWhite(raw_weak)) { | 263 // Key was white. Enqueue the weak property. |
| 309 // Key was white. Delayed the weak property. | 264 EnqueueWeakProperty(raw_weak); |
| 310 } else { | 265 return raw_weak->Size(); |
| 311 // Key is gray or black. Make the weak property black. | |
| 312 raw_weak->VisitPointers(this); | |
| 313 } | 266 } |
| 267 // Key is gray or black. Make the weak property black. | |
| 268 return raw_weak->VisitPointers(this); | |
| 314 } | 269 } |
| 315 | 270 |
| 316 // Called when all marking is complete. | 271 // Called when all marking is complete. |
| 317 void Finalize() { | 272 void Finalize() { |
| 318 work_list_.Finalize(); | 273 work_list_.Finalize(); |
| 274 // Detach code from functions. | |
| 319 if (skipped_code_functions_ != NULL) { | 275 if (skipped_code_functions_ != NULL) { |
| 320 skipped_code_functions_->DetachCode(); | 276 skipped_code_functions_->DetachCode(); |
| 321 } | 277 } |
| 278 // Clear pending weak properties. | |
| 279 RawWeakProperty* cur_weak = delayed_weak_properties_; | |
| 280 delayed_weak_properties_ = NULL; | |
| 281 intptr_t weak_properties_cleared = 0; | |
| 282 while (cur_weak != NULL) { | |
| 283 uword next_weak = cur_weak->ptr()->next_; | |
| 284 cur_weak->ptr()->next_ = 0; | |
| 285 WeakProperty::Clear(cur_weak); | |
|
siva
2016/05/23 20:35:33
Maybe set next_ to 0 inside Clear so reseting of a
| |
| 286 weak_properties_cleared++; | |
| 287 // Advance to next weak property in the queue. | |
| 288 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | |
| 289 } | |
| 322 } | 290 } |
| 323 | 291 |
| 324 void VisitingOldObject(RawObject* obj) { | 292 void VisitingOldObject(RawObject* obj) { |
| 325 ASSERT((obj == NULL) || obj->IsOldObject()); | 293 ASSERT((obj == NULL) || obj->IsOldObject()); |
| 326 visiting_old_object_ = obj; | 294 visiting_old_object_ = obj; |
| 327 } | 295 } |
| 328 | 296 |
| 329 private: | 297 private: |
| 330 void PushMarked(RawObject* raw_obj) { | 298 void PushMarked(RawObject* raw_obj) { |
| 331 ASSERT(raw_obj->IsHeapObject()); | 299 ASSERT(raw_obj->IsHeapObject()); |
| 332 ASSERT((FLAG_verify_before_gc || FLAG_verify_before_gc) ? | 300 ASSERT((FLAG_verify_before_gc || FLAG_verify_before_gc) ? |
| 333 page_space_->Contains(RawObject::ToAddr(raw_obj)) : | 301 page_space_->Contains(RawObject::ToAddr(raw_obj)) : |
| 334 true); | 302 true); |
| 335 | 303 |
| 336 // Push the marked object on the marking stack. | 304 // Push the marked object on the marking stack. |
| 337 ASSERT(raw_obj->IsMarked()); | 305 ASSERT(raw_obj->IsMarked()); |
| 338 const bool is_watched = raw_obj->IsWatched(); | |
| 339 // We acquired the mark bit => no other task is modifying the header. | 306 // We acquired the mark bit => no other task is modifying the header. |
| 340 // TODO(koda): For concurrent mutator, this needs synchronization. Consider | 307 // TODO(koda): For concurrent mutator, this needs synchronization. Consider |
| 341 // clearing these bits already in the CAS for the mark bit. | 308 // clearing these bits already in the CAS for the mark bit. |
| 342 raw_obj->ClearRememberedBitUnsynchronized(); | 309 raw_obj->ClearRememberedBitUnsynchronized(); |
| 343 raw_obj->ClearWatchedBitUnsynchronized(); | |
| 344 if (is_watched) { | |
| 345 delay_set_->VisitValuesForKey(raw_obj, this); | |
| 346 } | |
| 347 work_list_.Push(raw_obj); | 310 work_list_.Push(raw_obj); |
| 348 } | 311 } |
| 349 | 312 |
| 350 static bool TryAcquireMarkBit(RawObject* raw_obj) { | 313 static bool TryAcquireMarkBit(RawObject* raw_obj) { |
| 351 if (!sync) { | 314 if (!sync) { |
| 352 if (raw_obj->IsMarked()) return false; | 315 if (raw_obj->IsMarked()) return false; |
| 353 raw_obj->SetMarkBitUnsynchronized(); | 316 raw_obj->SetMarkBitUnsynchronized(); |
| 354 return true; | 317 return true; |
| 355 } | 318 } |
| 356 return raw_obj->TryAcquireMarkBit(); | 319 return raw_obj->TryAcquireMarkBit(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 class_stats_size_[class_id] += size; | 386 class_stats_size_[class_id] += size; |
| 424 } | 387 } |
| 425 | 388 |
| 426 Thread* thread_; | 389 Thread* thread_; |
| 427 Heap* heap_; | 390 Heap* heap_; |
| 428 Heap* vm_heap_; | 391 Heap* vm_heap_; |
| 429 GrowableArray<intptr_t> class_stats_count_; | 392 GrowableArray<intptr_t> class_stats_count_; |
| 430 GrowableArray<intptr_t> class_stats_size_; | 393 GrowableArray<intptr_t> class_stats_size_; |
| 431 PageSpace* page_space_; | 394 PageSpace* page_space_; |
| 432 MarkerWorkList work_list_; | 395 MarkerWorkList work_list_; |
| 433 DelaySet* delay_set_; | 396 RawWeakProperty* delayed_weak_properties_; |
| 434 RawObject* visiting_old_object_; | 397 RawObject* visiting_old_object_; |
| 435 SkippedCodeFunctions* skipped_code_functions_; | 398 SkippedCodeFunctions* skipped_code_functions_; |
| 436 uintptr_t marked_bytes_; | 399 uintptr_t marked_bytes_; |
| 437 | 400 |
| 438 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); | 401 DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase); |
| 439 }; | 402 }; |
| 440 | 403 |
| 441 | 404 |
| 442 typedef MarkingVisitorBase<false> UnsyncMarkingVisitor; | 405 typedef MarkingVisitorBase<false> UnsyncMarkingVisitor; |
| 443 typedef MarkingVisitorBase<true> SyncMarkingVisitor; | 406 typedef MarkingVisitorBase<true> SyncMarkingVisitor; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 } | 530 } |
| 568 | 531 |
| 569 | 532 |
| 570 class MarkTask : public ThreadPool::Task { | 533 class MarkTask : public ThreadPool::Task { |
| 571 public: | 534 public: |
| 572 MarkTask(GCMarker* marker, | 535 MarkTask(GCMarker* marker, |
| 573 Isolate* isolate, | 536 Isolate* isolate, |
| 574 Heap* heap, | 537 Heap* heap, |
| 575 PageSpace* page_space, | 538 PageSpace* page_space, |
| 576 MarkingStack* marking_stack, | 539 MarkingStack* marking_stack, |
| 577 DelaySet* delay_set, | |
| 578 ThreadBarrier* barrier, | 540 ThreadBarrier* barrier, |
| 579 bool collect_code, | 541 bool collect_code, |
| 580 intptr_t task_index, | 542 intptr_t task_index, |
| 581 intptr_t num_tasks, | 543 intptr_t num_tasks, |
| 582 uintptr_t* num_busy) | 544 uintptr_t* num_busy) |
| 583 : marker_(marker), | 545 : marker_(marker), |
| 584 isolate_(isolate), | 546 isolate_(isolate), |
| 585 heap_(heap), | 547 heap_(heap), |
| 586 page_space_(page_space), | 548 page_space_(page_space), |
| 587 marking_stack_(marking_stack), | 549 marking_stack_(marking_stack), |
| 588 delay_set_(delay_set), | |
| 589 barrier_(barrier), | 550 barrier_(barrier), |
| 590 collect_code_(collect_code), | 551 collect_code_(collect_code), |
| 591 task_index_(task_index), | 552 task_index_(task_index), |
| 592 num_tasks_(num_tasks), | 553 num_tasks_(num_tasks), |
| 593 num_busy_(num_busy) { | 554 num_busy_(num_busy) { |
| 594 } | 555 } |
| 595 | 556 |
| 596 virtual void Run() { | 557 virtual void Run() { |
| 597 bool result = | 558 bool result = |
| 598 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); | 559 Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true); |
| 599 ASSERT(result); | 560 ASSERT(result); |
| 600 { | 561 { |
| 601 Thread* thread = Thread::Current(); | 562 Thread* thread = Thread::Current(); |
| 602 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); | 563 TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask"); |
| 603 StackZone stack_zone(thread); | 564 StackZone stack_zone(thread); |
| 604 Zone* zone = stack_zone.GetZone(); | 565 Zone* zone = stack_zone.GetZone(); |
| 605 SkippedCodeFunctions* skipped_code_functions = | 566 SkippedCodeFunctions* skipped_code_functions = |
| 606 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL; | 567 collect_code_ ? new(zone) SkippedCodeFunctions() : NULL; |
| 607 SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, | 568 SyncMarkingVisitor visitor(isolate_, heap_, page_space_, marking_stack_, |
| 608 delay_set_, skipped_code_functions); | 569 skipped_code_functions); |
| 609 // Phase 1: Iterate over roots and drain marking stack in tasks. | 570 // Phase 1: Iterate over roots and drain marking stack in tasks. |
| 610 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); | 571 marker_->IterateRoots(isolate_, &visitor, task_index_, num_tasks_); |
| 611 do { | 572 do { |
| 612 visitor.DrainMarkingStack(); | 573 visitor.DrainMarkingStack(); |
| 613 | 574 |
| 614 // I can't find more work right now. If no other task is busy, | 575 // I can't find more work right now. If no other task is busy, |
| 615 // then there will never be more work (NB: 1 is *before* decrement). | 576 // then there will never be more work (NB: 1 is *before* decrement). |
| 616 if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break; | 577 if (AtomicOperations::FetchAndDecrement(num_busy_) == 1) break; |
| 617 | 578 |
| 618 // Wait for some work to appear. | 579 // Wait for some work to appear. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 646 // This task is done. Notify the original thread. | 607 // This task is done. Notify the original thread. |
| 647 barrier_->Exit(); | 608 barrier_->Exit(); |
| 648 } | 609 } |
| 649 | 610 |
| 650 private: | 611 private: |
| 651 GCMarker* marker_; | 612 GCMarker* marker_; |
| 652 Isolate* isolate_; | 613 Isolate* isolate_; |
| 653 Heap* heap_; | 614 Heap* heap_; |
| 654 PageSpace* page_space_; | 615 PageSpace* page_space_; |
| 655 MarkingStack* marking_stack_; | 616 MarkingStack* marking_stack_; |
| 656 DelaySet* delay_set_; | |
| 657 ThreadBarrier* barrier_; | 617 ThreadBarrier* barrier_; |
| 658 bool collect_code_; | 618 bool collect_code_; |
| 659 const intptr_t task_index_; | 619 const intptr_t task_index_; |
| 660 const intptr_t num_tasks_; | 620 const intptr_t num_tasks_; |
| 661 uintptr_t* num_busy_; | 621 uintptr_t* num_busy_; |
| 662 | 622 |
| 663 DISALLOW_COPY_AND_ASSIGN(MarkTask); | 623 DISALLOW_COPY_AND_ASSIGN(MarkTask); |
| 664 }; | 624 }; |
| 665 | 625 |
| 666 | 626 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 688 PageSpace* page_space, | 648 PageSpace* page_space, |
| 689 bool invoke_api_callbacks, | 649 bool invoke_api_callbacks, |
| 690 bool collect_code) { | 650 bool collect_code) { |
| 691 Prologue(isolate, invoke_api_callbacks); | 651 Prologue(isolate, invoke_api_callbacks); |
| 692 // The API prologue/epilogue may create/destroy zones, so we must not | 652 // The API prologue/epilogue may create/destroy zones, so we must not |
| 693 // depend on zone allocations surviving beyond the epilogue callback. | 653 // depend on zone allocations surviving beyond the epilogue callback. |
| 694 { | 654 { |
| 695 StackZone stack_zone(Thread::Current()); | 655 StackZone stack_zone(Thread::Current()); |
| 696 Zone* zone = stack_zone.GetZone(); | 656 Zone* zone = stack_zone.GetZone(); |
| 697 MarkingStack marking_stack; | 657 MarkingStack marking_stack; |
| 698 DelaySet delay_set; | |
| 699 marked_bytes_ = 0; | 658 marked_bytes_ = 0; |
| 700 const int num_tasks = FLAG_marker_tasks; | 659 const int num_tasks = FLAG_marker_tasks; |
| 701 if (num_tasks == 0) { | 660 if (num_tasks == 0) { |
| 702 // Mark everything on main thread. | 661 // Mark everything on main thread. |
| 703 SkippedCodeFunctions* skipped_code_functions = | 662 SkippedCodeFunctions* skipped_code_functions = |
| 704 collect_code ? new(zone) SkippedCodeFunctions() : NULL; | 663 collect_code ? new(zone) SkippedCodeFunctions() : NULL; |
| 705 UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, | 664 UnsyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, |
| 706 &delay_set, skipped_code_functions); | 665 skipped_code_functions); |
| 707 IterateRoots(isolate, &mark, 0, 1); | 666 IterateRoots(isolate, &mark, 0, 1); |
| 708 mark.DrainMarkingStack(); | 667 mark.DrainMarkingStack(); |
| 709 MarkingWeakVisitor mark_weak; | 668 MarkingWeakVisitor mark_weak; |
| 710 IterateWeakRoots(isolate, &mark_weak); | 669 IterateWeakRoots(isolate, &mark_weak); |
| 711 // All marking done; detach code, etc. | 670 // All marking done; detach code, etc. |
| 712 FinalizeResultsFrom(&mark); | 671 FinalizeResultsFrom(&mark); |
| 713 } else { | 672 } else { |
| 714 ThreadBarrier barrier(num_tasks + 1, | 673 ThreadBarrier barrier(num_tasks + 1, |
| 715 heap_->barrier(), | 674 heap_->barrier(), |
| 716 heap_->barrier_done()); | 675 heap_->barrier_done()); |
| 717 // Used to coordinate draining among tasks; all start out as 'busy'. | 676 // Used to coordinate draining among tasks; all start out as 'busy'. |
| 718 uintptr_t num_busy = num_tasks; | 677 uintptr_t num_busy = num_tasks; |
| 719 // Phase 1: Iterate over roots and drain marking stack in tasks. | 678 // Phase 1: Iterate over roots and drain marking stack in tasks. |
| 720 for (intptr_t i = 0; i < num_tasks; ++i) { | 679 for (intptr_t i = 0; i < num_tasks; ++i) { |
| 721 MarkTask* mark_task = | 680 MarkTask* mark_task = |
| 722 new MarkTask(this, isolate, heap_, page_space, &marking_stack, | 681 new MarkTask(this, isolate, heap_, page_space, &marking_stack, |
| 723 &delay_set, &barrier, collect_code, | 682 &barrier, collect_code, |
| 724 i, num_tasks, &num_busy); | 683 i, num_tasks, &num_busy); |
| 725 ThreadPool* pool = Dart::thread_pool(); | 684 ThreadPool* pool = Dart::thread_pool(); |
| 726 pool->Run(mark_task); | 685 pool->Run(mark_task); |
| 727 } | 686 } |
| 728 barrier.Sync(); | 687 barrier.Sync(); |
| 729 | 688 |
| 730 // Phase 2: Weak processing and follow-up marking on main thread. | 689 // Phase 2: Weak processing on main thread. |
| 731 SkippedCodeFunctions* skipped_code_functions = | |
| 732 collect_code ? new(zone) SkippedCodeFunctions() : NULL; | |
| 733 SyncMarkingVisitor mark(isolate, heap_, page_space, &marking_stack, | |
| 734 &delay_set, skipped_code_functions); | |
| 735 MarkingWeakVisitor mark_weak; | 690 MarkingWeakVisitor mark_weak; |
| 736 IterateWeakRoots(isolate, &mark_weak); | 691 IterateWeakRoots(isolate, &mark_weak); |
| 737 barrier.Sync(); | 692 barrier.Sync(); |
| 738 | 693 |
| 739 // Phase 3: Finalize results from all markers (detach code, etc.). | 694 // Phase 3: Finalize results from all markers (detach code, etc.). |
| 740 if (FLAG_log_marker_tasks) { | |
| 741 THR_Print("Main thread marked %" Pd " bytes.\n", | |
| 742 mark.marked_bytes()); | |
| 743 } | |
| 744 FinalizeResultsFrom(&mark); | |
| 745 barrier.Exit(); | 695 barrier.Exit(); |
| 746 } | 696 } |
| 747 delay_set.ClearReferences(); | |
| 748 ProcessWeakTables(page_space); | 697 ProcessWeakTables(page_space); |
| 749 ProcessObjectIdTable(isolate); | 698 ProcessObjectIdTable(isolate); |
| 750 } | 699 } |
| 751 Epilogue(isolate, invoke_api_callbacks); | 700 Epilogue(isolate, invoke_api_callbacks); |
| 752 } | 701 } |
| 753 | 702 |
| 754 } // namespace dart | 703 } // namespace dart |
| OLD | NEW |