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 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
319 // cleared eagerly immediately after the transition. | 319 // cleared eagerly immediately after the transition. |
320 | 320 |
321 #ifdef VERIFY_HEAP | 321 #ifdef VERIFY_HEAP |
322 if (FLAG_verify_heap) { | 322 if (FLAG_verify_heap) { |
323 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); | 323 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); |
324 RememberedSet<OLD_TO_OLD>::VerifyValidSlots(heap()); | 324 RememberedSet<OLD_TO_OLD>::VerifyValidSlots(heap()); |
325 } | 325 } |
326 #endif | 326 #endif |
327 } | 327 } |
328 | 328 |
329 | |
330 void MarkCompactCollector::CollectGarbage() { | 329 void MarkCompactCollector::CollectGarbage() { |
331 // Make sure that Prepare() has been called. The individual steps below will | 330 // Make sure that Prepare() has been called. The individual steps below will |
332 // update the state as they proceed. | 331 // update the state as they proceed. |
333 DCHECK(state_ == PREPARE_GC); | 332 DCHECK(state_ == PREPARE_GC); |
334 | 333 |
335 MarkLiveObjects(); | 334 MarkLiveObjects(); |
336 | 335 |
337 DCHECK(heap_->incremental_marking()->IsStopped()); | 336 DCHECK(heap_->incremental_marking()->IsStopped()); |
338 | 337 |
339 ClearNonLiveReferences(); | 338 ClearNonLiveReferences(); |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1295 // Visit the fields of the RegExp, including the updated FixedArray. | 1294 // Visit the fields of the RegExp, including the updated FixedArray. |
1296 VisitJSRegExp(map, object); | 1295 VisitJSRegExp(map, object); |
1297 } | 1296 } |
1298 }; | 1297 }; |
1299 | 1298 |
1300 | 1299 |
1301 void MarkCompactMarkingVisitor::Initialize() { | 1300 void MarkCompactMarkingVisitor::Initialize() { |
1302 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); | 1301 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); |
1303 | 1302 |
1304 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); | 1303 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); |
1305 | |
1306 if (FLAG_track_gc_object_stats) { | |
1307 MarkCompactObjectStatsVisitor::Initialize(&table_); | |
1308 } | |
1309 } | 1304 } |
1310 | 1305 |
1311 | 1306 |
1312 class CodeMarkingVisitor : public ThreadVisitor { | 1307 class CodeMarkingVisitor : public ThreadVisitor { |
1313 public: | 1308 public: |
1314 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 1309 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
1315 : collector_(collector) {} | 1310 : collector_(collector) {} |
1316 | 1311 |
1317 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1312 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
1318 collector_->PrepareThreadForCodeFlushing(isolate, top); | 1313 collector_->PrepareThreadForCodeFlushing(isolate, top); |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2275 } | 2270 } |
2276 | 2271 |
2277 void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) { | 2272 void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) { |
2278 DCHECK(in_use()); | 2273 DCHECK(in_use()); |
2279 HeapObject* heap_object = HeapObject::cast(*object); | 2274 HeapObject* heap_object = HeapObject::cast(*object); |
2280 DCHECK(heap_->Contains(heap_object)); | 2275 DCHECK(heap_->Contains(heap_object)); |
2281 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 2276 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
2282 MarkObject(heap_object, mark_bit); | 2277 MarkObject(heap_object, mark_bit); |
2283 } | 2278 } |
2284 | 2279 |
2280 class MarkCompactCollector::ObjectStatsVisitor | |
2281 : public MarkCompactCollector::HeapObjectVisitor { | |
2282 public: | |
2283 ObjectStatsVisitor(ObjectStats* live_stats, ObjectStats* dead_stats) | |
2284 : live_stats_(live_stats), dead_stats_(dead_stats) {} | |
2285 | |
2286 bool Visit(HeapObject* obj) override { | |
2287 if (Marking::IsBlack(Marking::MarkBitFrom(obj))) { | |
2288 if (live_stats_ != nullptr) | |
2289 ObjectStatsCollector::CollectStatistics(live_stats_, obj); | |
2290 } else { | |
2291 if (dead_stats_ != nullptr) | |
Hannes Payer (out of office)
2016/07/13 11:39:11
Just for fun: add a DCHECK that the object is not
Michael Lippautz
2016/07/13 12:20:17
Done.
| |
2292 ObjectStatsCollector::CollectStatistics(dead_stats_, obj); | |
2293 } | |
2294 return true; | |
2295 } | |
2296 | |
2297 private: | |
2298 ObjectStats* live_stats_; | |
2299 ObjectStats* dead_stats_; | |
2300 }; | |
2301 | |
2302 void MarkCompactCollector::VisitAllObjects(HeapObjectVisitor* visitor) { | |
2303 SpaceIterator space_it(heap()); | |
2304 HeapObject* obj = nullptr; | |
2305 while (space_it.has_next()) { | |
2306 ObjectIterator* it = space_it.next(); | |
2307 while ((obj = it->Next()) != nullptr) { | |
2308 visitor->Visit(obj); | |
2309 } | |
2310 } | |
2311 } | |
2312 | |
2285 void MarkCompactCollector::MarkLiveObjects() { | 2313 void MarkCompactCollector::MarkLiveObjects() { |
2286 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); | 2314 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); |
2287 double start_time = 0.0; | 2315 double start_time = 0.0; |
2288 if (FLAG_print_cumulative_gc_stat) { | 2316 if (FLAG_print_cumulative_gc_stat) { |
2289 start_time = heap_->MonotonicallyIncreasingTimeInMs(); | 2317 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
2290 } | 2318 } |
2291 // The recursive GC marker detects when it is nearing stack overflow, | 2319 // The recursive GC marker detects when it is nearing stack overflow, |
2292 // and switches to a different marking system. JS interrupts interfere | 2320 // and switches to a different marking system. JS interrupts interfere |
2293 // with the C stack limit check. | 2321 // with the C stack limit check. |
2294 PostponeInterruptsScope postpone(isolate()); | 2322 PostponeInterruptsScope postpone(isolate()); |
2295 | 2323 |
2296 { | 2324 { |
2297 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); | 2325 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); |
2298 IncrementalMarking* incremental_marking = heap_->incremental_marking(); | 2326 IncrementalMarking* incremental_marking = heap_->incremental_marking(); |
2299 if (was_marked_incrementally_) { | 2327 if (was_marked_incrementally_) { |
2300 incremental_marking->Finalize(); | 2328 incremental_marking->Finalize(); |
2301 } else { | 2329 } else { |
2302 // Abort any pending incremental activities e.g. incremental sweeping. | 2330 // Abort any pending incremental activities e.g. incremental sweeping. |
2303 incremental_marking->Stop(); | 2331 incremental_marking->Stop(); |
2304 if (FLAG_track_gc_object_stats) { | |
2305 // Clear object stats collected during incremental marking. | |
2306 heap()->object_stats_->ClearObjectStats(); | |
2307 } | |
2308 if (marking_deque_.in_use()) { | 2332 if (marking_deque_.in_use()) { |
2309 marking_deque_.Uninitialize(true); | 2333 marking_deque_.Uninitialize(true); |
2310 } | 2334 } |
2311 } | 2335 } |
2312 } | 2336 } |
2313 | 2337 |
2314 #ifdef DEBUG | 2338 #ifdef DEBUG |
2315 DCHECK(state_ == PREPARE_GC); | 2339 DCHECK(state_ == PREPARE_GC); |
2316 state_ = MARK_LIVE_OBJECTS; | 2340 state_ = MARK_LIVE_OBJECTS; |
2317 #endif | 2341 #endif |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2380 } | 2404 } |
2381 } | 2405 } |
2382 } | 2406 } |
2383 | 2407 |
2384 if (FLAG_print_cumulative_gc_stat) { | 2408 if (FLAG_print_cumulative_gc_stat) { |
2385 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2409 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
2386 start_time); | 2410 start_time); |
2387 } | 2411 } |
2388 if (FLAG_track_gc_object_stats) { | 2412 if (FLAG_track_gc_object_stats) { |
2389 if (FLAG_trace_gc_object_stats) { | 2413 if (FLAG_trace_gc_object_stats) { |
2390 heap()->object_stats_->TraceObjectStats(); | 2414 // Reuse the live stats that are already recorded with |
2415 // --track_gc_object_stats. | |
2416 ObjectStats dead_stats(heap()); | |
2417 ObjectStatsVisitor visitor(heap()->object_stats_, &dead_stats); | |
2418 VisitAllObjects(&visitor); | |
2419 heap()->object_stats_->PrintJSON("live"); | |
2420 dead_stats.PrintJSON("dead"); | |
2421 } else { | |
2422 ObjectStatsVisitor visitor(heap()->object_stats_, nullptr); | |
2423 VisitAllObjects(&visitor); | |
2391 } | 2424 } |
2392 heap()->object_stats_->CheckpointObjectStats(); | 2425 heap()->object_stats_->CheckpointObjectStats(); |
2393 } | 2426 } |
2394 } | 2427 } |
2395 | 2428 |
2396 | 2429 |
2397 void MarkCompactCollector::ClearNonLiveReferences() { | 2430 void MarkCompactCollector::ClearNonLiveReferences() { |
2398 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | 2431 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
2399 | 2432 |
2400 { | 2433 { |
(...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4086 // The target is always in old space, we don't have to record the slot in | 4119 // The target is always in old space, we don't have to record the slot in |
4087 // the old-to-new remembered set. | 4120 // the old-to-new remembered set. |
4088 DCHECK(!heap()->InNewSpace(target)); | 4121 DCHECK(!heap()->InNewSpace(target)); |
4089 RecordRelocSlot(host, &rinfo, target); | 4122 RecordRelocSlot(host, &rinfo, target); |
4090 } | 4123 } |
4091 } | 4124 } |
4092 } | 4125 } |
4093 | 4126 |
4094 } // namespace internal | 4127 } // namespace internal |
4095 } // namespace v8 | 4128 } // namespace v8 |
OLD | NEW |