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