| 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 21 matching lines...) Expand all Loading... |
| 32 intptr_t max_external_words) | 32 intptr_t max_external_words) |
| 33 : isolate_(isolate), | 33 : isolate_(isolate), |
| 34 new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset), | 34 new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset), |
| 35 old_space_(this, max_old_gen_words, max_external_words), | 35 old_space_(this, max_old_gen_words, max_external_words), |
| 36 barrier_(new Monitor()), | 36 barrier_(new Monitor()), |
| 37 barrier_done_(new Monitor()), | 37 barrier_done_(new Monitor()), |
| 38 finalization_tasks_lock_(new Monitor()), | 38 finalization_tasks_lock_(new Monitor()), |
| 39 finalization_tasks_(0), | 39 finalization_tasks_(0), |
| 40 read_only_(false), | 40 read_only_(false), |
| 41 gc_new_space_in_progress_(false), | 41 gc_new_space_in_progress_(false), |
| 42 gc_old_space_in_progress_(false), | 42 gc_old_space_in_progress_(false) { |
| 43 pretenure_policy_(0) { | |
| 44 for (int sel = 0; | 43 for (int sel = 0; |
| 45 sel < kNumWeakSelectors; | 44 sel < kNumWeakSelectors; |
| 46 sel++) { | 45 sel++) { |
| 47 new_weak_tables_[sel] = new WeakTable(); | 46 new_weak_tables_[sel] = new WeakTable(); |
| 48 old_weak_tables_[sel] = new WeakTable(); | 47 old_weak_tables_[sel] = new WeakTable(); |
| 49 } | 48 } |
| 50 stats_.num_ = 0; | 49 stats_.num_ = 0; |
| 51 } | 50 } |
| 52 | 51 |
| 53 | 52 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 if (addr != 0) { | 140 if (addr != 0) { |
| 142 return addr; | 141 return addr; |
| 143 } | 142 } |
| 144 // Give up allocating this object. | 143 // Give up allocating this object. |
| 145 OS::PrintErr( | 144 OS::PrintErr( |
| 146 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); | 145 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); |
| 147 return 0; | 146 return 0; |
| 148 } | 147 } |
| 149 | 148 |
| 150 | 149 |
| 151 uword Heap::AllocatePretenured(intptr_t size) { | |
| 152 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); | |
| 153 uword addr = old_space_.TryAllocateDataBump(size, PageSpace::kControlGrowth); | |
| 154 if (addr != 0) return addr; | |
| 155 return AllocateOld(size, HeapPage::kData); | |
| 156 } | |
| 157 | |
| 158 | |
| 159 void Heap::AllocateExternal(intptr_t size, Space space) { | 150 void Heap::AllocateExternal(intptr_t size, Space space) { |
| 160 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); | 151 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); |
| 161 if (space == kNew) { | 152 if (space == kNew) { |
| 162 isolate()->AssertCurrentThreadIsMutator(); | 153 isolate()->AssertCurrentThreadIsMutator(); |
| 163 new_space_.AllocateExternal(size); | 154 new_space_.AllocateExternal(size); |
| 164 if (new_space_.ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { | 155 if (new_space_.ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { |
| 165 // Attempt to free some external allocation by a scavenge. (If the total | 156 // Attempt to free some external allocation by a scavenge. (If the total |
| 166 // remains above the limit, next external alloc will trigger another.) | 157 // remains above the limit, next external alloc will trigger another.) |
| 167 CollectGarbage(kNew); | 158 CollectGarbage(kNew); |
| 168 } | 159 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 GCReason reason) { | 365 GCReason reason) { |
| 375 ASSERT((reason == kNewSpace) || (reason == kFull)); | 366 ASSERT((reason == kNewSpace) || (reason == kFull)); |
| 376 if (BeginNewSpaceGC(thread)) { | 367 if (BeginNewSpaceGC(thread)) { |
| 377 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 368 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 378 RecordBeforeGC(kNew, reason); | 369 RecordBeforeGC(kNew, reason); |
| 379 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); | 370 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); |
| 380 TIMELINE_FUNCTION_GC_DURATION(thread, "CollectNewGeneration"); | 371 TIMELINE_FUNCTION_GC_DURATION(thread, "CollectNewGeneration"); |
| 381 UpdateClassHeapStatsBeforeGC(kNew); | 372 UpdateClassHeapStatsBeforeGC(kNew); |
| 382 new_space_.Scavenge(invoke_api_callbacks); | 373 new_space_.Scavenge(invoke_api_callbacks); |
| 383 isolate()->class_table()->UpdatePromoted(); | 374 isolate()->class_table()->UpdatePromoted(); |
| 384 UpdatePretenurePolicy(); | |
| 385 RecordAfterGC(kNew); | 375 RecordAfterGC(kNew); |
| 386 PrintStats(); | 376 PrintStats(); |
| 387 NOT_IN_PRODUCT(PrintStatsToTimeline(&tds)); | 377 NOT_IN_PRODUCT(PrintStatsToTimeline(&tds)); |
| 388 EndNewSpaceGC(); | 378 EndNewSpaceGC(); |
| 389 if ((reason == kNewSpace) && old_space_.NeedsGarbageCollection()) { | 379 if ((reason == kNewSpace) && old_space_.NeedsGarbageCollection()) { |
| 390 // Old collections should call the API callbacks. | 380 // Old collections should call the API callbacks. |
| 391 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion); | 381 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion); |
| 392 } | 382 } |
| 393 } | 383 } |
| 394 } | 384 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 { | 447 { |
| 458 MonitorLocker ml(old_space_.tasks_lock()); | 448 MonitorLocker ml(old_space_.tasks_lock()); |
| 459 while (old_space_.tasks() > 0) { | 449 while (old_space_.tasks() > 0) { |
| 460 ml.WaitWithSafepointCheck(thread); | 450 ml.WaitWithSafepointCheck(thread); |
| 461 } | 451 } |
| 462 } | 452 } |
| 463 } | 453 } |
| 464 #endif | 454 #endif |
| 465 | 455 |
| 466 | 456 |
| 467 bool Heap::ShouldPretenure(intptr_t class_id) const { | |
| 468 if (class_id == kOneByteStringCid) { | |
| 469 return pretenure_policy_ > 0; | |
| 470 } else { | |
| 471 return false; | |
| 472 } | |
| 473 } | |
| 474 | |
| 475 | |
| 476 void Heap::UpdatePretenurePolicy() { | |
| 477 if (FLAG_disable_alloc_stubs_after_gc) { | |
| 478 ClassTable* table = isolate_->class_table(); | |
| 479 Zone* zone = Thread::Current()->zone(); | |
| 480 for (intptr_t cid = 1; cid < table->NumCids(); ++cid) { | |
| 481 if (((cid >= kNumPredefinedCids) || (cid == kArrayCid)) && | |
| 482 table->IsValidIndex(cid) && | |
| 483 table->HasValidClassAt(cid)) { | |
| 484 const Class& cls = Class::Handle(zone, table->At(cid)); | |
| 485 cls.DisableAllocationStub(); | |
| 486 } | |
| 487 } | |
| 488 } | |
| 489 ClassHeapStats* stats = | |
| 490 isolate_->class_table()->StatsWithUpdatedSize(kOneByteStringCid); | |
| 491 int allocated = stats->pre_gc.new_count; | |
| 492 int promo_percent = (allocated == 0) ? 0 : | |
| 493 (100 * stats->promoted_count) / allocated; | |
| 494 if (promo_percent >= FLAG_pretenure_threshold) { | |
| 495 pretenure_policy_ += FLAG_pretenure_interval; | |
| 496 } else { | |
| 497 pretenure_policy_ = Utils::Maximum(0, pretenure_policy_ - 1); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 | |
| 502 void Heap::UpdateGlobalMaxUsed() { | 457 void Heap::UpdateGlobalMaxUsed() { |
| 503 ASSERT(isolate_ != NULL); | 458 ASSERT(isolate_ != NULL); |
| 504 // We are accessing the used in words count for both new and old space | 459 // We are accessing the used in words count for both new and old space |
| 505 // without synchronizing. The value of this metric is approximate. | 460 // without synchronizing. The value of this metric is approximate. |
| 506 isolate_->GetHeapGlobalUsedMaxMetric()->SetValue( | 461 isolate_->GetHeapGlobalUsedMaxMetric()->SetValue( |
| 507 (UsedInWords(Heap::kNew) * kWordSize) + | 462 (UsedInWords(Heap::kNew) * kWordSize) + |
| 508 (UsedInWords(Heap::kOld) * kWordSize)); | 463 (UsedInWords(Heap::kOld) * kWordSize)); |
| 509 } | 464 } |
| 510 | 465 |
| 511 | 466 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 524 } | 479 } |
| 525 | 480 |
| 526 | 481 |
| 527 void Heap::WriteProtect(bool read_only) { | 482 void Heap::WriteProtect(bool read_only) { |
| 528 read_only_ = read_only; | 483 read_only_ = read_only; |
| 529 new_space_.WriteProtect(read_only); | 484 new_space_.WriteProtect(read_only); |
| 530 old_space_.WriteProtect(read_only); | 485 old_space_.WriteProtect(read_only); |
| 531 } | 486 } |
| 532 | 487 |
| 533 | 488 |
| 534 Heap::Space Heap::SpaceForAllocation(intptr_t cid) { | |
| 535 return FLAG_pretenure_all ? kPretenured : kNew; | |
| 536 } | |
| 537 | |
| 538 | |
| 539 intptr_t Heap::TopOffset(Heap::Space space) { | 489 intptr_t Heap::TopOffset(Heap::Space space) { |
| 540 if (space == kNew) { | 490 if (space == kNew) { |
| 541 return OFFSET_OF(Heap, new_space_) + Scavenger::top_offset(); | 491 return OFFSET_OF(Heap, new_space_) + Scavenger::top_offset(); |
| 542 } else { | 492 } else { |
| 543 ASSERT(space == kPretenured); | 493 ASSERT(space == kOld); |
| 544 return OFFSET_OF(Heap, old_space_) + PageSpace::top_offset(); | 494 return OFFSET_OF(Heap, old_space_) + PageSpace::top_offset(); |
| 545 } | 495 } |
| 546 } | 496 } |
| 547 | 497 |
| 548 | 498 |
| 549 intptr_t Heap::EndOffset(Heap::Space space) { | 499 intptr_t Heap::EndOffset(Heap::Space space) { |
| 550 if (space == kNew) { | 500 if (space == kNew) { |
| 551 return OFFSET_OF(Heap, new_space_) + Scavenger::end_offset(); | 501 return OFFSET_OF(Heap, new_space_) + Scavenger::end_offset(); |
| 552 } else { | 502 } else { |
| 553 ASSERT(space == kPretenured); | 503 ASSERT(space == kOld); |
| 554 return OFFSET_OF(Heap, old_space_) + PageSpace::end_offset(); | 504 return OFFSET_OF(Heap, old_space_) + PageSpace::end_offset(); |
| 555 } | 505 } |
| 556 } | 506 } |
| 557 | 507 |
| 558 | 508 |
| 559 void Heap::Init(Isolate* isolate, | 509 void Heap::Init(Isolate* isolate, |
| 560 intptr_t max_new_gen_words, | 510 intptr_t max_new_gen_words, |
| 561 intptr_t max_old_gen_words, | 511 intptr_t max_old_gen_words, |
| 562 intptr_t max_external_words) { | 512 intptr_t max_external_words) { |
| 563 ASSERT(isolate->heap() == NULL); | 513 ASSERT(isolate->heap() == NULL); |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 Dart::vm_isolate()->heap()->WriteProtect(false); | 868 Dart::vm_isolate()->heap()->WriteProtect(false); |
| 919 } | 869 } |
| 920 | 870 |
| 921 | 871 |
| 922 WritableVMIsolateScope::~WritableVMIsolateScope() { | 872 WritableVMIsolateScope::~WritableVMIsolateScope() { |
| 923 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); | 873 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); |
| 924 Dart::vm_isolate()->heap()->WriteProtect(true); | 874 Dart::vm_isolate()->heap()->WriteProtect(true); |
| 925 } | 875 } |
| 926 | 876 |
| 927 } // namespace dart | 877 } // namespace dart |
| OLD | NEW |