Remove AllocationProfileWatchpoint node
[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 RegExpExec:
183     case RegExpTest:
184     case CompareLess:
185     case CompareLessEq:
186     case CompareGreater:
187     case CompareGreaterEq:
188     case CompareEq:
189     case CompareEqConstant:
190     case CompareStrictEq:
191     case Call:
192     case Construct:
193     case CallVarargs:
194     case ConstructVarargs:
195     case LoadVarargs:
196     case CallForwardVarargs:
197     case ConstructForwardVarargs:
198     case NewObject:
199     case NewArray:
200     case NewArrayWithSize:
201     case NewArrayBuffer:
202     case NewRegexp:
203     case Breakpoint:
204     case ProfileWillCall:
205     case ProfileDidCall:
206     case ProfileType:
207     case ProfileControlFlow:
208     case CheckHasInstance:
209     case InstanceOf:
210     case IsUndefined:
211     case IsBoolean:
212     case IsNumber:
213     case IsString:
214     case IsObject:
215     case IsObjectOrNull:
216     case IsFunction:
217     case TypeOf:
218     case LogicalNot:
219     case ToPrimitive:
220     case ToString:
221     case CallStringConstructor:
222     case NewStringObject:
223     case MakeRope:
224     case In:
225     case CreateActivation:
226     case CreateDirectArguments:
227     case CreateScopedArguments:
228     case CreateClonedArguments:
229     case GetFromArguments:
230     case PutToArguments:
231     case NewFunction:
232     case Jump:
233     case Branch:
234     case Switch:
235     case Return:
236     case Throw:
237     case ThrowReferenceError:
238     case CountExecution:
239     case ForceOSRExit:
240     case CheckWatchdogTimer:
241     case StringFromCharCode:
242     case NewTypedArray:
243     case Unreachable:
244     case ExtractOSREntryLocal:
245     case CheckTierUpInLoop:
246     case CheckTierUpAtReturn:
247     case CheckTierUpAndOSREnter:
248     case LoopHint:
249     case StoreBarrier:
250     case StoreBarrierWithNullCheck:
251     case InvalidationPoint:
252     case NotifyWrite:
253     case CheckInBounds:
254     case ConstantStoragePointer:
255     case Check:
256     case MultiGetByOffset:
257     case MultiPutByOffset:
258     case ValueRep:
259     case DoubleRep:
260     case Int52Rep:
261     case BooleanToNumber:
262     case FiatInt52:
263     case GetGetter:
264     case GetSetter:
265     case GetEnumerableLength:
266     case HasGenericProperty:
267     case HasStructureProperty:
268     case HasIndexedProperty:
269     case GetDirectPname:
270     case GetPropertyEnumerator:
271     case GetEnumeratorStructurePname:
272     case GetEnumeratorGenericPname:
273     case ToIndexString:
274     case PhantomNewObject:
275     case PutHint:
276     case CheckStructureImmediate:
277     case MaterializeNewObject:
278     case PhantomDirectArguments:
279     case PhantomClonedArguments:
280     case GetMyArgumentByVal:
281     case ForwardVarargs:
282         return true;
283
284     case NativeCall:
285     case NativeConstruct:
286         return false; // TODO: add a check for already checked.  https://bugs.webkit.org/show_bug.cgi?id=133769
287
288     case BottomValue:
289         // If in doubt, assume that this isn't safe to execute, just because we have no way of
290         // compiling this node.
291         return false;
292
293     case GetByVal:
294     case GetIndexedPropertyStorage:
295     case GetArrayLength:
296     case ArrayPush:
297     case ArrayPop:
298     case StringCharAt:
299     case StringCharCodeAt:
300         return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
301         
302     case GetTypedArrayByteOffset:
303         return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
304             
305     case PutByValDirect:
306     case PutByVal:
307     case PutByValAlias:
308         return node->arrayMode().modeForPut().alreadyChecked(
309             graph, node, state.forNode(graph.varArgChild(node, 0)));
310
311     case PutStructure:
312     case AllocatePropertyStorage:
313     case ReallocatePropertyStorage:
314         return state.forNode(node->child1()).m_structure.isSubsetOf(
315             StructureSet(node->transition()->previous));
316         
317     case GetByOffset:
318     case GetGetterSetterByOffset:
319     case PutByOffset: {
320         StructureAbstractValue& value = state.forNode(node->child1()).m_structure;
321         if (value.isTop())
322             return false;
323         PropertyOffset offset = node->storageAccessData().offset;
324         for (unsigned i = value.size(); i--;) {
325             if (!value[i]->isValidOffset(offset))
326                 return false;
327         }
328         return true;
329     }
330         
331     case LastNodeType:
332         RELEASE_ASSERT_NOT_REACHED();
333         return false;
334     }
335     
336     RELEASE_ASSERT_NOT_REACHED();
337     return false;
338 }
339
340 } } // namespace JSC::DFG
341
342 #endif // ENABLE(DFG_JIT)
343
344 #endif // DFGSafeToExecute_h
345