OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 the V8 project authors. All rights reserved. | |
Benedikt Meurer
2015/01/12 05:36:27
Nit: 2015 ;-)
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/codegen.h" | |
6 #include "src/compiler/common-operator.h" | |
7 #include "src/compiler/diamond.h" | |
8 #include "src/compiler/graph.h" | |
9 #include "src/compiler/js-graph.h" | |
10 #include "src/compiler/js-operator.h" | |
11 #include "src/compiler/operator.h" | |
12 #include "src/compiler/osr.h" | |
13 #include "test/cctest/cctest.h" | |
14 | |
15 using namespace v8::internal; | |
16 using namespace v8::internal::compiler; | |
17 | |
18 // TODO(titzer): move this method to a common testing place. | |
19 | |
20 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, | |
21 Node* i2 = NULL, Node* i3 = NULL) { | |
22 int count = 4; | |
23 if (i3 == NULL) count = 3; | |
24 if (i2 == NULL) count = 2; | |
25 if (i1 == NULL) count = 1; | |
26 if (i0 == NULL) count = 0; | |
27 CHECK_EQ(count, node->InputCount()); | |
28 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); | |
29 if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); | |
30 if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); | |
31 if (i3 != NULL) CHECK_EQ(i3, node->InputAt(3)); | |
32 return count; | |
33 } | |
34 | |
35 | |
36 static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure, | |
Benedikt Meurer
2015/01/12 05:36:27
Why not use the MachineOperatorBuilder instead?
titzer
2015/01/12 10:43:53
I think we should add a TestOperatorBuilder, since
Benedikt Meurer
2015/01/12 11:12:12
Mhm, yeah we should think about something like tha
| |
37 "Int32LessThan", 2, 0, 0, 1, 0, 0); | |
38 | |
39 | |
40 static const int kMaxOsrValues = 10; | |
41 | |
42 class OsrDeconstructorTester : public HandleAndZoneScope { | |
43 public: | |
44 explicit OsrDeconstructorTester(int num_values) | |
45 : isolate(main_isolate()), | |
46 common(main_zone()), | |
47 graph(main_zone()), | |
48 jsgraph(&graph, &common, NULL, NULL), | |
49 start(graph.NewNode(common.Start(1))), | |
50 p0(graph.NewNode(common.Parameter(0), start)), | |
51 end(graph.NewNode(common.End(), start)), | |
52 osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start)), | |
53 osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start)), | |
54 self(graph.NewNode(common.Int32Constant(0xaabbccdd))) { | |
55 CHECK(num_values <= kMaxOsrValues); | |
56 graph.SetStart(start); | |
57 for (int i = 0; i < num_values; i++) { | |
58 osr_values[i] = graph.NewNode(common.OsrValue(i), osr_loop_entry); | |
59 } | |
60 } | |
61 | |
62 Isolate* isolate; | |
63 CommonOperatorBuilder common; | |
64 Graph graph; | |
65 JSGraph jsgraph; | |
66 Node* start; | |
67 Node* p0; | |
68 Node* end; | |
69 Node* osr_normal_entry; | |
70 Node* osr_loop_entry; | |
71 Node* self; | |
72 Node* osr_values[kMaxOsrValues]; | |
73 | |
74 Node* NewOsrPhi(Node* loop, Node* incoming, int osr_value, Node* back1 = NULL, | |
75 Node* back2 = NULL, Node* back3 = NULL) { | |
76 int count = 5; | |
77 if (back3 == NULL) count = 4; | |
78 if (back2 == NULL) count = 3; | |
79 if (back1 == NULL) count = 2; | |
80 CHECK_EQ(loop->InputCount(), count); | |
81 CHECK_EQ(osr_loop_entry, loop->InputAt(1)); | |
82 | |
83 Node* inputs[6]; | |
84 inputs[0] = incoming; | |
85 inputs[1] = osr_values[osr_value]; | |
86 if (count > 2) inputs[2] = back1; | |
87 if (count > 3) inputs[3] = back2; | |
88 if (count > 4) inputs[4] = back3; | |
89 inputs[count] = loop; | |
90 return graph.NewNode(common.Phi(kMachAnyTagged, count), count + 1, inputs); | |
91 } | |
92 | |
93 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) { | |
94 CHECK_LT(num_backedges, 4); | |
95 CHECK_GE(num_backedges, 0); | |
96 int count = 2 + num_backedges; | |
97 if (entry == NULL) entry = osr_normal_entry; | |
98 Node* inputs[5] = {entry, osr_loop_entry, self, self, self}; | |
99 | |
100 Node* loop = graph.NewNode(common.Loop(count), count, inputs); | |
101 for (int i = 0; i < num_backedges; i++) { | |
102 loop->ReplaceInput(2 + i, loop); | |
103 } | |
104 | |
105 return loop; | |
106 } | |
107 }; | |
108 | |
109 | |
110 TEST(Deconstruct_osr0) { | |
111 OsrDeconstructorTester T(0); | |
112 | |
113 Node* loop = T.NewOsrLoop(1); | |
114 | |
115 T.graph.SetEnd(loop); | |
116 | |
117 OsrHelper helper(0, 0); | |
118 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
119 | |
120 CheckInputs(loop, T.start, loop); | |
121 } | |
122 | |
123 | |
124 TEST(Deconstruct_osr1) { | |
125 OsrDeconstructorTester T(1); | |
126 | |
127 Node* loop = T.NewOsrLoop(1); | |
128 Node* osr_phi = | |
129 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | |
130 | |
131 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); | |
132 T.graph.SetEnd(ret); | |
133 | |
134 OsrHelper helper(0, 0); | |
135 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
136 | |
137 CheckInputs(loop, T.start, loop); | |
138 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | |
139 CheckInputs(ret, osr_phi, T.start, loop); | |
140 } | |
141 | |
142 | |
143 TEST(Deconstruct_osr_remove_prologue) { | |
144 OsrDeconstructorTester T(1); | |
145 Diamond d(&T.graph, &T.common, T.p0); | |
146 d.Chain(T.osr_normal_entry); | |
147 | |
148 Node* loop = T.NewOsrLoop(1, d.merge); | |
149 Node* osr_phi = | |
150 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | |
151 | |
152 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); | |
153 T.graph.SetEnd(ret); | |
154 | |
155 OsrHelper helper(0, 0); | |
156 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
157 | |
158 CheckInputs(loop, T.start, loop); | |
159 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | |
160 CheckInputs(ret, osr_phi, T.start, loop); | |
161 | |
162 // The control before the loop should have been removed. | |
163 CHECK(d.branch->IsDead()); | |
164 CHECK(d.if_true->IsDead()); | |
165 CHECK(d.if_false->IsDead()); | |
166 CHECK(d.merge->IsDead()); | |
167 } | |
168 | |
169 | |
170 TEST(Deconstruct_osr_with_body1) { | |
171 OsrDeconstructorTester T(1); | |
172 | |
173 Node* loop = T.NewOsrLoop(1); | |
174 | |
175 Node* branch = T.graph.NewNode(T.common.Branch(), T.p0, loop); | |
176 Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch); | |
177 Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch); | |
178 loop->ReplaceInput(2, if_true); | |
179 | |
180 Node* osr_phi = | |
181 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | |
182 | |
183 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false); | |
184 T.graph.SetEnd(ret); | |
185 | |
186 OsrHelper helper(0, 0); | |
187 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
188 | |
189 CheckInputs(loop, T.start, if_true); | |
190 CheckInputs(branch, T.p0, loop); | |
191 CheckInputs(if_true, branch); | |
192 CheckInputs(if_false, branch); | |
193 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | |
194 CheckInputs(ret, osr_phi, T.start, if_false); | |
195 } | |
196 | |
197 | |
198 TEST(Deconstruct_osr_with_body2) { | |
199 OsrDeconstructorTester T(1); | |
200 | |
201 Node* loop = T.NewOsrLoop(1); | |
202 | |
203 // Two chained branches in the the body of the loop. | |
204 Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop); | |
205 Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1); | |
206 Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1); | |
207 | |
208 Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1); | |
209 Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2); | |
210 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2); | |
211 loop->ReplaceInput(2, if_true2); | |
212 | |
213 Node* osr_phi = | |
214 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | |
215 | |
216 Node* merge = T.graph.NewNode(T.common.Merge(2), if_false1, if_false2); | |
217 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, merge); | |
218 T.graph.SetEnd(ret); | |
219 | |
220 OsrHelper helper(0, 0); | |
221 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
222 | |
223 CheckInputs(loop, T.start, if_true2); | |
224 CheckInputs(branch1, T.p0, loop); | |
225 CheckInputs(branch2, T.p0, if_true1); | |
226 CheckInputs(if_true1, branch1); | |
227 CheckInputs(if_false1, branch1); | |
228 CheckInputs(if_true2, branch2); | |
229 CheckInputs(if_false2, branch2); | |
230 | |
231 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | |
232 CheckInputs(ret, osr_phi, T.start, merge); | |
233 CheckInputs(merge, if_false1, if_false2); | |
234 } | |
235 | |
236 | |
237 TEST(Deconstruct_osr_with_body3) { | |
238 OsrDeconstructorTester T(1); | |
239 | |
240 Node* loop = T.NewOsrLoop(2); | |
241 | |
242 // Two branches that create two different backedges. | |
243 Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop); | |
244 Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1); | |
245 Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1); | |
246 | |
247 Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1); | |
248 Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2); | |
249 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2); | |
250 loop->ReplaceInput(2, if_false1); | |
251 loop->ReplaceInput(3, if_true2); | |
252 | |
253 Node* osr_phi = | |
254 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant(), | |
255 T.jsgraph.ZeroConstant()); | |
256 | |
257 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false2); | |
258 T.graph.SetEnd(ret); | |
259 | |
260 OsrHelper helper(0, 0); | |
261 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
262 | |
263 CheckInputs(loop, T.start, if_false1, if_true2); | |
264 CheckInputs(branch1, T.p0, loop); | |
265 CheckInputs(branch2, T.p0, if_true1); | |
266 CheckInputs(if_true1, branch1); | |
267 CheckInputs(if_false1, branch1); | |
268 CheckInputs(if_true2, branch2); | |
269 CheckInputs(if_false2, branch2); | |
270 | |
271 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), | |
272 T.jsgraph.ZeroConstant(), loop); | |
273 CheckInputs(ret, osr_phi, T.start, if_false2); | |
274 } | |
OLD | NEW |