Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / heap / SlotVisitor.h
1 /*
2  * Copyright (C) 2011-2017 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 "HandleTypes.h"
29 #include "IterationStatus.h"
30 #include "MarkStack.h"
31 #include "OpaqueRootSet.h"
32 #include "VisitRaceKey.h"
33 #include <wtf/MonotonicTime.h>
34 #include <wtf/text/CString.h>
35
36 namespace JSC {
37
38 class ConservativeRoots;
39 class GCThreadSharedData;
40 class Heap;
41 class HeapCell;
42 class HeapSnapshotBuilder;
43 class MarkedBlock;
44 class UnconditionalFinalizer;
45 template<typename T> class Weak;
46 class WeakReferenceHarvester;
47 template<typename T> class WriteBarrierBase;
48
49 typedef uint32_t HeapVersion;
50
51 class SlotVisitor {
52     WTF_MAKE_NONCOPYABLE(SlotVisitor);
53     WTF_MAKE_FAST_ALLOCATED;
54
55     friend class SetCurrentCellScope;
56     friend class Heap;
57
58 public:
59     SlotVisitor(Heap&, CString codeName);
60     ~SlotVisitor();
61
62     MarkStackArray& collectorMarkStack() { return m_collectorStack; }
63     MarkStackArray& mutatorMarkStack() { return m_mutatorStack; }
64     const MarkStackArray& collectorMarkStack() const { return m_collectorStack; }
65     const MarkStackArray& mutatorMarkStack() const { return m_mutatorStack; }
66     
67     VM& vm();
68     const VM& vm() const;
69     Heap* heap() const;
70
71     void append(ConservativeRoots&);
72     
73     template<typename T> void append(const WriteBarrierBase<T>&);
74     template<typename T> void appendHidden(const WriteBarrierBase<T>&);
75     template<typename Iterator> void append(Iterator begin , Iterator end);
76     void appendValues(const WriteBarrierBase<Unknown>*, size_t count);
77     void appendValuesHidden(const WriteBarrierBase<Unknown>*, size_t count);
78     
79     // These don't require you to prove that you have a WriteBarrier<>. That makes sense
80     // for:
81     //
82     // - roots.
83     // - sophisticated data structures that barrier through other means (like DFG::Plan and
84     //   friends).
85     //
86     // If you are not a root and you don't know what kind of barrier you have, then you
87     // shouldn't call these methods.
88     void appendUnbarriered(JSValue);
89     void appendUnbarriered(JSValue*, size_t);
90     void appendUnbarriered(JSCell*);
91     
92     template<typename T>
93     void append(const Weak<T>& weak);
94     
95     void appendHiddenUnbarriered(JSValue);
96     void appendHiddenUnbarriered(JSCell*);
97
98     JS_EXPORT_PRIVATE void addOpaqueRoot(void*);
99     
100     JS_EXPORT_PRIVATE bool containsOpaqueRoot(void*) const;
101     TriState containsOpaqueRootTriState(void*) const;
102
103     bool isEmpty() { return m_collectorStack.isEmpty() && m_mutatorStack.isEmpty(); }
104
105     void didStartMarking();
106     void reset();
107     void clearMarkStacks();
108
109     size_t bytesVisited() const { return m_bytesVisited; }
110     size_t visitCount() const { return m_visitCount; }
111     
112     void addToVisitCount(size_t value) { m_visitCount += value; }
113
114     void donate();
115     void drain(MonotonicTime timeout = MonotonicTime::infinity());
116     void donateAndDrain(MonotonicTime timeout = MonotonicTime::infinity());
117     
118     enum SharedDrainMode { SlaveDrain, MasterDrain };
119     enum class SharedDrainResult { Done, TimedOut };
120     SharedDrainResult drainFromShared(SharedDrainMode, MonotonicTime timeout = MonotonicTime::infinity());
121
122     SharedDrainResult drainInParallel(MonotonicTime timeout = MonotonicTime::infinity());
123     SharedDrainResult drainInParallelPassively(MonotonicTime timeout = MonotonicTime::infinity());
124
125     // Attempts to perform an increment of draining that involves only walking `bytes` worth of data. This
126     // is likely to accidentally walk more or less than that. It will usually mark more than bytes. It may
127     // mark less than bytes if we're reaching termination or if the global worklist is empty (which may in
128     // rare cases happen temporarily even if we're not reaching termination).
129     size_t performIncrementOfDraining(size_t bytes);
130     
131     JS_EXPORT_PRIVATE void mergeIfNecessary();
132
133     // This informs the GC about auxiliary of some size that we are keeping alive. If you don't do
134     // this then the space will be freed at end of GC.
135     void markAuxiliary(const void* base);
136
137     void reportExtraMemoryVisited(size_t);
138 #if ENABLE(RESOURCE_USAGE)
139     void reportExternalMemoryVisited(size_t);
140 #endif
141     
142     void addWeakReferenceHarvester(WeakReferenceHarvester*);
143     void addUnconditionalFinalizer(UnconditionalFinalizer*);
144
145     void dump(PrintStream&) const;
146
147     bool isBuildingHeapSnapshot() const { return !!m_heapSnapshotBuilder; }
148     
149     HeapVersion markingVersion() const { return m_markingVersion; }
150
151     bool mutatorIsStopped() const { return m_mutatorIsStopped; }
152     
153     Lock& rightToRun() { return m_rightToRun; }
154     
155     void updateMutatorIsStopped(const AbstractLocker&);
156     void updateMutatorIsStopped();
157     
158     bool hasAcknowledgedThatTheMutatorIsResumed() const;
159     bool mutatorIsStoppedIsUpToDate() const;
160     
161     void optimizeForStoppedMutator();
162     
163     void didRace(const VisitRaceKey&);
164     void didRace(JSCell* cell, const char* reason) { didRace(VisitRaceKey(cell, reason)); }
165     
166     void visitAsConstraint(const JSCell*);
167     
168     bool didReachTermination();
169     
170     void setIgnoreNewOpaqueRoots(bool value) { m_ignoreNewOpaqueRoots = value; }
171
172     void donateAll();
173     
174     const char* codeName() const { return m_codeName.data(); }
175
176 private:
177     friend class ParallelModeEnabler;
178     
179     void appendJSCellOrAuxiliary(HeapCell*);
180
181     JS_EXPORT_PRIVATE void appendSlow(JSCell*, Dependency);
182     JS_EXPORT_PRIVATE void appendHiddenSlow(JSCell*, Dependency);
183     void appendHiddenSlowImpl(JSCell*, Dependency);
184     
185     template<typename ContainerType>
186     void setMarkedAndAppendToMarkStack(ContainerType&, JSCell*, Dependency);
187     
188     void appendToMarkStack(JSCell*);
189     
190     template<typename ContainerType>
191     void appendToMarkStack(ContainerType&, JSCell*);
192     
193     void appendToMutatorMarkStack(const JSCell*);
194     
195     void noteLiveAuxiliaryCell(HeapCell*);
196     
197     void mergeOpaqueRoots();
198
199     void mergeOpaqueRootsIfProfitable();
200
201     void visitChildren(const JSCell*);
202     
203     void donateKnownParallel();
204     void donateKnownParallel(MarkStackArray& from, MarkStackArray& to);
205
206     void donateAll(const AbstractLocker&);
207
208     bool hasWork(const AbstractLocker&);
209     bool didReachTermination(const AbstractLocker&);
210
211     template<typename Func>
212     IterationStatus forEachMarkStack(const Func&);
213
214     MarkStackArray& correspondingGlobalStack(MarkStackArray&);
215
216     MarkStackArray m_collectorStack;
217     MarkStackArray m_mutatorStack;
218     OpaqueRootSet m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
219     bool m_ignoreNewOpaqueRoots { false }; // Useful as a debugging mode.
220     
221     size_t m_bytesVisited;
222     size_t m_visitCount;
223     size_t m_nonCellVisitCount { 0 }; // Used for incremental draining, ignored otherwise.
224     bool m_isInParallelMode;
225
226     HeapVersion m_markingVersion;
227     
228     Heap& m_heap;
229
230     HeapSnapshotBuilder* m_heapSnapshotBuilder { nullptr };
231     JSCell* m_currentCell { nullptr };
232     bool m_isFirstVisit { false };
233     bool m_mutatorIsStopped { false };
234     bool m_canOptimizeForStoppedMutator { false };
235     Lock m_rightToRun;
236     
237     CString m_codeName;
238     
239 public:
240 #if !ASSERT_DISABLED
241     bool m_isCheckingForDefaultMarkViolation;
242     bool m_isDraining;
243 #endif
244 };
245
246 class ParallelModeEnabler {
247 public:
248     ParallelModeEnabler(SlotVisitor& stack)
249         : m_stack(stack)
250     {
251         ASSERT(!m_stack.m_isInParallelMode);
252         m_stack.m_isInParallelMode = true;
253     }
254     
255     ~ParallelModeEnabler()
256     {
257         ASSERT(m_stack.m_isInParallelMode);
258         m_stack.m_isInParallelMode = false;
259     }
260     
261 private:
262     SlotVisitor& m_stack;
263 };
264
265 } // namespace JSC