]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGSafeToExecute.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGSafeToExecute.h
1 /*
2 * Copyright (C) 2013-2015 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 DFGSafeToExecute_h
27 #define DFGSafeToExecute_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32
33 namespace JSC { namespace DFG {
34
35 template<typename AbstractStateType>
36 class SafeToExecuteEdge {
37 public:
38 SafeToExecuteEdge(AbstractStateType& state)
39 : m_state(state)
40 , m_result(true)
41 {
42 }
43
44 void operator()(Node*, Edge edge)
45 {
46 switch (edge.useKind()) {
47 case UntypedUse:
48 case Int32Use:
49 case DoubleRepUse:
50 case DoubleRepRealUse:
51 case Int52RepUse:
52 case NumberUse:
53 case RealNumberUse:
54 case BooleanUse:
55 case CellUse:
56 case ObjectUse:
57 case FunctionUse:
58 case FinalObjectUse:
59 case ObjectOrOtherUse:
60 case StringIdentUse:
61 case StringUse:
62 case StringObjectUse:
63 case StringOrStringObjectUse:
64 case NotStringVarUse:
65 case NotCellUse:
66 case OtherUse:
67 case MiscUse:
68 case MachineIntUse:
69 case DoubleRepMachineIntUse:
70 return;
71
72 case KnownInt32Use:
73 if (m_state.forNode(edge).m_type & ~SpecInt32)
74 m_result = false;
75 return;
76
77 case KnownCellUse:
78 if (m_state.forNode(edge).m_type & ~SpecCell)
79 m_result = false;
80 return;
81
82 case KnownStringUse:
83 if (m_state.forNode(edge).m_type & ~SpecString)
84 m_result = false;
85 return;
86
87 case LastUseKind:
88 RELEASE_ASSERT_NOT_REACHED();
89 break;
90 }
91 RELEASE_ASSERT_NOT_REACHED();
92 }
93
94 bool result() const { return m_result; }
95 private:
96 AbstractStateType& m_state;
97 bool m_result;
98 };
99
100 // Determines if it's safe to execute a node within the given abstract state. This may
101 // return false conservatively. If it returns true, then you can hoist the given node
102 // up to the given point and expect that it will not crash. This doesn't guarantee that
103 // the node will produce the result you wanted other than not crashing.
104 template<typename AbstractStateType>
105 bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
106 {
107 SafeToExecuteEdge<AbstractStateType> safeToExecuteEdge(state);
108 DFG_NODE_DO_TO_CHILDREN(graph, node, safeToExecuteEdge);
109 if (!safeToExecuteEdge.result())
110 return false;
111
112 switch (node->op()) {
113 case JSConstant:
114 case DoubleConstant:
115 case Int52Constant:
116 case Identity:
117 case ToThis:
118 case CreateThis:
119 case GetCallee:
120 case GetArgumentCount:
121 case GetLocal:
122 case SetLocal:
123 case PutStack:
124 case KillStack:
125 case GetStack:
126 case MovHint:
127 case ZombieHint:
128 case Phantom:
129 case Upsilon:
130 case Phi:
131 case Flush:
132 case PhantomLocal:
133 case GetLocalUnlinked:
134 case SetArgument:
135 case BitAnd:
136 case BitOr:
137 case BitXor:
138 case BitLShift:
139 case BitRShift:
140 case BitURShift:
141 case ValueToInt32:
142 case UInt32ToNumber:
143 case DoubleAsInt32:
144 case ArithAdd:
145 case ArithClz32:
146 case ArithSub:
147 case ArithNegate:
148 case ArithMul:
149 case ArithIMul:
150 case ArithDiv:
151 case ArithMod:
152 case ArithAbs:
153 case ArithMin:
154 case ArithMax:
155 case ArithPow:
156 case ArithSqrt:
157 case ArithFRound:
158 case ArithRound:
159 case ArithSin:
160 case ArithCos:
161 case ArithLog:
162 case ValueAdd:
163 case GetById:
164 case GetByIdFlush:
165 case PutById:
166 case PutByIdFlush:
167 case PutByIdDirect:
168 case CheckStructure:
169 case GetExecutable:
170 case GetButterfly:
171 case CheckArray:
172 case Arrayify:
173 case ArrayifyToStructure:
174 case GetScope:
175 case SkipScope:
176 case GetClosureVar:
177 case PutClosureVar:
178 case GetGlobalVar:
179 case PutGlobalVar:
180 case VarInjectionWatchpoint:
181 case CheckCell:
182 case CheckBadCell:
183 case CheckNotEmpty:
184 case RegExpExec:
185 case RegExpTest:
186 case CompareLess:
187 case CompareLessEq:
188 case CompareGreater:
189 case CompareGreaterEq:
190 case CompareEq:
191 case CompareEqConstant:
192 case CompareStrictEq:
193 case Call:
194 case Construct:
195 case CallVarargs:
196 case ConstructVarargs:
197 case LoadVarargs:
198 case CallForwardVarargs:
199 case ConstructForwardVarargs:
200 case NewObject:
201 case NewArray:
202 case NewArrayWithSize:
203 case NewArrayBuffer:
204 case NewRegexp:
205 case Breakpoint:
206 case ProfileWillCall:
207 case ProfileDidCall:
208 case ProfileType:
209 case ProfileControlFlow:
210 case CheckHasInstance:
211 case InstanceOf:
212 case IsUndefined:
213 case IsBoolean:
214 case IsNumber:
215 case IsString:
216 case IsObject:
217 case IsObjectOrNull:
218 case IsFunction:
219 case TypeOf:
220 case LogicalNot:
221 case ToPrimitive:
222 case ToString:
223 case CallStringConstructor:
224 case NewStringObject:
225 case MakeRope:
226 case In:
227 case CreateActivation:
228 case CreateDirectArguments:
229 case CreateScopedArguments:
230 case CreateClonedArguments:
231 case GetFromArguments:
232 case PutToArguments:
233 case NewFunction:
234 case Jump:
235 case Branch:
236 case Switch:
237 case Return:
238 case Throw:
239 case ThrowReferenceError:
240 case CountExecution:
241 case ForceOSRExit:
242 case CheckWatchdogTimer:
243 case StringFromCharCode:
244 case NewTypedArray:
245 case Unreachable:
246 case ExtractOSREntryLocal:
247 case CheckTierUpInLoop:
248 case CheckTierUpAtReturn:
249 case CheckTierUpAndOSREnter:
250 case CheckTierUpWithNestedTriggerAndOSREnter:
251 case LoopHint:
252 case StoreBarrier:
253 case InvalidationPoint:
254 case NotifyWrite:
255 case CheckInBounds:
256 case ConstantStoragePointer:
257 case Check:
258 case MultiGetByOffset:
259 case MultiPutByOffset:
260 case ValueRep:
261 case DoubleRep:
262 case Int52Rep:
263 case BooleanToNumber:
264 case FiatInt52:
265 case GetGetter:
266 case GetSetter:
267 case GetEnumerableLength:
268 case HasGenericProperty:
269 case HasStructureProperty:
270 case HasIndexedProperty:
271 case GetDirectPname:
272 case GetPropertyEnumerator:
273 case GetEnumeratorStructurePname:
274 case GetEnumeratorGenericPname:
275 case ToIndexString:
276 case PhantomNewObject:
277 case PhantomNewFunction:
278 case PhantomCreateActivation:
279 case PutHint:
280 case CheckStructureImmediate:
281 case MaterializeNewObject:
282 case MaterializeCreateActivation:
283 case PhantomDirectArguments:
284 case PhantomClonedArguments:
285 case GetMyArgumentByVal:
286 case ForwardVarargs:
287 return true;
288
289 case NativeCall:
290 case NativeConstruct:
291 return false; // TODO: add a check for already checked. https://bugs.webkit.org/show_bug.cgi?id=133769
292
293 case BottomValue:
294 // If in doubt, assume that this isn't safe to execute, just because we have no way of
295 // compiling this node.
296 return false;
297
298 case GetByVal:
299 case GetIndexedPropertyStorage:
300 case GetArrayLength:
301 case ArrayPush:
302 case ArrayPop:
303 case StringCharAt:
304 case StringCharCodeAt:
305 return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
306
307 case GetTypedArrayByteOffset:
308 return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
309
310 case PutByValDirect:
311 case PutByVal:
312 case PutByValAlias:
313 return node->arrayMode().modeForPut().alreadyChecked(
314 graph, node, state.forNode(graph.varArgChild(node, 0)));
315
316 case PutStructure:
317 case AllocatePropertyStorage:
318 case ReallocatePropertyStorage:
319 return state.forNode(node->child1()).m_structure.isSubsetOf(
320 StructureSet(node->transition()->previous));
321
322 case GetByOffset:
323 case GetGetterSetterByOffset:
324 case PutByOffset: {
325 StructureAbstractValue& value = state.forNode(node->child1()).m_structure;
326 if (value.isTop())
327 return false;
328 PropertyOffset offset = node->storageAccessData().offset;
329 for (unsigned i = value.size(); i--;) {
330 if (!value[i]->isValidOffset(offset))
331 return false;
332 }
333 return true;
334 }
335
336 case LastNodeType:
337 RELEASE_ASSERT_NOT_REACHED();
338 return false;
339 }
340
341 RELEASE_ASSERT_NOT_REACHED();
342 return false;
343 }
344
345 } } // namespace JSC::DFG
346
347 #endif // ENABLE(DFG_JIT)
348
349 #endif // DFGSafeToExecute_h
350