OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/codegen.h" | 5 #include "src/codegen.h" |
| 6 #include "src/compiler/all-nodes.h" |
6 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
7 #include "src/compiler/diamond.h" | 8 #include "src/compiler/diamond.h" |
8 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
9 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/js-operator.h" | 11 #include "src/compiler/js-operator.h" |
11 #include "src/compiler/operator.h" | 12 #include "src/compiler/operator.h" |
12 #include "src/compiler/osr.h" | 13 #include "src/compiler/osr.h" |
13 #include "test/cctest/cctest.h" | 14 #include "test/cctest/cctest.h" |
14 | 15 |
15 using namespace v8::internal; | 16 using namespace v8::internal; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 for (int i = 0; i < loop->InputCount(); i++) { | 106 for (int i = 0; i < loop->InputCount(); i++) { |
106 if (loop->InputAt(i) == self) loop->ReplaceInput(i, loop); | 107 if (loop->InputAt(i) == self) loop->ReplaceInput(i, loop); |
107 } | 108 } |
108 | 109 |
109 return loop; | 110 return loop; |
110 } | 111 } |
111 | 112 |
112 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) { | 113 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) { |
113 return NewLoop(true, num_backedges, entry); | 114 return NewLoop(true, num_backedges, entry); |
114 } | 115 } |
| 116 |
| 117 void DeconstructOsr() { |
| 118 OsrHelper helper(0, 0); |
| 119 helper.Deconstruct(&jsgraph, &common, main_zone()); |
| 120 AllNodes nodes(main_zone(), &graph); |
| 121 // Should be edited out. |
| 122 CHECK(!nodes.IsLive(osr_normal_entry)); |
| 123 CHECK(!nodes.IsLive(osr_loop_entry)); |
| 124 // No dangling nodes should be left over. |
| 125 CHECK_EQ(0u, nodes.gray.size()); |
| 126 } |
115 }; | 127 }; |
116 | 128 |
117 | 129 |
118 TEST(Deconstruct_osr0) { | 130 TEST(Deconstruct_osr0) { |
119 OsrDeconstructorTester T(0); | 131 OsrDeconstructorTester T(0); |
120 | 132 |
121 Node* loop = T.NewOsrLoop(1); | 133 Node* loop = T.NewOsrLoop(1); |
122 | 134 |
123 T.graph.SetEnd(loop); | 135 T.graph.SetEnd(loop); |
124 | 136 |
125 OsrHelper helper(0, 0); | 137 T.DeconstructOsr(); |
126 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
127 | 138 |
128 CheckInputs(loop, T.start, loop); | 139 CheckInputs(loop, T.start, loop); |
129 } | 140 } |
130 | 141 |
131 | 142 |
132 TEST(Deconstruct_osr1) { | 143 TEST(Deconstruct_osr1) { |
133 OsrDeconstructorTester T(1); | 144 OsrDeconstructorTester T(1); |
134 | 145 |
135 Node* loop = T.NewOsrLoop(1); | 146 Node* loop = T.NewOsrLoop(1); |
136 Node* osr_phi = | 147 Node* osr_phi = |
137 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | 148 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); |
138 | 149 |
139 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); | 150 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); |
140 T.graph.SetEnd(ret); | 151 T.graph.SetEnd(ret); |
141 | 152 |
142 OsrHelper helper(0, 0); | 153 T.DeconstructOsr(); |
143 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
144 | 154 |
145 CheckInputs(loop, T.start, loop); | 155 CheckInputs(loop, T.start, loop); |
146 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | 156 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); |
147 CheckInputs(ret, osr_phi, T.start, loop); | 157 CheckInputs(ret, osr_phi, T.start, loop); |
148 } | 158 } |
149 | 159 |
150 | 160 |
151 TEST(Deconstruct_osr_remove_prologue) { | 161 TEST(Deconstruct_osr_remove_prologue) { |
152 OsrDeconstructorTester T(1); | 162 OsrDeconstructorTester T(1); |
153 Diamond d(&T.graph, &T.common, T.p0); | 163 Diamond d(&T.graph, &T.common, T.p0); |
154 d.Chain(T.osr_normal_entry); | 164 d.Chain(T.osr_normal_entry); |
155 | 165 |
156 Node* loop = T.NewOsrLoop(1, d.merge); | 166 Node* loop = T.NewOsrLoop(1, d.merge); |
157 Node* osr_phi = | 167 Node* osr_phi = |
158 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | 168 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); |
159 | 169 |
160 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); | 170 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); |
161 T.graph.SetEnd(ret); | 171 T.graph.SetEnd(ret); |
162 | 172 |
163 OsrHelper helper(0, 0); | 173 T.DeconstructOsr(); |
164 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
165 | 174 |
166 CheckInputs(loop, T.start, loop); | 175 CheckInputs(loop, T.start, loop); |
167 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | 176 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); |
168 CheckInputs(ret, osr_phi, T.start, loop); | 177 CheckInputs(ret, osr_phi, T.start, loop); |
169 | 178 |
170 // The control before the loop should have been removed. | 179 // The control before the loop should have been removed. |
171 CHECK(d.branch->IsDead()); | 180 AllNodes nodes(T.main_zone(), &T.graph); |
172 CHECK(d.if_true->IsDead()); | 181 CHECK(!nodes.IsLive(d.branch)); |
173 CHECK(d.if_false->IsDead()); | 182 CHECK(!nodes.IsLive(d.if_true)); |
174 CHECK(d.merge->IsDead()); | 183 CHECK(!nodes.IsLive(d.if_false)); |
| 184 CHECK(!nodes.IsLive(d.merge)); |
175 } | 185 } |
176 | 186 |
177 | 187 |
178 TEST(Deconstruct_osr_with_body1) { | 188 TEST(Deconstruct_osr_with_body1) { |
179 OsrDeconstructorTester T(1); | 189 OsrDeconstructorTester T(1); |
180 | 190 |
181 Node* loop = T.NewOsrLoop(1); | 191 Node* loop = T.NewOsrLoop(1); |
182 | 192 |
183 Node* branch = T.graph.NewNode(T.common.Branch(), T.p0, loop); | 193 Node* branch = T.graph.NewNode(T.common.Branch(), T.p0, loop); |
184 Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch); | 194 Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch); |
185 Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch); | 195 Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch); |
186 loop->ReplaceInput(2, if_true); | 196 loop->ReplaceInput(2, if_true); |
187 | 197 |
188 Node* osr_phi = | 198 Node* osr_phi = |
189 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | 199 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); |
190 | 200 |
191 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false); | 201 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false); |
192 T.graph.SetEnd(ret); | 202 T.graph.SetEnd(ret); |
193 | 203 |
194 OsrHelper helper(0, 0); | 204 T.DeconstructOsr(); |
195 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
196 | 205 |
197 CheckInputs(loop, T.start, if_true); | 206 CheckInputs(loop, T.start, if_true); |
198 CheckInputs(branch, T.p0, loop); | 207 CheckInputs(branch, T.p0, loop); |
199 CheckInputs(if_true, branch); | 208 CheckInputs(if_true, branch); |
200 CheckInputs(if_false, branch); | 209 CheckInputs(if_false, branch); |
201 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | 210 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); |
202 CheckInputs(ret, osr_phi, T.start, if_false); | 211 CheckInputs(ret, osr_phi, T.start, if_false); |
203 } | 212 } |
204 | 213 |
205 | 214 |
(...skipping 12 matching lines...) Expand all Loading... |
218 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2); | 227 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2); |
219 loop->ReplaceInput(2, if_true2); | 228 loop->ReplaceInput(2, if_true2); |
220 | 229 |
221 Node* osr_phi = | 230 Node* osr_phi = |
222 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); | 231 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); |
223 | 232 |
224 Node* merge = T.graph.NewNode(T.common.Merge(2), if_false1, if_false2); | 233 Node* merge = T.graph.NewNode(T.common.Merge(2), if_false1, if_false2); |
225 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, merge); | 234 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, merge); |
226 T.graph.SetEnd(ret); | 235 T.graph.SetEnd(ret); |
227 | 236 |
228 OsrHelper helper(0, 0); | 237 T.DeconstructOsr(); |
229 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
230 | 238 |
231 CheckInputs(loop, T.start, if_true2); | 239 CheckInputs(loop, T.start, if_true2); |
232 CheckInputs(branch1, T.p0, loop); | 240 CheckInputs(branch1, T.p0, loop); |
233 CheckInputs(branch2, T.p0, if_true1); | 241 CheckInputs(branch2, T.p0, if_true1); |
234 CheckInputs(if_true1, branch1); | 242 CheckInputs(if_true1, branch1); |
235 CheckInputs(if_false1, branch1); | 243 CheckInputs(if_false1, branch1); |
236 CheckInputs(if_true2, branch2); | 244 CheckInputs(if_true2, branch2); |
237 CheckInputs(if_false2, branch2); | 245 CheckInputs(if_false2, branch2); |
238 | 246 |
239 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); | 247 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); |
(...skipping 18 matching lines...) Expand all Loading... |
258 loop->ReplaceInput(2, if_false1); | 266 loop->ReplaceInput(2, if_false1); |
259 loop->ReplaceInput(3, if_true2); | 267 loop->ReplaceInput(3, if_true2); |
260 | 268 |
261 Node* osr_phi = | 269 Node* osr_phi = |
262 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant(), | 270 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant(), |
263 T.jsgraph.ZeroConstant()); | 271 T.jsgraph.ZeroConstant()); |
264 | 272 |
265 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false2); | 273 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false2); |
266 T.graph.SetEnd(ret); | 274 T.graph.SetEnd(ret); |
267 | 275 |
268 OsrHelper helper(0, 0); | 276 T.DeconstructOsr(); |
269 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
270 | 277 |
271 CheckInputs(loop, T.start, if_false1, if_true2); | 278 CheckInputs(loop, T.start, if_false1, if_true2); |
272 CheckInputs(branch1, T.p0, loop); | 279 CheckInputs(branch1, T.p0, loop); |
273 CheckInputs(branch2, T.p0, if_true1); | 280 CheckInputs(branch2, T.p0, if_true1); |
274 CheckInputs(if_true1, branch1); | 281 CheckInputs(if_true1, branch1); |
275 CheckInputs(if_false1, branch1); | 282 CheckInputs(if_false1, branch1); |
276 CheckInputs(if_true2, branch2); | 283 CheckInputs(if_true2, branch2); |
277 CheckInputs(if_false2, branch2); | 284 CheckInputs(if_false2, branch2); |
278 | 285 |
279 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), | 286 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], | 342 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], |
336 T.jsgraph.ZeroConstant()); | 343 T.jsgraph.ZeroConstant()); |
337 inner.branch->ReplaceInput(0, osr_phi); | 344 inner.branch->ReplaceInput(0, osr_phi); |
338 outer_phi->ReplaceInput(1, osr_phi); | 345 outer_phi->ReplaceInput(1, osr_phi); |
339 | 346 |
340 Node* ret = | 347 Node* ret = |
341 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); | 348 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); |
342 Node* end = T.graph.NewNode(T.common.End(), ret); | 349 Node* end = T.graph.NewNode(T.common.End(), ret); |
343 T.graph.SetEnd(end); | 350 T.graph.SetEnd(end); |
344 | 351 |
345 OsrHelper helper(0, 0); | 352 T.DeconstructOsr(); |
346 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
347 | 353 |
348 // Check structure of deconstructed graph. | 354 // Check structure of deconstructed graph. |
349 // Check inner OSR loop is directly connected to start. | 355 // Check inner OSR loop is directly connected to start. |
350 CheckInputs(inner.loop, T.start, inner.if_true); | 356 CheckInputs(inner.loop, T.start, inner.if_true); |
351 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); | 357 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); |
352 | 358 |
353 // Check control transfer to copy of outer loop. | 359 // Check control transfer to copy of outer loop. |
354 Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop); | 360 Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop); |
355 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); | 361 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi); |
356 CHECK_NE(new_outer_loop, outer.loop); | 362 CHECK_NE(new_outer_loop, outer.loop); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch); | 409 Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch); |
404 | 410 |
405 outer.loop->ReplaceInput(1, x_true); | 411 outer.loop->ReplaceInput(1, x_true); |
406 outer.loop->ReplaceInput(2, x_false); | 412 outer.loop->ReplaceInput(2, x_false); |
407 | 413 |
408 Node* ret = | 414 Node* ret = |
409 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); | 415 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); |
410 Node* end = T.graph.NewNode(T.common.End(), ret); | 416 Node* end = T.graph.NewNode(T.common.End(), ret); |
411 T.graph.SetEnd(end); | 417 T.graph.SetEnd(end); |
412 | 418 |
413 OsrHelper helper(0, 0); | 419 T.DeconstructOsr(); |
414 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); | |
415 | 420 |
416 // Check structure of deconstructed graph. | 421 // Check structure of deconstructed graph. |
417 // Check inner OSR loop is directly connected to start. | 422 // Check inner OSR loop is directly connected to start. |
418 CheckInputs(inner.loop, T.start, inner.if_true); | 423 CheckInputs(inner.loop, T.start, inner.if_true); |
419 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); | 424 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); |
420 | 425 |
421 // Check control transfer to copy of outer loop. | 426 // Check control transfer to copy of outer loop. |
422 Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge); | 427 Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge); |
423 CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge)); | 428 CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge)); |
424 CheckInputs(new_merge, x_true, x_false); | 429 CheckInputs(new_merge, x_true, x_false); |
(...skipping 23 matching lines...) Expand all Loading... |
448 | 453 |
449 // Check structure of inner loop. | 454 // Check structure of inner loop. |
450 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); | 455 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); |
451 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); | 456 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); |
452 | 457 |
453 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), | 458 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), |
454 new_inner_loop); | 459 new_inner_loop); |
455 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, | 460 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, |
456 T.jsgraph.ZeroConstant(), new_outer_loop); | 461 T.jsgraph.ZeroConstant(), new_outer_loop); |
457 } | 462 } |
OLD | NEW |