| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/heap.h" | 5 #include "vm/heap.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 } | 302 } |
| 303 raw_obj = FindOldObject(visitor); | 303 raw_obj = FindOldObject(visitor); |
| 304 if (raw_obj != Object::null()) { | 304 if (raw_obj != Object::null()) { |
| 305 return raw_obj; | 305 return raw_obj; |
| 306 } | 306 } |
| 307 raw_obj = FindObjectInCodeSpace(visitor); | 307 raw_obj = FindObjectInCodeSpace(visitor); |
| 308 return raw_obj; | 308 return raw_obj; |
| 309 } | 309 } |
| 310 | 310 |
| 311 | 311 |
| 312 bool Heap::gc_in_progress() { |
| 313 MutexLocker ml(&gc_in_progress_mutex_); |
| 314 return gc_in_progress_; |
| 315 } |
| 316 |
| 317 |
| 318 void Heap::BeginGC() { |
| 319 MutexLocker ml(&gc_in_progress_mutex_); |
| 320 ASSERT(!gc_in_progress_); |
| 321 gc_in_progress_ = true; |
| 322 } |
| 323 |
| 324 |
| 325 void Heap::EndGC() { |
| 326 MutexLocker ml(&gc_in_progress_mutex_); |
| 327 ASSERT(gc_in_progress_); |
| 328 gc_in_progress_ = false; |
| 329 } |
| 330 |
| 331 |
| 312 void Heap::CollectGarbage(Space space, | 332 void Heap::CollectGarbage(Space space, |
| 313 ApiCallbacks api_callbacks, | 333 ApiCallbacks api_callbacks, |
| 314 GCReason reason) { | 334 GCReason reason) { |
| 315 Thread* thread = Thread::Current(); | 335 Thread* thread = Thread::Current(); |
| 316 TIMERSCOPE(isolate(), time_gc); | |
| 317 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 336 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 318 switch (space) { | 337 switch (space) { |
| 319 case kNew: { | 338 case kNew: { |
| 339 RecordBeforeGC(kNew, reason); |
| 340 TimerScope timer(true, &(isolate()->timer_list().time_gc()), thread); |
| 320 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); | 341 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); |
| 321 TimelineDurationScope tds(isolate(), | 342 TimelineDurationScope tds(thread, |
| 322 isolate()->GetGCStream(), | 343 isolate()->GetGCStream(), |
| 323 "CollectNewGeneration"); | 344 "CollectNewGeneration"); |
| 324 RecordBeforeGC(kNew, reason); | |
| 325 UpdateClassHeapStatsBeforeGC(kNew); | 345 UpdateClassHeapStatsBeforeGC(kNew); |
| 326 new_space_.Scavenge(invoke_api_callbacks); | 346 new_space_.Scavenge(invoke_api_callbacks); |
| 327 isolate()->class_table()->UpdatePromoted(); | 347 isolate()->class_table()->UpdatePromoted(); |
| 328 UpdatePretenurePolicy(); | 348 UpdatePretenurePolicy(); |
| 329 RecordAfterGC(); | 349 RecordAfterGC(); |
| 330 PrintStats(); | 350 PrintStats(); |
| 331 if (old_space_.NeedsGarbageCollection()) { | 351 if (old_space_.NeedsGarbageCollection()) { |
| 332 // Old collections should call the API callbacks. | 352 // Old collections should call the API callbacks. |
| 333 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); | 353 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); |
| 334 } | 354 } |
| 335 break; | 355 break; |
| 336 } | 356 } |
| 337 case kOld: | 357 case kOld: |
| 338 case kCode: { | 358 case kCode: { |
| 359 RecordBeforeGC(kOld, reason); |
| 360 TimerScope timer(true, &(isolate()->timer_list().time_gc()), thread); |
| 339 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); | 361 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); |
| 340 TimelineDurationScope tds(isolate(), | 362 TimelineDurationScope tds(thread, |
| 341 isolate()->GetGCStream(), | 363 isolate()->GetGCStream(), |
| 342 "CollectOldGeneration"); | 364 "CollectOldGeneration"); |
| 343 RecordBeforeGC(kOld, reason); | |
| 344 UpdateClassHeapStatsBeforeGC(kOld); | 365 UpdateClassHeapStatsBeforeGC(kOld); |
| 345 old_space_.MarkSweep(invoke_api_callbacks); | 366 old_space_.MarkSweep(invoke_api_callbacks); |
| 346 RecordAfterGC(); | 367 RecordAfterGC(); |
| 347 PrintStats(); | 368 PrintStats(); |
| 348 break; | 369 break; |
| 349 } | 370 } |
| 350 default: | 371 default: |
| 351 UNREACHABLE(); | 372 UNREACHABLE(); |
| 352 } | 373 } |
| 353 } | 374 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 368 CollectGarbage(space, kInvokeApiCallbacks, kOldSpace); | 389 CollectGarbage(space, kInvokeApiCallbacks, kOldSpace); |
| 369 } else { | 390 } else { |
| 370 ASSERT(space == kNew); | 391 ASSERT(space == kNew); |
| 371 CollectGarbage(space, kInvokeApiCallbacks, kNewSpace); | 392 CollectGarbage(space, kInvokeApiCallbacks, kNewSpace); |
| 372 } | 393 } |
| 373 } | 394 } |
| 374 | 395 |
| 375 | 396 |
| 376 void Heap::CollectAllGarbage() { | 397 void Heap::CollectAllGarbage() { |
| 377 Thread* thread = Thread::Current(); | 398 Thread* thread = Thread::Current(); |
| 378 TIMERSCOPE(isolate(), time_gc); | |
| 379 { | 399 { |
| 400 RecordBeforeGC(kNew, kFull); |
| 401 TimerScope timer(true, &(isolate()->timer_list().time_gc()), thread); |
| 380 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); | 402 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); |
| 381 TimelineDurationScope tds(isolate(), | 403 TimelineDurationScope tds(thread, |
| 382 isolate()->GetGCStream(), | 404 isolate()->GetGCStream(), |
| 383 "CollectNewGeneration"); | 405 "CollectNewGeneration"); |
| 384 RecordBeforeGC(kNew, kFull); | |
| 385 UpdateClassHeapStatsBeforeGC(kNew); | 406 UpdateClassHeapStatsBeforeGC(kNew); |
| 386 new_space_.Scavenge(kInvokeApiCallbacks); | 407 new_space_.Scavenge(kInvokeApiCallbacks); |
| 387 isolate()->class_table()->UpdatePromoted(); | 408 isolate()->class_table()->UpdatePromoted(); |
| 388 UpdatePretenurePolicy(); | 409 UpdatePretenurePolicy(); |
| 389 RecordAfterGC(); | 410 RecordAfterGC(); |
| 390 PrintStats(); | 411 PrintStats(); |
| 391 } | 412 } |
| 392 { | 413 { |
| 414 RecordBeforeGC(kOld, kFull); |
| 415 TimerScope timer(true, &(isolate()->timer_list().time_gc()), thread); |
| 393 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); | 416 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); |
| 394 TimelineDurationScope tds(isolate(), | 417 TimelineDurationScope tds(thread, |
| 395 isolate()->GetGCStream(), | 418 isolate()->GetGCStream(), |
| 396 "CollectOldGeneration"); | 419 "CollectOldGeneration"); |
| 397 RecordBeforeGC(kOld, kFull); | |
| 398 UpdateClassHeapStatsBeforeGC(kOld); | 420 UpdateClassHeapStatsBeforeGC(kOld); |
| 399 old_space_.MarkSweep(kInvokeApiCallbacks); | 421 old_space_.MarkSweep(kInvokeApiCallbacks); |
| 400 RecordAfterGC(); | 422 RecordAfterGC(); |
| 401 PrintStats(); | 423 PrintStats(); |
| 402 } | 424 } |
| 403 } | 425 } |
| 404 | 426 |
| 405 | 427 |
| 406 bool Heap::ShouldPretenure(intptr_t class_id) const { | 428 bool Heap::ShouldPretenure(intptr_t class_id) const { |
| 407 if (class_id == kOneByteStringCid) { | 429 if (class_id == kOneByteStringCid) { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { | 668 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { |
| 647 if (space == kNew) { | 669 if (space == kNew) { |
| 648 new_space_.PrintToJSONObject(object); | 670 new_space_.PrintToJSONObject(object); |
| 649 } else { | 671 } else { |
| 650 old_space_.PrintToJSONObject(object); | 672 old_space_.PrintToJSONObject(object); |
| 651 } | 673 } |
| 652 } | 674 } |
| 653 | 675 |
| 654 | 676 |
| 655 void Heap::RecordBeforeGC(Space space, GCReason reason) { | 677 void Heap::RecordBeforeGC(Space space, GCReason reason) { |
| 656 ASSERT(!gc_in_progress_); | 678 BeginGC(); |
| 657 gc_in_progress_ = true; | |
| 658 stats_.num_++; | 679 stats_.num_++; |
| 659 stats_.space_ = space; | 680 stats_.space_ = space; |
| 660 stats_.reason_ = reason; | 681 stats_.reason_ = reason; |
| 661 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); | 682 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); |
| 662 stats_.before_.new_ = new_space_.GetCurrentUsage(); | 683 stats_.before_.new_ = new_space_.GetCurrentUsage(); |
| 663 stats_.before_.old_ = old_space_.GetCurrentUsage(); | 684 stats_.before_.old_ = old_space_.GetCurrentUsage(); |
| 664 stats_.times_[0] = 0; | 685 stats_.times_[0] = 0; |
| 665 stats_.times_[1] = 0; | 686 stats_.times_[1] = 0; |
| 666 stats_.times_[2] = 0; | 687 stats_.times_[2] = 0; |
| 667 stats_.times_[3] = 0; | 688 stats_.times_[3] = 0; |
| 668 stats_.data_[0] = 0; | 689 stats_.data_[0] = 0; |
| 669 stats_.data_[1] = 0; | 690 stats_.data_[1] = 0; |
| 670 stats_.data_[2] = 0; | 691 stats_.data_[2] = 0; |
| 671 stats_.data_[3] = 0; | 692 stats_.data_[3] = 0; |
| 672 } | 693 } |
| 673 | 694 |
| 674 | 695 |
| 675 void Heap::RecordAfterGC() { | 696 void Heap::RecordAfterGC() { |
| 676 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); | 697 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); |
| 677 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; | 698 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; |
| 678 if (stats_.space_ == kNew) { | 699 if (stats_.space_ == kNew) { |
| 679 new_space_.AddGCTime(delta); | 700 new_space_.AddGCTime(delta); |
| 680 new_space_.IncrementCollections(); | 701 new_space_.IncrementCollections(); |
| 681 } else { | 702 } else { |
| 682 old_space_.AddGCTime(delta); | 703 old_space_.AddGCTime(delta); |
| 683 old_space_.IncrementCollections(); | 704 old_space_.IncrementCollections(); |
| 684 } | 705 } |
| 685 stats_.after_.new_ = new_space_.GetCurrentUsage(); | 706 stats_.after_.new_ = new_space_.GetCurrentUsage(); |
| 686 stats_.after_.old_ = old_space_.GetCurrentUsage(); | 707 stats_.after_.old_ = old_space_.GetCurrentUsage(); |
| 687 ASSERT(gc_in_progress_); | 708 EndGC(); |
| 688 gc_in_progress_ = false; | |
| 689 if (Service::gc_stream.enabled()) { | 709 if (Service::gc_stream.enabled()) { |
| 690 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); | 710 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); |
| 691 event.set_gc_stats(&stats_); | 711 event.set_gc_stats(&stats_); |
| 692 Service::HandleEvent(&event); | 712 Service::HandleEvent(&event); |
| 693 } | 713 } |
| 694 } | 714 } |
| 695 | 715 |
| 696 | 716 |
| 697 void Heap::PrintStats() { | 717 void Heap::PrintStats() { |
| 698 if (!FLAG_verbose_gc) return; | 718 if (!FLAG_verbose_gc) return; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 heap->DisableGrowthControl(); | 787 heap->DisableGrowthControl(); |
| 768 } | 788 } |
| 769 | 789 |
| 770 | 790 |
| 771 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { | 791 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { |
| 772 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); | 792 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); |
| 773 heap->SetGrowthControlState(current_growth_controller_state_); | 793 heap->SetGrowthControlState(current_growth_controller_state_); |
| 774 } | 794 } |
| 775 | 795 |
| 776 } // namespace dart | 796 } // namespace dart |
| OLD | NEW |