Chromium Code Reviews| Index: Source/platform/heap/Heap.cpp | 
| diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp | 
| index 430e1121cd22fee3d4651aea19f3667277737c7f..7cb6d50bef15522dade2d2563aaf52e62ae13857 100644 | 
| --- a/Source/platform/heap/Heap.cpp | 
| +++ b/Source/platform/heap/Heap.cpp | 
| @@ -109,11 +109,30 @@ static String classOf(const void* object) | 
| } | 
| #endif | 
| +class GCForbiddenScope { | 
| +public: | 
| + explicit GCForbiddenScope(ThreadState* state) | 
| + : m_state(state) | 
| + { | 
| + // Prevent nested collectGarbage() invocations. | 
| + m_state->enterGCForbiddenScope(); | 
| + } | 
| + | 
| + ~GCForbiddenScope() | 
| + { | 
| + m_state->leaveGCForbiddenScope(); | 
| + } | 
| + | 
| +private: | 
| + ThreadState* m_state; | 
| +}; | 
| + | 
| class GCScope { | 
| public: | 
| - explicit GCScope(ThreadState::StackState stackState) | 
| - : m_state(ThreadState::current()) | 
| - , m_safePointScope(stackState) | 
| + GCScope(ThreadState* state, ThreadState::StackState stackState) | 
| + : m_state(state) | 
| + , m_gcForbiddenScope(state) | 
| + , m_safePointScope(stackState, state) | 
| , m_parkedAllThreads(false) | 
| { | 
| TRACE_EVENT0("blink_gc", "Heap::GCScope"); | 
| @@ -126,9 +145,9 @@ public: | 
| // FIXME: in an unlikely coincidence that two threads decide | 
| // to collect garbage at the same time, avoid doing two GCs in | 
| // a row. | 
| - if (LIKELY(ThreadState::stopThreads())) { | 
| + if (LIKELY(ThreadState::stopThreads())) | 
| m_parkedAllThreads = true; | 
| - } | 
| + | 
| if (m_state->isMainThread()) | 
| TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); | 
| } | 
| @@ -139,13 +158,13 @@ public: | 
| { | 
| // Only cleanup if we parked all threads in which case the GC happened | 
| // and we need to resume the other threads. | 
| - if (LIKELY(m_parkedAllThreads)) { | 
| + if (LIKELY(m_parkedAllThreads)) | 
| ThreadState::resumeThreads(); | 
| - } | 
| } | 
| private: | 
| ThreadState* m_state; | 
| + GCForbiddenScope m_gcForbiddenScope; | 
| SafePointScope m_safePointScope; | 
| 
 
haraken
2015/05/28 15:00:56
Add a comment and mention that the order between G
 
sof
2015/05/28 15:08:50
Will add a comment re: ordering.
 
sof
2015/05/29 18:52:18
Done.
 
 | 
| bool m_parkedAllThreads; // False if we fail to park all threads | 
| }; | 
| @@ -1872,20 +1891,14 @@ const char* Heap::gcReasonString(GCReason reason) | 
| void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCType gcType, GCReason reason) | 
| { | 
| ThreadState* state = ThreadState::current(); | 
| - RELEASE_ASSERT(!state->isInGC()); | 
| + RELEASE_ASSERT(!state->isGCForbidden()); | 
| 
 
haraken
2015/05/28 15:00:55
I'd move this check to GCForbiddenScope's construc
 
sof
2015/05/28 15:27:57
I don't understand the motivation behind the sugge
 
haraken
2015/05/28 15:28:46
ah, that makes sense!
 
sof
2015/05/29 18:52:18
Added a comment next to it.
 
 | 
| state->completeSweep(); | 
| - ThreadState::GCState originalGCState = state->gcState(); | 
| - state->setGCState(ThreadState::StoppingOtherThreads); | 
| - GCScope gcScope(stackState); | 
| + GCScope gcScope(state, stackState); | 
| // Check if we successfully parked the other threads. If not we bail out of | 
| // the GC. | 
| - if (!gcScope.allThreadsParked()) { | 
| - // Restore the original GCState. | 
| - if (LIKELY(state->gcState() == ThreadState::StoppingOtherThreads)) | 
| - state->setGCState(originalGCState); | 
| + if (!gcScope.allThreadsParked()) | 
| return; | 
| - } | 
| if (state->isMainThread()) | 
| ScriptForbiddenScope::enter(); |