]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/GCThreadSharedData.cpp
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / heap / GCThreadSharedData.cpp
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
37 namespace JSC {
38
39 #if ENABLE(PARALLEL_GC)
40 void GCThreadSharedData::resetChildren()
41 {
42 for (size_t i = 0; i < m_gcThreads.size(); ++i)
43 m_gcThreads[i]->slotVisitor()->reset();
44 }
45
46 size_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
55 GCThreadSharedData::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
87 GCThreadSharedData::~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
107 void 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
124 void 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
134 void 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
145 void GCThreadSharedData::didStartMarking()
146 {
147 MutexLocker markingLocker(m_markingLock);
148 m_parallelMarkersShouldExit = false;
149 startNextPhase(Mark);
150 }
151
152 void 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
164 void 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
182 void GCThreadSharedData::didFinishCopying()
183 {
184 ASSERT(m_currentPhase == Copy);
185 endCurrentPhase();
186 }
187
188 } // namespace JSC