| 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 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 DEFINE_FLAG(bool, verbose_gc, false, "Enables verbose GC."); | 27 DEFINE_FLAG(bool, verbose_gc, false, "Enables verbose GC."); |
| 28 DEFINE_FLAG(int, verbose_gc_hdr, 40, "Print verbose GC header interval."); | 28 DEFINE_FLAG(int, verbose_gc_hdr, 40, "Print verbose GC header interval."); |
| 29 DEFINE_FLAG(bool, verify_before_gc, false, | 29 DEFINE_FLAG(bool, verify_before_gc, false, |
| 30 "Enables heap verification before GC."); | 30 "Enables heap verification before GC."); |
| 31 DEFINE_FLAG(bool, verify_after_gc, false, | 31 DEFINE_FLAG(bool, verify_after_gc, false, |
| 32 "Enables heap verification after GC."); | 32 "Enables heap verification after GC."); |
| 33 DEFINE_FLAG(bool, gc_at_alloc, false, "GC at every allocation."); | 33 DEFINE_FLAG(bool, gc_at_alloc, false, "GC at every allocation."); |
| 34 DEFINE_FLAG(int, new_gen_ext_limit, 64, | 34 DEFINE_FLAG(int, new_gen_ext_limit, 64, |
| 35 "maximum total external size (MB) in new gen before triggering GC"); | 35 "maximum total external size (MB) in new gen before triggering GC"); |
| 36 DEFINE_FLAG(int, pretenure_threshold, 98, |
| 37 "Trigger pretenuring when this many percent are promoted."); |
| 38 DEFINE_FLAG(int, pretenure_interval, 10, |
| 39 "Back off pretenuring after this many cycles."); |
| 36 | 40 |
| 37 Heap::Heap(Isolate* isolate, | 41 Heap::Heap(Isolate* isolate, |
| 38 intptr_t max_new_gen_semi_words, | 42 intptr_t max_new_gen_semi_words, |
| 39 intptr_t max_old_gen_words) | 43 intptr_t max_old_gen_words) |
| 40 : isolate_(isolate), read_only_(false), gc_in_progress_(false) { | 44 : isolate_(isolate), |
| 45 read_only_(false), |
| 46 gc_in_progress_(false), |
| 47 pretenure_policy_(0) { |
| 41 for (int sel = 0; | 48 for (int sel = 0; |
| 42 sel < kNumWeakSelectors; | 49 sel < kNumWeakSelectors; |
| 43 sel++) { | 50 sel++) { |
| 44 new_weak_tables_[sel] = new WeakTable(); | 51 new_weak_tables_[sel] = new WeakTable(); |
| 45 old_weak_tables_[sel] = new WeakTable(); | 52 old_weak_tables_[sel] = new WeakTable(); |
| 46 } | 53 } |
| 47 new_space_ = new Scavenger(this, | 54 new_space_ = new Scavenger(this, |
| 48 max_new_gen_semi_words, | 55 max_new_gen_semi_words, |
| 49 kNewObjectAlignmentOffset); | 56 kNewObjectAlignmentOffset); |
| 50 old_space_ = new PageSpace(this, max_old_gen_words); | 57 old_space_ = new PageSpace(this, max_old_gen_words); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 addr = old_space_->TryAllocate(size, type, PageSpace::kForceGrowth); | 138 addr = old_space_->TryAllocate(size, type, PageSpace::kForceGrowth); |
| 132 if (addr != 0) { | 139 if (addr != 0) { |
| 133 return addr; | 140 return addr; |
| 134 } | 141 } |
| 135 // Give up allocating this object. | 142 // Give up allocating this object. |
| 136 OS::PrintErr( | 143 OS::PrintErr( |
| 137 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); | 144 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); |
| 138 return 0; | 145 return 0; |
| 139 } | 146 } |
| 140 | 147 |
| 148 |
| 149 uword Heap::AllocatePretenured(intptr_t size) { |
| 150 ASSERT(isolate()->no_gc_scope_depth() == 0); |
| 151 uword addr = old_space_->TryAllocateDataBump(size, PageSpace::kControlGrowth); |
| 152 if (addr != 0) return addr; |
| 153 return AllocateOld(size, HeapPage::kData); |
| 154 } |
| 155 |
| 156 |
| 141 void Heap::AllocateExternal(intptr_t size, Space space) { | 157 void Heap::AllocateExternal(intptr_t size, Space space) { |
| 142 ASSERT(isolate()->no_gc_scope_depth() == 0); | 158 ASSERT(isolate()->no_gc_scope_depth() == 0); |
| 143 if (space == kNew) { | 159 if (space == kNew) { |
| 144 new_space_->AllocateExternal(size); | 160 new_space_->AllocateExternal(size); |
| 145 if (new_space_->ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { | 161 if (new_space_->ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { |
| 146 // Attempt to free some external allocation by a scavenge. (If the total | 162 // Attempt to free some external allocation by a scavenge. (If the total |
| 147 // remains above the limit, next external alloc will trigger another.) | 163 // remains above the limit, next external alloc will trigger another.) |
| 148 CollectGarbage(kNew); | 164 CollectGarbage(kNew); |
| 149 } | 165 } |
| 150 } else { | 166 } else { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 GCReason reason) { | 278 GCReason reason) { |
| 263 TIMERSCOPE(isolate(), time_gc); | 279 TIMERSCOPE(isolate(), time_gc); |
| 264 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 280 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 265 switch (space) { | 281 switch (space) { |
| 266 case kNew: { | 282 case kNew: { |
| 267 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); | 283 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); |
| 268 RecordBeforeGC(kNew, reason); | 284 RecordBeforeGC(kNew, reason); |
| 269 UpdateClassHeapStatsBeforeGC(kNew); | 285 UpdateClassHeapStatsBeforeGC(kNew); |
| 270 new_space_->Scavenge(invoke_api_callbacks); | 286 new_space_->Scavenge(invoke_api_callbacks); |
| 271 isolate()->class_table()->UpdatePromoted(); | 287 isolate()->class_table()->UpdatePromoted(); |
| 288 UpdatePretenurePolicy(); |
| 272 RecordAfterGC(); | 289 RecordAfterGC(); |
| 273 PrintStats(); | 290 PrintStats(); |
| 274 if (old_space_->NeedsGarbageCollection()) { | 291 if (old_space_->NeedsGarbageCollection()) { |
| 275 // Old collections should call the API callbacks. | 292 // Old collections should call the API callbacks. |
| 276 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); | 293 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); |
| 277 } | 294 } |
| 278 break; | 295 break; |
| 279 } | 296 } |
| 280 case kOld: | 297 case kOld: |
| 281 case kCode: { | 298 case kCode: { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 331 |
| 315 | 332 |
| 316 void Heap::CollectAllGarbage() { | 333 void Heap::CollectAllGarbage() { |
| 317 TIMERSCOPE(isolate(), time_gc); | 334 TIMERSCOPE(isolate(), time_gc); |
| 318 { | 335 { |
| 319 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); | 336 VMTagScope tagScope(isolate(), VMTag::kGCNewSpaceTagId); |
| 320 RecordBeforeGC(kNew, kFull); | 337 RecordBeforeGC(kNew, kFull); |
| 321 UpdateClassHeapStatsBeforeGC(kNew); | 338 UpdateClassHeapStatsBeforeGC(kNew); |
| 322 new_space_->Scavenge(kInvokeApiCallbacks); | 339 new_space_->Scavenge(kInvokeApiCallbacks); |
| 323 isolate()->class_table()->UpdatePromoted(); | 340 isolate()->class_table()->UpdatePromoted(); |
| 341 UpdatePretenurePolicy(); |
| 324 RecordAfterGC(); | 342 RecordAfterGC(); |
| 325 PrintStats(); | 343 PrintStats(); |
| 326 } | 344 } |
| 327 { | 345 { |
| 328 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); | 346 VMTagScope tagScope(isolate(), VMTag::kGCOldSpaceTagId); |
| 329 RecordBeforeGC(kOld, kFull); | 347 RecordBeforeGC(kOld, kFull); |
| 330 UpdateClassHeapStatsBeforeGC(kOld); | 348 UpdateClassHeapStatsBeforeGC(kOld); |
| 331 old_space_->MarkSweep(kInvokeApiCallbacks); | 349 old_space_->MarkSweep(kInvokeApiCallbacks); |
| 332 RecordAfterGC(); | 350 RecordAfterGC(); |
| 333 PrintStats(); | 351 PrintStats(); |
| 334 } | 352 } |
| 335 } | 353 } |
| 336 | 354 |
| 337 | 355 |
| 356 bool Heap::ShouldPretenure(intptr_t class_id) const { |
| 357 if (class_id == kOneByteStringCid) { |
| 358 return pretenure_policy_ > 0; |
| 359 } else { |
| 360 return false; |
| 361 } |
| 362 } |
| 363 |
| 364 |
| 365 void Heap::UpdatePretenurePolicy() { |
| 366 ClassHeapStats* stats = |
| 367 isolate_->class_table()->StatsWithUpdatedSize(kOneByteStringCid); |
| 368 int allocated = stats->pre_gc.new_count; |
| 369 int promo_percent = (allocated == 0) ? 0 : |
| 370 (100 * stats->promoted_count) / allocated; |
| 371 if (promo_percent >= FLAG_pretenure_threshold) { |
| 372 pretenure_policy_ += FLAG_pretenure_interval; |
| 373 } else { |
| 374 pretenure_policy_ = Utils::Maximum(0, pretenure_policy_ - 1); |
| 375 } |
| 376 } |
| 377 |
| 378 |
| 338 void Heap::SetGrowthControlState(bool state) { | 379 void Heap::SetGrowthControlState(bool state) { |
| 339 old_space_->SetGrowthControlState(state); | 380 old_space_->SetGrowthControlState(state); |
| 340 } | 381 } |
| 341 | 382 |
| 342 | 383 |
| 343 bool Heap::GrowthControlState() { | 384 bool Heap::GrowthControlState() { |
| 344 return old_space_->GrowthControlState(); | 385 return old_space_->GrowthControlState(); |
| 345 } | 386 } |
| 346 | 387 |
| 347 | 388 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 heap->DisableGrowthControl(); | 688 heap->DisableGrowthControl(); |
| 648 } | 689 } |
| 649 | 690 |
| 650 | 691 |
| 651 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { | 692 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { |
| 652 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); | 693 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); |
| 653 heap->SetGrowthControlState(current_growth_controller_state_); | 694 heap->SetGrowthControlState(current_growth_controller_state_); |
| 654 } | 695 } |
| 655 | 696 |
| 656 } // namespace dart | 697 } // namespace dart |
| OLD | NEW |