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