Support compiling catch 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 Identity:
62     case IdentityWithProfile:
63     case GetLocal:
64     case LoopHint:
65     case Phi:
66     case Upsilon:
67     case ZombieHint:
68     case ExitOK:
69     case BottomValue:
70     case PutHint:
71     case PhantomNewObject:
72     case PutStack:
73     case KillStack:
74     case GetStack:
75     case GetCallee:
76     case GetArgumentCountIncludingThis:
77     case GetRestLength:
78     case GetScope:
79     case PhantomLocal:
80     case CountExecution:
81     case Jump:
82     case EntrySwitch:
83     case Branch:
84     case Unreachable:
85     case DoubleRep:
86     case Int52Rep:
87     case ValueRep:
88     case ExtractOSREntryLocal:
89     case ExtractCatchLocal:
90     case LogicalNot:
91     case NotifyWrite:
92     case PutStructure:
93     case StoreBarrier:
94     case FencedStoreBarrier:
95     case PutByOffset:
96     case PutClosureVar:
97     case RecordRegExpCachedResult:
98     case NukeStructureAndSetButterfly:
99         break;
100
101     case StrCat:
102     case Call:
103     case Construct:
104     case CallVarargs:
105     case CallEval:
106     case ConstructVarargs:
107     case CallForwardVarargs:
108     case ConstructForwardVarargs:
109     case CreateActivation:
110     case MaterializeCreateActivation:
111     case MaterializeNewObject:
112     case NewFunction:
113     case NewGeneratorFunction:
114     case NewAsyncFunction:
115     case NewAsyncGeneratorFunction:
116     case NewStringObject:
117     case ToNumber:
118         result = ExitsForExceptions;
119         break;
120
121     default:
122         // If in doubt, return true.
123         return Exits;
124     }
125     
126     graph.doToChildren(
127         node,
128         [&] (Edge& edge) {
129             if (state) {
130                 // Ignore the Check flag on the edge. This is important because that flag answers
131                 // the question: "would this edge have had a check if it executed wherever it
132                 // currently resides in control flow?" But when a state is passed, we want to ask a
133                 // different question: "would this edge have a check if it executed wherever this
134                 // state is?" Using the Check flag for this purpose wouldn't even be conservatively
135                 // correct. It would be wrong in both directions.
136                 if (mayHaveTypeCheck(edge.useKind())
137                     && (state.forNode(edge).m_type & ~typeFilterFor(edge.useKind()))) {
138                     result = Exits;
139                     return;
140                 }
141             } else {
142                 // FIXME: Maybe this should call mayHaveTypeCheck(edge.useKind()) instead.
143                 // https://bugs.webkit.org/show_bug.cgi?id=148545
144                 if (edge.willHaveCheck()) {
145                     result = Exits;
146                     return;
147                 }
148             }
149             
150             switch (edge.useKind()) {
151             // These are shady because nodes that have these use kinds will typically exit for
152             // unrelated reasons. For example CompareEq doesn't usually exit, but if it uses
153             // ObjectUse then it will.
154             case ObjectUse:
155             case ObjectOrOtherUse:
156                 result = Exits;
157                 break;
158                 
159             // These are shady because they check the structure even if the type of the child node
160             // passes the StringObject type filter.
161             case StringObjectUse:
162             case StringOrStringObjectUse:
163                 result = Exits;
164                 break;
165                 
166             default:
167                 break;
168             }
169         });
170
171     return result;
172 }
173
174 } // anonymous namespace
175
176 ExitMode mayExit(Graph& graph, Node* node)
177 {
178     NullAbstractState state;
179     return mayExitImpl(graph, node, state);
180 }
181
182 ExitMode mayExit(Graph& graph, Node* node, AtTailAbstractState& state)
183 {
184     return mayExitImpl(graph, node, state);
185 }
186
187 } } // namespace JSC::DFG
188
189 namespace WTF {
190
191 using namespace JSC::DFG;
192
193 void printInternal(PrintStream& out, ExitMode mode)
194 {
195     switch (mode) {
196     case DoesNotExit:
197         out.print("DoesNotExit");
198         return;
199     case ExitsForExceptions:
200         out.print("ExitsForExceptions");
201         return;
202     case Exits:
203         out.print("Exits");
204         return;
205     }
206     RELEASE_ASSERT_NOT_REACHED();
207 }
208
209 } // namespace WTF
210
211 #endif // ENABLE(DFG_JIT)