Copying collection shouldn't require O(live bytes) memory overhead
[WebKit-https.git] / Source / JavaScriptCore / heap / SlotVisitorInlineMethods.h
1 /*
2  * Copyright (C) 2012 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 SlotVisitorInlineMethods_h
27 #define SlotVisitorInlineMethods_h
28
29 #include "CopiedSpaceInlineMethods.h"
30 #include "Options.h"
31 #include "SlotVisitor.h"
32
33 namespace JSC {
34
35 ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count)
36 {
37     for (size_t i = 0; i < count; ++i) {
38         JSValue& value = slot[i];
39         internalAppend(value);
40     }
41 }
42
43 template<typename T>
44 inline void SlotVisitor::appendUnbarrieredPointer(T** slot)
45 {
46     ASSERT(slot);
47     JSCell* cell = *slot;
48     internalAppend(cell);
49 }
50
51 ALWAYS_INLINE void SlotVisitor::append(JSValue* slot)
52 {
53     ASSERT(slot);
54     internalAppend(*slot);
55 }
56
57 ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot)
58 {
59     ASSERT(slot);
60     internalAppend(*slot);
61 }
62
63 ALWAYS_INLINE void SlotVisitor::append(JSCell** slot)
64 {
65     ASSERT(slot);
66     internalAppend(*slot);
67 }
68
69 ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue value)
70 {
71     if (!value || !value.isCell())
72         return;
73     internalAppend(value.asCell());
74 }
75
76 inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
77 {
78     m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester);
79 }
80
81 inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer)
82 {
83     m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
84 }
85
86 inline void SlotVisitor::addOpaqueRoot(void* root)
87 {
88 #if ENABLE(PARALLEL_GC)
89     if (Options::numberOfGCMarkers() == 1) {
90         // Put directly into the shared HashSet.
91         m_shared.m_opaqueRoots.add(root);
92         return;
93     }
94     // Put into the local set, but merge with the shared one every once in
95     // a while to make sure that the local sets don't grow too large.
96     mergeOpaqueRootsIfProfitable();
97     m_opaqueRoots.add(root);
98 #else
99     m_opaqueRoots.add(root);
100 #endif
101 }
102
103 inline bool SlotVisitor::containsOpaqueRoot(void* root)
104 {
105     ASSERT(!m_isInParallelMode);
106 #if ENABLE(PARALLEL_GC)
107     ASSERT(m_opaqueRoots.isEmpty());
108     return m_shared.m_opaqueRoots.contains(root);
109 #else
110     return m_opaqueRoots.contains(root);
111 #endif
112 }
113
114 inline int SlotVisitor::opaqueRootCount()
115 {
116     ASSERT(!m_isInParallelMode);
117 #if ENABLE(PARALLEL_GC)
118     ASSERT(m_opaqueRoots.isEmpty());
119     return m_shared.m_opaqueRoots.size();
120 #else
121     return m_opaqueRoots.size();
122 #endif
123 }
124
125 inline void SlotVisitor::mergeOpaqueRootsIfNecessary()
126 {
127     if (m_opaqueRoots.isEmpty())
128         return;
129     mergeOpaqueRoots();
130 }
131     
132 inline void SlotVisitor::mergeOpaqueRootsIfProfitable()
133 {
134     if (static_cast<unsigned>(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold())
135         return;
136     mergeOpaqueRoots();
137 }
138     
139 inline void SlotVisitor::donate()
140 {
141     ASSERT(m_isInParallelMode);
142     if (Options::numberOfGCMarkers() == 1)
143         return;
144     
145     donateKnownParallel();
146 }
147
148 inline void SlotVisitor::donateAndDrain()
149 {
150     donate();
151     drain();
152 }
153
154 inline void SlotVisitor::copyLater(void* ptr, size_t bytes)
155 {
156     if (CopiedSpace::isOversize(bytes)) {
157         m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr));
158         return;
159     }
160
161     CopiedBlock* block = CopiedSpace::blockFor(ptr);
162     if (block->isPinned())
163         return;
164
165     block->reportLiveBytes(bytes);
166
167     if (!block->shouldEvacuate())
168         m_shared.m_copiedSpace->pin(block);
169 }
170     
171 } // namespace JSC
172
173 #endif // SlotVisitorInlineMethods_h
174