bf99b12d3d5810dcf986c5780747cc47bc724040
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSafeToExecute.h
1 /*
2  * Copyright (C) 2013 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 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGGraph.h"
34
35 namespace JSC { namespace DFG {
36
37 template<typename AbstractStateType>
38 class SafeToExecuteEdge {
39 public:
40     SafeToExecuteEdge(AbstractStateType& state)
41         : m_state(state)
42         , m_result(true)
43     {
44     }
45     
46     void operator()(Node*, Edge edge)
47     {
48         switch (edge.useKind()) {
49         case UntypedUse:
50         case Int32Use:
51         case RealNumberUse:
52         case NumberUse:
53         case BooleanUse:
54         case CellUse:
55         case ObjectUse:
56         case ObjectOrOtherUse:
57         case StringIdentUse:
58         case StringUse:
59         case StringObjectUse:
60         case StringOrStringObjectUse:
61         case NotCellUse:
62         case OtherUse:
63             return;
64             
65         case KnownInt32Use:
66             if (m_state.forNode(edge).m_type & ~SpecInt32)
67                 m_result = false;
68             return;
69             
70         case KnownNumberUse:
71             if (m_state.forNode(edge).m_type & ~SpecNumber)
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 WeakJSConstant:
113     case Identity:
114     case ToThis:
115     case CreateThis:
116     case GetCallee:
117     case SetCallee:
118     case GetLocal:
119     case SetLocal:
120     case MovHintAndCheck:
121     case MovHint:
122     case ZombieHint:
123     case GetArgument:
124     case Phantom:
125     case Upsilon:
126     case Phi:
127     case Flush:
128     case PhantomLocal:
129     case GetLocalUnlinked:
130     case SetArgument:
131     case InlineStart:
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 Int32ToDouble:
141     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:
153     case ValueAdd:
154     case GetById:
155     case GetByIdFlush:
156     case PutById:
157     case PutByIdDirect:
158     case CheckStructure:
159     case CheckExecutable:
160     case GetButterfly:
161     case CheckArray:
162     case Arrayify:
163     case ArrayifyToStructure:
164     case GetScope:
165     case GetMyScope:
166     case SetMyScope:
167     case SkipTopScope:
168     case SkipScope:
169     case GetClosureRegisters:
170     case GetClosureVar:
171     case PutClosureVar:
172     case GetGlobalVar:
173     case PutGlobalVar:
174     case GlobalVarWatchpoint:
175     case VarInjectionWatchpoint:
176     case CheckFunction:
177     case AllocationProfileWatchpoint:
178     case RegExpExec:
179     case RegExpTest:
180     case CompareLess:
181     case CompareLessEq:
182     case CompareGreater:
183     case CompareGreaterEq:
184     case CompareEq:
185     case CompareEqConstant:
186     case CompareStrictEq:
187     case CompareStrictEqConstant:
188     case Call:
189     case Construct:
190     case NewObject:
191     case NewArray:
192     case NewArrayWithSize:
193     case NewArrayBuffer:
194     case NewRegexp:
195     case Breakpoint:
196     case CheckHasInstance:
197     case InstanceOf:
198     case IsUndefined:
199     case IsBoolean:
200     case IsNumber:
201     case IsString:
202     case IsObject:
203     case IsFunction:
204     case TypeOf:
205     case LogicalNot:
206     case ToPrimitive:
207     case ToString:
208     case NewStringObject:
209     case MakeRope:
210     case In:
211     case CreateActivation:
212     case TearOffActivation:
213     case CreateArguments:
214     case PhantomArguments:
215     case TearOffArguments:
216     case GetMyArgumentsLength:
217     case GetMyArgumentByVal:
218     case GetMyArgumentsLengthSafe:
219     case GetMyArgumentByValSafe:
220     case CheckArgumentsNotCreated:
221     case NewFunctionNoCheck:
222     case NewFunction:
223     case NewFunctionExpression:
224     case Jump:
225     case Branch:
226     case Switch:
227     case Return:
228     case Throw:
229     case ThrowReferenceError:
230     case CountExecution:
231     case ForceOSRExit:
232     case CheckWatchdogTimer:
233     case StringFromCharCode:
234     case NewTypedArray:
235     case Unreachable:
236         return true;
237         
238     case GetByVal:
239     case GetIndexedPropertyStorage:
240     case GetArrayLength:
241     case ArrayPush:
242     case ArrayPop:
243     case StringCharAt:
244     case StringCharCodeAt:
245         return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
246         
247     case GetTypedArrayByteOffset:
248         return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
249         
250     case PutByVal:
251     case PutByValAlias:
252         return node->arrayMode().modeForPut().alreadyChecked(
253             graph, node, state.forNode(graph.varArgChild(node, 0)));
254
255     case StructureTransitionWatchpoint:
256         return state.forNode(node->child1()).m_futurePossibleStructure.isSubsetOf(
257             StructureSet(node->structure()));
258         
259     case PutStructure:
260     case PhantomPutStructure:
261     case AllocatePropertyStorage:
262     case ReallocatePropertyStorage:
263         return state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf(
264             StructureSet(node->structureTransitionData().previousStructure));
265         
266     case GetByOffset:
267     case PutByOffset:
268         return state.forNode(node->child1()).m_currentKnownStructure.isValidOffset(
269             graph.m_storageAccessData[node->storageAccessDataIndex()].offset);
270         
271     case LastNodeType:
272         RELEASE_ASSERT_NOT_REACHED();
273         return false;
274     }
275     
276     RELEASE_ASSERT_NOT_REACHED();
277     return false;
278 }
279
280 } } // namespace JSC::DFG
281
282 #endif // ENABLE(DFG_JIT)
283
284 #endif // DFGSafeToExecute_h
285