blob: 508a589d67f71da1df64ed0bf9a402a3ba6a2a7b [file] [log] [blame]
oliver@apple.com83d2d022013-07-25 04:05:20 +00001/*
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +00002 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
oliver@apple.com83d2d022013-07-25 04:05:20 +00003 *
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
oliver@apple.com83d2d022013-07-25 04:05:20 +000029#if ENABLE(DFG_JIT)
30
31#include "DFGGraph.h"
32
33namespace JSC { namespace DFG {
34
35template<typename AbstractStateType>
36class SafeToExecuteEdge {
37public:
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 RealNumberUse:
50 case NumberUse:
51 case BooleanUse:
52 case CellUse:
53 case ObjectUse:
fpizlo@apple.com0fa83862013-09-06 19:01:21 +000054 case FinalObjectUse:
oliver@apple.com83d2d022013-07-25 04:05:20 +000055 case ObjectOrOtherUse:
56 case StringIdentUse:
57 case StringUse:
58 case StringObjectUse:
59 case StringOrStringObjectUse:
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000060 case NotStringVarUse:
oliver@apple.com83d2d022013-07-25 04:05:20 +000061 case NotCellUse:
62 case OtherUse:
fpizlo@apple.come079bb52014-03-05 07:41:03 +000063 case MiscUse:
fpizlo@apple.com6921b292013-09-18 17:14:02 +000064 case MachineIntUse:
oliver@apple.com83d2d022013-07-25 04:05:20 +000065 return;
66
67 case KnownInt32Use:
68 if (m_state.forNode(edge).m_type & ~SpecInt32)
69 m_result = false;
70 return;
71
72 case KnownNumberUse:
fpizlo@apple.com6921b292013-09-18 17:14:02 +000073 if (m_state.forNode(edge).m_type & ~SpecFullNumber)
oliver@apple.com83d2d022013-07-25 04:05:20 +000074 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; }
95private:
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.
104template<typename AbstractStateType>
105bool 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 WeakJSConstant:
115 case Identity:
116 case ToThis:
117 case CreateThis:
118 case GetCallee:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000119 case GetLocal:
120 case SetLocal:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000121 case MovHint:
122 case ZombieHint:
123 case GetArgument:
124 case Phantom:
fpizlo@apple.com4c96a842014-02-13 22:46:51 +0000125 case HardPhantom:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000126 case Upsilon:
127 case Phi:
128 case Flush:
129 case PhantomLocal:
130 case GetLocalUnlinked:
131 case SetArgument:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000132 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 Int32ToDouble:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000141 case DoubleAsInt32:
142 case ArithAdd:
143 case ArithSub:
144 case ArithNegate:
145 case ArithMul:
146 case ArithIMul:
147 case ArithDiv:
148 case ArithMod:
149 case ArithAbs:
150 case ArithMin:
151 case ArithMax:
152 case ArithSqrt:
fpizlo@apple.comb3336c72013-10-31 19:19:15 +0000153 case ArithSin:
154 case ArithCos:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000155 case ValueAdd:
156 case GetById:
157 case GetByIdFlush:
158 case PutById:
oliver@apple.com11ce5ff2014-03-06 21:27:13 +0000159 case PutByIdFlush:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000160 case PutByIdDirect:
161 case CheckStructure:
162 case CheckExecutable:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000163 case GetButterfly:
164 case CheckArray:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000165 case Arrayify:
166 case ArrayifyToStructure:
167 case GetScope:
168 case GetMyScope:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000169 case SkipTopScope:
170 case SkipScope:
171 case GetClosureRegisters:
172 case GetClosureVar:
173 case PutClosureVar:
174 case GetGlobalVar:
175 case PutGlobalVar:
fpizlo@apple.com86468342013-11-27 02:47:43 +0000176 case VariableWatchpoint:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000177 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:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000189 case Call:
190 case Construct:
191 case NewObject:
192 case NewArray:
193 case NewArrayWithSize:
194 case NewArrayBuffer:
195 case NewRegexp:
196 case Breakpoint:
mark.lam@apple.comeb19fea2014-01-23 23:13:23 +0000197 case ProfileWillCall:
198 case ProfileDidCall:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000199 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:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000235 case CheckWatchdogTimer:
236 case StringFromCharCode:
fpizlo@apple.com372fa822013-08-21 19:43:47 +0000237 case NewTypedArray:
oliver@apple.com1fc04182013-08-19 19:40:13 +0000238 case Unreachable:
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000239 case ExtractOSREntryLocal:
240 case CheckTierUpInLoop:
241 case CheckTierUpAtReturn:
242 case CheckTierUpAndOSREnter:
243 case LoopHint:
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000244 case Int52ToDouble:
245 case Int52ToValue:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000246 case StoreBarrier:
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +0000247 case StoreBarrierWithNullCheck:
fpizlo@apple.comd84425d2013-10-30 19:58:08 +0000248 case InvalidationPoint:
fpizlo@apple.com86468342013-11-27 02:47:43 +0000249 case NotifyWrite:
fpizlo@apple.coma4ea0662013-12-02 19:09:15 +0000250 case FunctionReentryWatchpoint:
fpizlo@apple.comce995b22013-12-08 19:01:17 +0000251 case TypedArrayWatchpoint:
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000252 case CheckInBounds:
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +0000253 case ConstantStoragePointer:
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000254 case Check:
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000255 case MultiGetByOffset:
fpizlo@apple.com43219522014-02-25 02:02:50 +0000256 case MultiPutByOffset:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000257 return true;
258
259 case GetByVal:
260 case GetIndexedPropertyStorage:
261 case GetArrayLength:
262 case ArrayPush:
263 case ArrayPop:
264 case StringCharAt:
265 case StringCharCodeAt:
266 return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
267
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000268 case GetTypedArrayByteOffset:
269 return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
oliver@apple.come050d642013-10-19 00:09:28 +0000270
271 case PutByValDirect:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000272 case PutByVal:
273 case PutByValAlias:
274 return node->arrayMode().modeForPut().alreadyChecked(
275 graph, node, state.forNode(graph.varArgChild(node, 0)));
276
277 case StructureTransitionWatchpoint:
oliver@apple.com83d2d022013-07-25 04:05:20 +0000278 return state.forNode(node->child1()).m_futurePossibleStructure.isSubsetOf(
279 StructureSet(node->structure()));
280
281 case PutStructure:
282 case PhantomPutStructure:
283 case AllocatePropertyStorage:
284 case ReallocatePropertyStorage:
285 return state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf(
286 StructureSet(node->structureTransitionData().previousStructure));
287
288 case GetByOffset:
289 case PutByOffset:
290 return state.forNode(node->child1()).m_currentKnownStructure.isValidOffset(
291 graph.m_storageAccessData[node->storageAccessDataIndex()].offset);
292
293 case LastNodeType:
294 RELEASE_ASSERT_NOT_REACHED();
295 return false;
296 }
297
298 RELEASE_ASSERT_NOT_REACHED();
299 return false;
300}
301
302} } // namespace JSC::DFG
303
304#endif // ENABLE(DFG_JIT)
305
306#endif // DFGSafeToExecute_h
307