| 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 if (space == kNew) { | 97 if (space == kNew) { |
| 98 new_space_->AllocateExternal(size); | 98 new_space_->AllocateExternal(size); |
| 99 if (new_space_->ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { | 99 if (new_space_->ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) { |
| 100 // Attempt to free some external allocation by a scavenge. (If the total | 100 // Attempt to free some external allocation by a scavenge. (If the total |
| 101 // remains above the limit, next external alloc will trigger another.) | 101 // remains above the limit, next external alloc will trigger another.) |
| 102 CollectGarbage(kNew); | 102 CollectGarbage(kNew); |
| 103 } | 103 } |
| 104 } else { | 104 } else { |
| 105 ASSERT(space == kOld); | 105 ASSERT(space == kOld); |
| 106 old_space_->AllocateExternal(size); | 106 old_space_->AllocateExternal(size); |
| 107 if (old_space_->NeedsGarbageCollection()) { |
| 108 CollectGarbage(kOld); |
| 109 } |
| 107 } | 110 } |
| 108 } | 111 } |
| 109 | 112 |
| 110 void Heap::FreeExternal(intptr_t size, Space space) { | 113 void Heap::FreeExternal(intptr_t size, Space space) { |
| 111 if (space == kNew) { | 114 if (space == kNew) { |
| 112 new_space_->FreeExternal(size); | 115 new_space_->FreeExternal(size); |
| 113 } else { | 116 } else { |
| 114 ASSERT(space == kOld); | 117 ASSERT(space == kOld); |
| 115 old_space_->FreeExternal(size); | 118 old_space_->FreeExternal(size); |
| 116 } | 119 } |
| 117 } | 120 } |
| 118 | 121 |
| 122 void Heap::PromoteExternal(intptr_t size) { |
| 123 new_space_->FreeExternal(size); |
| 124 old_space_->AllocateExternal(size); |
| 125 } |
| 126 |
| 119 bool Heap::Contains(uword addr) const { | 127 bool Heap::Contains(uword addr) const { |
| 120 return new_space_->Contains(addr) || | 128 return new_space_->Contains(addr) || |
| 121 old_space_->Contains(addr); | 129 old_space_->Contains(addr); |
| 122 } | 130 } |
| 123 | 131 |
| 124 | 132 |
| 125 bool Heap::NewContains(uword addr) const { | 133 bool Heap::NewContains(uword addr) const { |
| 126 return new_space_->Contains(addr); | 134 return new_space_->Contains(addr); |
| 127 } | 135 } |
| 128 | 136 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 } | 204 } |
| 197 raw_obj = FindOldObject(visitor); | 205 raw_obj = FindOldObject(visitor); |
| 198 if (raw_obj != Object::null()) { | 206 if (raw_obj != Object::null()) { |
| 199 return raw_obj; | 207 return raw_obj; |
| 200 } | 208 } |
| 201 raw_obj = FindObjectInCodeSpace(visitor); | 209 raw_obj = FindObjectInCodeSpace(visitor); |
| 202 return raw_obj; | 210 return raw_obj; |
| 203 } | 211 } |
| 204 | 212 |
| 205 | 213 |
| 206 void Heap::CollectGarbage(Space space, ApiCallbacks api_callbacks) { | 214 void Heap::CollectGarbage(Space space, |
| 215 ApiCallbacks api_callbacks, |
| 216 GCReason reason) { |
| 207 Isolate* isolate = Isolate::Current(); | 217 Isolate* isolate = Isolate::Current(); |
| 208 TIMERSCOPE(isolate, time_gc); | 218 TIMERSCOPE(isolate, time_gc); |
| 209 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 219 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 210 switch (space) { | 220 switch (space) { |
| 211 case kNew: { | 221 case kNew: { |
| 212 VMTagScope tagScope(isolate, VMTag::kGCNewSpaceTagId); | 222 VMTagScope tagScope(isolate, VMTag::kGCNewSpaceTagId); |
| 213 RecordBeforeGC(kNew, kNewSpace); | 223 RecordBeforeGC(kNew, reason); |
| 214 UpdateClassHeapStatsBeforeGC(kNew); | 224 UpdateClassHeapStatsBeforeGC(kNew); |
| 215 new_space_->Scavenge(invoke_api_callbacks); | 225 new_space_->Scavenge(invoke_api_callbacks); |
| 216 RecordAfterGC(); | 226 RecordAfterGC(); |
| 217 PrintStats(); | 227 PrintStats(); |
| 218 // TODO(koda): Replace promotion failure tracking with | 228 if (old_space_->NeedsGarbageCollection()) { |
| 219 // old_space_->NeedsGarbageCollection. | |
| 220 if (new_space_->HadPromotionFailure() || old_space_->NeedExternalGC()) { | |
| 221 // Old collections should call the API callbacks. | 229 // Old collections should call the API callbacks. |
| 222 CollectGarbage(kOld, kInvokeApiCallbacks); | 230 CollectGarbage(kOld, kInvokeApiCallbacks, kPromotion); |
| 223 } | 231 } |
| 224 break; | 232 break; |
| 225 } | 233 } |
| 226 case kOld: | 234 case kOld: |
| 227 case kCode: { | 235 case kCode: { |
| 228 VMTagScope tagScope(isolate, VMTag::kGCOldSpaceTagId); | 236 VMTagScope tagScope(isolate, VMTag::kGCOldSpaceTagId); |
| 229 bool promotion_failure = new_space_->HadPromotionFailure(); | 237 RecordBeforeGC(kOld, reason); |
| 230 RecordBeforeGC(kOld, promotion_failure ? kPromotionFailure : kOldSpace); | |
| 231 UpdateClassHeapStatsBeforeGC(kOld); | 238 UpdateClassHeapStatsBeforeGC(kOld); |
| 232 old_space_->MarkSweep(invoke_api_callbacks); | 239 old_space_->MarkSweep(invoke_api_callbacks); |
| 233 RecordAfterGC(); | 240 RecordAfterGC(); |
| 234 PrintStats(); | 241 PrintStats(); |
| 235 break; | 242 break; |
| 236 } | 243 } |
| 237 default: | 244 default: |
| 238 UNREACHABLE(); | 245 UNREACHABLE(); |
| 239 } | 246 } |
| 240 } | 247 } |
| 241 | 248 |
| 242 | 249 |
| 243 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) { | 250 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) { |
| 244 Isolate* isolate = Isolate::Current(); | 251 Isolate* isolate = Isolate::Current(); |
| 245 ClassTable* class_table = isolate->class_table(); | 252 ClassTable* class_table = isolate->class_table(); |
| 246 if (space == kNew) { | 253 if (space == kNew) { |
| 247 class_table->ResetCountersNew(); | 254 class_table->ResetCountersNew(); |
| 248 } else { | 255 } else { |
| 249 class_table->ResetCountersOld(); | 256 class_table->ResetCountersOld(); |
| 250 } | 257 } |
| 251 } | 258 } |
| 252 | 259 |
| 253 | 260 |
| 254 void Heap::CollectGarbage(Space space) { | 261 void Heap::CollectGarbage(Space space) { |
| 255 ApiCallbacks api_callbacks; | |
| 256 if (space == kOld) { | 262 if (space == kOld) { |
| 257 api_callbacks = kInvokeApiCallbacks; | 263 CollectGarbage(space, kInvokeApiCallbacks, kOldSpace); |
| 258 } else { | 264 } else { |
| 259 api_callbacks = kIgnoreApiCallbacks; | 265 ASSERT(space == kNew); |
| 266 CollectGarbage(space, kIgnoreApiCallbacks, kNewSpace); |
| 260 } | 267 } |
| 261 CollectGarbage(space, api_callbacks); | |
| 262 } | 268 } |
| 263 | 269 |
| 264 | 270 |
| 265 void Heap::CollectAllGarbage() { | 271 void Heap::CollectAllGarbage() { |
| 266 Isolate* isolate = Isolate::Current(); | 272 Isolate* isolate = Isolate::Current(); |
| 267 TIMERSCOPE(isolate, time_gc); | 273 TIMERSCOPE(isolate, time_gc); |
| 268 { | 274 { |
| 269 VMTagScope tagScope(isolate, VMTag::kGCNewSpaceTagId); | 275 VMTagScope tagScope(isolate, VMTag::kGCNewSpaceTagId); |
| 270 RecordBeforeGC(kNew, kFull); | 276 RecordBeforeGC(kNew, kFull); |
| 271 UpdateClassHeapStatsBeforeGC(kNew); | 277 UpdateClassHeapStatsBeforeGC(kNew); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 return new_space_->collections(); | 407 return new_space_->collections(); |
| 402 } | 408 } |
| 403 return old_space_->collections(); | 409 return old_space_->collections(); |
| 404 } | 410 } |
| 405 | 411 |
| 406 | 412 |
| 407 const char* Heap::GCReasonToString(GCReason gc_reason) { | 413 const char* Heap::GCReasonToString(GCReason gc_reason) { |
| 408 switch (gc_reason) { | 414 switch (gc_reason) { |
| 409 case kNewSpace: | 415 case kNewSpace: |
| 410 return "new space"; | 416 return "new space"; |
| 411 case kPromotionFailure: | 417 case kPromotion: |
| 412 return "promotion failure"; | 418 return "promotion"; |
| 413 case kOldSpace: | 419 case kOldSpace: |
| 414 return "old space"; | 420 return "old space"; |
| 415 case kFull: | 421 case kFull: |
| 416 return "full"; | 422 return "full"; |
| 417 case kGCAtAlloc: | 423 case kGCAtAlloc: |
| 418 return "debugging"; | 424 return "debugging"; |
| 419 case kGCTestCase: | 425 case kGCTestCase: |
| 420 return "test case"; | 426 return "test case"; |
| 421 default: | 427 default: |
| 422 UNREACHABLE(); | 428 UNREACHABLE(); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 heap->DisableGrowthControl(); | 581 heap->DisableGrowthControl(); |
| 576 } | 582 } |
| 577 | 583 |
| 578 | 584 |
| 579 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { | 585 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { |
| 580 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); | 586 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); |
| 581 heap->SetGrowthControlState(current_growth_controller_state_); | 587 heap->SetGrowthControlState(current_growth_controller_state_); |
| 582 } | 588 } |
| 583 | 589 |
| 584 } // namespace dart | 590 } // namespace dart |
| OLD | NEW |