| 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 |