Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 ThreadState* m_state; | 70 ThreadState* m_state; |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 class GCScope final { | 73 class GCScope final { |
| 74 public: | 74 public: |
| 75 GCScope(ThreadState* state, BlinkGC::StackState stackState, BlinkGC::GCType gcType) | 75 GCScope(ThreadState* state, BlinkGC::StackState stackState, BlinkGC::GCType gcType) |
| 76 : m_state(state) | 76 : m_state(state) |
| 77 , m_gcForbiddenScope(state) | 77 , m_gcForbiddenScope(state) |
| 78 // See collectGarbageForTerminatingThread() comment on why a | 78 // See collectGarbageForTerminatingThread() comment on why a |
| 79 // safepoint scope isn't entered for its GCScope. | 79 // safepoint scope isn't entered for its GCScope. |
| 80 , m_safePointScope(stackState, gcType != BlinkGC::ThreadTerminationGC ? state : nullptr) | 80 , m_safePointScope(stackState, gcType != BlinkGC::ThreadTerminationGC ? state : nullptr, true) |
|
haraken
2015/11/09 06:20:11
It seems that it's no longer worth using a SafePoi
sof
2015/11/09 06:33:56
That's better, delineating the two scope objects.
| |
| 81 , m_gcType(gcType) | |
| 82 , m_parkedAllThreads(false) | |
| 83 { | 81 { |
| 84 TRACE_EVENT0("blink_gc", "Heap::GCScope"); | |
| 85 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | |
| 86 if (m_state->isMainThread()) | |
| 87 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); | |
| 88 | |
| 89 ASSERT(m_state->checkThread()); | 82 ASSERT(m_state->checkThread()); |
| 90 | 83 |
| 91 double startTime = WTF::currentTimeMS(); | |
| 92 // TODO(haraken): In an unlikely coincidence that two threads decide | |
| 93 // to collect garbage at the same time, avoid doing two GCs in | |
| 94 // a row. | |
| 95 if (LIKELY(gcType != BlinkGC::ThreadTerminationGC && ThreadState::stopTh reads())) | |
| 96 m_parkedAllThreads = true; | |
| 97 double timeForStoppingThreads = WTF::currentTimeMS() - startTime; | |
| 98 Platform::current()->histogramCustomCounts("BlinkGC.TimeForStoppingThrea ds", timeForStoppingThreads, 1, 1000, 50); | |
| 99 | |
| 100 switch (gcType) { | 84 switch (gcType) { |
| 101 case BlinkGC::GCWithSweep: | 85 case BlinkGC::GCWithSweep: |
| 102 case BlinkGC::GCWithoutSweep: | 86 case BlinkGC::GCWithoutSweep: |
| 103 m_visitor = adoptPtr(new MarkingVisitor<Visitor::GlobalMarking>()); | 87 m_visitor = adoptPtr(new MarkingVisitor<Visitor::GlobalMarking>()); |
| 104 break; | 88 break; |
| 105 case BlinkGC::TakeSnapshot: | 89 case BlinkGC::TakeSnapshot: |
| 106 m_visitor = adoptPtr(new MarkingVisitor<Visitor::SnapshotMarking>()) ; | 90 m_visitor = adoptPtr(new MarkingVisitor<Visitor::SnapshotMarking>()) ; |
| 107 break; | 91 break; |
| 108 case BlinkGC::ThreadTerminationGC: | 92 case BlinkGC::ThreadTerminationGC: |
| 109 m_visitor = adoptPtr(new MarkingVisitor<Visitor::ThreadLocalMarking> ()); | 93 m_visitor = adoptPtr(new MarkingVisitor<Visitor::ThreadLocalMarking> ()); |
| 110 break; | 94 break; |
| 111 default: | 95 default: |
| 112 ASSERT_NOT_REACHED(); | 96 ASSERT_NOT_REACHED(); |
| 113 } | 97 } |
| 98 } | |
| 99 | |
| 100 bool parkAllThreads(BlinkGC::StackState stackState, BlinkGC::GCType gcType) | |
| 101 { | |
| 102 TRACE_EVENT0("blink_gc", "Heap::GCScope"); | |
| 103 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | |
| 104 if (m_state->isMainThread()) | |
| 105 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); | |
| 106 | |
| 107 m_safePointScope.enter(stackState); | |
| 108 | |
| 109 // TODO(haraken): In an unlikely coincidence that two threads decide | |
| 110 // to collect garbage at the same time, avoid doing two GCs in | |
| 111 // a row and return false. | |
| 112 double startTime = WTF::currentTimeMS(); | |
| 113 bool allParked = gcType != BlinkGC::ThreadTerminationGC && ThreadState:: stopThreads(); | |
| 114 double timeForStoppingThreads = WTF::currentTimeMS() - startTime; | |
| 115 Platform::current()->histogramCustomCounts("BlinkGC.TimeForStoppingThrea ds", timeForStoppingThreads, 1, 1000, 50); | |
| 114 | 116 |
| 115 if (m_state->isMainThread()) | 117 if (m_state->isMainThread()) |
| 116 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); | 118 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); |
| 119 | |
| 120 return allParked; | |
| 117 } | 121 } |
| 118 | 122 |
| 119 bool allThreadsParked() const { return m_parkedAllThreads; } | |
| 120 Visitor* visitor() const { return m_visitor.get(); } | 123 Visitor* visitor() const { return m_visitor.get(); } |
| 121 | 124 |
| 122 ~GCScope() | 125 ~GCScope() |
| 123 { | 126 { |
| 124 // Only cleanup if we parked all threads in which case the GC happened | |
| 125 // and we need to resume the other threads. | |
| 126 if (LIKELY(m_gcType != BlinkGC::ThreadTerminationGC && m_parkedAllThread s)) | |
| 127 ThreadState::resumeThreads(); | |
| 128 } | 127 } |
| 129 | 128 |
| 130 private: | 129 private: |
| 131 ThreadState* m_state; | 130 ThreadState* m_state; |
| 132 // The ordering of the two scope objects matters: GCs must first be forbidde n | 131 // The ordering of the two scope objects matters: GCs must first be forbidde n |
| 133 // before entering the safe point scope. Prior to reaching the safe point, | 132 // before entering the safe point scope. Prior to reaching the safe point, |
| 134 // ThreadState::runScheduledGC() is called. See its comment why we need | 133 // ThreadState::runScheduledGC() is called. See its comment why we need |
| 135 // to be in a GC forbidden scope when doing so. | 134 // to be in a GC forbidden scope when doing so. |
| 136 GCForbiddenScope m_gcForbiddenScope; | 135 GCForbiddenScope m_gcForbiddenScope; |
| 137 SafePointScope m_safePointScope; | 136 SafePointScope m_safePointScope; |
| 138 BlinkGC::GCType m_gcType; | |
| 139 OwnPtr<Visitor> m_visitor; | 137 OwnPtr<Visitor> m_visitor; |
| 140 bool m_parkedAllThreads; // False if we fail to park all threads | 138 }; |
| 139 | |
| 140 class ResumeThreadScope { | |
| 141 public: | |
| 142 explicit ResumeThreadScope(BlinkGC::GCType gcType) | |
| 143 : m_resumeThreads(gcType != BlinkGC::ThreadTerminationGC) | |
| 144 { | |
| 145 } | |
| 146 ~ResumeThreadScope() | |
| 147 { | |
| 148 // Only cleanup if we parked all threads in which case the GC happened | |
| 149 // and we need to resume the other threads. | |
| 150 if (m_resumeThreads) | |
| 151 ThreadState::resumeThreads(); | |
| 152 } | |
| 153 private: | |
| 154 bool m_resumeThreads; | |
| 141 }; | 155 }; |
| 142 | 156 |
| 143 void Heap::flushHeapDoesNotContainCache() | 157 void Heap::flushHeapDoesNotContainCache() |
| 144 { | 158 { |
| 145 s_heapDoesNotContainCache->flush(); | 159 s_heapDoesNotContainCache->flush(); |
| 146 } | 160 } |
| 147 | 161 |
| 148 void Heap::init() | 162 void Heap::init() |
| 149 { | 163 { |
| 150 ThreadState::init(); | 164 ThreadState::init(); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 } | 388 } |
| 375 | 389 |
| 376 void Heap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType gcType , BlinkGC::GCReason reason) | 390 void Heap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType gcType , BlinkGC::GCReason reason) |
| 377 { | 391 { |
| 378 ThreadState* state = ThreadState::current(); | 392 ThreadState* state = ThreadState::current(); |
| 379 // Nested collectGarbage() invocations aren't supported. | 393 // Nested collectGarbage() invocations aren't supported. |
| 380 RELEASE_ASSERT(!state->isGCForbidden()); | 394 RELEASE_ASSERT(!state->isGCForbidden()); |
| 381 state->completeSweep(); | 395 state->completeSweep(); |
| 382 | 396 |
| 383 GCScope gcScope(state, stackState, gcType); | 397 GCScope gcScope(state, stackState, gcType); |
| 384 // Check if we successfully parked the other threads. If not we bail out of | 398 |
| 385 // the GC. | 399 // Try to park the other threads. If we're unable to, bail out of the GC. |
| 386 if (!gcScope.allThreadsParked()) | 400 if (!gcScope.parkAllThreads(stackState, gcType)) |
| 387 return; | 401 return; |
| 388 | 402 |
| 403 // Resume all parked threads upon leaving this scope. | |
| 404 ResumeThreadScope resumeThreads(gcType); | |
| 405 | |
| 389 if (state->isMainThread()) | 406 if (state->isMainThread()) |
| 390 ScriptForbiddenScope::enter(); | 407 ScriptForbiddenScope::enter(); |
| 391 | 408 |
| 392 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", | 409 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", |
| 393 "lazySweeping", gcType == BlinkGC::GCWithoutSweep, | 410 "lazySweeping", gcType == BlinkGC::GCWithoutSweep, |
| 394 "gcReason", gcReasonString(reason)); | 411 "gcReason", gcReasonString(reason)); |
| 395 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | 412 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); |
| 396 double startTime = WTF::currentTimeMS(); | 413 double startTime = WTF::currentTimeMS(); |
| 397 | 414 |
| 398 if (gcType == BlinkGC::TakeSnapshot) | 415 if (gcType == BlinkGC::TakeSnapshot) |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 size_t Heap::s_wrapperCount = 0; | 775 size_t Heap::s_wrapperCount = 0; |
| 759 size_t Heap::s_wrapperCountAtLastGC = 0; | 776 size_t Heap::s_wrapperCountAtLastGC = 0; |
| 760 size_t Heap::s_collectedWrapperCount = 0; | 777 size_t Heap::s_collectedWrapperCount = 0; |
| 761 size_t Heap::s_partitionAllocSizeAtLastGC = 0; | 778 size_t Heap::s_partitionAllocSizeAtLastGC = 0; |
| 762 double Heap::s_estimatedMarkingTimePerByte = 0.0; | 779 double Heap::s_estimatedMarkingTimePerByte = 0.0; |
| 763 #if ENABLE(ASSERT) | 780 #if ENABLE(ASSERT) |
| 764 uint16_t Heap::s_gcGeneration = 0; | 781 uint16_t Heap::s_gcGeneration = 0; |
| 765 #endif | 782 #endif |
| 766 | 783 |
| 767 } // namespace blink | 784 } // namespace blink |
| OLD | NEW |