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
37namespace JSC { namespace DFG {
38
39namespace {
40
41template<typename StateType>
42ExitMode 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 NewSymbol:
128 case NewRegexp:
129 case ToNumber:
130 case RegExpExecNonGlobalOrSticky:
131 case RegExpMatchFastGlobal:
132 result = ExitsForExceptions;
133 break;
134
135 case SetRegExpObjectLastIndex:
136 if (node->ignoreLastIndexIsWritable())
137 break;
138 return Exits;
139
140 default:
141 // If in doubt, return true.
142 return Exits;
143 }
144
145 graph.doToChildren(
146 node,
147 [&] (Edge& edge) {
148 if (state) {
149 // Ignore the Check flag on the edge. This is important because that flag answers
150 // the question: "would this edge have had a check if it executed wherever it
151 // currently resides in control flow?" But when a state is passed, we want to ask a
152 // different question: "would this edge have a check if it executed wherever this
153 // state is?" Using the Check flag for this purpose wouldn't even be conservatively
154 // correct. It would be wrong in both directions.
155 if (mayHaveTypeCheck(edge.useKind())
156 && (state.forNode(edge).m_type & ~typeFilterFor(edge.useKind()))) {
157 result = Exits;
158 return;
159 }
160 } else {
161 // FIXME: Maybe this should call mayHaveTypeCheck(edge.useKind()) instead.
162 // https://bugs.webkit.org/show_bug.cgi?id=148545
163 if (edge.willHaveCheck()) {
164 result = Exits;
165 return;
166 }
167 }
168
169 switch (edge.useKind()) {
170 // These are shady because nodes that have these use kinds will typically exit for
171 // unrelated reasons. For example CompareEq doesn't usually exit, but if it uses
172 // ObjectUse then it will.
173 case ObjectUse:
174 case ObjectOrOtherUse:
175 result = Exits;
176 break;
177
178 default:
179 break;
180 }
181 });
182
183 return result;
184}
185
186} // anonymous namespace
187
188ExitMode mayExit(Graph& graph, Node* node)
189{
190 NullAbstractState state;
191 return mayExitImpl(graph, node, state);
192}
193
194ExitMode mayExit(Graph& graph, Node* node, AtTailAbstractState& state)
195{
196 return mayExitImpl(graph, node, state);
197}
198
199} } // namespace JSC::DFG
200
201namespace WTF {
202
203using namespace JSC::DFG;
204
205void printInternal(PrintStream& out, ExitMode mode)
206{
207 switch (mode) {
208 case DoesNotExit:
209 out.print("DoesNotExit");
210 return;
211 case ExitsForExceptions:
212 out.print("ExitsForExceptions");
213 return;
214 case Exits:
215 out.print("Exits");
216 return;
217 }
218 RELEASE_ASSERT_NOT_REACHED();
219}
220
221} // namespace WTF
222
223#endif // ENABLE(DFG_JIT)
224