| 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 |