[ES6] DFG and FTL should be aware of that StringConstructor behavior for symbols...
[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 TypedArrayWatchpoint:
255     case CheckInBounds:
256     case ConstantStoragePointer:
257     case Check:
258     case MultiGetByOffset:
259     case MultiPutByOffset:
260     case ValueRep:
261     case DoubleRep:
262     case Int52Rep:
263     case BooleanToNumber:
264     case FiatInt52:
265     case GetGetter:
266     case GetSetter:
267     case GetEnumerableLength:
268     case HasGenericProperty:
269     case HasStructureProperty:
270     case HasIndexedProperty:
271     case GetDirectPname:
272     case GetPropertyEnumerator:
273     case GetEnumeratorStructurePname:
274     case GetEnumeratorGenericPname:
275     case ToIndexString:
276     case PhantomNewObject:
277     case PutHint:
278     case CheckStructureImmediate:
279     case MaterializeNewObject:
280     case PhantomDirectArguments:
281     case PhantomClonedArguments:
282     case GetMyArgumentByVal:
283     case ForwardVarargs:
284         return true;
285
286     case NativeCall:
287     case NativeConstruct:
288         return false; // TODO: add a check for already checked.  https://bugs.webkit.org/show_bug.cgi?id=133769
289
290     case BottomValue:
291         // If in doubt, assume that this isn't safe to execute, just because we have no way of
292         // compiling this node.
293         return false;
294
295     case GetByVal:
296     case GetIndexedPropertyStorage:
297     case GetArrayLength:
298     case ArrayPush:
299     case ArrayPop:
300     case StringCharAt:
301     case StringCharCodeAt:
302         return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
303         
304     case GetTypedArrayByteOffset:
305         return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
306             
307     case PutByValDirect:
308     case PutByVal:
309     case PutByValAlias:
310         return node->arrayMode().modeForPut().alreadyChecked(
311             graph, node, state.forNode(graph.varArgChild(node, 0)));
312
313     case PutStructure:
314     case AllocatePropertyStorage:
315     case ReallocatePropertyStorage:
316         return state.forNode(node->child1()).m_structure.isSubsetOf(
317             StructureSet(node->transition()->previous));
318         
319     case GetByOffset:
320     case GetGetterSetterByOffset:
321     case PutByOffset: {
322         StructureAbstractValue& value = state.forNode(node->child1()).m_structure;
323         if (value.isTop())
324             return false;
325         PropertyOffset offset = node->storageAccessData().offset;
326         for (unsigned i = value.size(); i--;) {
327             if (!value[i]->isValidOffset(offset))
328                 return false;
329         }
330         return true;
331     }
332         
333     case LastNodeType:
334         RELEASE_ASSERT_NOT_REACHED();
335         return false;
336     }
337     
338     RELEASE_ASSERT_NOT_REACHED();
339     return false;
340 }
341
342 } } // namespace JSC::DFG
343
344 #endif // ENABLE(DFG_JIT)
345
346 #endif // DFGSafeToExecute_h
347