2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
29 #include "CopyVisitor.h"
30 #include "CopyVisitorInlines.h"
31 #include "GCThreadSharedData.h"
32 #include "JSCInlines.h"
33 #include "SlotVisitor.h"
34 #include <wtf/MainThread.h>
35 #include <wtf/PassOwnPtr.h>
39 GCThread::GCThread(GCThreadSharedData
& shared
, SlotVisitor
* slotVisitor
, CopyVisitor
* copyVisitor
)
42 , m_slotVisitor(WTF::adoptPtr(slotVisitor
))
43 , m_copyVisitor(WTF::adoptPtr(copyVisitor
))
47 ThreadIdentifier
GCThread::threadID()
53 void GCThread::initializeThreadID(ThreadIdentifier threadID
)
56 m_threadID
= threadID
;
59 SlotVisitor
* GCThread::slotVisitor()
61 ASSERT(m_slotVisitor
);
62 return m_slotVisitor
.get();
65 CopyVisitor
* GCThread::copyVisitor()
67 ASSERT(m_copyVisitor
);
68 return m_copyVisitor
.get();
71 GCPhase
GCThread::waitForNextPhase()
73 std::unique_lock
<std::mutex
> lock(m_shared
.m_phaseMutex
);
74 m_shared
.m_phaseConditionVariable
.wait(lock
, [this] { return !m_shared
.m_gcThreadsShouldWait
; });
76 m_shared
.m_numberOfActiveGCThreads
--;
77 if (!m_shared
.m_numberOfActiveGCThreads
)
78 m_shared
.m_activityConditionVariable
.notify_one();
80 m_shared
.m_phaseConditionVariable
.wait(lock
, [this] { return m_shared
.m_currentPhase
!= NoPhase
; });
81 m_shared
.m_numberOfActiveGCThreads
++;
82 return m_shared
.m_currentPhase
;
85 void GCThread::gcThreadMain()
88 #if ENABLE(PARALLEL_GC)
89 WTF::registerGCThread();
91 // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
92 // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
94 std::lock_guard
<std::mutex
> lock(m_shared
.m_phaseMutex
);
97 ParallelModeEnabler
enabler(*m_slotVisitor
);
98 while ((currentPhase
= waitForNextPhase()) != Exit
) {
99 // Note: Each phase is responsible for its own termination conditions. The comments below describe
100 // how each phase reaches termination.
101 switch (currentPhase
) {
103 m_slotVisitor
->drainFromShared(SlotVisitor::SlaveDrain
);
104 // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit
105 // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes
106 // that all of the various subphases in Heap::markRoots() have been fully finished and there is
107 // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
110 // We don't have to call startCopying() because it's called for us on the main thread to avoid a
112 m_copyVisitor
->copyFromShared();
113 // We know we're done copying when we return from copyFromShared() because we would
114 // only do so if there were no more chunks of copying work left to do. When there is no
115 // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until
116 // all of the blocks that the GCThreads borrowed have been returned. doneCopying()
117 // returns our borrowed CopiedBlock, allowing the copying phase to finish.
118 m_copyVisitor
->doneCopying();
121 RELEASE_ASSERT_NOT_REACHED();
124 RELEASE_ASSERT_NOT_REACHED();
131 void GCThread::gcThreadStartFunc(void* data
)
133 GCThread
* thread
= static_cast<GCThread
*>(data
);
134 thread
->gcThreadMain();