[JSC] Rename LargeAllocation to PreciseAllocation
[WebKit-https.git] / Source / JavaScriptCore / heap / SlotVisitorInlines.h
1 /*
2  * Copyright (C) 2012-2019 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 #pragma once
27
28 #include "SlotVisitor.h"
29 #include "Weak.h"
30 #include "WeakInlines.h"
31
32 namespace JSC {
33
34 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSValue* slot, size_t count)
35 {
36     for (size_t i = count; i--;)
37         appendUnbarriered(slot[i]);
38 }
39
40 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSCell* cell)
41 {
42     // This needs to be written in a very specific way to ensure that it gets inlined
43     // properly. In particular, it appears that using templates here breaks ALWAYS_INLINE.
44     
45     if (!cell)
46         return;
47     
48     Dependency dependency;
49     if (UNLIKELY(cell->isPreciseAllocation())) {
50         if (LIKELY(cell->preciseAllocation().isMarked())) {
51             if (LIKELY(!m_heapAnalyzer))
52                 return;
53         }
54     } else {
55         MarkedBlock& block = cell->markedBlock();
56         dependency = block.aboutToMark(m_markingVersion);
57         if (LIKELY(block.isMarked(cell, dependency))) {
58             if (LIKELY(!m_heapAnalyzer))
59                 return;
60         }
61     }
62     
63     appendSlow(cell, dependency);
64 }
65
66 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSValue value)
67 {
68     if (value.isCell())
69         appendUnbarriered(value.asCell());
70 }
71
72 ALWAYS_INLINE void SlotVisitor::appendHiddenUnbarriered(JSValue value)
73 {
74     if (value.isCell())
75         appendHiddenUnbarriered(value.asCell());
76 }
77
78 ALWAYS_INLINE void SlotVisitor::appendHiddenUnbarriered(JSCell* cell)
79 {
80     // This needs to be written in a very specific way to ensure that it gets inlined
81     // properly. In particular, it appears that using templates here breaks ALWAYS_INLINE.
82     
83     if (!cell)
84         return;
85     
86     Dependency dependency;
87     if (UNLIKELY(cell->isPreciseAllocation())) {
88         if (LIKELY(cell->preciseAllocation().isMarked()))
89             return;
90     } else {
91         MarkedBlock& block = cell->markedBlock();
92         dependency = block.aboutToMark(m_markingVersion);
93         if (LIKELY(block.isMarked(cell, dependency)))
94             return;
95     }
96     
97     appendHiddenSlow(cell, dependency);
98 }
99
100 template<typename T>
101 ALWAYS_INLINE void SlotVisitor::append(const Weak<T>& weak)
102 {
103     appendUnbarriered(weak.get());
104 }
105
106 template<typename T, typename Traits>
107 ALWAYS_INLINE void SlotVisitor::append(const WriteBarrierBase<T, Traits>& slot)
108 {
109     appendUnbarriered(slot.get());
110 }
111
112 template<typename T, typename Traits>
113 ALWAYS_INLINE void SlotVisitor::appendHidden(const WriteBarrierBase<T, Traits>& slot)
114 {
115     appendHiddenUnbarriered(slot.get());
116 }
117
118 template<typename Iterator>
119 ALWAYS_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(const WriteBarrierBase<Unknown>* barriers, size_t count)
126 {
127     for (size_t i = 0; i < count; ++i)
128         append(barriers[i]);
129 }
130
131 ALWAYS_INLINE void SlotVisitor::appendValuesHidden(const WriteBarrierBase<Unknown>* barriers, size_t count)
132 {
133     for (size_t i = 0; i < count; ++i)
134         appendHidden(barriers[i]);
135 }
136
137 inline bool SlotVisitor::addOpaqueRoot(void* ptr)
138 {
139     if (!ptr)
140         return false;
141     if (m_ignoreNewOpaqueRoots)
142         return false;
143     if (!heap()->m_opaqueRoots.add(ptr))
144         return false;
145     m_visitCount++;
146     return true;
147 }
148
149 inline bool SlotVisitor::containsOpaqueRoot(void* ptr) const
150 {
151     return heap()->m_opaqueRoots.contains(ptr);
152 }
153
154 inline void SlotVisitor::reportExtraMemoryVisited(size_t size)
155 {
156     if (m_isFirstVisit) {
157         m_nonCellVisitCount += size;
158         // FIXME: Change this to use SaturatedArithmetic when available.
159         // https://bugs.webkit.org/show_bug.cgi?id=170411
160         m_extraMemorySize += size;
161     }
162 }
163
164 #if ENABLE(RESOURCE_USAGE)
165 inline void SlotVisitor::reportExternalMemoryVisited(size_t size)
166 {
167     if (m_isFirstVisit)
168         heap()->reportExternalMemoryVisited(size);
169 }
170 #endif
171
172 inline Heap* SlotVisitor::heap() const
173 {
174     return &m_heap;
175 }
176
177 inline VM& SlotVisitor::vm()
178 {
179     return m_heap.vm();
180 }
181
182 inline const VM& SlotVisitor::vm() const
183 {
184     return m_heap.vm();
185 }
186
187 template<typename Func>
188 IterationStatus SlotVisitor::forEachMarkStack(const Func& func)
189 {
190     if (func(m_collectorStack) == IterationStatus::Done)
191         return IterationStatus::Done;
192     if (func(m_mutatorStack) == IterationStatus::Done)
193         return IterationStatus::Done;
194     return IterationStatus::Continue;
195 }
196
197 } // namespace JSC