| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 | 45 |
| 46 Heap::Heap(Isolate* isolate, | 46 Heap::Heap(Isolate* isolate, |
| 47 intptr_t max_new_gen_semi_words, | 47 intptr_t max_new_gen_semi_words, |
| 48 intptr_t max_old_gen_words, | 48 intptr_t max_old_gen_words, |
| 49 intptr_t max_external_words) | 49 intptr_t max_external_words) |
| 50 : isolate_(isolate), | 50 : isolate_(isolate), |
| 51 new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset), | 51 new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset), |
| 52 old_space_(this, max_old_gen_words, max_external_words), | 52 old_space_(this, max_old_gen_words, max_external_words), |
| 53 read_only_(false), | 53 read_only_(false), |
| 54 gc_in_progress_(false), | 54 gc_new_space_in_progress_(false), |
| 55 gc_old_space_in_progress_(false), |
| 55 pretenure_policy_(0) { | 56 pretenure_policy_(0) { |
| 56 for (int sel = 0; | 57 for (int sel = 0; |
| 57 sel < kNumWeakSelectors; | 58 sel < kNumWeakSelectors; |
| 58 sel++) { | 59 sel++) { |
| 59 new_weak_tables_[sel] = new WeakTable(); | 60 new_weak_tables_[sel] = new WeakTable(); |
| 60 old_weak_tables_[sel] = new WeakTable(); | 61 old_weak_tables_[sel] = new WeakTable(); |
| 61 } | 62 } |
| 62 stats_.num_ = 0; | 63 stats_.num_ = 0; |
| 63 } | 64 } |
| 64 | 65 |
| 65 | 66 |
| 66 Heap::~Heap() { | 67 Heap::~Heap() { |
| 67 for (int sel = 0; | 68 for (int sel = 0; |
| 68 sel < kNumWeakSelectors; | 69 sel < kNumWeakSelectors; |
| 69 sel++) { | 70 sel++) { |
| 70 delete new_weak_tables_[sel]; | 71 delete new_weak_tables_[sel]; |
| 71 delete old_weak_tables_[sel]; | 72 delete old_weak_tables_[sel]; |
| 72 } | 73 } |
| 73 } | 74 } |
| 74 | 75 |
| 75 | 76 |
| 76 uword Heap::AllocateNew(intptr_t size) { | 77 uword Heap::AllocateNew(intptr_t size) { |
| 77 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); | 78 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); |
| 78 // Currently, only the Dart thread may allocate in new space. | 79 // Currently, only the Dart thread may allocate in new space. |
| 79 isolate()->AssertCurrentThreadIsMutator(); | 80 isolate()->AssertCurrentThreadIsMutator(); |
| 80 uword addr = new_space_.TryAllocate(size); | 81 uword addr = new_space_.TryAllocate(size); |
| 81 if (addr == 0) { | 82 if (addr == 0) { |
| 83 // This call to CollectGarbage might end up "reusing" a collection spawned |
| 84 // from a different thread and will be racing to allocate the requested |
| 85 // memory with other threads being released after the collection. |
| 82 CollectGarbage(kNew); | 86 CollectGarbage(kNew); |
| 83 addr = new_space_.TryAllocate(size); | 87 addr = new_space_.TryAllocate(size); |
| 84 if (addr == 0) { | 88 if (addr == 0) { |
| 85 return AllocateOld(size, HeapPage::kData); | 89 return AllocateOld(size, HeapPage::kData); |
| 86 } | 90 } |
| 87 } | 91 } |
| 88 return addr; | 92 return addr; |
| 89 } | 93 } |
| 90 | 94 |
| 91 | 95 |
| 92 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) { | 96 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) { |
| 93 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); | 97 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); |
| 94 uword addr = old_space_.TryAllocate(size, type); | 98 uword addr = old_space_.TryAllocate(size, type); |
| 95 if (addr != 0) { | 99 if (addr != 0) { |
| 96 return addr; | 100 return addr; |
| 97 } | 101 } |
| 98 // If we are in the process of running a sweep wait for the sweeper to free | 102 // If we are in the process of running a sweep wait for the sweeper to free |
| 99 // memory. | 103 // memory. |
| 100 { | 104 { |
| 101 MonitorLocker ml(old_space_.tasks_lock()); | 105 MonitorLocker ml(old_space_.tasks_lock()); |
| 102 addr = old_space_.TryAllocate(size, type); | 106 addr = old_space_.TryAllocate(size, type); |
| 103 while ((addr == 0) && (old_space_.tasks() > 0)) { | 107 while ((addr == 0) && (old_space_.tasks() > 0)) { |
| 104 ml.Wait(); | 108 ml.Wait(); |
| 105 addr = old_space_.TryAllocate(size, type); | 109 addr = old_space_.TryAllocate(size, type); |
| 106 } | 110 } |
| 107 } | 111 } |
| 108 if (addr != 0) { | 112 if (addr != 0) { |
| 109 return addr; | 113 return addr; |
| 110 } | 114 } |
| 111 // All GC tasks finished without allocating successfully. Run a full GC. | 115 Thread* thread = Thread::Current(); |
| 112 CollectAllGarbage(); | 116 if (thread->CanCollectGarbage()) { |
| 113 addr = old_space_.TryAllocate(size, type); | 117 // All GC tasks finished without allocating successfully. Run a full GC. |
| 114 if (addr != 0) { | 118 CollectAllGarbage(); |
| 115 return addr; | |
| 116 } | |
| 117 // Wait for all of the concurrent tasks to finish before giving up. | |
| 118 { | |
| 119 MonitorLocker ml(old_space_.tasks_lock()); | |
| 120 addr = old_space_.TryAllocate(size, type); | 119 addr = old_space_.TryAllocate(size, type); |
| 121 while ((addr == 0) && (old_space_.tasks() > 0)) { | 120 if (addr != 0) { |
| 122 ml.Wait(); | 121 return addr; |
| 122 } |
| 123 // Wait for all of the concurrent tasks to finish before giving up. |
| 124 { |
| 125 MonitorLocker ml(old_space_.tasks_lock()); |
| 123 addr = old_space_.TryAllocate(size, type); | 126 addr = old_space_.TryAllocate(size, type); |
| 127 while ((addr == 0) && (old_space_.tasks() > 0)) { |
| 128 ml.Wait(); |
| 129 addr = old_space_.TryAllocate(size, type); |
| 130 } |
| 124 } | 131 } |
| 125 } | 132 if (addr != 0) { |
| 126 if (addr != 0) { | 133 return addr; |
| 127 return addr; | 134 } |
| 128 } | 135 // Force growth before attempting another synchronous GC. |
| 129 // Force growth before attempting a synchronous GC. | 136 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); |
| 130 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); | 137 if (addr != 0) { |
| 131 if (addr != 0) { | 138 return addr; |
| 132 return addr; | 139 } |
| 133 } | 140 // Before throwing an out-of-memory error try a synchronous GC. |
| 134 // Before throwing an out-of-memory error try a synchronous GC. | 141 CollectAllGarbage(); |
| 135 CollectAllGarbage(); | 142 { |
| 136 { | 143 MonitorLocker ml(old_space_.tasks_lock()); |
| 137 MonitorLocker ml(old_space_.tasks_lock()); | 144 while (old_space_.tasks() > 0) { |
| 138 while (old_space_.tasks() > 0) { | 145 ml.Wait(); |
| 139 ml.Wait(); | 146 } |
| 140 } | 147 } |
| 141 } | 148 } |
| 142 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); | 149 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); |
| 143 if (addr != 0) { | 150 if (addr != 0) { |
| 144 return addr; | 151 return addr; |
| 145 } | 152 } |
| 146 // Give up allocating this object. | 153 // Give up allocating this object. |
| 147 OS::PrintErr( | 154 OS::PrintErr( |
| 148 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); | 155 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); |
| 149 return 0; | 156 return 0; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 } | 307 } |
| 301 raw_obj = FindOldObject(visitor); | 308 raw_obj = FindOldObject(visitor); |
| 302 if (raw_obj != Object::null()) { | 309 if (raw_obj != Object::null()) { |
| 303 return raw_obj; | 310 return raw_obj; |
| 304 } | 311 } |
| 305 raw_obj = FindObjectInCodeSpace(visitor); | 312 raw_obj = FindObjectInCodeSpace(visitor); |
| 306 return raw_obj; | 313 return raw_obj; |
| 307 } | 314 } |
| 308 | 315 |
| 309 | 316 |
| 310 bool Heap::gc_in_progress() { | 317 bool Heap::BeginNewSpaceGC() { |
| 311 MutexLocker ml(&gc_in_progress_mutex_); | 318 MonitorLocker ml(&gc_in_progress_monitor_); |
| 312 return gc_in_progress_; | 319 bool start_gc_on_thread = true; |
| 320 while (gc_new_space_in_progress_ || |
| 321 gc_old_space_in_progress_) { |
| 322 start_gc_on_thread = !gc_new_space_in_progress_; |
| 323 ml.Wait(); |
| 324 } |
| 325 if (start_gc_on_thread) { |
| 326 gc_new_space_in_progress_ = true; |
| 327 return true; |
| 328 } |
| 329 return false; |
| 313 } | 330 } |
| 314 | 331 |
| 315 | 332 |
| 316 void Heap::BeginGC() { | 333 void Heap::EndNewSpaceGC() { |
| 317 MutexLocker ml(&gc_in_progress_mutex_); | 334 MonitorLocker ml(&gc_in_progress_monitor_); |
| 318 ASSERT(!gc_in_progress_); | 335 ASSERT(gc_new_space_in_progress_); |
| 319 gc_in_progress_ = true; | 336 gc_new_space_in_progress_ = false; |
| 337 ml.NotifyAll(); |
| 320 } | 338 } |
| 321 | 339 |
| 322 | 340 |
| 323 void Heap::EndGC() { | 341 bool Heap::BeginOldSpaceGC() { |
| 324 MutexLocker ml(&gc_in_progress_mutex_); | 342 MonitorLocker ml(&gc_in_progress_monitor_); |
| 325 ASSERT(gc_in_progress_); | 343 bool start_gc_on_thread = true; |
| 326 gc_in_progress_ = false; | 344 while (gc_new_space_in_progress_ || |
| 345 gc_old_space_in_progress_) { |
| 346 start_gc_on_thread = !gc_old_space_in_progress_; |
| 347 ml.Wait(); |
| 348 } |
| 349 if (start_gc_on_thread) { |
| 350 gc_old_space_in_progress_ = true; |
| 351 return true; |
| 352 } |
| 353 return false; |
| 327 } | 354 } |
| 328 | 355 |
| 329 | 356 |
| 330 void Heap::CollectGarbage(Space space, | 357 void Heap::EndOldSpaceGC() { |
| 331 ApiCallbacks api_callbacks, | 358 MonitorLocker ml(&gc_in_progress_monitor_); |
| 332 GCReason reason) { | 359 ASSERT(gc_old_space_in_progress_); |
| 333 Thread* thread = Thread::Current(); | 360 gc_old_space_in_progress_ = false; |
| 334 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 361 ml.NotifyAll(); |
| 335 switch (space) { | |
| 336 case kNew: { | |
| 337 RecordBeforeGC(kNew, reason); | |
| 338 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); | |
| 339 TimelineDurationScope tds(thread, | |
| 340 isolate()->GetGCStream(), | |
| 341 "CollectNewGeneration"); | |
| 342 UpdateClassHeapStatsBeforeGC(kNew); | |
| 343 new_space_.Scavenge(invoke_api_callbacks); | |
| 344 isolate()->class_table()->UpdatePromoted(); | |
| 345 UpdatePretenurePolicy(); | |
| 346 RecordAfterGC(); | |
| 347 PrintStats(); | |
| 348 if (old_space_.NeedsGarbageCollection()) { | |
| 349 // Old collections should call the API callbacks. | |
| 350 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); | |
| 351 } | |
| 352 break; | |
| 353 } | |
| 354 case kOld: | |
| 355 case kCode: { | |
| 356 RecordBeforeGC(kOld, reason); | |
| 357 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); | |
| 358 TimelineDurationScope tds(thread, | |
| 359 isolate()->GetGCStream(), | |
| 360 "CollectOldGeneration"); | |
| 361 UpdateClassHeapStatsBeforeGC(kOld); | |
| 362 old_space_.MarkSweep(invoke_api_callbacks); | |
| 363 RecordAfterGC(); | |
| 364 PrintStats(); | |
| 365 break; | |
| 366 } | |
| 367 default: | |
| 368 UNREACHABLE(); | |
| 369 } | |
| 370 } | 362 } |
| 371 | 363 |
| 372 | 364 |
| 373 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) { | 365 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) { |
| 374 ClassTable* class_table = isolate()->class_table(); | 366 ClassTable* class_table = isolate()->class_table(); |
| 375 if (space == kNew) { | 367 if (space == kNew) { |
| 376 class_table->ResetCountersNew(); | 368 class_table->ResetCountersNew(); |
| 377 } else { | 369 } else { |
| 378 class_table->ResetCountersOld(); | 370 class_table->ResetCountersOld(); |
| 379 } | 371 } |
| 380 } | 372 } |
| 381 | 373 |
| 382 | 374 |
| 375 void Heap::CollectNewSpaceGarbage(Thread* thread, |
| 376 ApiCallbacks api_callbacks, |
| 377 GCReason reason) { |
| 378 if (BeginNewSpaceGC()) { |
| 379 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 380 RecordBeforeGC(kNew, reason); |
| 381 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); |
| 382 TimelineDurationScope tds(thread, |
| 383 isolate()->GetGCStream(), |
| 384 "CollectNewGeneration"); |
| 385 UpdateClassHeapStatsBeforeGC(kNew); |
| 386 new_space_.Scavenge(invoke_api_callbacks); |
| 387 isolate()->class_table()->UpdatePromoted(); |
| 388 UpdatePretenurePolicy(); |
| 389 RecordAfterGC(kNew); |
| 390 PrintStats(); |
| 391 EndNewSpaceGC(); |
| 392 if (old_space_.NeedsGarbageCollection()) { |
| 393 // Old collections should call the API callbacks. |
| 394 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion); |
| 395 } |
| 396 } |
| 397 } |
| 398 |
| 399 |
| 400 void Heap::CollectOldSpaceGarbage(Thread* thread, |
| 401 ApiCallbacks api_callbacks, |
| 402 GCReason reason) { |
| 403 if (BeginOldSpaceGC()) { |
| 404 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 405 RecordBeforeGC(kOld, reason); |
| 406 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); |
| 407 TimelineDurationScope tds(thread, |
| 408 isolate()->GetGCStream(), |
| 409 "CollectOldGeneration"); |
| 410 UpdateClassHeapStatsBeforeGC(kOld); |
| 411 old_space_.MarkSweep(invoke_api_callbacks); |
| 412 RecordAfterGC(kOld); |
| 413 PrintStats(); |
| 414 EndOldSpaceGC(); |
| 415 } |
| 416 } |
| 417 |
| 418 |
| 419 void Heap::CollectGarbage(Space space, |
| 420 ApiCallbacks api_callbacks, |
| 421 GCReason reason) { |
| 422 Thread* thread = Thread::Current(); |
| 423 switch (space) { |
| 424 case kNew: { |
| 425 CollectNewSpaceGarbage(thread, api_callbacks, reason); |
| 426 break; |
| 427 } |
| 428 case kOld: |
| 429 case kCode: { |
| 430 CollectOldSpaceGarbage(thread, api_callbacks, reason); |
| 431 break; |
| 432 } |
| 433 default: |
| 434 UNREACHABLE(); |
| 435 } |
| 436 } |
| 437 |
| 438 |
| 383 void Heap::CollectGarbage(Space space) { | 439 void Heap::CollectGarbage(Space space) { |
| 440 Thread* thread = Thread::Current(); |
| 384 if (space == kOld) { | 441 if (space == kOld) { |
| 385 CollectGarbage(space, kInvokeApiCallbacks, kOldSpace); | 442 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kOldSpace); |
| 386 } else { | 443 } else { |
| 387 ASSERT(space == kNew); | 444 ASSERT(space == kNew); |
| 388 CollectGarbage(space, kInvokeApiCallbacks, kNewSpace); | 445 CollectNewSpaceGarbage(thread, kInvokeApiCallbacks, kNewSpace); |
| 389 } | 446 } |
| 390 } | 447 } |
| 391 | 448 |
| 392 | 449 |
| 393 void Heap::CollectAllGarbage() { | 450 void Heap::CollectAllGarbage() { |
| 394 Thread* thread = Thread::Current(); | 451 Thread* thread = Thread::Current(); |
| 395 { | 452 CollectNewSpaceGarbage(thread, kInvokeApiCallbacks, kFull); |
| 396 RecordBeforeGC(kNew, kFull); | 453 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kFull); |
| 397 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); | |
| 398 TimelineDurationScope tds(thread, | |
| 399 isolate()->GetGCStream(), | |
| 400 "CollectNewGeneration"); | |
| 401 UpdateClassHeapStatsBeforeGC(kNew); | |
| 402 new_space_.Scavenge(kInvokeApiCallbacks); | |
| 403 isolate()->class_table()->UpdatePromoted(); | |
| 404 UpdatePretenurePolicy(); | |
| 405 RecordAfterGC(); | |
| 406 PrintStats(); | |
| 407 } | |
| 408 { | |
| 409 RecordBeforeGC(kOld, kFull); | |
| 410 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); | |
| 411 TimelineDurationScope tds(thread, | |
| 412 isolate()->GetGCStream(), | |
| 413 "CollectOldGeneration"); | |
| 414 UpdateClassHeapStatsBeforeGC(kOld); | |
| 415 old_space_.MarkSweep(kInvokeApiCallbacks); | |
| 416 RecordAfterGC(); | |
| 417 PrintStats(); | |
| 418 } | |
| 419 } | 454 } |
| 420 | 455 |
| 421 | 456 |
| 422 bool Heap::ShouldPretenure(intptr_t class_id) const { | 457 bool Heap::ShouldPretenure(intptr_t class_id) const { |
| 423 if (class_id == kOneByteStringCid) { | 458 if (class_id == kOneByteStringCid) { |
| 424 return pretenure_policy_ > 0; | 459 return pretenure_policy_ > 0; |
| 425 } else { | 460 } else { |
| 426 return false; | 461 return false; |
| 427 } | 462 } |
| 428 } | 463 } |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { | 722 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { |
| 688 if (space == kNew) { | 723 if (space == kNew) { |
| 689 new_space_.PrintToJSONObject(object); | 724 new_space_.PrintToJSONObject(object); |
| 690 } else { | 725 } else { |
| 691 old_space_.PrintToJSONObject(object); | 726 old_space_.PrintToJSONObject(object); |
| 692 } | 727 } |
| 693 } | 728 } |
| 694 | 729 |
| 695 | 730 |
| 696 void Heap::RecordBeforeGC(Space space, GCReason reason) { | 731 void Heap::RecordBeforeGC(Space space, GCReason reason) { |
| 697 BeginGC(); | 732 ASSERT((space == kNew && gc_new_space_in_progress_) || |
| 733 (space == kOld && gc_old_space_in_progress_)); |
| 698 stats_.num_++; | 734 stats_.num_++; |
| 699 stats_.space_ = space; | 735 stats_.space_ = space; |
| 700 stats_.reason_ = reason; | 736 stats_.reason_ = reason; |
| 701 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); | 737 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); |
| 702 stats_.before_.new_ = new_space_.GetCurrentUsage(); | 738 stats_.before_.new_ = new_space_.GetCurrentUsage(); |
| 703 stats_.before_.old_ = old_space_.GetCurrentUsage(); | 739 stats_.before_.old_ = old_space_.GetCurrentUsage(); |
| 704 stats_.times_[0] = 0; | 740 stats_.times_[0] = 0; |
| 705 stats_.times_[1] = 0; | 741 stats_.times_[1] = 0; |
| 706 stats_.times_[2] = 0; | 742 stats_.times_[2] = 0; |
| 707 stats_.times_[3] = 0; | 743 stats_.times_[3] = 0; |
| 708 stats_.data_[0] = 0; | 744 stats_.data_[0] = 0; |
| 709 stats_.data_[1] = 0; | 745 stats_.data_[1] = 0; |
| 710 stats_.data_[2] = 0; | 746 stats_.data_[2] = 0; |
| 711 stats_.data_[3] = 0; | 747 stats_.data_[3] = 0; |
| 712 } | 748 } |
| 713 | 749 |
| 714 | 750 |
| 715 void Heap::RecordAfterGC() { | 751 void Heap::RecordAfterGC(Space space) { |
| 716 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); | 752 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); |
| 717 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; | 753 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; |
| 718 if (stats_.space_ == kNew) { | 754 if (stats_.space_ == kNew) { |
| 719 new_space_.AddGCTime(delta); | 755 new_space_.AddGCTime(delta); |
| 720 new_space_.IncrementCollections(); | 756 new_space_.IncrementCollections(); |
| 721 } else { | 757 } else { |
| 722 old_space_.AddGCTime(delta); | 758 old_space_.AddGCTime(delta); |
| 723 old_space_.IncrementCollections(); | 759 old_space_.IncrementCollections(); |
| 724 } | 760 } |
| 725 stats_.after_.new_ = new_space_.GetCurrentUsage(); | 761 stats_.after_.new_ = new_space_.GetCurrentUsage(); |
| 726 stats_.after_.old_ = old_space_.GetCurrentUsage(); | 762 stats_.after_.old_ = old_space_.GetCurrentUsage(); |
| 727 EndGC(); | 763 ASSERT((space == kNew && gc_new_space_in_progress_) || |
| 764 (space == kOld && gc_old_space_in_progress_)); |
| 728 if (Service::gc_stream.enabled()) { | 765 if (Service::gc_stream.enabled()) { |
| 729 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); | 766 ServiceEvent event(Isolate::Current(), ServiceEvent::kGC); |
| 730 event.set_gc_stats(&stats_); | 767 event.set_gc_stats(&stats_); |
| 731 Service::HandleEvent(&event); | 768 Service::HandleEvent(&event); |
| 732 } | 769 } |
| 733 } | 770 } |
| 734 | 771 |
| 735 | 772 |
| 736 void Heap::PrintStats() { | 773 void Heap::PrintStats() { |
| 737 if (!FLAG_verbose_gc) return; | 774 if (!FLAG_verbose_gc) return; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 Dart::vm_isolate()->heap()->WriteProtect(false, include_code_pages_); | 844 Dart::vm_isolate()->heap()->WriteProtect(false, include_code_pages_); |
| 808 } | 845 } |
| 809 | 846 |
| 810 | 847 |
| 811 WritableVMIsolateScope::~WritableVMIsolateScope() { | 848 WritableVMIsolateScope::~WritableVMIsolateScope() { |
| 812 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); | 849 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); |
| 813 Dart::vm_isolate()->heap()->WriteProtect(true, include_code_pages_); | 850 Dart::vm_isolate()->heap()->WriteProtect(true, include_code_pages_); |
| 814 } | 851 } |
| 815 | 852 |
| 816 } // namespace dart | 853 } // namespace dart |
| OLD | NEW |