| 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/heap_histogram.h" | 10 #include "vm/heap_histogram.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 RawObject* Heap::FindOldObject(FindObjectVisitor* visitor) const { | 157 RawObject* Heap::FindOldObject(FindObjectVisitor* visitor) const { |
| 158 return old_space_->FindObject(visitor, HeapPage::kData); | 158 return old_space_->FindObject(visitor, HeapPage::kData); |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 void Heap::CollectGarbage(Space space, ApiCallbacks api_callbacks) { | 162 void Heap::CollectGarbage(Space space, ApiCallbacks api_callbacks) { |
| 163 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); | 163 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); |
| 164 switch (space) { | 164 switch (space) { |
| 165 case kNew: { | 165 case kNew: { |
| 166 RecordBeforeGC(kNew, kNewSpace); | 166 RecordBeforeGC(kNew, kNewSpace); |
| 167 UpdateClassHeapStatsBeforeGC(kNew); |
| 167 new_space_->Scavenge(invoke_api_callbacks); | 168 new_space_->Scavenge(invoke_api_callbacks); |
| 168 RecordAfterGC(); | 169 RecordAfterGC(); |
| 169 PrintStats(); | 170 PrintStats(); |
| 170 if (new_space_->HadPromotionFailure()) { | 171 if (new_space_->HadPromotionFailure()) { |
| 171 // Old collections should call the API callbacks. | 172 // Old collections should call the API callbacks. |
| 172 CollectGarbage(kOld, kInvokeApiCallbacks); | 173 CollectGarbage(kOld, kInvokeApiCallbacks); |
| 173 } | 174 } |
| 174 break; | 175 break; |
| 175 } | 176 } |
| 176 case kOld: | 177 case kOld: |
| 177 case kCode: { | 178 case kCode: { |
| 178 bool promotion_failure = new_space_->HadPromotionFailure(); | 179 bool promotion_failure = new_space_->HadPromotionFailure(); |
| 179 RecordBeforeGC(kOld, promotion_failure ? kPromotionFailure : kOldSpace); | 180 RecordBeforeGC(kOld, promotion_failure ? kPromotionFailure : kOldSpace); |
| 181 UpdateClassHeapStatsBeforeGC(kOld); |
| 180 old_space_->MarkSweep(invoke_api_callbacks); | 182 old_space_->MarkSweep(invoke_api_callbacks); |
| 181 RecordAfterGC(); | 183 RecordAfterGC(); |
| 182 PrintStats(); | 184 PrintStats(); |
| 183 UpdateObjectHistogram(); | 185 UpdateObjectHistogram(); |
| 184 break; | 186 break; |
| 185 } | 187 } |
| 186 default: | 188 default: |
| 187 UNREACHABLE(); | 189 UNREACHABLE(); |
| 188 } | 190 } |
| 189 } | 191 } |
| 190 | 192 |
| 191 | 193 |
| 192 void Heap::UpdateObjectHistogram() { | 194 void Heap::UpdateObjectHistogram() { |
| 193 Isolate* isolate = Isolate::Current(); | 195 Isolate* isolate = Isolate::Current(); |
| 194 if (isolate->object_histogram() == NULL) return; | 196 if (isolate->object_histogram() == NULL) return; |
| 195 isolate->object_histogram()->Collect(); | 197 isolate->object_histogram()->Collect(); |
| 196 } | 198 } |
| 197 | 199 |
| 198 | 200 |
| 201 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) { |
| 202 Isolate* isolate = Isolate::Current(); |
| 203 ClassTable* class_table = isolate->class_table(); |
| 204 if (space == kNew) { |
| 205 class_table->ResetCountersNew(); |
| 206 } else { |
| 207 class_table->ResetCountersOld(); |
| 208 } |
| 209 } |
| 210 |
| 211 |
| 199 void Heap::CollectGarbage(Space space) { | 212 void Heap::CollectGarbage(Space space) { |
| 200 ApiCallbacks api_callbacks; | 213 ApiCallbacks api_callbacks; |
| 201 if (space == kOld) { | 214 if (space == kOld) { |
| 202 api_callbacks = kInvokeApiCallbacks; | 215 api_callbacks = kInvokeApiCallbacks; |
| 203 } else { | 216 } else { |
| 204 api_callbacks = kIgnoreApiCallbacks; | 217 api_callbacks = kIgnoreApiCallbacks; |
| 205 } | 218 } |
| 206 CollectGarbage(space, api_callbacks); | 219 CollectGarbage(space, api_callbacks); |
| 207 } | 220 } |
| 208 | 221 |
| 209 | 222 |
| 210 void Heap::CollectAllGarbage() { | 223 void Heap::CollectAllGarbage() { |
| 211 RecordBeforeGC(kNew, kFull); | 224 RecordBeforeGC(kNew, kFull); |
| 225 UpdateClassHeapStatsBeforeGC(kNew); |
| 212 new_space_->Scavenge(kInvokeApiCallbacks); | 226 new_space_->Scavenge(kInvokeApiCallbacks); |
| 213 RecordAfterGC(); | 227 RecordAfterGC(); |
| 214 PrintStats(); | 228 PrintStats(); |
| 215 RecordBeforeGC(kOld, kFull); | 229 RecordBeforeGC(kOld, kFull); |
| 230 UpdateClassHeapStatsBeforeGC(kOld); |
| 216 old_space_->MarkSweep(kInvokeApiCallbacks); | 231 old_space_->MarkSweep(kInvokeApiCallbacks); |
| 217 RecordAfterGC(); | 232 RecordAfterGC(); |
| 218 PrintStats(); | 233 PrintStats(); |
| 219 UpdateObjectHistogram(); | 234 UpdateObjectHistogram(); |
| 220 } | 235 } |
| 221 | 236 |
| 222 | 237 |
| 223 void Heap::SetGrowthControlState(bool state) { | 238 void Heap::SetGrowthControlState(bool state) { |
| 224 old_space_->SetGrowthControlState(state); | 239 old_space_->SetGrowthControlState(state); |
| 225 } | 240 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 return space == kNew ? new_space_->UsedInWords() : old_space_->UsedInWords(); | 328 return space == kNew ? new_space_->UsedInWords() : old_space_->UsedInWords(); |
| 314 } | 329 } |
| 315 | 330 |
| 316 | 331 |
| 317 intptr_t Heap::CapacityInWords(Space space) const { | 332 intptr_t Heap::CapacityInWords(Space space) const { |
| 318 return space == kNew ? new_space_->CapacityInWords() : | 333 return space == kNew ? new_space_->CapacityInWords() : |
| 319 old_space_->CapacityInWords(); | 334 old_space_->CapacityInWords(); |
| 320 } | 335 } |
| 321 | 336 |
| 322 | 337 |
| 338 int64_t Heap::GCTimeInMicros(Space space) const { |
| 339 if (space == kNew) { |
| 340 return new_space_->gc_time_micros(); |
| 341 } |
| 342 return old_space_->gc_time_micros(); |
| 343 } |
| 344 |
| 345 |
| 346 intptr_t Heap::Collections(Space space) const { |
| 347 if (space == kNew) { |
| 348 return new_space_->collections(); |
| 349 } |
| 350 return old_space_->collections(); |
| 351 } |
| 352 |
| 353 |
| 323 const char* Heap::GCReasonToString(GCReason gc_reason) { | 354 const char* Heap::GCReasonToString(GCReason gc_reason) { |
| 324 switch (gc_reason) { | 355 switch (gc_reason) { |
| 325 case kNewSpace: | 356 case kNewSpace: |
| 326 return "new space"; | 357 return "new space"; |
| 327 case kPromotionFailure: | 358 case kPromotionFailure: |
| 328 return "promotion failure"; | 359 return "promotion failure"; |
| 329 case kOldSpace: | 360 case kOldSpace: |
| 330 return "old space"; | 361 return "old space"; |
| 331 case kFull: | 362 case kFull: |
| 332 return "full"; | 363 return "full"; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 void Heap::SetWeakEntry(RawObject* raw_obj, WeakSelector sel, intptr_t val) { | 395 void Heap::SetWeakEntry(RawObject* raw_obj, WeakSelector sel, intptr_t val) { |
| 365 if (raw_obj->IsNewObject()) { | 396 if (raw_obj->IsNewObject()) { |
| 366 new_weak_tables_[sel]->SetValue(raw_obj, val); | 397 new_weak_tables_[sel]->SetValue(raw_obj, val); |
| 367 } else { | 398 } else { |
| 368 ASSERT(raw_obj->IsOldObject()); | 399 ASSERT(raw_obj->IsOldObject()); |
| 369 old_weak_tables_[sel]->SetValue(raw_obj, val); | 400 old_weak_tables_[sel]->SetValue(raw_obj, val); |
| 370 } | 401 } |
| 371 } | 402 } |
| 372 | 403 |
| 373 | 404 |
| 405 void Heap::PrintToJSONObject(Space space, JSONObject* object) const { |
| 406 if (space == kNew) { |
| 407 new_space_->PrintToJSONObject(object); |
| 408 } else { |
| 409 old_space_->PrintToJSONObject(object); |
| 410 } |
| 411 } |
| 412 |
| 413 |
| 374 void Heap::RecordBeforeGC(Space space, GCReason reason) { | 414 void Heap::RecordBeforeGC(Space space, GCReason reason) { |
| 375 ASSERT(!gc_in_progress_); | 415 ASSERT(!gc_in_progress_); |
| 376 gc_in_progress_ = true; | 416 gc_in_progress_ = true; |
| 377 stats_.num_++; | 417 stats_.num_++; |
| 378 stats_.space_ = space; | 418 stats_.space_ = space; |
| 379 stats_.reason_ = reason; | 419 stats_.reason_ = reason; |
| 380 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); | 420 stats_.before_.micros_ = OS::GetCurrentTimeMicros(); |
| 381 stats_.before_.new_used_in_words_ = new_space_->UsedInWords(); | 421 stats_.before_.new_used_in_words_ = new_space_->UsedInWords(); |
| 382 stats_.before_.new_capacity_in_words_ = new_space_->CapacityInWords(); | 422 stats_.before_.new_capacity_in_words_ = new_space_->CapacityInWords(); |
| 383 stats_.before_.old_used_in_words_ = old_space_->UsedInWords(); | 423 stats_.before_.old_used_in_words_ = old_space_->UsedInWords(); |
| 384 stats_.before_.old_capacity_in_words_ = old_space_->CapacityInWords(); | 424 stats_.before_.old_capacity_in_words_ = old_space_->CapacityInWords(); |
| 385 stats_.times_[0] = 0; | 425 stats_.times_[0] = 0; |
| 386 stats_.times_[1] = 0; | 426 stats_.times_[1] = 0; |
| 387 stats_.times_[2] = 0; | 427 stats_.times_[2] = 0; |
| 388 stats_.times_[3] = 0; | 428 stats_.times_[3] = 0; |
| 389 stats_.data_[0] = 0; | 429 stats_.data_[0] = 0; |
| 390 stats_.data_[1] = 0; | 430 stats_.data_[1] = 0; |
| 391 stats_.data_[2] = 0; | 431 stats_.data_[2] = 0; |
| 392 stats_.data_[3] = 0; | 432 stats_.data_[3] = 0; |
| 393 } | 433 } |
| 394 | 434 |
| 395 | 435 |
| 396 void Heap::RecordAfterGC() { | 436 void Heap::RecordAfterGC() { |
| 397 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); | 437 stats_.after_.micros_ = OS::GetCurrentTimeMicros(); |
| 438 int64_t delta = stats_.after_.micros_ - stats_.before_.micros_; |
| 439 if (stats_.space_ == kNew) { |
| 440 new_space_->AddGCTime(delta); |
| 441 new_space_->IncrementCollections(); |
| 442 } else { |
| 443 old_space_->AddGCTime(delta); |
| 444 old_space_->IncrementCollections(); |
| 445 } |
| 398 stats_.after_.new_used_in_words_ = new_space_->UsedInWords(); | 446 stats_.after_.new_used_in_words_ = new_space_->UsedInWords(); |
| 399 stats_.after_.new_capacity_in_words_ = new_space_->CapacityInWords(); | 447 stats_.after_.new_capacity_in_words_ = new_space_->CapacityInWords(); |
| 400 stats_.after_.old_used_in_words_ = old_space_->UsedInWords(); | 448 stats_.after_.old_used_in_words_ = old_space_->UsedInWords(); |
| 401 stats_.after_.old_capacity_in_words_ = old_space_->CapacityInWords(); | 449 stats_.after_.old_capacity_in_words_ = old_space_->CapacityInWords(); |
| 402 ASSERT(gc_in_progress_); | 450 ASSERT(gc_in_progress_); |
| 403 gc_in_progress_ = false; | 451 gc_in_progress_ = false; |
| 404 } | 452 } |
| 405 | 453 |
| 406 | 454 |
| 407 void Heap::PrintStats() { | 455 void Heap::PrintStats() { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 heap->DisableGrowthControl(); | 520 heap->DisableGrowthControl(); |
| 473 } | 521 } |
| 474 | 522 |
| 475 | 523 |
| 476 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { | 524 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() { |
| 477 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); | 525 Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap(); |
| 478 heap->SetGrowthControlState(current_growth_controller_state_); | 526 heap->SetGrowthControlState(current_growth_controller_state_); |
| 479 } | 527 } |
| 480 | 528 |
| 481 } // namespace dart | 529 } // namespace dart |
| OLD | NEW |