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 |