We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGMayExit.cpp
1 /*
2  * Copyright (C) 2014-2016 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 #include "config.h"
27 #include "DFGMayExit.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGAtTailAbstractState.h"
32 #include "DFGGraph.h"
33 #include "DFGNode.h"
34 #include "DFGNullAbstractState.h"
35 #include "Operations.h"
36
37 namespace JSC { namespace DFG {
38
39 namespace {
40
41 template<typename StateType>
42 ExitMode mayExitImpl(Graph& graph, Node* node, StateType& state)
43 {
44     ExitMode result = DoesNotExit;
45     
46     switch (node->op()) {
47     // This is a carefully curated list of nodes that definitely do not exit. We try to be very
48     // conservative when maintaining this list, because adding new node types to it doesn't
49     // generally make things a lot better but it might introduce subtle bugs.
50     case SetArgument:
51     case JSConstant:
52     case DoubleConstant:
53     case LazyJSConstant:
54     case Int52Constant:
55     case MovHint:
56     case InitializeEntrypointArguments:
57     case SetLocal:
58     case Flush:
59     case Phantom:
60     case Check:
61     case CheckVarargs:
62     case Identity:
63     case IdentityWithProfile:
64     case GetLocal:
65     case LoopHint:
66     case Phi:
67     case Upsilon:
68     case ZombieHint:
69     case ExitOK:
70     case BottomValue:
71     case PutHint:
72     case PhantomNewObject:
73     case PutStack:
74     case KillStack:
75     case GetStack:
76     case GetCallee:
77     case SetCallee:
78     case GetArgumentCountIncludingThis:
79     case SetArgumentCountIncludingThis:
80     case GetRestLength:
81     case GetScope:
82     case PhantomLocal:
83     case CountExecution:
84     case SuperSamplerBegin:
85     case SuperSamplerEnd:
86     case Jump:
87     case EntrySwitch:
88     case Branch:
89     case Unreachable:
90     case DoubleRep:
91     case Int52Rep:
92     case ValueRep:
93     case ExtractOSREntryLocal:
94     case ExtractCatchLocal:
95     case ClearCatchLocals:
96     case LogicalNot:
97     case NotifyWrite:
98     case PutStructure:
99     case StoreBarrier:
100     case FencedStoreBarrier:
101     case PutByOffset:
102     case PutClosureVar:
103     case RecordRegExpCachedResult:
104     case NukeStructureAndSetButterfly:
105     case FilterCallLinkStatus:
106     case FilterGetByIdStatus:
107     case FilterPutByIdStatus:
108     case FilterInByIdStatus:
109         break;
110
111     case StrCat:
112     case Call:
113     case Construct:
114     case CallVarargs:
115     case CallEval:
116     case ConstructVarargs:
117     case CallForwardVarargs:
118     case ConstructForwardVarargs:
119     case CreateActivation:
120     case MaterializeCreateActivation:
121     case MaterializeNewObject:
122     case NewFunction:
123     case NewGeneratorFunction:
124     case NewAsyncFunction:
125     case NewAsyncGeneratorFunction:
126     case NewStringObject:
127     case NewRegexp:
128     case ToNumber:
129     case RegExpExecNonGlobalOrSticky:
130     case RegExpMatchFastGlobal:
131         result = ExitsForExceptions;
132         break;
133
134     case SetRegExpObjectLastIndex:
135         if (node->ignoreLastIndexIsWritable())
136             break;
137         return Exits;
138
139     default:
140         // If in doubt, return true.
141         return Exits;
142     }
143     
144     graph.doToChildren(
145         node,
146         [&] (Edge& edge) {
147             if (state) {
148                 // Ignore the Check flag on the edge. This is important because that flag answers
149                 // the question: "would this edge have had a check if it executed wherever it
150                 // currently resides in control flow?" But when a state is passed, we want to ask a
151                 // different question: "would this edge have a check if it executed wherever this
152                 // state is?" Using the Check flag for this purpose wouldn't even be conservatively
153                 // correct. It would be wrong in both directions.
154                 if (mayHaveTypeCheck(edge.useKind())
155                     && (state.forNode(edge).m_type & ~typeFilterFor(edge.useKind()))) {
156                     result = Exits;
157                     return;
158                 }
159             } else {
160                 // FIXME: Maybe this should call mayHaveTypeCheck(edge.useKind()) instead.
161                 // https://bugs.webkit.org/show_bug.cgi?id=148545
162                 if (edge.willHaveCheck()) {
163                     result = Exits;
164                     return;
165                 }
166             }
167             
168             switch (edge.useKind()) {
169             // These are shady because nodes that have these use kinds will typically exit for
170             // unrelated reasons. For example CompareEq doesn't usually exit, but if it uses
171             // ObjectUse then it will.
172             case ObjectUse:
173             case ObjectOrOtherUse:
174                 result = Exits;
175                 break;
176                 
177             // These are shady because they check the structure even if the type of the child node
178             // passes the StringObject type filter.
179             case StringObjectUse:
180             case StringOrStringObjectUse:
181                 result = Exits;
182                 break;
183                 
184             default:
185                 break;
186             }
187         });
188
189     return result;
190 }
191
192 } // anonymous namespace
193
194 ExitMode mayExit(Graph& graph, Node* node)
195 {
196     NullAbstractState state;
197     return mayExitImpl(graph, node, state);
198 }
199
200 ExitMode mayExit(Graph& graph, Node* node, AtTailAbstractState& state)
201 {
202     return mayExitImpl(graph, node, state);
203 }
204
205 } } // namespace JSC::DFG
206
207 namespace WTF {
208
209 using namespace JSC::DFG;
210
211 void printInternal(PrintStream& out, ExitMode mode)
212 {
213     switch (mode) {
214     case DoesNotExit:
215         out.print("DoesNotExit");
216         return;
217     case ExitsForExceptions:
218         out.print("ExitsForExceptions");
219         return;
220     case Exits:
221         out.print("Exits");
222         return;
223     }
224     RELEASE_ASSERT_NOT_REACHED();
225 }
226
227 } // namespace WTF
228
229 #endif // ENABLE(DFG_JIT)