2 * Copyright (C) 2012, 2015 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>
38 GCThread::GCThread(GCThreadSharedData
& shared
, std::unique_ptr
<SlotVisitor
> slotVisitor
, std::unique_ptr
<CopyVisitor
> copyVisitor
)
41 , m_slotVisitor(WTF::move(slotVisitor
))
42 , m_copyVisitor(WTF::move(copyVisitor
))
46 ThreadIdentifier
GCThread::threadID()
52 void GCThread::initializeThreadID(ThreadIdentifier threadID
)
55 m_threadID
= threadID
;
58 SlotVisitor
* GCThread::slotVisitor()
60 ASSERT(m_slotVisitor
);
61 return m_slotVisitor
.get();
64 CopyVisitor
* GCThread::copyVisitor()
66 ASSERT(m_copyVisitor
);
67 return m_copyVisitor
.get();
70 GCPhase
GCThread::waitForNextPhase()
72 std::unique_lock
<std::mutex
> lock(m_shared
.m_phaseMutex
);
73 m_shared
.m_phaseConditionVariable
.wait(lock
, [this] { return !m_shared
.m_gcThreadsShouldWait
; });
75 m_shared
.m_numberOfActiveGCThreads
--;
76 if (!m_shared
.m_numberOfActiveGCThreads
)
77 m_shared
.m_activityConditionVariable
.notify_one();
79 m_shared
.m_phaseConditionVariable
.wait(lock
, [this] { return m_shared
.m_currentPhase
!= NoPhase
; });
80 m_shared
.m_numberOfActiveGCThreads
++;
81 return m_shared
.m_currentPhase
;
84 void GCThread::gcThreadMain()
87 #if ENABLE(PARALLEL_GC)
88 WTF::registerGCThread();
90 // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
91 // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
93 std::lock_guard
<std::mutex
> lock(m_shared
.m_phaseMutex
);
96 ParallelModeEnabler
enabler(*m_slotVisitor
);
97 while ((currentPhase
= waitForNextPhase()) != Exit
) {
98 // Note: Each phase is responsible for its own termination conditions. The comments below describe
99 // how each phase reaches termination.
100 switch (currentPhase
) {
102 m_slotVisitor
->drainFromShared(SlotVisitor::SlaveDrain
);
103 // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit
104 // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes
105 // that all of the various subphases in Heap::markRoots() have been fully finished and there is
106 // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
109 // We don't have to call startCopying() because it's called for us on the main thread to avoid a
111 m_copyVisitor
->copyFromShared();
112 // We know we're done copying when we return from copyFromShared() because we would
113 // only do so if there were no more chunks of copying work left to do. When there is no
114 // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until
115 // all of the blocks that the GCThreads borrowed have been returned. doneCopying()
116 // returns our borrowed CopiedBlock, allowing the copying phase to finish.
117 m_copyVisitor
->doneCopying();
119 WTF::releaseFastMallocFreeMemoryForThisThread();
123 RELEASE_ASSERT_NOT_REACHED();
126 RELEASE_ASSERT_NOT_REACHED();
133 void GCThread::gcThreadStartFunc(void* data
)
135 GCThread
* thread
= static_cast<GCThread
*>(data
);
136 thread
->gcThreadMain();