]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/GCThreadSharedData.cpp
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / heap / GCThreadSharedData.cpp
CommitLineData
93a37866
A
1/*
2 * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "GCThreadSharedData.h"
28
29#include "CopyVisitor.h"
30#include "CopyVisitorInlines.h"
31#include "GCThread.h"
32#include "VM.h"
33#include "MarkStack.h"
34#include "SlotVisitor.h"
35#include "SlotVisitorInlines.h"
36
37namespace JSC {
38
39#if ENABLE(PARALLEL_GC)
40void GCThreadSharedData::resetChildren()
41{
42 for (size_t i = 0; i < m_gcThreads.size(); ++i)
43 m_gcThreads[i]->slotVisitor()->reset();
44}
45
46size_t GCThreadSharedData::childVisitCount()
47{
48 unsigned long result = 0;
49 for (unsigned i = 0; i < m_gcThreads.size(); ++i)
50 result += m_gcThreads[i]->slotVisitor()->visitCount();
51 return result;
52}
53#endif
54
55GCThreadSharedData::GCThreadSharedData(VM* vm)
56 : m_vm(vm)
57 , m_copiedSpace(&vm->heap.m_storageSpace)
58 , m_shouldHashCons(false)
59 , m_sharedMarkStack(vm->heap.blockAllocator())
60 , m_numberOfActiveParallelMarkers(0)
61 , m_parallelMarkersShouldExit(false)
62 , m_copyIndex(0)
63 , m_numberOfActiveGCThreads(0)
64 , m_gcThreadsShouldWait(false)
65 , m_currentPhase(NoPhase)
66{
67 m_copyLock.Init();
68#if ENABLE(PARALLEL_GC)
69 // Grab the lock so the new GC threads can be properly initialized before they start running.
70 MutexLocker locker(m_phaseLock);
71 for (unsigned i = 1; i < Options::numberOfGCMarkers(); ++i) {
72 m_numberOfActiveGCThreads++;
73 SlotVisitor* slotVisitor = new SlotVisitor(*this);
74 CopyVisitor* copyVisitor = new CopyVisitor(*this);
75 GCThread* newThread = new GCThread(*this, slotVisitor, copyVisitor);
76 ThreadIdentifier threadID = createThread(GCThread::gcThreadStartFunc, newThread, "JavaScriptCore::Marking");
77 newThread->initializeThreadID(threadID);
78 m_gcThreads.append(newThread);
79 }
80
81 // Wait for all the GCThreads to get to the right place.
82 while (m_numberOfActiveGCThreads)
83 m_activityCondition.wait(m_phaseLock);
84#endif
85}
86
87GCThreadSharedData::~GCThreadSharedData()
88{
89#if ENABLE(PARALLEL_GC)
90 // Destroy our marking threads.
91 {
92 MutexLocker markingLocker(m_markingLock);
93 MutexLocker phaseLocker(m_phaseLock);
94 ASSERT(m_currentPhase == NoPhase);
95 m_parallelMarkersShouldExit = true;
96 m_gcThreadsShouldWait = false;
97 m_currentPhase = Exit;
98 m_phaseCondition.broadcast();
99 }
100 for (unsigned i = 0; i < m_gcThreads.size(); ++i) {
101 waitForThreadCompletion(m_gcThreads[i]->threadID());
102 delete m_gcThreads[i];
103 }
104#endif
105}
106
107void GCThreadSharedData::reset()
108{
109 ASSERT(m_sharedMarkStack.isEmpty());
110
111#if ENABLE(PARALLEL_GC)
112 m_opaqueRoots.clear();
113#else
114 ASSERT(m_opaqueRoots.isEmpty());
115#endif
116 m_weakReferenceHarvesters.removeAll();
117
118 if (m_shouldHashCons) {
119 m_vm->resetNewStringsSinceLastHashCons();
120 m_shouldHashCons = false;
121 }
122}
123
124void GCThreadSharedData::startNextPhase(GCPhase phase)
125{
126 MutexLocker phaseLocker(m_phaseLock);
127 ASSERT(!m_gcThreadsShouldWait);
128 ASSERT(m_currentPhase == NoPhase);
129 m_gcThreadsShouldWait = true;
130 m_currentPhase = phase;
131 m_phaseCondition.broadcast();
132}
133
134void GCThreadSharedData::endCurrentPhase()
135{
136 ASSERT(m_gcThreadsShouldWait);
137 MutexLocker locker(m_phaseLock);
138 m_currentPhase = NoPhase;
139 m_gcThreadsShouldWait = false;
140 m_phaseCondition.broadcast();
141 while (m_numberOfActiveGCThreads)
142 m_activityCondition.wait(m_phaseLock);
143}
144
145void GCThreadSharedData::didStartMarking()
146{
147 MutexLocker markingLocker(m_markingLock);
148 m_parallelMarkersShouldExit = false;
149 startNextPhase(Mark);
150}
151
152void GCThreadSharedData::didFinishMarking()
153{
154 {
155 MutexLocker markingLocker(m_markingLock);
156 m_parallelMarkersShouldExit = true;
157 m_markingCondition.broadcast();
158 }
159
160 ASSERT(m_currentPhase == Mark);
161 endCurrentPhase();
162}
163
164void GCThreadSharedData::didStartCopying()
165{
166 {
167 SpinLockHolder locker(&m_copyLock);
168 WTF::copyToVector(m_copiedSpace->m_blockSet, m_blocksToCopy);
169 m_copyIndex = 0;
170 }
171
172 // We do this here so that we avoid a race condition where the main thread can
173 // blow through all of the copying work before the GCThreads fully wake up.
174 // The GCThreads then request a block from the CopiedSpace when the copying phase
175 // has completed, which isn't allowed.
176 for (size_t i = 0; i < m_gcThreads.size(); i++)
177 m_gcThreads[i]->copyVisitor()->startCopying();
178
179 startNextPhase(Copy);
180}
181
182void GCThreadSharedData::didFinishCopying()
183{
184 ASSERT(m_currentPhase == Copy);
185 endCurrentPhase();
186}
187
188} // namespace JSC