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/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 // cleared eagerly immediately after the transition. | 318 // cleared eagerly immediately after the transition. |
319 | 319 |
320 #ifdef VERIFY_HEAP | 320 #ifdef VERIFY_HEAP |
321 if (FLAG_verify_heap) { | 321 if (FLAG_verify_heap) { |
322 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); | 322 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); |
323 RememberedSet<OLD_TO_OLD>::VerifyValidSlots(heap()); | 323 RememberedSet<OLD_TO_OLD>::VerifyValidSlots(heap()); |
324 } | 324 } |
325 #endif | 325 #endif |
326 } | 326 } |
327 | 327 |
328 | |
329 void MarkCompactCollector::CollectGarbage() { | 328 void MarkCompactCollector::CollectGarbage() { |
330 // Make sure that Prepare() has been called. The individual steps below will | 329 // Make sure that Prepare() has been called. The individual steps below will |
331 // update the state as they proceed. | 330 // update the state as they proceed. |
332 DCHECK(state_ == PREPARE_GC); | 331 DCHECK(state_ == PREPARE_GC); |
333 | 332 |
334 MarkLiveObjects(); | 333 MarkLiveObjects(); |
335 | 334 |
336 DCHECK(heap_->incremental_marking()->IsStopped()); | 335 DCHECK(heap_->incremental_marking()->IsStopped()); |
337 | 336 |
338 ClearNonLiveReferences(); | 337 ClearNonLiveReferences(); |
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 // Visit the fields of the RegExp, including the updated FixedArray. | 1255 // Visit the fields of the RegExp, including the updated FixedArray. |
1257 VisitJSRegExp(map, object); | 1256 VisitJSRegExp(map, object); |
1258 } | 1257 } |
1259 }; | 1258 }; |
1260 | 1259 |
1261 | 1260 |
1262 void MarkCompactMarkingVisitor::Initialize() { | 1261 void MarkCompactMarkingVisitor::Initialize() { |
1263 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); | 1262 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); |
1264 | 1263 |
1265 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); | 1264 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); |
1266 | |
1267 if (FLAG_track_gc_object_stats) { | |
1268 MarkCompactObjectStatsVisitor::Initialize(&table_); | |
1269 } | |
1270 } | 1265 } |
1271 | 1266 |
1272 | 1267 |
1273 class CodeMarkingVisitor : public ThreadVisitor { | 1268 class CodeMarkingVisitor : public ThreadVisitor { |
1274 public: | 1269 public: |
1275 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 1270 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
1276 : collector_(collector) {} | 1271 : collector_(collector) {} |
1277 | 1272 |
1278 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1273 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
1279 collector_->PrepareThreadForCodeFlushing(isolate, top); | 1274 collector_->PrepareThreadForCodeFlushing(isolate, top); |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2236 } | 2231 } |
2237 | 2232 |
2238 void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) { | 2233 void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) { |
2239 DCHECK(in_use()); | 2234 DCHECK(in_use()); |
2240 HeapObject* heap_object = HeapObject::cast(*object); | 2235 HeapObject* heap_object = HeapObject::cast(*object); |
2241 DCHECK(heap_->Contains(heap_object)); | 2236 DCHECK(heap_->Contains(heap_object)); |
2242 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); | 2237 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); |
2243 MarkObject(heap_object, mark_bit); | 2238 MarkObject(heap_object, mark_bit); |
2244 } | 2239 } |
2245 | 2240 |
| 2241 class MarkCompactCollector::ObjectStatsVisitor |
| 2242 : public MarkCompactCollector::HeapObjectVisitor { |
| 2243 public: |
| 2244 ObjectStatsVisitor(ObjectStats* live_stats, ObjectStats* dead_stats) |
| 2245 : live_stats_(live_stats), dead_stats_(dead_stats) { |
| 2246 DCHECK_NOT_NULL(live_stats_); |
| 2247 DCHECK_NOT_NULL(dead_stats_); |
| 2248 } |
| 2249 |
| 2250 bool Visit(HeapObject* obj) override { |
| 2251 if (Marking::IsBlack(ObjectMarking::MarkBitFrom(obj))) { |
| 2252 ObjectStatsCollector::CollectStatistics(live_stats_, obj); |
| 2253 } else { |
| 2254 DCHECK(!Marking::IsGrey(ObjectMarking::MarkBitFrom(obj))); |
| 2255 ObjectStatsCollector::CollectStatistics(dead_stats_, obj); |
| 2256 } |
| 2257 return true; |
| 2258 } |
| 2259 |
| 2260 private: |
| 2261 ObjectStats* live_stats_; |
| 2262 ObjectStats* dead_stats_; |
| 2263 }; |
| 2264 |
| 2265 void MarkCompactCollector::VisitAllObjects(HeapObjectVisitor* visitor) { |
| 2266 SpaceIterator space_it(heap()); |
| 2267 HeapObject* obj = nullptr; |
| 2268 while (space_it.has_next()) { |
| 2269 ObjectIterator* it = space_it.next(); |
| 2270 while ((obj = it->Next()) != nullptr) { |
| 2271 visitor->Visit(obj); |
| 2272 } |
| 2273 } |
| 2274 } |
| 2275 |
2246 void MarkCompactCollector::MarkLiveObjects() { | 2276 void MarkCompactCollector::MarkLiveObjects() { |
2247 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); | 2277 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); |
2248 double start_time = 0.0; | 2278 double start_time = 0.0; |
2249 if (FLAG_print_cumulative_gc_stat) { | 2279 if (FLAG_print_cumulative_gc_stat) { |
2250 start_time = heap_->MonotonicallyIncreasingTimeInMs(); | 2280 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
2251 } | 2281 } |
2252 // The recursive GC marker detects when it is nearing stack overflow, | 2282 // The recursive GC marker detects when it is nearing stack overflow, |
2253 // and switches to a different marking system. JS interrupts interfere | 2283 // and switches to a different marking system. JS interrupts interfere |
2254 // with the C stack limit check. | 2284 // with the C stack limit check. |
2255 PostponeInterruptsScope postpone(isolate()); | 2285 PostponeInterruptsScope postpone(isolate()); |
2256 | 2286 |
2257 { | 2287 { |
2258 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); | 2288 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); |
2259 IncrementalMarking* incremental_marking = heap_->incremental_marking(); | 2289 IncrementalMarking* incremental_marking = heap_->incremental_marking(); |
2260 if (was_marked_incrementally_) { | 2290 if (was_marked_incrementally_) { |
2261 incremental_marking->Finalize(); | 2291 incremental_marking->Finalize(); |
2262 } else { | 2292 } else { |
2263 // Abort any pending incremental activities e.g. incremental sweeping. | 2293 // Abort any pending incremental activities e.g. incremental sweeping. |
2264 incremental_marking->Stop(); | 2294 incremental_marking->Stop(); |
2265 if (FLAG_track_gc_object_stats) { | |
2266 // Clear object stats collected during incremental marking. | |
2267 heap()->object_stats_->ClearObjectStats(); | |
2268 } | |
2269 if (marking_deque_.in_use()) { | 2295 if (marking_deque_.in_use()) { |
2270 marking_deque_.Uninitialize(true); | 2296 marking_deque_.Uninitialize(true); |
2271 } | 2297 } |
2272 } | 2298 } |
2273 } | 2299 } |
2274 | 2300 |
2275 #ifdef DEBUG | 2301 #ifdef DEBUG |
2276 DCHECK(state_ == PREPARE_GC); | 2302 DCHECK(state_ == PREPARE_GC); |
2277 state_ = MARK_LIVE_OBJECTS; | 2303 state_ = MARK_LIVE_OBJECTS; |
2278 #endif | 2304 #endif |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 embedder_heap_tracer()->TraceEpilogue(); | 2366 embedder_heap_tracer()->TraceEpilogue(); |
2341 } | 2367 } |
2342 } | 2368 } |
2343 } | 2369 } |
2344 | 2370 |
2345 if (FLAG_print_cumulative_gc_stat) { | 2371 if (FLAG_print_cumulative_gc_stat) { |
2346 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2372 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
2347 start_time); | 2373 start_time); |
2348 } | 2374 } |
2349 if (FLAG_track_gc_object_stats) { | 2375 if (FLAG_track_gc_object_stats) { |
| 2376 ObjectStatsVisitor visitor(heap()->live_object_stats_, |
| 2377 heap()->dead_object_stats_); |
| 2378 VisitAllObjects(&visitor); |
2350 if (FLAG_trace_gc_object_stats) { | 2379 if (FLAG_trace_gc_object_stats) { |
2351 heap()->object_stats_->TraceObjectStats(); | 2380 heap()->live_object_stats_->PrintJSON("live"); |
| 2381 heap()->dead_object_stats_->PrintJSON("dead"); |
2352 } | 2382 } |
2353 heap()->object_stats_->CheckpointObjectStats(); | 2383 heap()->live_object_stats_->CheckpointObjectStats(); |
| 2384 heap()->dead_object_stats_->ClearObjectStats(); |
2354 } | 2385 } |
2355 } | 2386 } |
2356 | 2387 |
2357 | 2388 |
2358 void MarkCompactCollector::ClearNonLiveReferences() { | 2389 void MarkCompactCollector::ClearNonLiveReferences() { |
2359 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | 2390 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
2360 | 2391 |
2361 { | 2392 { |
2362 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); | 2393 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
2363 | 2394 |
(...skipping 1683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4047 // The target is always in old space, we don't have to record the slot in | 4078 // The target is always in old space, we don't have to record the slot in |
4048 // the old-to-new remembered set. | 4079 // the old-to-new remembered set. |
4049 DCHECK(!heap()->InNewSpace(target)); | 4080 DCHECK(!heap()->InNewSpace(target)); |
4050 RecordRelocSlot(host, &rinfo, target); | 4081 RecordRelocSlot(host, &rinfo, target); |
4051 } | 4082 } |
4052 } | 4083 } |
4053 } | 4084 } |
4054 | 4085 |
4055 } // namespace internal | 4086 } // namespace internal |
4056 } // namespace v8 | 4087 } // namespace v8 |
OLD | NEW |