| 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/compiler/escape-analysis.h" | 5 #include "src/compiler/escape-analysis.h" |
| 6 #include "src/bit-vector.h" | 6 #include "src/bit-vector.h" |
| 7 #include "src/compiler/escape-analysis-reducer.h" | 7 #include "src/compiler/escape-analysis-reducer.h" |
| 8 #include "src/compiler/graph-visualizer.h" | 8 #include "src/compiler/graph-visualizer.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 control); | 112 control); |
| 113 } | 113 } |
| 114 | 114 |
| 115 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) { | 115 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) { |
| 116 if (!effect) { | 116 if (!effect) { |
| 117 effect = effect_; | 117 effect = effect_; |
| 118 } | 118 } |
| 119 if (!control) { | 119 if (!control) { |
| 120 control = control_; | 120 control = control_; |
| 121 } | 121 } |
| 122 Node* zero = graph()->NewNode(common()->Int32Constant(0)); | 122 return control_ = |
| 123 return control_ = graph()->NewNode(common()->Return(), zero, value, effect, | 123 graph()->NewNode(common()->Return(), value, effect, control); |
| 124 control); | |
| 125 } | 124 } |
| 126 | 125 |
| 127 void EndGraph() { | 126 void EndGraph() { |
| 128 for (Edge edge : graph()->end()->input_edges()) { | 127 for (Edge edge : graph()->end()->input_edges()) { |
| 129 if (NodeProperties::IsControlEdge(edge)) { | 128 if (NodeProperties::IsControlEdge(edge)) { |
| 130 edge.UpdateTo(control_); | 129 edge.UpdateTo(control_); |
| 131 } | 130 } |
| 132 } | 131 } |
| 133 } | 132 } |
| 134 | 133 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 Node* result = Return(load); | 217 Node* result = Return(load); |
| 219 EndGraph(); | 218 EndGraph(); |
| 220 | 219 |
| 221 Analysis(); | 220 Analysis(); |
| 222 | 221 |
| 223 ExpectVirtual(allocation); | 222 ExpectVirtual(allocation); |
| 224 ExpectReplacement(load, object1); | 223 ExpectReplacement(load, object1); |
| 225 | 224 |
| 226 Transformation(); | 225 Transformation(); |
| 227 | 226 |
| 228 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 227 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 229 } | 228 } |
| 230 | 229 |
| 231 | 230 |
| 232 TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) { | 231 TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) { |
| 233 Node* object1 = Constant(1); | 232 Node* object1 = Constant(1); |
| 234 Node* object2 = Constant(2); | 233 Node* object2 = Constant(2); |
| 235 BeginRegion(); | 234 BeginRegion(); |
| 236 Node* allocation = Allocate(Constant(kPointerSize)); | 235 Node* allocation = Allocate(Constant(kPointerSize)); |
| 237 Store(FieldAccessAtIndex(0), allocation, object1); | 236 Store(FieldAccessAtIndex(0), allocation, object1); |
| 238 Node* index = | 237 Node* index = |
| 239 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), | 238 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), |
| 240 object1, object2, control()); | 239 object1, object2, control()); |
| 241 StoreElement(MakeElementAccess(0), allocation, index, object1); | 240 StoreElement(MakeElementAccess(0), allocation, index, object1); |
| 242 Node* finish = FinishRegion(allocation); | 241 Node* finish = FinishRegion(allocation); |
| 243 Node* load = Load(FieldAccessAtIndex(0), finish); | 242 Node* load = Load(FieldAccessAtIndex(0), finish); |
| 244 Node* result = Return(load); | 243 Node* result = Return(load); |
| 245 EndGraph(); | 244 EndGraph(); |
| 246 | 245 |
| 247 Analysis(); | 246 Analysis(); |
| 248 | 247 |
| 249 ExpectEscaped(allocation); | 248 ExpectEscaped(allocation); |
| 250 ExpectReplacement(load, nullptr); | 249 ExpectReplacement(load, nullptr); |
| 251 | 250 |
| 252 Transformation(); | 251 Transformation(); |
| 253 | 252 |
| 254 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 1)); | 253 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0)); |
| 255 } | 254 } |
| 256 | 255 |
| 257 | 256 |
| 258 TEST_F(EscapeAnalysisTest, StraightEscape) { | 257 TEST_F(EscapeAnalysisTest, StraightEscape) { |
| 259 Node* object1 = Constant(1); | 258 Node* object1 = Constant(1); |
| 260 BeginRegion(); | 259 BeginRegion(); |
| 261 Node* allocation = Allocate(Constant(kPointerSize)); | 260 Node* allocation = Allocate(Constant(kPointerSize)); |
| 262 Store(FieldAccessAtIndex(0), allocation, object1); | 261 Store(FieldAccessAtIndex(0), allocation, object1); |
| 263 Node* finish = FinishRegion(allocation); | 262 Node* finish = FinishRegion(allocation); |
| 264 Node* load = Load(FieldAccessAtIndex(0), finish); | 263 Node* load = Load(FieldAccessAtIndex(0), finish); |
| 265 Node* result = Return(allocation); | 264 Node* result = Return(allocation); |
| 266 EndGraph(); | 265 EndGraph(); |
| 267 graph()->end()->AppendInput(zone(), load); | 266 graph()->end()->AppendInput(zone(), load); |
| 268 | 267 |
| 269 Analysis(); | 268 Analysis(); |
| 270 | 269 |
| 271 ExpectEscaped(allocation); | 270 ExpectEscaped(allocation); |
| 272 ExpectReplacement(load, object1); | 271 ExpectReplacement(load, object1); |
| 273 | 272 |
| 274 Transformation(); | 273 Transformation(); |
| 275 | 274 |
| 276 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 1)); | 275 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); |
| 277 } | 276 } |
| 278 | 277 |
| 279 | 278 |
| 280 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { | 279 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { |
| 281 Node* object1 = Constant(1); | 280 Node* object1 = Constant(1); |
| 282 | 281 |
| 283 BeginRegion(); | 282 BeginRegion(); |
| 284 Node* allocation1 = Allocate(Constant(kPointerSize)); | 283 Node* allocation1 = Allocate(Constant(kPointerSize)); |
| 285 Store(FieldAccessAtIndex(0), allocation1, object1); | 284 Store(FieldAccessAtIndex(0), allocation1, object1); |
| 286 Node* finish1 = FinishRegion(allocation1); | 285 Node* finish1 = FinishRegion(allocation1); |
| 287 | 286 |
| 288 BeginRegion(); | 287 BeginRegion(); |
| 289 Node* allocation2 = Allocate(Constant(kPointerSize)); | 288 Node* allocation2 = Allocate(Constant(kPointerSize)); |
| 290 Store(FieldAccessAtIndex(0), allocation2, finish1); | 289 Store(FieldAccessAtIndex(0), allocation2, finish1); |
| 291 Node* finish2 = FinishRegion(allocation2); | 290 Node* finish2 = FinishRegion(allocation2); |
| 292 | 291 |
| 293 Node* load = Load(FieldAccessAtIndex(0), finish2); | 292 Node* load = Load(FieldAccessAtIndex(0), finish2); |
| 294 Node* result = Return(load); | 293 Node* result = Return(load); |
| 295 EndGraph(); | 294 EndGraph(); |
| 296 Analysis(); | 295 Analysis(); |
| 297 | 296 |
| 298 ExpectEscaped(allocation1); | 297 ExpectEscaped(allocation1); |
| 299 ExpectVirtual(allocation2); | 298 ExpectVirtual(allocation2); |
| 300 ExpectReplacement(load, finish1); | 299 ExpectReplacement(load, finish1); |
| 301 | 300 |
| 302 Transformation(); | 301 Transformation(); |
| 303 | 302 |
| 304 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 1)); | 303 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 0)); |
| 305 } | 304 } |
| 306 | 305 |
| 307 | 306 |
| 308 TEST_F(EscapeAnalysisTest, BranchNonEscape) { | 307 TEST_F(EscapeAnalysisTest, BranchNonEscape) { |
| 309 Node* object1 = Constant(1); | 308 Node* object1 = Constant(1); |
| 310 Node* object2 = Constant(2); | 309 Node* object2 = Constant(2); |
| 311 BeginRegion(); | 310 BeginRegion(); |
| 312 Node* allocation = Allocate(Constant(kPointerSize)); | 311 Node* allocation = Allocate(Constant(kPointerSize)); |
| 313 Store(FieldAccessAtIndex(0), allocation, object1); | 312 Store(FieldAccessAtIndex(0), allocation, object1); |
| 314 Node* finish = FinishRegion(allocation); | 313 Node* finish = FinishRegion(allocation); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 327 graph()->end()->AppendInput(zone(), result); | 326 graph()->end()->AppendInput(zone(), result); |
| 328 | 327 |
| 329 Analysis(); | 328 Analysis(); |
| 330 | 329 |
| 331 ExpectVirtual(allocation); | 330 ExpectVirtual(allocation); |
| 332 ExpectReplacementPhi(load, object1, object2); | 331 ExpectReplacementPhi(load, object1, object2); |
| 333 Node* replacement_phi = escape_analysis()->GetReplacement(load); | 332 Node* replacement_phi = escape_analysis()->GetReplacement(load); |
| 334 | 333 |
| 335 Transformation(); | 334 Transformation(); |
| 336 | 335 |
| 337 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 1)); | 336 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); |
| 338 } | 337 } |
| 339 | 338 |
| 340 | 339 |
| 341 TEST_F(EscapeAnalysisTest, BranchEscapeOne) { | 340 TEST_F(EscapeAnalysisTest, BranchEscapeOne) { |
| 342 Node* object1 = Constant(1); | 341 Node* object1 = Constant(1); |
| 343 Node* object2 = Constant(2); | 342 Node* object2 = Constant(2); |
| 344 Node* index = graph()->NewNode(common()->Parameter(0), start()); | 343 Node* index = graph()->NewNode(common()->Parameter(0), start()); |
| 345 BeginRegion(); | 344 BeginRegion(); |
| 346 Node* allocation = Allocate(Constant(kPointerSize)); | 345 Node* allocation = Allocate(Constant(kPointerSize)); |
| 347 Store(FieldAccessAtIndex(0), allocation, object1); | 346 Store(FieldAccessAtIndex(0), allocation, object1); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 359 Node* result = Return(load, phi); | 358 Node* result = Return(load, phi); |
| 360 EndGraph(); | 359 EndGraph(); |
| 361 | 360 |
| 362 Analysis(); | 361 Analysis(); |
| 363 | 362 |
| 364 ExpectEscaped(allocation); | 363 ExpectEscaped(allocation); |
| 365 ExpectReplacement(load, nullptr); | 364 ExpectReplacement(load, nullptr); |
| 366 | 365 |
| 367 Transformation(); | 366 Transformation(); |
| 368 | 367 |
| 369 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 1)); | 368 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0)); |
| 370 } | 369 } |
| 371 | 370 |
| 372 | 371 |
| 373 TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) { | 372 TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) { |
| 374 Node* object1 = Constant(1); | 373 Node* object1 = Constant(1); |
| 375 Node* object2 = Constant(2); | 374 Node* object2 = Constant(2); |
| 376 BeginRegion(); | 375 BeginRegion(); |
| 377 Node* allocation = Allocate(Constant(kPointerSize)); | 376 Node* allocation = Allocate(Constant(kPointerSize)); |
| 378 Store(FieldAccessAtIndex(0), allocation, object1); | 377 Store(FieldAccessAtIndex(0), allocation, object1); |
| 379 FinishRegion(allocation); | 378 FinishRegion(allocation); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 394 graph()->end()->AppendInput(zone(), load); | 393 graph()->end()->AppendInput(zone(), load); |
| 395 | 394 |
| 396 Analysis(); | 395 Analysis(); |
| 397 | 396 |
| 398 ExpectEscaped(allocation); | 397 ExpectEscaped(allocation); |
| 399 ExpectEscaped(allocation2); | 398 ExpectEscaped(allocation2); |
| 400 ExpectReplacement(load, nullptr); | 399 ExpectReplacement(load, nullptr); |
| 401 | 400 |
| 402 Transformation(); | 401 Transformation(); |
| 403 | 402 |
| 404 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 1)); | 403 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); |
| 405 } | 404 } |
| 406 | 405 |
| 407 | 406 |
| 408 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { | 407 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { |
| 409 Node* object1 = Constant(1); | 408 Node* object1 = Constant(1); |
| 410 Node* object2 = Constant(2); | 409 Node* object2 = Constant(2); |
| 411 Node* allocation = Allocate(Constant(kPointerSize)); | 410 Node* allocation = Allocate(Constant(kPointerSize)); |
| 412 Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1); | 411 Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1); |
| 413 Node* load1 = Load(FieldAccessAtIndex(0), allocation); | 412 Node* load1 = Load(FieldAccessAtIndex(0), allocation); |
| 414 Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2); | 413 Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2); |
| 415 Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1); | 414 Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1); |
| 416 Node* result = Return(load2); | 415 Node* result = Return(load2); |
| 417 EndGraph(); | 416 EndGraph(); |
| 418 graph()->end()->AppendInput(zone(), store2); | 417 graph()->end()->AppendInput(zone(), store2); |
| 419 graph()->end()->AppendInput(zone(), load1); | 418 graph()->end()->AppendInput(zone(), load1); |
| 420 | 419 |
| 421 Analysis(); | 420 Analysis(); |
| 422 | 421 |
| 423 ExpectVirtual(allocation); | 422 ExpectVirtual(allocation); |
| 424 ExpectReplacement(load1, object1); | 423 ExpectReplacement(load1, object1); |
| 425 ExpectReplacement(load2, object1); | 424 ExpectReplacement(load2, object1); |
| 426 | 425 |
| 427 Transformation(); | 426 Transformation(); |
| 428 | 427 |
| 429 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 428 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 430 } | 429 } |
| 431 | 430 |
| 432 | 431 |
| 433 TEST_F(EscapeAnalysisTest, DeoptReplacement) { | 432 TEST_F(EscapeAnalysisTest, DeoptReplacement) { |
| 434 Node* object1 = Constant(1); | 433 Node* object1 = Constant(1); |
| 435 BeginRegion(); | 434 BeginRegion(); |
| 436 Node* allocation = Allocate(Constant(kPointerSize)); | 435 Node* allocation = Allocate(Constant(kPointerSize)); |
| 437 Store(FieldAccessAtIndex(0), allocation, object1); | 436 Store(FieldAccessAtIndex(0), allocation, object1); |
| 438 Node* finish = FinishRegion(allocation); | 437 Node* finish = FinishRegion(allocation); |
| 439 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); | 438 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 455 Node* result = Return(load, effect1, ifTrue); | 454 Node* result = Return(load, effect1, ifTrue); |
| 456 EndGraph(); | 455 EndGraph(); |
| 457 graph()->end()->AppendInput(zone(), deopt); | 456 graph()->end()->AppendInput(zone(), deopt); |
| 458 Analysis(); | 457 Analysis(); |
| 459 | 458 |
| 460 ExpectVirtual(allocation); | 459 ExpectVirtual(allocation); |
| 461 ExpectReplacement(load, object1); | 460 ExpectReplacement(load, object1); |
| 462 | 461 |
| 463 Transformation(); | 462 Transformation(); |
| 464 | 463 |
| 465 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 464 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 466 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 465 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
| 467 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 466 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
| 468 ASSERT_EQ(1, object_state->op()->ValueInputCount()); | 467 ASSERT_EQ(1, object_state->op()->ValueInputCount()); |
| 469 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 468 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
| 470 } | 469 } |
| 471 | 470 |
| 472 TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) { | 471 TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) { |
| 473 Node* object1 = Constant(1); | 472 Node* object1 = Constant(1); |
| 474 BeginRegion(); | 473 BeginRegion(); |
| 475 Node* allocation = Allocate(Constant(kPointerSize * 2)); | 474 Node* allocation = Allocate(Constant(kPointerSize * 2)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 495 Node* result = Return(load, effect1, ifTrue); | 494 Node* result = Return(load, effect1, ifTrue); |
| 496 EndGraph(); | 495 EndGraph(); |
| 497 graph()->end()->AppendInput(zone(), deopt); | 496 graph()->end()->AppendInput(zone(), deopt); |
| 498 Analysis(); | 497 Analysis(); |
| 499 | 498 |
| 500 ExpectVirtual(allocation); | 499 ExpectVirtual(allocation); |
| 501 ExpectReplacement(load, object1); | 500 ExpectReplacement(load, object1); |
| 502 | 501 |
| 503 Transformation(); | 502 Transformation(); |
| 504 | 503 |
| 505 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 504 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
| 506 | 505 |
| 507 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 506 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
| 508 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 507 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
| 509 ASSERT_EQ(2, object_state->op()->ValueInputCount()); | 508 ASSERT_EQ(2, object_state->op()->ValueInputCount()); |
| 510 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 509 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
| 511 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); | 510 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); |
| 512 | 511 |
| 513 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); | 512 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); |
| 514 ASSERT_EQ(object_state, object_state2); | 513 ASSERT_EQ(object_state, object_state2); |
| 515 } | 514 } |
| 516 | 515 |
| 517 } // namespace compiler | 516 } // namespace compiler |
| 518 } // namespace internal | 517 } // namespace internal |
| 519 } // namespace v8 | 518 } // namespace v8 |
| OLD | NEW |