Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Unified Diff: third_party/WebKit/Source/platform/heap/Heap.cpp

Issue 1411643006: Avoid data races on initializing GCScope. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: move SafePointScope out of GCScope Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/heap/Heap.cpp
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index 66850722296c66cd4bc2678d7f00a2c2ef34acc2..fd2b765e5fb3dccf9ab3f7b998422668810d292d 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -75,28 +75,9 @@ public:
GCScope(ThreadState* state, BlinkGC::StackState stackState, BlinkGC::GCType gcType)
: m_state(state)
, m_gcForbiddenScope(state)
- // See collectGarbageForTerminatingThread() comment on why a
- // safepoint scope isn't entered for its GCScope.
- , m_safePointScope(stackState, gcType != BlinkGC::ThreadTerminationGC ? state : nullptr)
- , m_gcType(gcType)
- , m_parkedAllThreads(false)
{
- TRACE_EVENT0("blink_gc", "Heap::GCScope");
- const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
- if (m_state->isMainThread())
- TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting");
-
ASSERT(m_state->checkThread());
- double startTime = WTF::currentTimeMS();
- // TODO(haraken): In an unlikely coincidence that two threads decide
- // to collect garbage at the same time, avoid doing two GCs in
- // a row.
- if (LIKELY(gcType != BlinkGC::ThreadTerminationGC && ThreadState::stopThreads()))
- m_parkedAllThreads = true;
- double timeForStoppingThreads = WTF::currentTimeMS() - startTime;
- Platform::current()->histogramCustomCounts("BlinkGC.TimeForStoppingThreads", timeForStoppingThreads, 1, 1000, 50);
-
switch (gcType) {
case BlinkGC::GCWithSweep:
case BlinkGC::GCWithoutSweep:
@@ -111,33 +92,58 @@ public:
default:
ASSERT_NOT_REACHED();
}
+ }
+
+ ~GCScope()
+ {
+ }
+
+ bool parkAllThreads(BlinkGC::StackState stackState, BlinkGC::GCType gcType)
+ {
+ TRACE_EVENT0("blink_gc", "Heap::GCScope");
+ const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
+ if (m_state->isMainThread())
+ TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting");
+
+ // TODO(haraken): In an unlikely coincidence that two threads decide
+ // to collect garbage at the same time, avoid doing two GCs in
+ // a row and return false.
+ double startTime = WTF::currentTimeMS();
+ bool allParked = gcType != BlinkGC::ThreadTerminationGC && ThreadState::stopThreads();
+ double timeForStoppingThreads = WTF::currentTimeMS() - startTime;
+ Platform::current()->histogramCustomCounts("BlinkGC.TimeForStoppingThreads", timeForStoppingThreads, 1, 1000, 50);
if (m_state->isMainThread())
TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState);
+
+ return allParked;
}
- bool allThreadsParked() const { return m_parkedAllThreads; }
Visitor* visitor() const { return m_visitor.get(); }
- ~GCScope()
+private:
+ ThreadState* m_state;
+ // See ThreadState::runScheduledGC() why we need to already be in a
+ // GCForbiddenScope before any safe point is entered.
+ GCForbiddenScope m_gcForbiddenScope;
+ OwnPtr<Visitor> m_visitor;
+};
+
+class ResumeThreadScope {
+public:
+ explicit ResumeThreadScope(BlinkGC::GCType gcType)
+ : m_resumeThreads(gcType != BlinkGC::ThreadTerminationGC)
+ {
+ }
+ ~ResumeThreadScope()
{
// Only cleanup if we parked all threads in which case the GC happened
// and we need to resume the other threads.
- if (LIKELY(m_gcType != BlinkGC::ThreadTerminationGC && m_parkedAllThreads))
+ if (m_resumeThreads)
ThreadState::resumeThreads();
}
-
private:
- ThreadState* m_state;
- // The ordering of the two scope objects matters: GCs must first be forbidden
- // before entering the safe point scope. Prior to reaching the safe point,
- // ThreadState::runScheduledGC() is called. See its comment why we need
- // to be in a GC forbidden scope when doing so.
- GCForbiddenScope m_gcForbiddenScope;
- SafePointScope m_safePointScope;
- BlinkGC::GCType m_gcType;
- OwnPtr<Visitor> m_visitor;
- bool m_parkedAllThreads; // False if we fail to park all threads
+ bool m_resumeThreads;
};
void Heap::flushHeapDoesNotContainCache()
@@ -381,11 +387,17 @@ void Heap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType gcType
state->completeSweep();
GCScope gcScope(state, stackState, gcType);
- // Check if we successfully parked the other threads. If not we bail out of
- // the GC.
- if (!gcScope.allThreadsParked())
+ // See collectGarbageForTerminatingThread() comment on why a
+ // safepoint scope isn't entered for it.
+ SafePointScope safePointScope(stackState, gcType != BlinkGC::ThreadTerminationGC ? state : nullptr);
+
+ // Try to park the other threads. If we're unable to, bail out of the GC.
+ if (!gcScope.parkAllThreads(stackState, gcType))
return;
+ // Resume all parked threads upon leaving this scope.
+ ResumeThreadScope resumeThreads(gcType);
+
if (state->isMainThread())
ScriptForbiddenScope::enter();
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698