| 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/heap/incremental-marking.h" | 5 #include "src/heap/incremental-marking.h" |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/compilation-cache.h" | 8 #include "src/compilation-cache.h" |
| 9 #include "src/conversions.h" | 9 #include "src/conversions.h" |
| 10 #include "src/heap/gc-idle-time-handler.h" | 10 #include "src/heap/gc-idle-time-handler.h" |
| 11 #include "src/heap/gc-tracer.h" | 11 #include "src/heap/gc-tracer.h" |
| 12 #include "src/heap/mark-compact-inl.h" | 12 #include "src/heap/mark-compact-inl.h" |
| 13 #include "src/heap/object-stats.h" | 13 #include "src/heap/object-stats.h" |
| 14 #include "src/heap/objects-visiting-inl.h" | 14 #include "src/heap/objects-visiting-inl.h" |
| 15 #include "src/heap/objects-visiting.h" | 15 #include "src/heap/objects-visiting.h" |
| 16 #include "src/tracing/trace-event.h" | 16 #include "src/tracing/trace-event.h" |
| 17 #include "src/v8.h" | 17 #include "src/v8.h" |
| 18 | 18 |
| 19 namespace v8 { | 19 namespace v8 { |
| 20 namespace internal { | 20 namespace internal { |
| 21 | 21 |
| 22 IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() { | |
| 23 return StepActions(IncrementalMarking::NO_GC_VIA_STACK_GUARD, | |
| 24 IncrementalMarking::FORCE_MARKING, | |
| 25 IncrementalMarking::DO_NOT_FORCE_COMPLETION); | |
| 26 } | |
| 27 | |
| 28 IncrementalMarking::IncrementalMarking(Heap* heap) | 22 IncrementalMarking::IncrementalMarking(Heap* heap) |
| 29 : heap_(heap), | 23 : heap_(heap), |
| 30 observer_(*this, kAllocatedThreshold), | 24 observer_(*this, kAllocatedThreshold), |
| 31 state_(STOPPED), | 25 state_(STOPPED), |
| 32 is_compacting_(false), | 26 is_compacting_(false), |
| 33 steps_count_(0), | 27 steps_count_(0), |
| 34 old_generation_space_available_at_start_of_incremental_(0), | 28 old_generation_space_available_at_start_of_incremental_(0), |
| 35 old_generation_space_used_at_start_of_incremental_(0), | 29 old_generation_space_used_at_start_of_incremental_(0), |
| 36 bytes_rescanned_(0), | 30 bytes_rescanned_(0), |
| 37 should_hurry_(false), | 31 should_hurry_(false), |
| (...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 } | 1044 } |
| 1051 | 1045 |
| 1052 | 1046 |
| 1053 void IncrementalMarking::Epilogue() { | 1047 void IncrementalMarking::Epilogue() { |
| 1054 was_activated_ = false; | 1048 was_activated_ = false; |
| 1055 finalize_marking_completed_ = false; | 1049 finalize_marking_completed_ = false; |
| 1056 incremental_marking_finalization_rounds_ = 0; | 1050 incremental_marking_finalization_rounds_ = 0; |
| 1057 } | 1051 } |
| 1058 | 1052 |
| 1059 double IncrementalMarking::AdvanceIncrementalMarking( | 1053 double IncrementalMarking::AdvanceIncrementalMarking( |
| 1060 double deadline_in_ms, IncrementalMarking::StepActions step_actions) { | 1054 double deadline_in_ms, CompletionAction completion_action, |
| 1055 ForceCompletionAction force_completion) { |
| 1061 DCHECK(!IsStopped()); | 1056 DCHECK(!IsStopped()); |
| 1062 | 1057 |
| 1058 double remaining_time_in_ms = 0.0; |
| 1063 intptr_t step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize( | 1059 intptr_t step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize( |
| 1064 GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs, | 1060 kStepSizeInMs, |
| 1065 heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); | 1061 heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); |
| 1066 double remaining_time_in_ms = 0.0; | |
| 1067 | 1062 |
| 1068 do { | 1063 do { |
| 1069 Step(step_size_in_bytes, step_actions.completion_action, | 1064 Step(step_size_in_bytes, completion_action, force_completion); |
| 1070 step_actions.force_marking, step_actions.force_completion); | |
| 1071 remaining_time_in_ms = | 1065 remaining_time_in_ms = |
| 1072 deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs(); | 1066 deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs(); |
| 1073 } while (!heap_->mark_compact_collector()->marking_deque()->IsEmpty() && | 1067 } while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() && |
| 1074 remaining_time_in_ms >= | |
| 1075 2.0 * GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs && | |
| 1076 !IsComplete() && | |
| 1077 !heap()->mark_compact_collector()->marking_deque()->IsEmpty()); | 1068 !heap()->mark_compact_collector()->marking_deque()->IsEmpty()); |
| 1078 return remaining_time_in_ms; | 1069 return remaining_time_in_ms; |
| 1079 } | 1070 } |
| 1080 | 1071 |
| 1081 | 1072 |
| 1082 void IncrementalMarking::OldSpaceStep(intptr_t allocated) { | |
| 1083 if (IsStopped() && ShouldActivateEvenWithoutIdleNotification()) { | |
| 1084 heap()->StartIncrementalMarking(Heap::kNoGCFlags, kNoGCCallbackFlags, | |
| 1085 "old space step"); | |
| 1086 } else { | |
| 1087 Step(allocated * kFastMarking / kInitialMarkingSpeed, GC_VIA_STACK_GUARD); | |
| 1088 } | |
| 1089 } | |
| 1090 | |
| 1091 | |
| 1092 void IncrementalMarking::SpeedUp() { | 1073 void IncrementalMarking::SpeedUp() { |
| 1093 bool speed_up = false; | 1074 bool speed_up = false; |
| 1094 | 1075 |
| 1095 if ((steps_count_ % kMarkingSpeedAccellerationInterval) == 0) { | 1076 if ((steps_count_ % kMarkingSpeedAccellerationInterval) == 0) { |
| 1096 if (FLAG_trace_incremental_marking) { | 1077 if (FLAG_trace_incremental_marking) { |
| 1097 heap()->isolate()->PrintWithTimestamp( | 1078 heap()->isolate()->PrintWithTimestamp( |
| 1098 "[IncrementalMarking] Speed up marking after %d steps\n", | 1079 "[IncrementalMarking] Speed up marking after %d steps\n", |
| 1099 static_cast<int>(kMarkingSpeedAccellerationInterval)); | 1080 static_cast<int>(kMarkingSpeedAccellerationInterval)); |
| 1100 } | 1081 } |
| 1101 speed_up = true; | 1082 speed_up = true; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 (heap_->mark_compact_collector()->sweeper().IsSweepingCompleted() || | 1152 (heap_->mark_compact_collector()->sweeper().IsSweepingCompleted() || |
| 1172 !FLAG_concurrent_sweeping)) { | 1153 !FLAG_concurrent_sweeping)) { |
| 1173 heap_->mark_compact_collector()->EnsureSweepingCompleted(); | 1154 heap_->mark_compact_collector()->EnsureSweepingCompleted(); |
| 1174 } | 1155 } |
| 1175 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { | 1156 if (!heap_->mark_compact_collector()->sweeping_in_progress()) { |
| 1176 bytes_scanned_ = 0; | 1157 bytes_scanned_ = 0; |
| 1177 StartMarking(); | 1158 StartMarking(); |
| 1178 } | 1159 } |
| 1179 } | 1160 } |
| 1180 | 1161 |
| 1181 intptr_t IncrementalMarking::Step(intptr_t allocated_bytes, | 1162 void IncrementalMarking::NotifyAllocatedBytes(intptr_t allocated_bytes) { |
| 1182 CompletionAction action, | |
| 1183 ForceMarkingAction marking, | |
| 1184 ForceCompletionAction completion) { | |
| 1185 DCHECK(allocated_bytes >= 0); | |
| 1186 | |
| 1187 if (heap_->gc_state() != Heap::NOT_IN_GC || !FLAG_incremental_marking || | 1163 if (heap_->gc_state() != Heap::NOT_IN_GC || !FLAG_incremental_marking || |
| 1188 (state_ != SWEEPING && state_ != MARKING)) { | 1164 (state_ != SWEEPING && state_ != MARKING)) { |
| 1189 return 0; | 1165 return; |
| 1190 } | 1166 } |
| 1191 | 1167 |
| 1192 allocated_ += allocated_bytes; | 1168 allocated_ += allocated_bytes; |
| 1193 | 1169 |
| 1194 if (marking == DO_NOT_FORCE_MARKING && allocated_ < kAllocatedThreshold && | 1170 if (allocated_ >= kAllocatedThreshold || |
| 1195 write_barriers_invoked_since_last_step_ < | 1171 write_barriers_invoked_since_last_step_ >= |
| 1196 kWriteBarriersInvokedThreshold) { | 1172 kWriteBarriersInvokedThreshold) { |
| 1197 return 0; | |
| 1198 } | |
| 1199 | |
| 1200 // If an idle notification happened recently, we delay marking steps. | |
| 1201 if (marking == DO_NOT_FORCE_MARKING && | |
| 1202 heap_->RecentIdleNotificationHappened()) { | |
| 1203 return 0; | |
| 1204 } | |
| 1205 | |
| 1206 intptr_t bytes_processed = 0; | |
| 1207 { | |
| 1208 HistogramTimerScope incremental_marking_scope( | |
| 1209 heap_->isolate()->counters()->gc_incremental_marking()); | |
| 1210 TRACE_EVENT0("v8", "V8.GCIncrementalMarking"); | |
| 1211 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL); | |
| 1212 double start = heap_->MonotonicallyIncreasingTimeInMs(); | |
| 1213 | |
| 1214 // The marking speed is driven either by the allocation rate or by the rate | 1173 // The marking speed is driven either by the allocation rate or by the rate |
| 1215 // at which we are having to check the color of objects in the write | 1174 // at which we are having to check the color of objects in the write |
| 1216 // barrier. | 1175 // barrier. |
| 1217 // It is possible for a tight non-allocating loop to run a lot of write | 1176 // It is possible for a tight non-allocating loop to run a lot of write |
| 1218 // barriers before we get here and check them (marking can only take place | 1177 // barriers before we get here and check them (marking can only take place |
| 1219 // on | 1178 // on |
| 1220 // allocation), so to reduce the lumpiness we don't use the write barriers | 1179 // allocation), so to reduce the lumpiness we don't use the write barriers |
| 1221 // invoked since last step directly to determine the amount of work to do. | 1180 // invoked since last step directly to determine the amount of work to do. |
| 1222 intptr_t bytes_to_process = | 1181 intptr_t bytes_to_process = |
| 1223 marking_speed_ * | 1182 marking_speed_ * |
| 1224 Max(allocated_, write_barriers_invoked_since_last_step_); | 1183 Max(allocated_, write_barriers_invoked_since_last_step_); |
| 1225 allocated_ = 0; | 1184 Step(bytes_to_process, GC_VIA_STACK_GUARD, FORCE_COMPLETION); |
| 1226 write_barriers_invoked_since_last_step_ = 0; | 1185 } |
| 1186 } |
| 1227 | 1187 |
| 1228 bytes_scanned_ += bytes_to_process; | 1188 void IncrementalMarking::Step(intptr_t bytes_to_process, |
| 1189 CompletionAction action, |
| 1190 ForceCompletionAction completion) { |
| 1191 HistogramTimerScope incremental_marking_scope( |
| 1192 heap_->isolate()->counters()->gc_incremental_marking()); |
| 1193 TRACE_EVENT0("v8", "V8.GCIncrementalMarking"); |
| 1194 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL); |
| 1195 double start = heap_->MonotonicallyIncreasingTimeInMs(); |
| 1229 | 1196 |
| 1230 if (state_ == SWEEPING) { | 1197 bytes_scanned_ += bytes_to_process; |
| 1231 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL_SWEEPING); | 1198 |
| 1232 FinalizeSweeping(); | 1199 allocated_ = 0; |
| 1200 write_barriers_invoked_since_last_step_ = 0; |
| 1201 |
| 1202 if (state_ == SWEEPING) { |
| 1203 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL_SWEEPING); |
| 1204 FinalizeSweeping(); |
| 1205 } |
| 1206 |
| 1207 intptr_t bytes_processed = 0; |
| 1208 if (state_ == MARKING) { |
| 1209 const bool incremental_wrapper_tracing = |
| 1210 FLAG_incremental_marking_wrappers && heap_->UsingEmbedderHeapTracer(); |
| 1211 const bool process_wrappers = |
| 1212 incremental_wrapper_tracing && |
| 1213 (heap_->mark_compact_collector() |
| 1214 ->RequiresImmediateWrapperProcessing() || |
| 1215 heap_->mark_compact_collector()->marking_deque()->IsEmpty()); |
| 1216 bool wrapper_work_left = incremental_wrapper_tracing; |
| 1217 if (!process_wrappers) { |
| 1218 bytes_processed = ProcessMarkingDeque(bytes_to_process); |
| 1219 } else { |
| 1220 const double wrapper_deadline = |
| 1221 heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs; |
| 1222 TRACE_GC(heap()->tracer(), |
| 1223 GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING); |
| 1224 heap_->mark_compact_collector()->RegisterWrappersWithEmbedderHeapTracer(); |
| 1225 wrapper_work_left = |
| 1226 heap_->mark_compact_collector() |
| 1227 ->embedder_heap_tracer() |
| 1228 ->AdvanceTracing(wrapper_deadline, |
| 1229 EmbedderHeapTracer::AdvanceTracingActions( |
| 1230 EmbedderHeapTracer::ForceCompletionAction:: |
| 1231 DO_NOT_FORCE_COMPLETION)); |
| 1233 } | 1232 } |
| 1234 | 1233 |
| 1235 if (state_ == MARKING) { | 1234 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty() && |
| 1236 const bool incremental_wrapper_tracing = | 1235 !wrapper_work_left) { |
| 1237 FLAG_incremental_marking_wrappers && heap_->UsingEmbedderHeapTracer(); | 1236 if (completion == FORCE_COMPLETION || |
| 1238 const bool process_wrappers = | 1237 IsIdleMarkingDelayCounterLimitReached()) { |
| 1239 incremental_wrapper_tracing && | 1238 if (!finalize_marking_completed_) { |
| 1240 (heap_->mark_compact_collector() | 1239 FinalizeMarking(action); |
| 1241 ->RequiresImmediateWrapperProcessing() || | 1240 } else { |
| 1242 heap_->mark_compact_collector()->marking_deque()->IsEmpty()); | 1241 MarkingComplete(action); |
| 1243 bool wrapper_work_left = incremental_wrapper_tracing; | 1242 } |
| 1244 if (!process_wrappers) { | |
| 1245 bytes_processed = ProcessMarkingDeque(bytes_to_process); | |
| 1246 } else { | 1243 } else { |
| 1247 const double kWrapperTracngStepMs = 1.0; | 1244 IncrementIdleMarkingDelayCounter(); |
| 1248 const double wrapper_deadline = | |
| 1249 heap_->MonotonicallyIncreasingTimeInMs() + kWrapperTracngStepMs; | |
| 1250 TRACE_GC(heap()->tracer(), | |
| 1251 GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING); | |
| 1252 heap_->mark_compact_collector() | |
| 1253 ->RegisterWrappersWithEmbedderHeapTracer(); | |
| 1254 wrapper_work_left = | |
| 1255 heap_->mark_compact_collector() | |
| 1256 ->embedder_heap_tracer() | |
| 1257 ->AdvanceTracing(wrapper_deadline, | |
| 1258 EmbedderHeapTracer::AdvanceTracingActions( | |
| 1259 EmbedderHeapTracer::ForceCompletionAction:: | |
| 1260 DO_NOT_FORCE_COMPLETION)); | |
| 1261 } | |
| 1262 | |
| 1263 if (heap_->mark_compact_collector()->marking_deque()->IsEmpty() && | |
| 1264 !wrapper_work_left) { | |
| 1265 if (completion == FORCE_COMPLETION || | |
| 1266 IsIdleMarkingDelayCounterLimitReached()) { | |
| 1267 if (!finalize_marking_completed_) { | |
| 1268 FinalizeMarking(action); | |
| 1269 } else { | |
| 1270 MarkingComplete(action); | |
| 1271 } | |
| 1272 } else { | |
| 1273 IncrementIdleMarkingDelayCounter(); | |
| 1274 } | |
| 1275 } | 1245 } |
| 1276 } | 1246 } |
| 1247 } |
| 1277 | 1248 |
| 1278 steps_count_++; | 1249 steps_count_++; |
| 1279 | 1250 |
| 1280 // Speed up marking if we are marking too slow or if we are almost done | 1251 // Speed up marking if we are marking too slow or if we are almost done |
| 1281 // with marking. | 1252 // with marking. |
| 1282 SpeedUp(); | 1253 SpeedUp(); |
| 1283 | 1254 |
| 1284 double end = heap_->MonotonicallyIncreasingTimeInMs(); | 1255 double end = heap_->MonotonicallyIncreasingTimeInMs(); |
| 1285 double duration = (end - start); | 1256 double duration = (end - start); |
| 1286 // Note that we report zero bytes here when sweeping was in progress or | 1257 // Note that we report zero bytes here when sweeping was in progress or |
| 1287 // when we just started incremental marking. In these cases we did not | 1258 // when we just started incremental marking. In these cases we did not |
| 1288 // process the marking deque. | 1259 // process the marking deque. |
| 1289 heap_->tracer()->AddIncrementalMarkingStep(duration, bytes_processed); | 1260 heap_->tracer()->AddIncrementalMarkingStep(duration, bytes_processed); |
| 1290 } | |
| 1291 return bytes_processed; | |
| 1292 } | 1261 } |
| 1293 | 1262 |
| 1294 | 1263 |
| 1295 void IncrementalMarking::ResetStepCounters() { | 1264 void IncrementalMarking::ResetStepCounters() { |
| 1296 steps_count_ = 0; | 1265 steps_count_ = 0; |
| 1297 old_generation_space_available_at_start_of_incremental_ = | 1266 old_generation_space_available_at_start_of_incremental_ = |
| 1298 SpaceLeftInOldSpace(); | 1267 SpaceLeftInOldSpace(); |
| 1299 old_generation_space_used_at_start_of_incremental_ = | 1268 old_generation_space_used_at_start_of_incremental_ = |
| 1300 heap_->PromotedTotalSize(); | 1269 heap_->PromotedTotalSize(); |
| 1301 bytes_rescanned_ = 0; | 1270 bytes_rescanned_ = 0; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1319 idle_marking_delay_counter_++; | 1288 idle_marking_delay_counter_++; |
| 1320 } | 1289 } |
| 1321 | 1290 |
| 1322 | 1291 |
| 1323 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1292 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
| 1324 idle_marking_delay_counter_ = 0; | 1293 idle_marking_delay_counter_ = 0; |
| 1325 } | 1294 } |
| 1326 | 1295 |
| 1327 } // namespace internal | 1296 } // namespace internal |
| 1328 } // namespace v8 | 1297 } // namespace v8 |
| OLD | NEW |