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 |