| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 PagedSpaces spaces(this); | 499 PagedSpaces spaces(this); |
| 500 for (PagedSpace* space = spaces.next(); | 500 for (PagedSpace* space = spaces.next(); |
| 501 space != NULL; | 501 space != NULL; |
| 502 space = spaces.next()) { | 502 space = spaces.next()) { |
| 503 space->RepairFreeListsAfterBoot(); | 503 space->RepairFreeListsAfterBoot(); |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 | 507 |
| 508 void Heap::ProcessPretenuringFeedback() { | 508 void Heap::ProcessPretenuringFeedback() { |
| 509 if (FLAG_allocation_site_pretenuring) { | 509 if (FLAG_allocation_site_pretenuring && |
| 510 new_space_high_promotion_mode_active_) { |
| 510 int tenure_decisions = 0; | 511 int tenure_decisions = 0; |
| 511 int dont_tenure_decisions = 0; | 512 int dont_tenure_decisions = 0; |
| 512 int allocation_mementos_found = 0; | 513 int allocation_mementos_found = 0; |
| 513 int allocation_sites = 0; | 514 int allocation_sites = 0; |
| 514 int active_allocation_sites = 0; | 515 int active_allocation_sites = 0; |
| 515 | 516 |
| 516 // If the scratchpad overflowed, we have to iterate over the allocation | 517 // If the scratchpad overflowed, we have to iterate over the allocation |
| 517 // stites list. | 518 // sites list. |
| 518 bool use_scratchpad = | 519 bool use_scratchpad = |
| 519 allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize; | 520 allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize; |
| 520 | 521 |
| 521 int i = 0; | 522 int i = 0; |
| 522 Object* list_element = allocation_sites_list(); | 523 Object* list_element = allocation_sites_list(); |
| 523 while (use_scratchpad ? | 524 while (use_scratchpad ? |
| 524 i < allocation_sites_scratchpad_length : | 525 i < allocation_sites_scratchpad_length : |
| 525 list_element->IsAllocationSite()) { | 526 list_element->IsAllocationSite()) { |
| 526 AllocationSite* site = use_scratchpad ? | 527 AllocationSite* site = use_scratchpad ? |
| 527 allocation_sites_scratchpad[i] : AllocationSite::cast(list_element); | 528 allocation_sites_scratchpad[i] : AllocationSite::cast(list_element); |
| 528 allocation_mementos_found += site->memento_found_count()->value(); | 529 allocation_mementos_found += site->memento_found_count(); |
| 529 if (site->memento_found_count()->value() > 0) { | 530 if (site->memento_found_count() > 0) { |
| 530 active_allocation_sites++; | 531 active_allocation_sites++; |
| 531 } | 532 } |
| 532 if (site->DigestPretenuringFeedback()) { | 533 if (site->DigestPretenuringFeedback()) { |
| 533 if (site->GetPretenureMode() == TENURED) { | 534 if (site->GetPretenureMode() == TENURED) { |
| 534 tenure_decisions++; | 535 tenure_decisions++; |
| 535 } else { | 536 } else { |
| 536 dont_tenure_decisions++; | 537 dont_tenure_decisions++; |
| 537 } | 538 } |
| 538 } | 539 } |
| 539 allocation_sites++; | 540 allocation_sites++; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 | 695 |
| 695 #if defined(DEBUG) | 696 #if defined(DEBUG) |
| 696 ReportStatisticsAfterGC(); | 697 ReportStatisticsAfterGC(); |
| 697 #endif // DEBUG | 698 #endif // DEBUG |
| 698 #ifdef ENABLE_DEBUGGER_SUPPORT | 699 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 699 isolate_->debug()->AfterGarbageCollection(); | 700 isolate_->debug()->AfterGarbageCollection(); |
| 700 #endif // ENABLE_DEBUGGER_SUPPORT | 701 #endif // ENABLE_DEBUGGER_SUPPORT |
| 701 } | 702 } |
| 702 | 703 |
| 703 | 704 |
| 704 void Heap::CollectAllGarbage(int flags, const char* gc_reason) { | 705 void Heap::CollectAllGarbage(int flags, |
| 706 const char* gc_reason, |
| 707 const v8::GCCallbackFlags gc_callback_flags) { |
| 705 // Since we are ignoring the return value, the exact choice of space does | 708 // Since we are ignoring the return value, the exact choice of space does |
| 706 // not matter, so long as we do not specify NEW_SPACE, which would not | 709 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 707 // cause a full GC. | 710 // cause a full GC. |
| 708 mark_compact_collector_.SetFlags(flags); | 711 mark_compact_collector_.SetFlags(flags); |
| 709 CollectGarbage(OLD_POINTER_SPACE, gc_reason); | 712 CollectGarbage(OLD_POINTER_SPACE, gc_reason, gc_callback_flags); |
| 710 mark_compact_collector_.SetFlags(kNoGCFlags); | 713 mark_compact_collector_.SetFlags(kNoGCFlags); |
| 711 } | 714 } |
| 712 | 715 |
| 713 | 716 |
| 714 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { | 717 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { |
| 715 // Since we are ignoring the return value, the exact choice of space does | 718 // Since we are ignoring the return value, the exact choice of space does |
| 716 // not matter, so long as we do not specify NEW_SPACE, which would not | 719 // not matter, so long as we do not specify NEW_SPACE, which would not |
| 717 // cause a full GC. | 720 // cause a full GC. |
| 718 // Major GC would invoke weak handle callbacks on weakly reachable | 721 // Major GC would invoke weak handle callbacks on weakly reachable |
| 719 // handles, but won't collect weakly reachable objects until next | 722 // handles, but won't collect weakly reachable objects until next |
| (...skipping 22 matching lines...) Expand all Loading... |
| 742 mark_compact_collector()->SetFlags(kNoGCFlags); | 745 mark_compact_collector()->SetFlags(kNoGCFlags); |
| 743 new_space_.Shrink(); | 746 new_space_.Shrink(); |
| 744 UncommitFromSpace(); | 747 UncommitFromSpace(); |
| 745 incremental_marking()->UncommitMarkingDeque(); | 748 incremental_marking()->UncommitMarkingDeque(); |
| 746 } | 749 } |
| 747 | 750 |
| 748 | 751 |
| 749 bool Heap::CollectGarbage(AllocationSpace space, | 752 bool Heap::CollectGarbage(AllocationSpace space, |
| 750 GarbageCollector collector, | 753 GarbageCollector collector, |
| 751 const char* gc_reason, | 754 const char* gc_reason, |
| 752 const char* collector_reason) { | 755 const char* collector_reason, |
| 756 const v8::GCCallbackFlags gc_callback_flags) { |
| 753 // The VM is in the GC state until exiting this function. | 757 // The VM is in the GC state until exiting this function. |
| 754 VMState<GC> state(isolate_); | 758 VMState<GC> state(isolate_); |
| 755 | 759 |
| 756 #ifdef DEBUG | 760 #ifdef DEBUG |
| 757 // Reset the allocation timeout to the GC interval, but make sure to | 761 // Reset the allocation timeout to the GC interval, but make sure to |
| 758 // allow at least a few allocations after a collection. The reason | 762 // allow at least a few allocations after a collection. The reason |
| 759 // for this is that we have a lot of allocation sequences and we | 763 // for this is that we have a lot of allocation sequences and we |
| 760 // assume that a garbage collection will allow the subsequent | 764 // assume that a garbage collection will allow the subsequent |
| 761 // allocation attempts to go through. | 765 // allocation attempts to go through. |
| 762 allocation_timeout_ = Max(6, FLAG_gc_interval); | 766 allocation_timeout_ = Max(6, FLAG_gc_interval); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 tracer.set_gc_count(gc_count_); | 801 tracer.set_gc_count(gc_count_); |
| 798 | 802 |
| 799 // Tell the tracer which collector we've selected. | 803 // Tell the tracer which collector we've selected. |
| 800 tracer.set_collector(collector); | 804 tracer.set_collector(collector); |
| 801 | 805 |
| 802 { | 806 { |
| 803 HistogramTimerScope histogram_timer_scope( | 807 HistogramTimerScope histogram_timer_scope( |
| 804 (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger() | 808 (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger() |
| 805 : isolate_->counters()->gc_compactor()); | 809 : isolate_->counters()->gc_compactor()); |
| 806 next_gc_likely_to_collect_more = | 810 next_gc_likely_to_collect_more = |
| 807 PerformGarbageCollection(collector, &tracer); | 811 PerformGarbageCollection(collector, &tracer, gc_callback_flags); |
| 808 } | 812 } |
| 809 | 813 |
| 810 GarbageCollectionEpilogue(); | 814 GarbageCollectionEpilogue(); |
| 811 } | 815 } |
| 812 | 816 |
| 813 // Start incremental marking for the next cycle. The heap snapshot | 817 // Start incremental marking for the next cycle. The heap snapshot |
| 814 // generator needs incremental marking to stay off after it aborted. | 818 // generator needs incremental marking to stay off after it aborted. |
| 815 if (!mark_compact_collector()->abort_incremental_marking() && | 819 if (!mark_compact_collector()->abort_incremental_marking() && |
| 816 incremental_marking()->IsStopped() && | 820 incremental_marking()->IsStopped() && |
| 817 incremental_marking()->WorthActivating() && | 821 incremental_marking()->WorthActivating() && |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 set_survival_rate_trend(DECREASING); | 1028 set_survival_rate_trend(DECREASING); |
| 1025 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { | 1029 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { |
| 1026 set_survival_rate_trend(INCREASING); | 1030 set_survival_rate_trend(INCREASING); |
| 1027 } else { | 1031 } else { |
| 1028 set_survival_rate_trend(STABLE); | 1032 set_survival_rate_trend(STABLE); |
| 1029 } | 1033 } |
| 1030 | 1034 |
| 1031 survival_rate_ = survival_rate; | 1035 survival_rate_ = survival_rate; |
| 1032 } | 1036 } |
| 1033 | 1037 |
| 1034 bool Heap::PerformGarbageCollection(GarbageCollector collector, | 1038 bool Heap::PerformGarbageCollection( |
| 1035 GCTracer* tracer) { | 1039 GarbageCollector collector, |
| 1040 GCTracer* tracer, |
| 1041 const v8::GCCallbackFlags gc_callback_flags) { |
| 1036 bool next_gc_likely_to_collect_more = false; | 1042 bool next_gc_likely_to_collect_more = false; |
| 1037 | 1043 |
| 1038 if (collector != SCAVENGER) { | 1044 if (collector != SCAVENGER) { |
| 1039 PROFILE(isolate_, CodeMovingGCEvent()); | 1045 PROFILE(isolate_, CodeMovingGCEvent()); |
| 1040 } | 1046 } |
| 1041 | 1047 |
| 1042 #ifdef VERIFY_HEAP | 1048 #ifdef VERIFY_HEAP |
| 1043 if (FLAG_verify_heap) { | 1049 if (FLAG_verify_heap) { |
| 1044 VerifyStringTable(this); | 1050 VerifyStringTable(this); |
| 1045 } | 1051 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 IsHighSurvivalRate()) { | 1099 IsHighSurvivalRate()) { |
| 1094 // Stable high survival rates even though young generation is at | 1100 // Stable high survival rates even though young generation is at |
| 1095 // maximum capacity indicates that most objects will be promoted. | 1101 // maximum capacity indicates that most objects will be promoted. |
| 1096 // To decrease scavenger pauses and final mark-sweep pauses, we | 1102 // To decrease scavenger pauses and final mark-sweep pauses, we |
| 1097 // have to limit maximal capacity of the young generation. | 1103 // have to limit maximal capacity of the young generation. |
| 1098 SetNewSpaceHighPromotionModeActive(true); | 1104 SetNewSpaceHighPromotionModeActive(true); |
| 1099 if (FLAG_trace_gc) { | 1105 if (FLAG_trace_gc) { |
| 1100 PrintPID("Limited new space size due to high promotion rate: %d MB\n", | 1106 PrintPID("Limited new space size due to high promotion rate: %d MB\n", |
| 1101 new_space_.InitialCapacity() / MB); | 1107 new_space_.InitialCapacity() / MB); |
| 1102 } | 1108 } |
| 1103 // Support for global pre-tenuring uses the high promotion mode as a | 1109 // The high promotion mode is our indicator to turn on pretenuring. We have |
| 1104 // heuristic indicator of whether to pretenure or not, we trigger | 1110 // to deoptimize all optimized code in global pretenuring mode and all |
| 1105 // deoptimization here to take advantage of pre-tenuring as soon as | 1111 // code which should be tenured in local pretenuring mode. |
| 1106 // possible. | |
| 1107 if (FLAG_pretenuring) { | 1112 if (FLAG_pretenuring) { |
| 1108 isolate_->stack_guard()->FullDeopt(); | 1113 if (FLAG_allocation_site_pretenuring) { |
| 1114 ResetAllAllocationSitesDependentCode(NOT_TENURED); |
| 1115 } else { |
| 1116 isolate_->stack_guard()->FullDeopt(); |
| 1117 } |
| 1109 } | 1118 } |
| 1110 } else if (new_space_high_promotion_mode_active_ && | 1119 } else if (new_space_high_promotion_mode_active_ && |
| 1111 IsStableOrDecreasingSurvivalTrend() && | 1120 IsStableOrDecreasingSurvivalTrend() && |
| 1112 IsLowSurvivalRate()) { | 1121 IsLowSurvivalRate()) { |
| 1113 // Decreasing low survival rates might indicate that the above high | 1122 // Decreasing low survival rates might indicate that the above high |
| 1114 // promotion mode is over and we should allow the young generation | 1123 // promotion mode is over and we should allow the young generation |
| 1115 // to grow again. | 1124 // to grow again. |
| 1116 SetNewSpaceHighPromotionModeActive(false); | 1125 SetNewSpaceHighPromotionModeActive(false); |
| 1117 if (FLAG_trace_gc) { | 1126 if (FLAG_trace_gc) { |
| 1118 PrintPID("Unlimited new space size due to low promotion rate: %d MB\n", | 1127 PrintPID("Unlimited new space size due to low promotion rate: %d MB\n", |
| 1119 new_space_.MaximumCapacity() / MB); | 1128 new_space_.MaximumCapacity() / MB); |
| 1120 } | 1129 } |
| 1121 // Trigger deoptimization here to turn off pre-tenuring as soon as | 1130 // Trigger deoptimization here to turn off global pretenuring as soon as |
| 1122 // possible. | 1131 // possible. |
| 1123 if (FLAG_pretenuring) { | 1132 if (FLAG_pretenuring && !FLAG_allocation_site_pretenuring) { |
| 1124 isolate_->stack_guard()->FullDeopt(); | 1133 isolate_->stack_guard()->FullDeopt(); |
| 1125 } | 1134 } |
| 1126 } | 1135 } |
| 1127 | 1136 |
| 1128 if (new_space_high_promotion_mode_active_ && | 1137 if (new_space_high_promotion_mode_active_ && |
| 1129 new_space_.Capacity() > new_space_.InitialCapacity()) { | 1138 new_space_.Capacity() > new_space_.InitialCapacity()) { |
| 1130 new_space_.Shrink(); | 1139 new_space_.Shrink(); |
| 1131 } | 1140 } |
| 1132 | 1141 |
| 1133 isolate_->counters()->objs_since_last_young()->Set(0); | 1142 isolate_->counters()->objs_since_last_young()->Set(0); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1153 if (collector == MARK_COMPACTOR) { | 1162 if (collector == MARK_COMPACTOR) { |
| 1154 // Register the amount of external allocated memory. | 1163 // Register the amount of external allocated memory. |
| 1155 amount_of_external_allocated_memory_at_last_global_gc_ = | 1164 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1156 amount_of_external_allocated_memory_; | 1165 amount_of_external_allocated_memory_; |
| 1157 } | 1166 } |
| 1158 | 1167 |
| 1159 { | 1168 { |
| 1160 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 1169 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 1161 VMState<EXTERNAL> state(isolate_); | 1170 VMState<EXTERNAL> state(isolate_); |
| 1162 HandleScope handle_scope(isolate_); | 1171 HandleScope handle_scope(isolate_); |
| 1163 CallGCEpilogueCallbacks(gc_type); | 1172 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); |
| 1164 } | 1173 } |
| 1165 | 1174 |
| 1166 #ifdef VERIFY_HEAP | 1175 #ifdef VERIFY_HEAP |
| 1167 if (FLAG_verify_heap) { | 1176 if (FLAG_verify_heap) { |
| 1168 VerifyStringTable(this); | 1177 VerifyStringTable(this); |
| 1169 } | 1178 } |
| 1170 #endif | 1179 #endif |
| 1171 | 1180 |
| 1172 return next_gc_likely_to_collect_more; | 1181 return next_gc_likely_to_collect_more; |
| 1173 } | 1182 } |
| 1174 | 1183 |
| 1175 | 1184 |
| 1176 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { | 1185 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { |
| 1177 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { | 1186 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { |
| 1178 if (gc_type & gc_prologue_callbacks_[i].gc_type) { | 1187 if (gc_type & gc_prologue_callbacks_[i].gc_type) { |
| 1179 if (!gc_prologue_callbacks_[i].pass_isolate_) { | 1188 if (!gc_prologue_callbacks_[i].pass_isolate_) { |
| 1180 v8::GCPrologueCallback callback = | 1189 v8::GCPrologueCallback callback = |
| 1181 reinterpret_cast<v8::GCPrologueCallback>( | 1190 reinterpret_cast<v8::GCPrologueCallback>( |
| 1182 gc_prologue_callbacks_[i].callback); | 1191 gc_prologue_callbacks_[i].callback); |
| 1183 callback(gc_type, flags); | 1192 callback(gc_type, flags); |
| 1184 } else { | 1193 } else { |
| 1185 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); | 1194 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); |
| 1186 gc_prologue_callbacks_[i].callback(isolate, gc_type, flags); | 1195 gc_prologue_callbacks_[i].callback(isolate, gc_type, flags); |
| 1187 } | 1196 } |
| 1188 } | 1197 } |
| 1189 } | 1198 } |
| 1190 } | 1199 } |
| 1191 | 1200 |
| 1192 | 1201 |
| 1193 void Heap::CallGCEpilogueCallbacks(GCType gc_type) { | 1202 void Heap::CallGCEpilogueCallbacks(GCType gc_type, |
| 1203 GCCallbackFlags gc_callback_flags) { |
| 1194 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { | 1204 for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { |
| 1195 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { | 1205 if (gc_type & gc_epilogue_callbacks_[i].gc_type) { |
| 1196 if (!gc_epilogue_callbacks_[i].pass_isolate_) { | 1206 if (!gc_epilogue_callbacks_[i].pass_isolate_) { |
| 1197 v8::GCPrologueCallback callback = | 1207 v8::GCPrologueCallback callback = |
| 1198 reinterpret_cast<v8::GCPrologueCallback>( | 1208 reinterpret_cast<v8::GCPrologueCallback>( |
| 1199 gc_epilogue_callbacks_[i].callback); | 1209 gc_epilogue_callbacks_[i].callback); |
| 1200 callback(gc_type, kNoGCCallbackFlags); | 1210 callback(gc_type, gc_callback_flags); |
| 1201 } else { | 1211 } else { |
| 1202 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); | 1212 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); |
| 1203 gc_epilogue_callbacks_[i].callback( | 1213 gc_epilogue_callbacks_[i].callback( |
| 1204 isolate, gc_type, kNoGCCallbackFlags); | 1214 isolate, gc_type, gc_callback_flags); |
| 1205 } | 1215 } |
| 1206 } | 1216 } |
| 1207 } | 1217 } |
| 1208 } | 1218 } |
| 1209 | 1219 |
| 1210 | 1220 |
| 1211 void Heap::MarkCompact(GCTracer* tracer) { | 1221 void Heap::MarkCompact(GCTracer* tracer) { |
| 1212 gc_state_ = MARK_COMPACT; | 1222 gc_state_ = MARK_COMPACT; |
| 1213 LOG(isolate_, ResourceEvent("markcompact", "begin")); | 1223 LOG(isolate_, ResourceEvent("markcompact", "begin")); |
| 1214 | 1224 |
| 1225 uint64_t size_of_objects_before_gc = SizeOfObjects(); |
| 1226 |
| 1215 mark_compact_collector_.Prepare(tracer); | 1227 mark_compact_collector_.Prepare(tracer); |
| 1216 | 1228 |
| 1217 ms_count_++; | 1229 ms_count_++; |
| 1218 tracer->set_full_gc_count(ms_count_); | 1230 tracer->set_full_gc_count(ms_count_); |
| 1219 | 1231 |
| 1220 MarkCompactPrologue(); | 1232 MarkCompactPrologue(); |
| 1221 | 1233 |
| 1222 mark_compact_collector_.CollectGarbage(); | 1234 mark_compact_collector_.CollectGarbage(); |
| 1223 | 1235 |
| 1224 LOG(isolate_, ResourceEvent("markcompact", "end")); | 1236 LOG(isolate_, ResourceEvent("markcompact", "end")); |
| 1225 | 1237 |
| 1226 gc_state_ = NOT_IN_GC; | 1238 gc_state_ = NOT_IN_GC; |
| 1227 | 1239 |
| 1228 isolate_->counters()->objs_since_last_full()->Set(0); | 1240 isolate_->counters()->objs_since_last_full()->Set(0); |
| 1229 | 1241 |
| 1230 flush_monomorphic_ics_ = false; | 1242 flush_monomorphic_ics_ = false; |
| 1243 |
| 1244 if (FLAG_allocation_site_pretenuring) { |
| 1245 EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc); |
| 1246 } |
| 1231 } | 1247 } |
| 1232 | 1248 |
| 1233 | 1249 |
| 1234 void Heap::MarkCompactPrologue() { | 1250 void Heap::MarkCompactPrologue() { |
| 1235 // At any old GC clear the keyed lookup cache to enable collection of unused | 1251 // At any old GC clear the keyed lookup cache to enable collection of unused |
| 1236 // maps. | 1252 // maps. |
| 1237 isolate_->keyed_lookup_cache()->Clear(); | 1253 isolate_->keyed_lookup_cache()->Clear(); |
| 1238 isolate_->context_slot_cache()->Clear(); | 1254 isolate_->context_slot_cache()->Clear(); |
| 1239 isolate_->descriptor_lookup_cache()->Clear(); | 1255 isolate_->descriptor_lookup_cache()->Clear(); |
| 1240 RegExpResultsCache::Clear(string_split_cache()); | 1256 RegExpResultsCache::Clear(string_split_cache()); |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1959 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer, | 1975 void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer, |
| 1960 bool record_slots) { | 1976 bool record_slots) { |
| 1961 Object* allocation_site_obj = | 1977 Object* allocation_site_obj = |
| 1962 VisitWeakList<AllocationSite>(this, | 1978 VisitWeakList<AllocationSite>(this, |
| 1963 allocation_sites_list(), | 1979 allocation_sites_list(), |
| 1964 retainer, record_slots); | 1980 retainer, record_slots); |
| 1965 set_allocation_sites_list(allocation_site_obj); | 1981 set_allocation_sites_list(allocation_site_obj); |
| 1966 } | 1982 } |
| 1967 | 1983 |
| 1968 | 1984 |
| 1985 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { |
| 1986 Object* cur = allocation_sites_list(); |
| 1987 while (cur->IsAllocationSite()) { |
| 1988 AllocationSite* casted = AllocationSite::cast(cur); |
| 1989 if (casted->GetPretenureMode() == flag) { |
| 1990 casted->ResetPretenureDecision(); |
| 1991 } |
| 1992 cur = casted->weak_next(); |
| 1993 } |
| 1994 } |
| 1995 |
| 1996 |
| 1997 void Heap::EvaluateOldSpaceLocalPretenuring( |
| 1998 uint64_t size_of_objects_before_gc) { |
| 1999 uint64_t size_of_objects_after_gc = SizeOfObjects(); |
| 2000 double old_generation_survival_rate = |
| 2001 (static_cast<double>(size_of_objects_after_gc) * 100) / |
| 2002 static_cast<double>(size_of_objects_before_gc); |
| 2003 |
| 2004 if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) { |
| 2005 // Too many objects died in the old generation, pretenuring of wrong |
| 2006 // allocation sites may be the cause for that. We have to deopt all |
| 2007 // dependent code registered in the allocation sites to re-evaluate |
| 2008 // our pretenuring decisions. |
| 2009 ResetAllAllocationSitesDependentCode(TENURED); |
| 2010 if (FLAG_trace_pretenuring) { |
| 2011 PrintF("Deopt all allocation sites dependent code due to low survival " |
| 2012 "rate in the old generation %f\n", old_generation_survival_rate); |
| 2013 } |
| 2014 } |
| 2015 } |
| 2016 |
| 2017 |
| 1969 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { | 2018 void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { |
| 1970 DisallowHeapAllocation no_allocation; | 2019 DisallowHeapAllocation no_allocation; |
| 1971 // All external strings are listed in the external string table. | 2020 // All external strings are listed in the external string table. |
| 1972 | 2021 |
| 1973 class ExternalStringTableVisitorAdapter : public ObjectVisitor { | 2022 class ExternalStringTableVisitorAdapter : public ObjectVisitor { |
| 1974 public: | 2023 public: |
| 1975 explicit ExternalStringTableVisitorAdapter( | 2024 explicit ExternalStringTableVisitorAdapter( |
| 1976 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} | 2025 v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {} |
| 1977 virtual void VisitPointers(Object** start, Object** end) { | 2026 virtual void VisitPointers(Object** start, Object** end) { |
| 1978 for (Object** p = start; p < end; p++) { | 2027 for (Object** p = start; p < end; p++) { |
| (...skipping 5761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7740 static_cast<int>(object_sizes_last_time_[index])); | 7789 static_cast<int>(object_sizes_last_time_[index])); |
| 7741 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 7790 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7742 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7791 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7743 | 7792 |
| 7744 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7793 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7745 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7794 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7746 ClearObjectStats(); | 7795 ClearObjectStats(); |
| 7747 } | 7796 } |
| 7748 | 7797 |
| 7749 } } // namespace v8::internal | 7798 } } // namespace v8::internal |
| OLD | NEW |