Unreviewed, rolling out r161540.
[WebKit.git] / Source / JavaScriptCore / heap / SlotVisitorInlines.h
1 /*
2  * Copyright (C) 2012, 2013 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. 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.
24  */
25
26 #ifndef SlotVisitorInlines_h
27 #define SlotVisitorInlines_h
28
29 #include "CopiedBlockInlines.h"
30 #include "CopiedSpaceInlines.h"
31 #include "Options.h"
32 #include "SlotVisitor.h"
33 #include "Weak.h"
34 #include "WeakInlines.h"
35
36 namespace JSC {
37
38 ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count)
39 {
40     for (size_t i = 0; i < count; ++i) {
41         JSValue& value = slot[i];
42         internalAppend(&value, value);
43     }
44 }
45
46 template<typename T>
47 inline void SlotVisitor::appendUnbarrieredPointer(T** slot)
48 {
49     ASSERT(slot);
50     JSCell* cell = *slot;
51     internalAppend(slot, cell);
52 }
53
54 ALWAYS_INLINE void SlotVisitor::append(JSValue* slot)
55 {
56     ASSERT(slot);
57     internalAppend(slot, *slot);
58 }
59
60 ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot)
61 {
62     ASSERT(slot);
63     internalAppend(slot, *slot);
64 }
65
66 ALWAYS_INLINE void SlotVisitor::append(JSCell** slot)
67 {
68     ASSERT(slot);
69     internalAppend(slot, *slot);
70 }
71
72 template<typename T>
73 ALWAYS_INLINE void SlotVisitor::appendUnbarrieredWeak(Weak<T>* weak)
74 {
75     ASSERT(weak);
76     if (weak->get())
77         internalAppend(0, weak->get());
78 }
79
80 ALWAYS_INLINE void SlotVisitor::internalAppend(void* from, JSValue value)
81 {
82     if (!value || !value.isCell())
83         return;
84     internalAppend(from, value.asCell());
85 }
86
87 ALWAYS_INLINE void SlotVisitor::internalAppend(void* from, JSCell* cell)
88 {
89     ASSERT(!m_isCheckingForDefaultMarkViolation);
90     if (!cell)
91         return;
92 #if ENABLE(ALLOCATION_LOGGING)
93     dataLogF("JSC GC noticing reference from %p to %p.\n", from, cell);
94 #else
95     UNUSED_PARAM(from);
96 #endif
97 #if ENABLE(GC_VALIDATION)
98     validate(cell);
99 #endif
100     if (Heap::testAndSetMarked(cell) || !cell->structure())
101         return;
102
103     m_bytesVisited += MarkedBlock::blockFor(cell)->cellSize();
104     m_visitCount++;
105         
106     MARK_LOG_CHILD(*this, cell);
107
108     // Should never attempt to mark something that is zapped.
109     ASSERT(!cell->isZapped());
110         
111     m_stack.append(cell);
112 }
113
114 template<typename T> inline void SlotVisitor::append(WriteBarrierBase<T>* slot)
115 {
116     internalAppend(slot, *slot->slot());
117 }
118
119 template<typename Iterator> inline void SlotVisitor::append(Iterator begin, Iterator end)
120 {
121     for (auto it = begin; it != end; ++it)
122         append(&*it);
123 }
124
125 ALWAYS_INLINE void SlotVisitor::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count)
126 {
127     append(barriers->slot(), count);
128 }
129
130 inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
131 {
132     m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester);
133 }
134
135 inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer)
136 {
137     m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
138 }
139
140 inline void SlotVisitor::addOpaqueRoot(void* root)
141 {
142 #if ENABLE(PARALLEL_GC)
143     if (Options::numberOfGCMarkers() == 1) {
144         // Put directly into the shared HashSet.
145         m_shared.m_opaqueRoots.add(root);
146         return;
147     }
148     // Put into the local set, but merge with the shared one every once in
149     // a while to make sure that the local sets don't grow too large.
150     mergeOpaqueRootsIfProfitable();
151     m_opaqueRoots.add(root);
152 #else
153     m_opaqueRoots.add(root);
154 #endif
155 }
156
157 inline bool SlotVisitor::containsOpaqueRoot(void* root)
158 {
159     ASSERT(!m_isInParallelMode);
160 #if ENABLE(PARALLEL_GC)
161     ASSERT(m_opaqueRoots.isEmpty());
162     return m_shared.m_opaqueRoots.contains(root);
163 #else
164     return m_opaqueRoots.contains(root);
165 #endif
166 }
167
168 inline TriState SlotVisitor::containsOpaqueRootTriState(void* root)
169 {
170     if (m_opaqueRoots.contains(root))
171         return TrueTriState;
172     MutexLocker locker(m_shared.m_opaqueRootsLock);
173     if (m_shared.m_opaqueRoots.contains(root))
174         return TrueTriState;
175     return MixedTriState;
176 }
177
178 inline int SlotVisitor::opaqueRootCount()
179 {
180     ASSERT(!m_isInParallelMode);
181 #if ENABLE(PARALLEL_GC)
182     ASSERT(m_opaqueRoots.isEmpty());
183     return m_shared.m_opaqueRoots.size();
184 #else
185     return m_opaqueRoots.size();
186 #endif
187 }
188
189 inline void SlotVisitor::mergeOpaqueRootsIfNecessary()
190 {
191     if (m_opaqueRoots.isEmpty())
192         return;
193     mergeOpaqueRoots();
194 }
195     
196 inline void SlotVisitor::mergeOpaqueRootsIfProfitable()
197 {
198     if (static_cast<unsigned>(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold())
199         return;
200     mergeOpaqueRoots();
201 }
202     
203 inline void SlotVisitor::donate()
204 {
205     ASSERT(m_isInParallelMode);
206     if (Options::numberOfGCMarkers() == 1)
207         return;
208     
209     donateKnownParallel();
210 }
211
212 inline void SlotVisitor::donateAndDrain()
213 {
214     donate();
215     drain();
216 }
217
218 inline void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes)
219 {
220     ASSERT(bytes);
221     m_bytesCopied += bytes;
222
223     CopiedBlock* block = CopiedSpace::blockFor(ptr);
224     if (block->isOversize()) {
225         m_shared.m_copiedSpace->pin(block);
226         return;
227     }
228
229     if (block->isPinned())
230         return;
231
232     block->reportLiveBytes(owner, token, bytes);
233 }
234     
235 inline void SlotVisitor::reportExtraMemoryUsage(size_t size)
236 {
237     size_t* counter = &m_shared.m_vm->heap.m_extraMemoryUsage;
238     
239 #if ENABLE(COMPARE_AND_SWAP)
240     for (;;) {
241         size_t oldSize = *counter;
242         if (WTF::weakCompareAndSwapSize(counter, oldSize, oldSize + size))
243             return;
244     }
245 #else
246     (*counter) += size;
247 #endif
248 }
249
250 } // namespace JSC
251
252 #endif // SlotVisitorInlines_h
253