04baacfb3a76d797772c264db4fc5ff1041dc5e7
[WebKit.git] / Source / JavaScriptCore / heap / SlotVisitor.h
1 /*
2  * Copyright (C) 2011-2013, 2015-2016 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 "CellState.h"
29 #include "HandleTypes.h"
30 #include "MarkStack.h"
31 #include "OpaqueRootSet.h"
32 #include "VisitRaceKey.h"
33 #include <wtf/MonotonicTime.h>
34
35 namespace JSC {
36
37 class ConservativeRoots;
38 class GCThreadSharedData;
39 class Heap;
40 class HeapCell;
41 class HeapSnapshotBuilder;
42 class MarkedBlock;
43 class UnconditionalFinalizer;
44 template<typename T> class Weak;
45 class WeakReferenceHarvester;
46 template<typename T> class WriteBarrierBase;
47
48 typedef uint32_t HeapVersion;
49
50 class SlotVisitor {
51     WTF_MAKE_NONCOPYABLE(SlotVisitor);
52     WTF_MAKE_FAST_ALLOCATED;
53
54     friend class SetCurrentCellScope;
55     friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly.
56     friend class Heap;
57
58 public:
59     SlotVisitor(Heap&);
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(WriteBarrierBase<T>*);
74     template<typename T> void appendHidden(WriteBarrierBase<T>*);
75     template<typename Iterator> void append(Iterator begin , Iterator end);
76     void appendValues(WriteBarrierBase<Unknown>*, size_t count);
77     void appendValuesHidden(WriteBarrierBase<Unknown>*, size_t count);
78     
79     template<typename T>
80     void appendUnbarrieredPointer(T**);
81     void appendUnbarrieredValue(JSValue*);
82     template<typename T>
83     void appendUnbarrieredWeak(Weak<T>*);
84     template<typename T>
85     void appendUnbarrieredReadOnlyPointer(T*);
86     void appendUnbarrieredReadOnlyValue(JSValue);
87     
88     void visitSubsequently(JSCell*);
89     
90     // Does your visitChildren do logic that depends on non-JS-object state that can
91     // change during the course of a GC, or in between GCs? Then you should call this
92     // method! It will cause the GC to invoke your visitChildren method again just before
93     // terminating with the world stopped.
94     JS_EXPORT_PRIVATE void rescanAsConstraint();
95     
96     // Implies rescanAsConstraint, so you don't have to call rescanAsConstraint() if you
97     // call this unconditionally.
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 donate();
113     void drain(MonotonicTime timeout = MonotonicTime::infinity());
114     void donateAndDrain(MonotonicTime timeout = MonotonicTime::infinity());
115     
116     enum SharedDrainMode { SlaveDrain, MasterDrain };
117     enum class SharedDrainResult { Done, TimedOut };
118     SharedDrainResult drainFromShared(SharedDrainMode, MonotonicTime timeout = MonotonicTime::infinity());
119
120     SharedDrainResult drainInParallel(MonotonicTime timeout = MonotonicTime::infinity());
121     SharedDrainResult drainInParallelPassively(MonotonicTime timeout = MonotonicTime::infinity());
122     
123     void mergeIfNecessary();
124
125     // This informs the GC about auxiliary of some size that we are keeping alive. If you don't do
126     // this then the space will be freed at end of GC.
127     void markAuxiliary(const void* base);
128
129     void reportExtraMemoryVisited(size_t);
130 #if ENABLE(RESOURCE_USAGE)
131     void reportExternalMemoryVisited(size_t);
132 #endif
133     
134     void addWeakReferenceHarvester(WeakReferenceHarvester*);
135     void addUnconditionalFinalizer(UnconditionalFinalizer*);
136
137     void dump(PrintStream&) const;
138
139     bool isBuildingHeapSnapshot() const { return !!m_heapSnapshotBuilder; }
140     
141     HeapVersion markingVersion() const { return m_markingVersion; }
142
143     bool mutatorIsStopped() const { return m_mutatorIsStopped; }
144     
145     Lock& rightToRun() { return m_rightToRun; }
146     
147     void updateMutatorIsStopped(const AbstractLocker&);
148     void updateMutatorIsStopped();
149     
150     bool hasAcknowledgedThatTheMutatorIsResumed() const;
151     bool mutatorIsStoppedIsUpToDate() const;
152     
153     void optimizeForStoppedMutator();
154     
155     void didRace(const VisitRaceKey&);
156     void didRace(JSCell* cell, const char* reason) { didRace(VisitRaceKey(cell, reason)); }
157     void didNotRace(const VisitRaceKey&);
158     void didNotRace(JSCell* cell, const char* reason) { didNotRace(VisitRaceKey(cell, reason)); }
159
160 private:
161     friend class ParallelModeEnabler;
162     
163     JS_EXPORT_PRIVATE void append(JSValue); // This is private to encourage clients to use WriteBarrier<T>.
164     void appendJSCellOrAuxiliary(HeapCell*);
165     void appendHidden(JSValue);
166
167     JS_EXPORT_PRIVATE void setMarkedAndAppendToMarkStack(JSCell*);
168     
169     template<typename ContainerType>
170     void setMarkedAndAppendToMarkStack(ContainerType&, JSCell*);
171     
172     void appendToMarkStack(JSCell*);
173     
174     template<typename ContainerType>
175     void appendToMarkStack(ContainerType&, JSCell*);
176     
177     void appendToMutatorMarkStack(const JSCell*);
178     
179     void noteLiveAuxiliaryCell(HeapCell*);
180     
181     void mergeOpaqueRoots();
182     void mergeOpaqueRootsAndConstraints();
183
184     void mergeOpaqueRootsIfProfitable();
185
186     void visitChildren(const JSCell*);
187     
188     void donateKnownParallel();
189     void donateKnownParallel(MarkStackArray& from, MarkStackArray& to);
190     
191     bool hasWork();
192     bool didReachTermination();
193
194     MarkStackArray m_collectorStack;
195     MarkStackArray m_mutatorStack;
196     OpaqueRootSet m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
197     HashSet<JSCell*> m_constraints;
198     
199     size_t m_bytesVisited;
200     size_t m_visitCount;
201     bool m_isInParallelMode;
202     
203     HeapVersion m_markingVersion;
204     
205     Heap& m_heap;
206
207     HeapSnapshotBuilder* m_heapSnapshotBuilder { nullptr };
208     JSCell* m_currentCell { nullptr };
209     bool m_isFirstVisit { false };
210     bool m_mutatorIsStopped { false };
211     bool m_canOptimizeForStoppedMutator { false };
212     Lock m_rightToRun;
213     
214 public:
215 #if !ASSERT_DISABLED
216     bool m_isCheckingForDefaultMarkViolation;
217     bool m_isDraining;
218 #endif
219 };
220
221 class ParallelModeEnabler {
222 public:
223     ParallelModeEnabler(SlotVisitor& stack)
224         : m_stack(stack)
225     {
226         ASSERT(!m_stack.m_isInParallelMode);
227         m_stack.m_isInParallelMode = true;
228     }
229     
230     ~ParallelModeEnabler()
231     {
232         ASSERT(m_stack.m_isInParallelMode);
233         m_stack.m_isInParallelMode = false;
234     }
235     
236 private:
237     SlotVisitor& m_stack;
238 };
239
240 } // namespace JSC