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" |
(...skipping 15 matching lines...) Expand all Loading... |
26 is_compacting_(false), | 26 is_compacting_(false), |
27 steps_count_(0), | 27 steps_count_(0), |
28 old_generation_space_available_at_start_of_incremental_(0), | 28 old_generation_space_available_at_start_of_incremental_(0), |
29 old_generation_space_used_at_start_of_incremental_(0), | 29 old_generation_space_used_at_start_of_incremental_(0), |
30 bytes_rescanned_(0), | 30 bytes_rescanned_(0), |
31 should_hurry_(false), | 31 should_hurry_(false), |
32 marking_speed_(0), | 32 marking_speed_(0), |
33 bytes_scanned_(0), | 33 bytes_scanned_(0), |
34 allocated_(0), | 34 allocated_(0), |
35 write_barriers_invoked_since_last_step_(0), | 35 write_barriers_invoked_since_last_step_(0), |
| 36 bytes_marked_ahead_of_schedule_(0), |
36 idle_marking_delay_counter_(0), | 37 idle_marking_delay_counter_(0), |
37 unscanned_bytes_of_large_object_(0), | 38 unscanned_bytes_of_large_object_(0), |
38 was_activated_(false), | 39 was_activated_(false), |
39 black_allocation_(false), | 40 black_allocation_(false), |
40 finalize_marking_completed_(false), | 41 finalize_marking_completed_(false), |
41 incremental_marking_finalization_rounds_(0), | 42 incremental_marking_finalization_rounds_(0), |
42 request_type_(NONE) {} | 43 request_type_(NONE) {} |
43 | 44 |
44 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { | 45 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { |
45 HeapObject* value_heap_obj = HeapObject::cast(value); | 46 HeapObject* value_heap_obj = HeapObject::cast(value); |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 | 1049 |
1049 | 1050 |
1050 void IncrementalMarking::Epilogue() { | 1051 void IncrementalMarking::Epilogue() { |
1051 was_activated_ = false; | 1052 was_activated_ = false; |
1052 finalize_marking_completed_ = false; | 1053 finalize_marking_completed_ = false; |
1053 incremental_marking_finalization_rounds_ = 0; | 1054 incremental_marking_finalization_rounds_ = 0; |
1054 } | 1055 } |
1055 | 1056 |
1056 double IncrementalMarking::AdvanceIncrementalMarking( | 1057 double IncrementalMarking::AdvanceIncrementalMarking( |
1057 double deadline_in_ms, CompletionAction completion_action, | 1058 double deadline_in_ms, CompletionAction completion_action, |
1058 ForceCompletionAction force_completion) { | 1059 ForceCompletionAction force_completion, StepOrigin step_origin) { |
1059 DCHECK(!IsStopped()); | 1060 DCHECK(!IsStopped()); |
1060 | 1061 |
1061 double remaining_time_in_ms = 0.0; | 1062 double remaining_time_in_ms = 0.0; |
1062 intptr_t step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize( | 1063 intptr_t step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize( |
1063 kStepSizeInMs, | 1064 kStepSizeInMs, |
1064 heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); | 1065 heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); |
1065 | 1066 |
1066 do { | 1067 do { |
1067 Step(step_size_in_bytes, completion_action, force_completion); | 1068 Step(step_size_in_bytes, completion_action, force_completion, step_origin); |
1068 remaining_time_in_ms = | 1069 remaining_time_in_ms = |
1069 deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs(); | 1070 deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs(); |
1070 } while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() && | 1071 } while (remaining_time_in_ms >= kStepSizeInMs && !IsComplete() && |
1071 !heap()->mark_compact_collector()->marking_deque()->IsEmpty()); | 1072 !heap()->mark_compact_collector()->marking_deque()->IsEmpty()); |
1072 return remaining_time_in_ms; | 1073 return remaining_time_in_ms; |
1073 } | 1074 } |
1074 | 1075 |
1075 | 1076 |
1076 void IncrementalMarking::SpeedUp() { | 1077 void IncrementalMarking::SpeedUp() { |
1077 bool speed_up = false; | 1078 bool speed_up = false; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 // at which we are having to check the color of objects in the write | 1178 // at which we are having to check the color of objects in the write |
1178 // barrier. | 1179 // barrier. |
1179 // It is possible for a tight non-allocating loop to run a lot of write | 1180 // It is possible for a tight non-allocating loop to run a lot of write |
1180 // barriers before we get here and check them (marking can only take place | 1181 // barriers before we get here and check them (marking can only take place |
1181 // on | 1182 // on |
1182 // allocation), so to reduce the lumpiness we don't use the write barriers | 1183 // allocation), so to reduce the lumpiness we don't use the write barriers |
1183 // invoked since last step directly to determine the amount of work to do. | 1184 // invoked since last step directly to determine the amount of work to do. |
1184 intptr_t bytes_to_process = | 1185 intptr_t bytes_to_process = |
1185 marking_speed_ * | 1186 marking_speed_ * |
1186 Max(allocated_, write_barriers_invoked_since_last_step_); | 1187 Max(allocated_, write_barriers_invoked_since_last_step_); |
1187 Step(bytes_to_process, GC_VIA_STACK_GUARD, FORCE_COMPLETION); | 1188 Step(bytes_to_process, GC_VIA_STACK_GUARD, FORCE_COMPLETION, |
| 1189 StepOrigin::kV8); |
1188 } | 1190 } |
1189 } | 1191 } |
1190 | 1192 |
1191 void IncrementalMarking::Step(intptr_t bytes_to_process, | 1193 void IncrementalMarking::Step(intptr_t bytes_to_process, |
1192 CompletionAction action, | 1194 CompletionAction action, |
1193 ForceCompletionAction completion) { | 1195 ForceCompletionAction completion, |
| 1196 StepOrigin step_origin) { |
1194 HistogramTimerScope incremental_marking_scope( | 1197 HistogramTimerScope incremental_marking_scope( |
1195 heap_->isolate()->counters()->gc_incremental_marking()); | 1198 heap_->isolate()->counters()->gc_incremental_marking()); |
1196 TRACE_EVENT0("v8", "V8.GCIncrementalMarking"); | 1199 TRACE_EVENT0("v8", "V8.GCIncrementalMarking"); |
1197 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL); | 1200 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL); |
1198 double start = heap_->MonotonicallyIncreasingTimeInMs(); | 1201 double start = heap_->MonotonicallyIncreasingTimeInMs(); |
1199 | 1202 |
1200 bytes_scanned_ += bytes_to_process; | 1203 bytes_scanned_ += bytes_to_process; |
1201 | 1204 |
1202 allocated_ = 0; | 1205 allocated_ = 0; |
1203 write_barriers_invoked_since_last_step_ = 0; | 1206 write_barriers_invoked_since_last_step_ = 0; |
1204 | 1207 |
1205 if (state_ == SWEEPING) { | 1208 if (state_ == SWEEPING) { |
1206 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL_SWEEPING); | 1209 TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL_SWEEPING); |
1207 FinalizeSweeping(); | 1210 FinalizeSweeping(); |
1208 } | 1211 } |
1209 | 1212 |
1210 intptr_t bytes_processed = 0; | 1213 intptr_t bytes_processed = 0; |
1211 if (state_ == MARKING) { | 1214 if (state_ == MARKING) { |
1212 const bool incremental_wrapper_tracing = | 1215 const bool incremental_wrapper_tracing = |
1213 FLAG_incremental_marking_wrappers && heap_->UsingEmbedderHeapTracer(); | 1216 FLAG_incremental_marking_wrappers && heap_->UsingEmbedderHeapTracer(); |
1214 const bool process_wrappers = | 1217 const bool process_wrappers = |
1215 incremental_wrapper_tracing && | 1218 incremental_wrapper_tracing && |
1216 (heap_->mark_compact_collector() | 1219 (heap_->mark_compact_collector() |
1217 ->RequiresImmediateWrapperProcessing() || | 1220 ->RequiresImmediateWrapperProcessing() || |
1218 heap_->mark_compact_collector()->marking_deque()->IsEmpty()); | 1221 heap_->mark_compact_collector()->marking_deque()->IsEmpty()); |
1219 bool wrapper_work_left = incremental_wrapper_tracing; | 1222 bool wrapper_work_left = incremental_wrapper_tracing; |
1220 if (!process_wrappers) { | 1223 if (!process_wrappers) { |
1221 bytes_processed = ProcessMarkingDeque(bytes_to_process); | 1224 if (step_origin == StepOrigin::kV8 && |
| 1225 bytes_marked_ahead_of_schedule_ >= bytes_to_process) { |
| 1226 // Steps performed in tasks have put us ahead of schedule. |
| 1227 // We skip processing of marking dequeue here and thus |
| 1228 // shift marking time from inside V8 to standalone tasks. |
| 1229 bytes_marked_ahead_of_schedule_ -= bytes_to_process; |
| 1230 } else { |
| 1231 bytes_processed = ProcessMarkingDeque(bytes_to_process); |
| 1232 if (step_origin == StepOrigin::kTask) { |
| 1233 bytes_marked_ahead_of_schedule_ += bytes_processed; |
| 1234 } |
| 1235 } |
1222 } else { | 1236 } else { |
1223 const double wrapper_deadline = | 1237 const double wrapper_deadline = |
1224 heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs; | 1238 heap_->MonotonicallyIncreasingTimeInMs() + kStepSizeInMs; |
1225 TRACE_GC(heap()->tracer(), | 1239 TRACE_GC(heap()->tracer(), |
1226 GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING); | 1240 GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING); |
1227 heap_->mark_compact_collector()->RegisterWrappersWithEmbedderHeapTracer(); | 1241 heap_->mark_compact_collector()->RegisterWrappersWithEmbedderHeapTracer(); |
1228 wrapper_work_left = | 1242 wrapper_work_left = |
1229 heap_->mark_compact_collector() | 1243 heap_->mark_compact_collector() |
1230 ->embedder_heap_tracer() | 1244 ->embedder_heap_tracer() |
1231 ->AdvanceTracing(wrapper_deadline, | 1245 ->AdvanceTracing(wrapper_deadline, |
(...skipping 22 matching lines...) Expand all Loading... |
1254 // Speed up marking if we are marking too slow or if we are almost done | 1268 // Speed up marking if we are marking too slow or if we are almost done |
1255 // with marking. | 1269 // with marking. |
1256 SpeedUp(); | 1270 SpeedUp(); |
1257 | 1271 |
1258 double end = heap_->MonotonicallyIncreasingTimeInMs(); | 1272 double end = heap_->MonotonicallyIncreasingTimeInMs(); |
1259 double duration = (end - start); | 1273 double duration = (end - start); |
1260 // Note that we report zero bytes here when sweeping was in progress or | 1274 // Note that we report zero bytes here when sweeping was in progress or |
1261 // when we just started incremental marking. In these cases we did not | 1275 // when we just started incremental marking. In these cases we did not |
1262 // process the marking deque. | 1276 // process the marking deque. |
1263 heap_->tracer()->AddIncrementalMarkingStep(duration, bytes_processed); | 1277 heap_->tracer()->AddIncrementalMarkingStep(duration, bytes_processed); |
| 1278 if (FLAG_trace_incremental_marking) { |
| 1279 heap_->isolate()->PrintWithTimestamp( |
| 1280 "[IncrementalMarking] Step %s %d bytes (%d) in %.1f\n", |
| 1281 step_origin == StepOrigin::kV8 ? "in v8" : "in task", |
| 1282 static_cast<int>(bytes_processed), static_cast<int>(bytes_to_process), |
| 1283 duration); |
| 1284 } |
1264 } | 1285 } |
1265 | 1286 |
1266 | 1287 |
1267 void IncrementalMarking::ResetStepCounters() { | 1288 void IncrementalMarking::ResetStepCounters() { |
1268 steps_count_ = 0; | 1289 steps_count_ = 0; |
1269 old_generation_space_available_at_start_of_incremental_ = | 1290 old_generation_space_available_at_start_of_incremental_ = |
1270 SpaceLeftInOldSpace(); | 1291 SpaceLeftInOldSpace(); |
1271 old_generation_space_used_at_start_of_incremental_ = | 1292 old_generation_space_used_at_start_of_incremental_ = |
1272 heap_->PromotedTotalSize(); | 1293 heap_->PromotedTotalSize(); |
1273 bytes_rescanned_ = 0; | 1294 bytes_rescanned_ = 0; |
1274 marking_speed_ = kInitialMarkingSpeed; | 1295 marking_speed_ = kInitialMarkingSpeed; |
1275 bytes_scanned_ = 0; | 1296 bytes_scanned_ = 0; |
1276 write_barriers_invoked_since_last_step_ = 0; | 1297 write_barriers_invoked_since_last_step_ = 0; |
| 1298 bytes_marked_ahead_of_schedule_ = 0; |
1277 } | 1299 } |
1278 | 1300 |
1279 | 1301 |
1280 int64_t IncrementalMarking::SpaceLeftInOldSpace() { | 1302 int64_t IncrementalMarking::SpaceLeftInOldSpace() { |
1281 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); | 1303 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); |
1282 } | 1304 } |
1283 | 1305 |
1284 | 1306 |
1285 bool IncrementalMarking::IsIdleMarkingDelayCounterLimitReached() { | 1307 bool IncrementalMarking::IsIdleMarkingDelayCounterLimitReached() { |
1286 return idle_marking_delay_counter_ > kMaxIdleMarkingDelayCounter; | 1308 return idle_marking_delay_counter_ > kMaxIdleMarkingDelayCounter; |
1287 } | 1309 } |
1288 | 1310 |
1289 | 1311 |
1290 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { | 1312 void IncrementalMarking::IncrementIdleMarkingDelayCounter() { |
1291 idle_marking_delay_counter_++; | 1313 idle_marking_delay_counter_++; |
1292 } | 1314 } |
1293 | 1315 |
1294 | 1316 |
1295 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1317 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1296 idle_marking_delay_counter_ = 0; | 1318 idle_marking_delay_counter_ = 0; |
1297 } | 1319 } |
1298 | 1320 |
1299 } // namespace internal | 1321 } // namespace internal |
1300 } // namespace v8 | 1322 } // namespace v8 |
OLD | NEW |