summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap/GCThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/heap/GCThread.cpp')
-rw-r--r--Source/JavaScriptCore/heap/GCThread.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/GCThread.cpp b/Source/JavaScriptCore/heap/GCThread.cpp
new file mode 100644
index 000000000..ea43456bd
--- /dev/null
+++ b/Source/JavaScriptCore/heap/GCThread.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GCThread.h"
+
+#include "CopyVisitor.h"
+#include "CopyVisitorInlineMethods.h"
+#include "GCThreadSharedData.h"
+#include "SlotVisitor.h"
+#include <wtf/MainThread.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace JSC {
+
+GCThread::GCThread(GCThreadSharedData& shared, SlotVisitor* slotVisitor, CopyVisitor* copyVisitor)
+ : m_threadID(0)
+ , m_shared(shared)
+ , m_slotVisitor(WTF::adoptPtr(slotVisitor))
+ , m_copyVisitor(WTF::adoptPtr(copyVisitor))
+{
+}
+
+ThreadIdentifier GCThread::threadID()
+{
+ ASSERT(m_threadID);
+ return m_threadID;
+}
+
+void GCThread::initializeThreadID(ThreadIdentifier threadID)
+{
+ ASSERT(!m_threadID);
+ m_threadID = threadID;
+}
+
+SlotVisitor* GCThread::slotVisitor()
+{
+ ASSERT(m_slotVisitor);
+ return m_slotVisitor.get();
+}
+
+CopyVisitor* GCThread::copyVisitor()
+{
+ ASSERT(m_copyVisitor);
+ return m_copyVisitor.get();
+}
+
+GCPhase GCThread::waitForNextPhase()
+{
+ MutexLocker locker(m_shared.m_phaseLock);
+ while (m_shared.m_currentPhase == NoPhase)
+ m_shared.m_phaseCondition.wait(m_shared.m_phaseLock);
+ return m_shared.m_currentPhase;
+}
+
+void GCThread::gcThreadMain()
+{
+ GCPhase currentPhase;
+#if ENABLE(PARALLEL_GC)
+ WTF::registerGCThread();
+#endif
+ // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
+ // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
+ {
+ MutexLocker locker(m_shared.m_markingLock);
+ }
+ {
+ ParallelModeEnabler enabler(*m_slotVisitor);
+ while ((currentPhase = waitForNextPhase()) != Exit) {
+ // Note: Each phase is responsible for its own termination conditions. The comments below describe
+ // how each phase reaches termination.
+ switch (currentPhase) {
+ case Mark:
+ m_slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
+ // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit
+ // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes
+ // that all of the various subphases in Heap::markRoots() have been fully finished and there is
+ // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
+ break;
+ case Copy:
+ // We don't have to call startCopying() because it's called for us on the main thread to avoid a
+ // race condition.
+ m_copyVisitor->copyFromShared();
+ // We know we're done copying when we return from copyFromShared() because we would
+ // only do so if there were no more chunks of copying work left to do. When there is no
+ // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until
+ // all of the blocks that the GCThreads borrowed have been returned. doneCopying()
+ // returns our borrowed CopiedBlock, allowing the copying phase to finish.
+ m_copyVisitor->doneCopying();
+ break;
+ case NoPhase:
+ ASSERT_NOT_REACHED();
+ break;
+ case Exit:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+ }
+}
+
+void GCThread::gcThreadStartFunc(void* data)
+{
+ GCThread* thread = static_cast<GCThread*>(data);
+ thread->gcThreadMain();
+}
+
+} // namespace JSC