]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGDesiredWatchpoints.h
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / dfg / DFGDesiredWatchpoints.h
1 /*
2 * Copyright (C) 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef DFGDesiredWatchpoints_h
27 #define DFGDesiredWatchpoints_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeOrigin.h"
32 #include "DFGCommonData.h"
33 #include "JSArrayBufferView.h"
34 #include "Watchpoint.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/HashSet.h>
37 #include <wtf/Noncopyable.h>
38 #include <wtf/Vector.h>
39
40 namespace JSC { namespace DFG {
41
42 template<typename WatchpointSetType>
43 struct WatchpointForGenericWatchpointSet {
44 WatchpointForGenericWatchpointSet()
45 : m_exitKind(ExitKindUnset)
46 , m_set(0)
47 {
48 }
49
50 WatchpointForGenericWatchpointSet(
51 CodeOrigin codeOrigin, ExitKind exitKind, WatchpointSetType* set)
52 : m_codeOrigin(codeOrigin)
53 , m_exitKind(exitKind)
54 , m_set(set)
55 {
56 }
57
58 CodeOrigin m_codeOrigin;
59 ExitKind m_exitKind;
60 WatchpointSetType* m_set;
61 };
62
63 template<typename T>
64 struct GenericSetAdaptor {
65 static void add(CodeBlock*, T* set, Watchpoint* watchpoint)
66 {
67 return set->add(watchpoint);
68 }
69 static bool hasBeenInvalidated(T* set) { return set->hasBeenInvalidated(); }
70 };
71
72 struct ArrayBufferViewWatchpointAdaptor {
73 static void add(CodeBlock*, JSArrayBufferView*, Watchpoint*);
74 static bool hasBeenInvalidated(JSArrayBufferView* view)
75 {
76 bool result = !view->length();
77 WTF::loadLoadFence();
78 return result;
79 }
80 };
81
82 template<typename WatchpointSetType, typename Adaptor = GenericSetAdaptor<WatchpointSetType>>
83 class GenericDesiredWatchpoints {
84 #if !ASSERT_DISABLED
85 typedef HashMap<WatchpointSetType*, bool> StateMap;
86 #endif
87 public:
88 GenericDesiredWatchpoints()
89 : m_reallyAdded(false)
90 {
91 }
92
93 void addLazily(WatchpointSetType* set)
94 {
95 m_sets.add(set);
96 }
97
98 void addLazily(CodeOrigin codeOrigin, ExitKind exitKind, WatchpointSetType* set)
99 {
100 m_profiledWatchpoints.append(
101 WatchpointForGenericWatchpointSet<WatchpointSetType>(codeOrigin, exitKind, set));
102 }
103
104 void reallyAdd(CodeBlock* codeBlock, CommonData& common)
105 {
106 RELEASE_ASSERT(!m_reallyAdded);
107
108 typename HashSet<WatchpointSetType*>::iterator iter = m_sets.begin();
109 typename HashSet<WatchpointSetType*>::iterator end = m_sets.end();
110 for (; iter != end; ++iter) {
111 common.watchpoints.append(CodeBlockJettisoningWatchpoint(codeBlock));
112 Adaptor::add(codeBlock, *iter, &common.watchpoints.last());
113 }
114
115 for (unsigned i = m_profiledWatchpoints.size(); i--;) {
116 WatchpointForGenericWatchpointSet<WatchpointSetType> watchpoint =
117 m_profiledWatchpoints[i];
118 common.profiledWatchpoints.append(
119 ProfiledCodeBlockJettisoningWatchpoint(watchpoint.m_codeOrigin, watchpoint.m_exitKind, codeBlock));
120 Adaptor::add(codeBlock, watchpoint.m_set, &common.profiledWatchpoints.last());
121 }
122
123 m_reallyAdded = true;
124 }
125
126 bool areStillValid() const
127 {
128 typename HashSet<WatchpointSetType*>::iterator iter = m_sets.begin();
129 typename HashSet<WatchpointSetType*>::iterator end = m_sets.end();
130 for (; iter != end; ++iter) {
131 if (Adaptor::hasBeenInvalidated(*iter))
132 return false;
133 }
134
135 for (unsigned i = m_profiledWatchpoints.size(); i--;) {
136 if (Adaptor::hasBeenInvalidated(m_profiledWatchpoints[i].m_set))
137 return false;
138 }
139
140 return true;
141 }
142
143 #if ASSERT_DISABLED
144 bool isStillValid(WatchpointSetType* set)
145 {
146 return !Adaptor::hasBeenInvalidated(set);
147 }
148
149 bool shouldAssumeMixedState(WatchpointSetType*)
150 {
151 return true;
152 }
153 #else
154 bool isStillValid(WatchpointSetType* set)
155 {
156 bool result = !Adaptor::hasBeenInvalidated(set);
157 m_firstKnownState.add(set, result);
158 return result;
159 }
160
161 bool shouldAssumeMixedState(WatchpointSetType* set)
162 {
163 typename StateMap::iterator iter = m_firstKnownState.find(set);
164 if (iter == m_firstKnownState.end())
165 return false;
166
167 return iter->value != !Adaptor::hasBeenInvalidated(set);
168 }
169 #endif
170
171 bool isValidOrMixed(WatchpointSetType* set)
172 {
173 return isStillValid(set) || shouldAssumeMixedState(set);
174 }
175
176 private:
177 Vector<WatchpointForGenericWatchpointSet<WatchpointSetType>> m_profiledWatchpoints;
178 HashSet<WatchpointSetType*> m_sets;
179 #if !ASSERT_DISABLED
180 StateMap m_firstKnownState;
181 #endif
182 bool m_reallyAdded;
183 };
184
185 class DesiredWatchpoints {
186 public:
187 DesiredWatchpoints();
188 ~DesiredWatchpoints();
189
190 void addLazily(WatchpointSet*);
191 void addLazily(InlineWatchpointSet&);
192 void addLazily(JSArrayBufferView*);
193 void addLazily(CodeOrigin, ExitKind, WatchpointSet*);
194 void addLazily(CodeOrigin, ExitKind, InlineWatchpointSet&);
195
196 void reallyAdd(CodeBlock*, CommonData&);
197
198 bool areStillValid() const;
199
200 bool isStillValid(WatchpointSet* set)
201 {
202 return m_sets.isStillValid(set);
203 }
204 bool isStillValid(InlineWatchpointSet& set)
205 {
206 return m_inlineSets.isStillValid(&set);
207 }
208 bool isStillValid(JSArrayBufferView* view)
209 {
210 return m_bufferViews.isStillValid(view);
211 }
212 bool shouldAssumeMixedState(WatchpointSet* set)
213 {
214 return m_sets.shouldAssumeMixedState(set);
215 }
216 bool shouldAssumeMixedState(InlineWatchpointSet& set)
217 {
218 return m_inlineSets.shouldAssumeMixedState(&set);
219 }
220 bool shouldAssumeMixedState(JSArrayBufferView* view)
221 {
222 return m_bufferViews.shouldAssumeMixedState(view);
223 }
224 bool isValidOrMixed(WatchpointSet* set)
225 {
226 return m_sets.isValidOrMixed(set);
227 }
228 bool isValidOrMixed(InlineWatchpointSet& set)
229 {
230 return m_inlineSets.isValidOrMixed(&set);
231 }
232 bool isValidOrMixed(JSArrayBufferView* view)
233 {
234 return m_bufferViews.isValidOrMixed(view);
235 }
236
237 private:
238 GenericDesiredWatchpoints<WatchpointSet> m_sets;
239 GenericDesiredWatchpoints<InlineWatchpointSet> m_inlineSets;
240 GenericDesiredWatchpoints<JSArrayBufferView, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
241 };
242
243 } } // namespace JSC::DFG
244
245 #endif // ENABLE(DFG_JIT)
246
247 #endif // DFGDesiredWatchpoints_h
248