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