OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 | 523 |
524 void Heap::RepairFreeListsAfterDeserialization() { | 524 void Heap::RepairFreeListsAfterDeserialization() { |
525 PagedSpaces spaces(this); | 525 PagedSpaces spaces(this); |
526 for (PagedSpace* space = spaces.next(); space != NULL; | 526 for (PagedSpace* space = spaces.next(); space != NULL; |
527 space = spaces.next()) { | 527 space = spaces.next()) { |
528 space->RepairFreeListsAfterDeserialization(); | 528 space->RepairFreeListsAfterDeserialization(); |
529 } | 529 } |
530 } | 530 } |
531 | 531 |
532 | 532 |
533 void Heap::ProcessPretenuringFeedback() { | 533 bool Heap::ProcessPretenuringFeedback() { |
| 534 bool trigger_deoptimization = false; |
534 if (FLAG_allocation_site_pretenuring) { | 535 if (FLAG_allocation_site_pretenuring) { |
535 int tenure_decisions = 0; | 536 int tenure_decisions = 0; |
536 int dont_tenure_decisions = 0; | 537 int dont_tenure_decisions = 0; |
537 int allocation_mementos_found = 0; | 538 int allocation_mementos_found = 0; |
538 int allocation_sites = 0; | 539 int allocation_sites = 0; |
539 int active_allocation_sites = 0; | 540 int active_allocation_sites = 0; |
540 | 541 |
541 // If the scratchpad overflowed, we have to iterate over the allocation | 542 // If the scratchpad overflowed, we have to iterate over the allocation |
542 // sites list. | 543 // sites list. |
543 // TODO(hpayer): We iterate over the whole list of allocation sites when | 544 // TODO(hpayer): We iterate over the whole list of allocation sites when |
544 // we grew to the maximum semi-space size to deopt maybe tenured | 545 // we grew to the maximum semi-space size to deopt maybe tenured |
545 // allocation sites. We could hold the maybe tenured allocation sites | 546 // allocation sites. We could hold the maybe tenured allocation sites |
546 // in a seperate data structure if this is a performance problem. | 547 // in a seperate data structure if this is a performance problem. |
547 bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites(); | 548 bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites(); |
548 bool use_scratchpad = | 549 bool use_scratchpad = |
549 allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize && | 550 allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize && |
550 !deopt_maybe_tenured; | 551 !deopt_maybe_tenured; |
551 | 552 |
552 int i = 0; | 553 int i = 0; |
553 Object* list_element = allocation_sites_list(); | 554 Object* list_element = allocation_sites_list(); |
554 bool trigger_deoptimization = false; | |
555 bool maximum_size_scavenge = MaximumSizeScavenge(); | 555 bool maximum_size_scavenge = MaximumSizeScavenge(); |
556 while (use_scratchpad ? i < allocation_sites_scratchpad_length_ | 556 while (use_scratchpad ? i < allocation_sites_scratchpad_length_ |
557 : list_element->IsAllocationSite()) { | 557 : list_element->IsAllocationSite()) { |
558 AllocationSite* site = | 558 AllocationSite* site = |
559 use_scratchpad | 559 use_scratchpad |
560 ? AllocationSite::cast(allocation_sites_scratchpad()->get(i)) | 560 ? AllocationSite::cast(allocation_sites_scratchpad()->get(i)) |
561 : AllocationSite::cast(list_element); | 561 : AllocationSite::cast(list_element); |
562 allocation_mementos_found += site->memento_found_count(); | 562 allocation_mementos_found += site->memento_found_count(); |
563 if (site->memento_found_count() > 0) { | 563 if (site->memento_found_count() > 0) { |
564 active_allocation_sites++; | 564 active_allocation_sites++; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 dont_tenure_decisions > 0)) { | 596 dont_tenure_decisions > 0)) { |
597 PrintF( | 597 PrintF( |
598 "GC: (mode, #visited allocation sites, #active allocation sites, " | 598 "GC: (mode, #visited allocation sites, #active allocation sites, " |
599 "#mementos, #tenure decisions, #donttenure decisions) " | 599 "#mementos, #tenure decisions, #donttenure decisions) " |
600 "(%s, %d, %d, %d, %d, %d)\n", | 600 "(%s, %d, %d, %d, %d, %d)\n", |
601 use_scratchpad ? "use scratchpad" : "use list", allocation_sites, | 601 use_scratchpad ? "use scratchpad" : "use list", allocation_sites, |
602 active_allocation_sites, allocation_mementos_found, tenure_decisions, | 602 active_allocation_sites, allocation_mementos_found, tenure_decisions, |
603 dont_tenure_decisions); | 603 dont_tenure_decisions); |
604 } | 604 } |
605 } | 605 } |
| 606 return trigger_deoptimization; |
606 } | 607 } |
607 | 608 |
608 | 609 |
609 void Heap::DeoptMarkedAllocationSites() { | 610 void Heap::DeoptMarkedAllocationSites() { |
610 // TODO(hpayer): If iterating over the allocation sites list becomes a | 611 // TODO(hpayer): If iterating over the allocation sites list becomes a |
611 // performance issue, use a cache heap data structure instead (similar to the | 612 // performance issue, use a cache heap data structure instead (similar to the |
612 // allocation sites scratchpad). | 613 // allocation sites scratchpad). |
613 Object* list_element = allocation_sites_list(); | 614 Object* list_element = allocation_sites_list(); |
614 while (list_element->IsAllocationSite()) { | 615 while (list_element->IsAllocationSite()) { |
615 AllocationSite* site = AllocationSite::cast(list_element); | 616 AllocationSite* site = AllocationSite::cast(list_element); |
616 if (site->deopt_dependent_code()) { | 617 if (site->deopt_dependent_code()) { |
617 site->dependent_code()->MarkCodeForDeoptimization( | 618 site->dependent_code()->MarkCodeForDeoptimization( |
618 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); | 619 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); |
619 site->set_deopt_dependent_code(false); | 620 site->set_deopt_dependent_code(false); |
620 } | 621 } |
621 list_element = site->weak_next(); | 622 list_element = site->weak_next(); |
622 } | 623 } |
623 Deoptimizer::DeoptimizeMarkedCode(isolate_); | 624 Deoptimizer::DeoptimizeMarkedCode(isolate_); |
624 } | 625 } |
625 | 626 |
626 | 627 |
627 void Heap::GarbageCollectionEpilogue() { | 628 void Heap::GarbageCollectionEpilogue() { |
628 store_buffer()->GCEpilogue(); | 629 store_buffer()->GCEpilogue(); |
629 | 630 |
630 // In release mode, we only zap the from space under heap verification. | 631 // In release mode, we only zap the from space under heap verification. |
631 if (Heap::ShouldZapGarbage()) { | 632 if (Heap::ShouldZapGarbage()) { |
632 ZapFromSpace(); | 633 ZapFromSpace(); |
633 } | 634 } |
634 | 635 |
635 // Process pretenuring feedback and update allocation sites. | |
636 ProcessPretenuringFeedback(); | |
637 | |
638 #ifdef VERIFY_HEAP | 636 #ifdef VERIFY_HEAP |
639 if (FLAG_verify_heap) { | 637 if (FLAG_verify_heap) { |
640 Verify(); | 638 Verify(); |
641 } | 639 } |
642 #endif | 640 #endif |
643 | 641 |
644 AllowHeapAllocation for_the_rest_of_the_epilogue; | 642 AllowHeapAllocation for_the_rest_of_the_epilogue; |
645 | 643 |
646 #ifdef DEBUG | 644 #ifdef DEBUG |
647 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); | 645 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 old_generation_size_configured_ = true; | 1241 old_generation_size_configured_ = true; |
1244 // This should be updated before PostGarbageCollectionProcessing, which can | 1242 // This should be updated before PostGarbageCollectionProcessing, which can |
1245 // cause another GC. Take into account the objects promoted during GC. | 1243 // cause another GC. Take into account the objects promoted during GC. |
1246 old_generation_allocation_counter_ += | 1244 old_generation_allocation_counter_ += |
1247 static_cast<size_t>(promoted_objects_size_); | 1245 static_cast<size_t>(promoted_objects_size_); |
1248 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); | 1246 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); |
1249 } else { | 1247 } else { |
1250 Scavenge(); | 1248 Scavenge(); |
1251 } | 1249 } |
1252 | 1250 |
| 1251 bool deopted = ProcessPretenuringFeedback(); |
| 1252 UpdateSurvivalStatistics(start_new_space_size); |
1253 | 1253 |
1254 UpdateSurvivalStatistics(start_new_space_size); | 1254 // When pretenuring is collecting new feedback, we do not shrink the new space |
1255 ConfigureNewGenerationSize(); | 1255 // right away. |
| 1256 if (!deopted) { |
| 1257 ConfigureNewGenerationSize(); |
| 1258 } |
1256 ConfigureInitialOldGenerationSize(); | 1259 ConfigureInitialOldGenerationSize(); |
1257 | 1260 |
1258 isolate_->counters()->objs_since_last_young()->Set(0); | 1261 isolate_->counters()->objs_since_last_young()->Set(0); |
1259 | 1262 |
1260 if (collector != SCAVENGER) { | 1263 if (collector != SCAVENGER) { |
1261 // Callbacks that fire after this point might trigger nested GCs and | 1264 // Callbacks that fire after this point might trigger nested GCs and |
1262 // restart incremental marking, the assertion can't be moved down. | 1265 // restart incremental marking, the assertion can't be moved down. |
1263 DCHECK(incremental_marking()->IsStopped()); | 1266 DCHECK(incremental_marking()->IsStopped()); |
1264 | 1267 |
1265 // We finished a marking cycle. We can uncommit the marking deque until | 1268 // We finished a marking cycle. We can uncommit the marking deque until |
(...skipping 5495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6761 *object_type = "CODE_TYPE"; \ | 6764 *object_type = "CODE_TYPE"; \ |
6762 *object_sub_type = "CODE_AGE/" #name; \ | 6765 *object_sub_type = "CODE_AGE/" #name; \ |
6763 return true; | 6766 return true; |
6764 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6767 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6765 #undef COMPARE_AND_RETURN_NAME | 6768 #undef COMPARE_AND_RETURN_NAME |
6766 } | 6769 } |
6767 return false; | 6770 return false; |
6768 } | 6771 } |
6769 } // namespace internal | 6772 } // namespace internal |
6770 } // namespace v8 | 6773 } // namespace v8 |
OLD | NEW |