OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 void Heap::CollectAllGarbage(bool force_compaction) { | 422 void Heap::CollectAllGarbage(bool force_compaction) { |
423 // Since we are ignoring the return value, the exact choice of space does | 423 // Since we are ignoring the return value, the exact choice of space does |
424 // not matter, so long as we do not specify NEW_SPACE, which would not | 424 // not matter, so long as we do not specify NEW_SPACE, which would not |
425 // cause a full GC. | 425 // cause a full GC. |
426 MarkCompactCollector::SetForceCompaction(force_compaction); | 426 MarkCompactCollector::SetForceCompaction(force_compaction); |
427 CollectGarbage(OLD_POINTER_SPACE); | 427 CollectGarbage(OLD_POINTER_SPACE); |
428 MarkCompactCollector::SetForceCompaction(false); | 428 MarkCompactCollector::SetForceCompaction(false); |
429 } | 429 } |
430 | 430 |
431 | 431 |
432 void Heap::CollectGarbage(AllocationSpace space) { | 432 void Heap::CollectAllAvailableGarbage() { |
| 433 // Since we are ignoring the return value, the exact choice of space does |
| 434 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 435 // cause a full GC. |
| 436 MarkCompactCollector::SetForceCompaction(true); |
| 437 |
| 438 // Major GC would invoke weak handle callbacks on weakly reachable |
| 439 // handles, but won't collect weakly reachable objects until next |
| 440 // major GC. Therefore if we collect aggressively and weak handle callback |
| 441 // has been invoked, we rerun major GC to release objects which become |
| 442 // garbage. |
| 443 // Note: as weak callbacks can execute arbitrary code, we cannot |
| 444 // hope that eventually there will be no weak callbacks invocations. |
| 445 // Therefore stop recollecting after several attempts. |
| 446 const int kMaxNumberOfAttempts = 7; |
| 447 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
| 448 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) { |
| 449 break; |
| 450 } |
| 451 } |
| 452 MarkCompactCollector::SetForceCompaction(false); |
| 453 } |
| 454 |
| 455 |
| 456 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { |
433 // The VM is in the GC state until exiting this function. | 457 // The VM is in the GC state until exiting this function. |
434 VMState state(GC); | 458 VMState state(GC); |
435 | 459 |
436 #ifdef DEBUG | 460 #ifdef DEBUG |
437 // Reset the allocation timeout to the GC interval, but make sure to | 461 // Reset the allocation timeout to the GC interval, but make sure to |
438 // allow at least a few allocations after a collection. The reason | 462 // allow at least a few allocations after a collection. The reason |
439 // for this is that we have a lot of allocation sequences and we | 463 // for this is that we have a lot of allocation sequences and we |
440 // assume that a garbage collection will allow the subsequent | 464 // assume that a garbage collection will allow the subsequent |
441 // allocation attempts to go through. | 465 // allocation attempts to go through. |
442 allocation_timeout_ = Max(6, FLAG_gc_interval); | 466 allocation_timeout_ = Max(6, FLAG_gc_interval); |
443 #endif | 467 #endif |
444 | 468 |
| 469 bool next_gc_likely_to_collect_more = false; |
| 470 |
445 { GCTracer tracer; | 471 { GCTracer tracer; |
446 GarbageCollectionPrologue(); | 472 GarbageCollectionPrologue(); |
447 // The GC count was incremented in the prologue. Tell the tracer about | 473 // The GC count was incremented in the prologue. Tell the tracer about |
448 // it. | 474 // it. |
449 tracer.set_gc_count(gc_count_); | 475 tracer.set_gc_count(gc_count_); |
450 | 476 |
451 GarbageCollector collector = SelectGarbageCollector(space); | |
452 // Tell the tracer which collector we've selected. | 477 // Tell the tracer which collector we've selected. |
453 tracer.set_collector(collector); | 478 tracer.set_collector(collector); |
454 | 479 |
455 HistogramTimer* rate = (collector == SCAVENGER) | 480 HistogramTimer* rate = (collector == SCAVENGER) |
456 ? &Counters::gc_scavenger | 481 ? &Counters::gc_scavenger |
457 : &Counters::gc_compactor; | 482 : &Counters::gc_compactor; |
458 rate->Start(); | 483 rate->Start(); |
459 PerformGarbageCollection(collector, &tracer); | 484 next_gc_likely_to_collect_more = |
| 485 PerformGarbageCollection(collector, &tracer); |
460 rate->Stop(); | 486 rate->Stop(); |
461 | 487 |
462 GarbageCollectionEpilogue(); | 488 GarbageCollectionEpilogue(); |
463 } | 489 } |
464 | 490 |
465 | 491 |
466 #ifdef ENABLE_LOGGING_AND_PROFILING | 492 #ifdef ENABLE_LOGGING_AND_PROFILING |
467 if (FLAG_log_gc) HeapProfiler::WriteSample(); | 493 if (FLAG_log_gc) HeapProfiler::WriteSample(); |
468 if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions(); | 494 if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions(); |
469 #endif | 495 #endif |
| 496 |
| 497 return next_gc_likely_to_collect_more; |
470 } | 498 } |
471 | 499 |
472 | 500 |
473 void Heap::PerformScavenge() { | 501 void Heap::PerformScavenge() { |
474 GCTracer tracer; | 502 GCTracer tracer; |
475 PerformGarbageCollection(SCAVENGER, &tracer); | 503 PerformGarbageCollection(SCAVENGER, &tracer); |
476 } | 504 } |
477 | 505 |
478 | 506 |
479 #ifdef DEBUG | 507 #ifdef DEBUG |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 set_survival_rate_trend(DECREASING); | 674 set_survival_rate_trend(DECREASING); |
647 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { | 675 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { |
648 set_survival_rate_trend(INCREASING); | 676 set_survival_rate_trend(INCREASING); |
649 } else { | 677 } else { |
650 set_survival_rate_trend(STABLE); | 678 set_survival_rate_trend(STABLE); |
651 } | 679 } |
652 | 680 |
653 survival_rate_ = survival_rate; | 681 survival_rate_ = survival_rate; |
654 } | 682 } |
655 | 683 |
656 void Heap::PerformGarbageCollection(GarbageCollector collector, | 684 bool Heap::PerformGarbageCollection(GarbageCollector collector, |
657 GCTracer* tracer) { | 685 GCTracer* tracer) { |
| 686 bool next_gc_likely_to_collect_more = false; |
| 687 |
658 if (collector != SCAVENGER) { | 688 if (collector != SCAVENGER) { |
659 PROFILE(CodeMovingGCEvent()); | 689 PROFILE(CodeMovingGCEvent()); |
660 } | 690 } |
661 | 691 |
662 VerifySymbolTable(); | 692 VerifySymbolTable(); |
663 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { | 693 if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { |
664 ASSERT(!allocation_allowed_); | 694 ASSERT(!allocation_allowed_); |
665 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 695 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
666 global_gc_prologue_callback_(); | 696 global_gc_prologue_callback_(); |
667 } | 697 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 tracer_ = NULL; | 743 tracer_ = NULL; |
714 | 744 |
715 UpdateSurvivalRateTrend(start_new_space_size); | 745 UpdateSurvivalRateTrend(start_new_space_size); |
716 } | 746 } |
717 | 747 |
718 Counters::objs_since_last_young.Set(0); | 748 Counters::objs_since_last_young.Set(0); |
719 | 749 |
720 if (collector == MARK_COMPACTOR) { | 750 if (collector == MARK_COMPACTOR) { |
721 DisableAssertNoAllocation allow_allocation; | 751 DisableAssertNoAllocation allow_allocation; |
722 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 752 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
723 GlobalHandles::PostGarbageCollectionProcessing(); | 753 next_gc_likely_to_collect_more = |
| 754 GlobalHandles::PostGarbageCollectionProcessing(); |
724 } | 755 } |
725 | 756 |
726 // Update relocatables. | 757 // Update relocatables. |
727 Relocatable::PostGarbageCollectionProcessing(); | 758 Relocatable::PostGarbageCollectionProcessing(); |
728 | 759 |
729 if (collector == MARK_COMPACTOR) { | 760 if (collector == MARK_COMPACTOR) { |
730 // Register the amount of external allocated memory. | 761 // Register the amount of external allocated memory. |
731 amount_of_external_allocated_memory_at_last_global_gc_ = | 762 amount_of_external_allocated_memory_at_last_global_gc_ = |
732 amount_of_external_allocated_memory_; | 763 amount_of_external_allocated_memory_; |
733 } | 764 } |
734 | 765 |
735 GCCallbackFlags callback_flags = tracer->is_compacting() | 766 GCCallbackFlags callback_flags = tracer->is_compacting() |
736 ? kGCCallbackFlagCompacted | 767 ? kGCCallbackFlagCompacted |
737 : kNoGCCallbackFlags; | 768 : kNoGCCallbackFlags; |
738 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { | 769 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { |
739 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { | 770 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { |
740 gc_epilogue_callbacks_[i].callback(gc_type, callback_flags); | 771 gc_epilogue_callbacks_[i].callback(gc_type, callback_flags); |
741 } | 772 } |
742 } | 773 } |
743 | 774 |
744 if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) { | 775 if (collector == MARK_COMPACTOR && global_gc_epilogue_callback_) { |
745 ASSERT(!allocation_allowed_); | 776 ASSERT(!allocation_allowed_); |
746 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 777 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
747 global_gc_epilogue_callback_(); | 778 global_gc_epilogue_callback_(); |
748 } | 779 } |
749 VerifySymbolTable(); | 780 VerifySymbolTable(); |
| 781 |
| 782 return next_gc_likely_to_collect_more; |
750 } | 783 } |
751 | 784 |
752 | 785 |
753 void Heap::MarkCompact(GCTracer* tracer) { | 786 void Heap::MarkCompact(GCTracer* tracer) { |
754 gc_state_ = MARK_COMPACT; | 787 gc_state_ = MARK_COMPACT; |
755 LOG(ResourceEvent("markcompact", "begin")); | 788 LOG(ResourceEvent("markcompact", "begin")); |
756 | 789 |
757 MarkCompactCollector::Prepare(tracer); | 790 MarkCompactCollector::Prepare(tracer); |
758 | 791 |
759 bool is_compacting = MarkCompactCollector::IsCompacting(); | 792 bool is_compacting = MarkCompactCollector::IsCompacting(); |
(...skipping 4472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5232 void ExternalStringTable::TearDown() { | 5265 void ExternalStringTable::TearDown() { |
5233 new_space_strings_.Free(); | 5266 new_space_strings_.Free(); |
5234 old_space_strings_.Free(); | 5267 old_space_strings_.Free(); |
5235 } | 5268 } |
5236 | 5269 |
5237 | 5270 |
5238 List<Object*> ExternalStringTable::new_space_strings_; | 5271 List<Object*> ExternalStringTable::new_space_strings_; |
5239 List<Object*> ExternalStringTable::old_space_strings_; | 5272 List<Object*> ExternalStringTable::old_space_strings_; |
5240 | 5273 |
5241 } } // namespace v8::internal | 5274 } } // namespace v8::internal |
OLD | NEW |