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/scavenger.h" | 5 #include "vm/scavenger.h" |
6 | 6 |
7 #include "vm/dart.h" | 7 #include "vm/dart.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/lockers.h" | 10 #include "vm/lockers.h" |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 Scavenger::Scavenger(Heap* heap, | 330 Scavenger::Scavenger(Heap* heap, |
331 intptr_t max_semi_capacity_in_words, | 331 intptr_t max_semi_capacity_in_words, |
332 uword object_alignment) | 332 uword object_alignment) |
333 : heap_(heap), | 333 : heap_(heap), |
334 max_semi_capacity_in_words_(max_semi_capacity_in_words), | 334 max_semi_capacity_in_words_(max_semi_capacity_in_words), |
335 object_alignment_(object_alignment), | 335 object_alignment_(object_alignment), |
336 scavenging_(false), | 336 scavenging_(false), |
337 delayed_weak_properties_(NULL), | 337 delayed_weak_properties_(NULL), |
338 gc_time_micros_(0), | 338 gc_time_micros_(0), |
339 collections_(0), | 339 collections_(0), |
340 external_size_(0) { | 340 external_size_(0), |
341 space_lock_(new Mutex()) { | |
341 // Verify assumptions about the first word in objects which the scavenger is | 342 // Verify assumptions about the first word in objects which the scavenger is |
342 // going to use for forwarding pointers. | 343 // going to use for forwarding pointers. |
343 ASSERT(Object::tags_offset() == 0); | 344 ASSERT(Object::tags_offset() == 0); |
344 | 345 |
345 // Set initial size resulting in a total of three different levels. | 346 // Set initial size resulting in a total of three different levels. |
346 const intptr_t initial_semi_capacity_in_words = | 347 const intptr_t initial_semi_capacity_in_words = |
347 max_semi_capacity_in_words / | 348 max_semi_capacity_in_words / |
348 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); | 349 (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor); |
349 to_ = SemiSpace::New(initial_semi_capacity_in_words); | 350 to_ = SemiSpace::New(initial_semi_capacity_in_words); |
350 if (to_ == NULL) { | 351 if (to_ == NULL) { |
351 OUT_OF_MEMORY(); | 352 OUT_OF_MEMORY(); |
352 } | 353 } |
353 // Setup local fields. | 354 // Setup local fields. |
354 top_ = FirstObjectStart(); | 355 top_ = FirstObjectStart(); |
355 resolved_top_ = top_; | 356 resolved_top_ = top_; |
356 end_ = to_->end(); | 357 end_ = to_->end(); |
357 | 358 |
358 survivor_end_ = FirstObjectStart(); | 359 survivor_end_ = FirstObjectStart(); |
359 | 360 |
360 UpdateMaxHeapCapacity(); | 361 UpdateMaxHeapCapacity(); |
361 UpdateMaxHeapUsage(); | 362 UpdateMaxHeapUsage(); |
362 } | 363 } |
363 | 364 |
364 | 365 |
365 Scavenger::~Scavenger() { | 366 Scavenger::~Scavenger() { |
366 ASSERT(!scavenging_); | 367 ASSERT(!scavenging_); |
367 to_->Delete(); | 368 to_->Delete(); |
369 delete space_lock_; | |
368 } | 370 } |
369 | 371 |
370 | 372 |
371 intptr_t Scavenger::NewSizeInWords(intptr_t old_size_in_words) const { | 373 intptr_t Scavenger::NewSizeInWords(intptr_t old_size_in_words) const { |
372 if (stats_history_.Size() == 0) { | 374 if (stats_history_.Size() == 0) { |
373 return old_size_in_words; | 375 return old_size_in_words; |
374 } | 376 } |
375 double garbage = stats_history_.Get(0).GarbageFraction(); | 377 double garbage = stats_history_.Get(0).GarbageFraction(); |
376 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { | 378 if (garbage < (FLAG_new_gen_garbage_threshold / 100.0)) { |
377 return Utils::Minimum(max_semi_capacity_in_words_, | 379 return Utils::Minimum(max_semi_capacity_in_words_, |
378 old_size_in_words * FLAG_new_gen_growth_factor); | 380 old_size_in_words * FLAG_new_gen_growth_factor); |
379 } else { | 381 } else { |
380 return old_size_in_words; | 382 return old_size_in_words; |
381 } | 383 } |
382 } | 384 } |
383 | 385 |
384 | 386 |
385 SemiSpace* Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { | 387 SemiSpace* Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) { |
386 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { | 388 if (invoke_api_callbacks && (isolate->gc_prologue_callback() != NULL)) { |
387 (isolate->gc_prologue_callback())(); | 389 (isolate->gc_prologue_callback())(); |
388 } | 390 } |
389 isolate->PrepareForGC(); | 391 isolate->PrepareForGC(); |
392 | |
393 ASSERT(isolate->mutator_thread()->top() == top_); | |
394 | |
390 // Flip the two semi-spaces so that to_ is always the space for allocating | 395 // Flip the two semi-spaces so that to_ is always the space for allocating |
391 // objects. | 396 // objects. |
392 SemiSpace* from = to_; | 397 SemiSpace* from = to_; |
393 to_ = SemiSpace::New(NewSizeInWords(from->size_in_words())); | 398 to_ = SemiSpace::New(NewSizeInWords(from->size_in_words())); |
394 if (to_ == NULL) { | 399 if (to_ == NULL) { |
395 // TODO(koda): We could try to recover (collect old space, wait for another | 400 // TODO(koda): We could try to recover (collect old space, wait for another |
396 // isolate to finish scavenge, etc.). | 401 // isolate to finish scavenge, etc.). |
397 OUT_OF_MEMORY(); | 402 OUT_OF_MEMORY(); |
398 } | 403 } |
399 UpdateMaxHeapCapacity(); | 404 UpdateMaxHeapCapacity(); |
400 top_ = FirstObjectStart(); | 405 top_ = FirstObjectStart(); |
401 resolved_top_ = top_; | 406 resolved_top_ = top_; |
402 end_ = to_->end(); | 407 end_ = to_->end(); |
408 | |
409 isolate->mutator_thread()->set_top_offset(top_); | |
410 isolate->mutator_thread()->set_end_offset(end_); | |
411 | |
403 return from; | 412 return from; |
404 } | 413 } |
405 | 414 |
406 | 415 |
407 void Scavenger::Epilogue(Isolate* isolate, | 416 void Scavenger::Epilogue(Isolate* isolate, |
408 SemiSpace* from, | 417 SemiSpace* from, |
409 bool invoke_api_callbacks) { | 418 bool invoke_api_callbacks) { |
410 // All objects in the to space have been copied from the from space at this | 419 // All objects in the to space have been copied from the from space at this |
411 // moment. | 420 // moment. |
421 | |
422 isolate->mutator_thread()->set_top_offset(top_); | |
423 isolate->mutator_thread()->set_end_offset(end_); | |
424 | |
412 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); | 425 double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction(); |
413 if (stats_history_.Size() >= 2) { | 426 if (stats_history_.Size() >= 2) { |
414 // Previous scavenge is only given half as much weight. | 427 // Previous scavenge is only given half as much weight. |
415 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); | 428 avg_frac += 0.5 * stats_history_.Get(1).PromoCandidatesSuccessFraction(); |
416 avg_frac /= 1.0 + 0.5; // Normalize. | 429 avg_frac /= 1.0 + 0.5; // Normalize. |
417 } | 430 } |
418 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { | 431 if (avg_frac < (FLAG_early_tenuring_threshold / 100.0)) { |
419 // Remember the limit to which objects have been copied. | 432 // Remember the limit to which objects have been copied. |
420 survivor_end_ = top_; | 433 survivor_end_ = top_; |
421 } else { | 434 } else { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 } | 551 } |
539 | 552 |
540 | 553 |
541 void Scavenger::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { | 554 void Scavenger::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { |
542 isolate->VisitWeakPersistentHandles(visitor); | 555 isolate->VisitWeakPersistentHandles(visitor); |
543 } | 556 } |
544 | 557 |
545 | 558 |
546 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { | 559 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) { |
547 // Iterate until all work has been drained. | 560 // Iterate until all work has been drained. |
561 | |
562 ASSERT(Isolate::Current()->mutator_thread()->top() == top_); | |
563 | |
548 while ((resolved_top_ < top_) || PromotedStackHasMore()) { | 564 while ((resolved_top_ < top_) || PromotedStackHasMore()) { |
549 while (resolved_top_ < top_) { | 565 while (resolved_top_ < top_) { |
550 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); | 566 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); |
551 intptr_t class_id = raw_obj->GetClassId(); | 567 intptr_t class_id = raw_obj->GetClassId(); |
552 if (class_id != kWeakPropertyCid) { | 568 if (class_id != kWeakPropertyCid) { |
553 resolved_top_ += raw_obj->VisitPointersNonvirtual(visitor); | 569 resolved_top_ += raw_obj->VisitPointersNonvirtual(visitor); |
554 } else { | 570 } else { |
555 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); | 571 RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj); |
556 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); | 572 resolved_top_ += ProcessWeakProperty(raw_weak, visitor); |
557 } | 573 } |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
716 | 732 |
717 // Advance to next weak property in the queue. | 733 // Advance to next weak property in the queue. |
718 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); | 734 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); |
719 } | 735 } |
720 } | 736 } |
721 } | 737 } |
722 | 738 |
723 | 739 |
724 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 740 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
725 uword cur = FirstObjectStart(); | 741 uword cur = FirstObjectStart(); |
726 while (cur < top_) { | 742 while (cur < top_) { |
rmacnak
2017/06/22 22:31:50
top_ may be stale
danunez
2017/06/30 20:35:57
Right. top_ is now retrieved from the mutator thre
| |
727 RawObject* raw_obj = RawObject::FromAddr(cur); | 743 RawObject* raw_obj = RawObject::FromAddr(cur); |
728 cur += raw_obj->VisitPointers(visitor); | 744 cur += raw_obj->VisitPointers(visitor); |
729 } | 745 } |
730 } | 746 } |
731 | 747 |
732 | 748 |
733 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { | 749 void Scavenger::VisitObjects(ObjectVisitor* visitor) const { |
734 uword cur = FirstObjectStart(); | 750 uword cur = FirstObjectStart(); |
735 while (cur < top_) { | 751 while (cur < top_) { |
rmacnak
2017/06/22 22:31:50
top_ may be stale
danunez
2017/06/30 20:35:57
Right. top_ is now retrieved from the mutator thre
| |
736 RawObject* raw_obj = RawObject::FromAddr(cur); | 752 RawObject* raw_obj = RawObject::FromAddr(cur); |
737 visitor->VisitObject(raw_obj); | 753 visitor->VisitObject(raw_obj); |
738 cur += raw_obj->Size(); | 754 cur += raw_obj->Size(); |
739 } | 755 } |
740 } | 756 } |
741 | 757 |
742 | 758 |
743 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { | 759 void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const { |
744 set->AddRegion(to_->start(), to_->end()); | 760 set->AddRegion(to_->start(), to_->end()); |
745 } | 761 } |
746 | 762 |
747 | 763 |
748 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { | 764 RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const { |
749 ASSERT(!scavenging_); | 765 ASSERT(!scavenging_); |
750 uword cur = FirstObjectStart(); | 766 uword cur = FirstObjectStart(); |
751 if (visitor->VisitRange(cur, top_)) { | 767 if (visitor->VisitRange(cur, top_)) { |
rmacnak
2017/06/22 22:31:50
top_ may be stale
danunez
2017/06/30 20:35:57
Right. top_ is now retrieved from the mutator thre
| |
752 while (cur < top_) { | 768 while (cur < top_) { |
753 RawObject* raw_obj = RawObject::FromAddr(cur); | 769 RawObject* raw_obj = RawObject::FromAddr(cur); |
754 uword next = cur + raw_obj->Size(); | 770 uword next = cur + raw_obj->Size(); |
755 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { | 771 if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) { |
756 return raw_obj; // Found object, return it. | 772 return raw_obj; // Found object, return it. |
757 } | 773 } |
758 cur = next; | 774 cur = next; |
759 } | 775 } |
760 ASSERT(cur == top_); | 776 ASSERT(cur == top_); |
761 } | 777 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
890 } | 906 } |
891 | 907 |
892 | 908 |
893 void Scavenger::FreeExternal(intptr_t size) { | 909 void Scavenger::FreeExternal(intptr_t size) { |
894 ASSERT(size >= 0); | 910 ASSERT(size >= 0); |
895 external_size_ -= size; | 911 external_size_ -= size; |
896 ASSERT(external_size_ >= 0); | 912 ASSERT(external_size_ >= 0); |
897 } | 913 } |
898 | 914 |
899 } // namespace dart | 915 } // namespace dart |
OLD | NEW |