]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGSafeToExecute.h
52bbfe4799f8df9f318df33b8eafa47e517fc929
[apple/javascriptcore.git] / dfg / DFGSafeToExecute.h
1 /*
2 * Copyright (C) 2013, 2014 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 BooleanUse:
54 case CellUse:
55 case ObjectUse:
56 case FinalObjectUse:
57 case ObjectOrOtherUse:
58 case StringIdentUse:
59 case StringUse:
60 case StringObjectUse:
61 case StringOrStringObjectUse:
62 case NotStringVarUse:
63 case NotCellUse:
64 case OtherUse:
65 case MiscUse:
66 case MachineIntUse:
67 case DoubleRepMachineIntUse:
68 return;
69
70 case KnownInt32Use:
71 if (m_state.forNode(edge).m_type & ~SpecInt32)
72 m_result = false;
73 return;
74
75 case KnownCellUse:
76 if (m_state.forNode(edge).m_type & ~SpecCell)
77 m_result = false;
78 return;
79
80 case KnownStringUse:
81 if (m_state.forNode(edge).m_type & ~SpecString)
82 m_result = false;
83 return;
84
85 case LastUseKind:
86 RELEASE_ASSERT_NOT_REACHED();
87 break;
88 }
89 RELEASE_ASSERT_NOT_REACHED();
90 }
91
92 bool result() const { return m_result; }
93 private:
94 AbstractStateType& m_state;
95 bool m_result;
96 };
97
98 // Determines if it's safe to execute a node within the given abstract state. This may
99 // return false conservatively. If it returns true, then you can hoist the given node
100 // up to the given point and expect that it will not crash. This doesn't guarantee that
101 // the node will produce the result you wanted other than not crashing.
102 template<typename AbstractStateType>
103 bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
104 {
105 SafeToExecuteEdge<AbstractStateType> safeToExecuteEdge(state);
106 DFG_NODE_DO_TO_CHILDREN(graph, node, safeToExecuteEdge);
107 if (!safeToExecuteEdge.result())
108 return false;
109
110 switch (node->op()) {
111 case JSConstant:
112 case DoubleConstant:
113 case Int52Constant:
114 case WeakJSConstant:
115 case Identity:
116 case ToThis:
117 case CreateThis:
118 case GetCallee:
119 case GetLocal:
120 case SetLocal:
121 case MovHint:
122 case ZombieHint:
123 case GetArgument:
124 case Phantom:
125 case HardPhantom:
126 case Upsilon:
127 case Phi:
128 case Flush:
129 case PhantomLocal:
130 case GetLocalUnlinked:
131 case SetArgument:
132 case BitAnd:
133 case BitOr:
134 case BitXor:
135 case BitLShift:
136 case BitRShift:
137 case BitURShift:
138 case ValueToInt32:
139 case UInt32ToNumber:
140 case DoubleAsInt32:
141 case ArithAdd:
142 case ArithSub:
143 case ArithNegate:
144 case ArithMul:
145 case ArithIMul:
146 case ArithDiv:
147 case ArithMod:
148 case ArithAbs:
149 case ArithMin:
150 case ArithMax:
151 case ArithSqrt:
152 case ArithFRound:
153 case ArithSin:
154 case ArithCos:
155 case ValueAdd:
156 case GetById:
157 case GetByIdFlush:
158 case PutById:
159 case PutByIdFlush:
160 case PutByIdDirect:
161 case CheckStructure:
162 case CheckExecutable:
163 case GetButterfly:
164 case CheckArray:
165 case Arrayify:
166 case ArrayifyToStructure:
167 case GetScope:
168 case GetMyScope:
169 case SkipTopScope:
170 case SkipScope:
171 case GetClosureRegisters:
172 case GetClosureVar:
173 case PutClosureVar:
174 case GetGlobalVar:
175 case PutGlobalVar:
176 case VariableWatchpoint:
177 case VarInjectionWatchpoint:
178 case CheckFunction:
179 case AllocationProfileWatchpoint:
180 case RegExpExec:
181 case RegExpTest:
182 case CompareLess:
183 case CompareLessEq:
184 case CompareGreater:
185 case CompareGreaterEq:
186 case CompareEq:
187 case CompareEqConstant:
188 case CompareStrictEq:
189 case Call:
190 case Construct:
191 case NewObject:
192 case NewArray:
193 case NewArrayWithSize:
194 case NewArrayBuffer:
195 case NewRegexp:
196 case Breakpoint:
197 case ProfileWillCall:
198 case ProfileDidCall:
199 case CheckHasInstance:
200 case InstanceOf:
201 case IsUndefined:
202 case IsBoolean:
203 case IsNumber:
204 case IsString:
205 case IsObject:
206 case IsFunction:
207 case TypeOf:
208 case LogicalNot:
209 case ToPrimitive:
210 case ToString:
211 case NewStringObject:
212 case MakeRope:
213 case In:
214 case CreateActivation:
215 case TearOffActivation:
216 case CreateArguments:
217 case PhantomArguments:
218 case TearOffArguments:
219 case GetMyArgumentsLength:
220 case GetMyArgumentByVal:
221 case GetMyArgumentsLengthSafe:
222 case GetMyArgumentByValSafe:
223 case CheckArgumentsNotCreated:
224 case NewFunctionNoCheck:
225 case NewFunction:
226 case NewFunctionExpression:
227 case Jump:
228 case Branch:
229 case Switch:
230 case Return:
231 case Throw:
232 case ThrowReferenceError:
233 case CountExecution:
234 case ForceOSRExit:
235 case CheckWatchdogTimer:
236 case StringFromCharCode:
237 case NewTypedArray:
238 case Unreachable:
239 case ExtractOSREntryLocal:
240 case CheckTierUpInLoop:
241 case CheckTierUpAtReturn:
242 case CheckTierUpAndOSREnter:
243 case LoopHint:
244 case StoreBarrier:
245 case StoreBarrierWithNullCheck:
246 case InvalidationPoint:
247 case NotifyWrite:
248 case FunctionReentryWatchpoint:
249 case TypedArrayWatchpoint:
250 case CheckInBounds:
251 case ConstantStoragePointer:
252 case Check:
253 case MultiGetByOffset:
254 case MultiPutByOffset:
255 case ValueRep:
256 case DoubleRep:
257 case Int52Rep:
258 case BooleanToNumber:
259 case FiatInt52:
260 return true;
261
262 case GetByVal:
263 case GetIndexedPropertyStorage:
264 case GetArrayLength:
265 case ArrayPush:
266 case ArrayPop:
267 case StringCharAt:
268 case StringCharCodeAt:
269 return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
270
271 case GetTypedArrayByteOffset:
272 return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
273
274 case PutByValDirect:
275 case PutByVal:
276 case PutByValAlias:
277 return node->arrayMode().modeForPut().alreadyChecked(
278 graph, node, state.forNode(graph.varArgChild(node, 0)));
279
280 case StructureTransitionWatchpoint:
281 return state.forNode(node->child1()).m_futurePossibleStructure.isSubsetOf(
282 StructureSet(node->structure()));
283
284 case PutStructure:
285 case PhantomPutStructure:
286 case AllocatePropertyStorage:
287 case ReallocatePropertyStorage:
288 return state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf(
289 StructureSet(node->structureTransitionData().previousStructure));
290
291 case GetByOffset:
292 case PutByOffset:
293 return state.forNode(node->child1()).m_currentKnownStructure.isValidOffset(
294 graph.m_storageAccessData[node->storageAccessDataIndex()].offset);
295
296 case LastNodeType:
297 RELEASE_ASSERT_NOT_REACHED();
298 return false;
299 }
300
301 RELEASE_ASSERT_NOT_REACHED();
302 return false;
303 }
304
305 } } // namespace JSC::DFG
306
307 #endif // ENABLE(DFG_JIT)
308
309 #endif // DFGSafeToExecute_h
310