Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class BailoutInfo { | 7 class BailoutInfo { |
| 8 int instructionId; | 8 int instructionId; |
| 9 int bailoutId; | 9 int bailoutId; |
| 10 BailoutInfo(this.instructionId, this.bailoutId); | 10 BailoutInfo(this.instructionId, this.bailoutId); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 } | 387 } |
| 388 | 388 |
| 389 /** | 389 /** |
| 390 * Propagates bailout information to blocks that need it. This visitor | 390 * Propagates bailout information to blocks that need it. This visitor |
| 391 * is run before codegen, to know which blocks have to deal with | 391 * is run before codegen, to know which blocks have to deal with |
| 392 * bailouts. | 392 * bailouts. |
| 393 */ | 393 */ |
| 394 class SsaBailoutPropagator extends HBaseVisitor { | 394 class SsaBailoutPropagator extends HBaseVisitor { |
| 395 final Compiler compiler; | 395 final Compiler compiler; |
| 396 final List<HBasicBlock> blocks; | 396 final List<HBasicBlock> blocks; |
| 397 final List<HLabeledBlockInformation> labeledBlockInformations; | |
| 398 final Set<HInstruction> generateAtUseSite; | |
| 399 SubGraph subGraph; | 397 SubGraph subGraph; |
| 398 HBlockInformation currentBlockInformation; | |
| 399 | |
| 400 /** | 400 /** |
| 401 * Max number of arguments to the bailout (not counting the state). | 401 * Max number of arguments to the bailout (not counting the state). |
| 402 */ | 402 */ |
| 403 int bailoutArity; | 403 int bailoutArity; |
| 404 /** | 404 /** |
| 405 * A map from variables to their names. These are the names in the | 405 * A map from variables to their names. These are the names in the |
| 406 * unoptimized (bailout) version of the function. Their names could be | 406 * unoptimized (bailout) version of the function. Their names could be |
| 407 * different in the optimized version. | 407 * different in the optimized version. |
| 408 */ | 408 */ |
| 409 VariableNames variableNames; | 409 VariableNames variableNames; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 427 * The first type guard in the graph. | 427 * The first type guard in the graph. |
| 428 */ | 428 */ |
| 429 HBailoutTarget firstBailoutTarget; | 429 HBailoutTarget firstBailoutTarget; |
| 430 | 430 |
| 431 /** | 431 /** |
| 432 * If set, it is the first block in the graph where we generate | 432 * If set, it is the first block in the graph where we generate |
| 433 * code. Blocks before this one are dead code in the bailout | 433 * code. Blocks before this one are dead code in the bailout |
| 434 * version. | 434 * version. |
| 435 */ | 435 */ |
| 436 | 436 |
| 437 SsaBailoutPropagator(this.compiler, | 437 SsaBailoutPropagator(this.compiler, this.variableNames) |
| 438 this.generateAtUseSite, | |
| 439 this.variableNames) | |
| 440 : blocks = <HBasicBlock>[], | 438 : blocks = <HBasicBlock>[], |
| 441 labeledBlockInformations = <HLabeledBlockInformation>[], | |
| 442 bailoutArity = 0, | 439 bailoutArity = 0, |
| 443 parameterNames = new Map<String, int>(); | 440 parameterNames = new Map<String, int>(); |
| 444 | 441 |
| 445 void visitGraph(HGraph graph) { | 442 void visitGraph(HGraph graph) { |
| 446 subGraph = new SubGraph(graph.entry, graph.exit); | 443 subGraph = new SubGraph(graph.entry, graph.exit); |
| 447 visitBasicBlock(graph.entry); | 444 visitBasicBlock(graph.entry); |
| 448 if (!blocks.isEmpty) { | 445 if (!blocks.isEmpty) { |
| 449 compiler.internalError('Bailout propagation', | 446 compiler.internalError('Bailout propagation', |
| 450 node: compiler.currentElement.parseNode(compiler)); | 447 node: compiler.currentElement.parseNode(compiler)); |
| 451 } | 448 } |
| 452 } | 449 } |
| 453 | 450 |
| 451 bool handleBlockFlow(HBlockFlow blockFlow) { | |
| 452 HBlockInformation body = blockFlow.body; | |
| 453 | |
| 454 // We reach here again when starting to visit a subgraph. Just | |
| 455 // return to visiting the block. | |
| 456 if (currentBlockInformation == body) return false; | |
| 457 | |
| 458 HBlockInformation oldInformation = currentBlockInformation; | |
| 459 if (body is HLabeledBlockInformation) { | |
| 460 currentBlockInformation = body; | |
| 461 HLabeledBlockInformation info = body; | |
| 462 visitStatements(info.body, newFlow: true); | |
| 463 } else if (body is HLoopBlockInformation) { | |
| 464 currentBlockInformation = body; | |
| 465 HLoopBlockInformation info = body; | |
| 466 if (info.initializer != null) { | |
| 467 visitExpression(info.initializer); | |
| 468 } | |
| 469 blocks.addLast(info.loopHeader); | |
| 470 if (!info.isDoWhile()) { | |
| 471 visitExpression(info.condition); | |
| 472 } | |
| 473 visitStatements(info.body, newFlow: false); | |
| 474 if (info.isDoWhile()) { | |
| 475 visitExpression(info.condition); | |
| 476 } | |
| 477 if (info.updates != null) { | |
| 478 visitExpression(info.updates); | |
| 479 } | |
| 480 blocks.removeLast(); | |
| 481 } else { | |
| 482 return false; | |
|
Lasse Reichstein Nielsen
2013/01/30 14:00:43
Perhaps make comment saying what is not being hand
ngeoffray
2013/01/30 14:19:34
Done.
| |
| 483 } | |
| 484 | |
| 485 currentBlockInformation = oldInformation; | |
| 486 if (blockFlow.continuation != null) { | |
| 487 visitBasicBlock(blockFlow.continuation); | |
| 488 } | |
| 489 return true; | |
| 490 } | |
| 491 | |
| 454 void visitBasicBlock(HBasicBlock block) { | 492 void visitBasicBlock(HBasicBlock block) { |
| 455 // Abort traversal if we are leaving the currently active sub-graph. | 493 // Abort traversal if we are leaving the currently active sub-graph. |
| 456 if (!subGraph.contains(block)) return; | 494 if (!subGraph.contains(block)) return; |
| 457 | 495 |
| 458 if (block.isLoopHeader()) { | 496 HBlockFlow blockFlow = block.blockFlow; |
| 459 blocks.addLast(block); | 497 if (blockFlow != null && handleBlockFlow(blockFlow)) return; |
| 460 } else if (block.isLabeledBlock() | |
| 461 && (blocks.isEmpty || !identical(blocks.last, block))) { | |
| 462 HLabeledBlockInformation info = block.blockFlow.body; | |
| 463 visitStatements(info.body); | |
| 464 return; | |
| 465 } | |
| 466 | 498 |
| 467 HInstruction instruction = block.first; | 499 HInstruction instruction = block.first; |
| 468 while (instruction != null) { | 500 while (instruction != null) { |
| 469 instruction.accept(this); | 501 instruction.accept(this); |
| 470 instruction = instruction.next; | 502 instruction = instruction.next; |
| 471 } | 503 } |
| 472 } | 504 } |
| 473 | 505 |
| 474 void visitStatements(HStatementInformation info) { | 506 void visitExpression(HSubExpressionBlockInformation info) { |
| 475 assert(info is HSubGraphBlockInformation); | 507 visitSubGraph(info.subExpression); |
| 476 HSubGraphBlockInformation graph = info; | 508 } |
| 477 visitSubGraph(graph.subGraph); | 509 |
| 510 void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) { | |
| 511 SubGraph graph = info.subGraph; | |
| 512 if (newFlow) blocks.addLast(graph.start); | |
| 513 visitSubGraph(graph); | |
| 514 if (newFlow) blocks.removeLast(); | |
| 478 } | 515 } |
| 479 | 516 |
| 480 void visitSubGraph(SubGraph graph) { | 517 void visitSubGraph(SubGraph graph) { |
| 481 SubGraph oldSubGraph = subGraph; | 518 SubGraph oldSubGraph = subGraph; |
| 482 subGraph = graph; | 519 subGraph = graph; |
| 483 HBasicBlock start = graph.start; | 520 visitBasicBlock(graph.start); |
| 484 blocks.addLast(start); | |
| 485 visitBasicBlock(start); | |
| 486 blocks.removeLast(); | |
| 487 subGraph = oldSubGraph; | 521 subGraph = oldSubGraph; |
| 488 | |
| 489 if (start.isLabeledBlock()) { | |
| 490 HBasicBlock continuation = start.blockFlow.continuation; | |
| 491 if (continuation != null) { | |
| 492 visitBasicBlock(continuation); | |
| 493 } | |
| 494 } | |
| 495 } | 522 } |
| 496 | 523 |
| 497 void visitIf(HIf instruction) { | 524 void visitIf(HIf instruction) { |
| 498 int preVisitedBlocks = 0; | 525 int preVisitedBlocks = 0; |
| 499 HIfBlockInformation info = instruction.blockInformation.body; | 526 HIfBlockInformation info = instruction.blockInformation.body; |
| 500 visitStatements(info.thenGraph); | 527 visitStatements(info.thenGraph, newFlow: true); |
| 501 preVisitedBlocks++; | 528 preVisitedBlocks++; |
| 502 visitStatements(info.elseGraph); | 529 visitStatements(info.elseGraph, newFlow: true); |
| 503 preVisitedBlocks++; | 530 preVisitedBlocks++; |
| 504 | 531 |
| 505 HBasicBlock joinBlock = instruction.joinBlock; | 532 HBasicBlock joinBlock = instruction.joinBlock; |
| 506 if (joinBlock != null | 533 if (joinBlock != null |
| 507 && !identical(joinBlock.dominator, instruction.block)) { | 534 && !identical(joinBlock.dominator, instruction.block)) { |
| 508 // The join block is dominated by a block in one of the branches. | 535 // The join block is dominated by a block in one of the branches. |
| 509 // The subgraph traversal never reached it, so we visit it here | 536 // The subgraph traversal never reached it, so we visit it here |
| 510 // instead. | 537 // instead. |
| 511 visitBasicBlock(joinBlock); | 538 visitBasicBlock(joinBlock); |
| 512 } | 539 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 525 | 552 |
| 526 void visitGoto(HGoto goto) { | 553 void visitGoto(HGoto goto) { |
| 527 HBasicBlock block = goto.block; | 554 HBasicBlock block = goto.block; |
| 528 HBasicBlock successor = block.successors[0]; | 555 HBasicBlock successor = block.successors[0]; |
| 529 if (identical(successor.dominator, block)) { | 556 if (identical(successor.dominator, block)) { |
| 530 visitBasicBlock(block.successors[0]); | 557 visitBasicBlock(block.successors[0]); |
| 531 } | 558 } |
| 532 } | 559 } |
| 533 | 560 |
| 534 void visitLoopBranch(HLoopBranch branch) { | 561 void visitLoopBranch(HLoopBranch branch) { |
| 535 HBasicBlock branchBlock = branch.block; | |
| 536 List<HBasicBlock> dominated = branchBlock.dominatedBlocks; | |
| 537 // For a do-while loop, the body has already been visited. | 562 // For a do-while loop, the body has already been visited. |
| 538 if (!branch.isDoWhile()) { | 563 if (!branch.isDoWhile()) { |
| 539 visitBasicBlock(dominated[0]); | 564 visitBasicBlock(branch.block.dominatedBlocks[0]); |
| 540 } | |
| 541 blocks.removeLast(); | |
| 542 | |
| 543 // If the branch does not dominate the code after the loop, the | |
| 544 // dominator will visit it. | |
| 545 if (!identical(branchBlock.successors[1].dominator, branchBlock)) return; | |
| 546 | |
| 547 visitBasicBlock(branchBlock.successors[1]); | |
| 548 // With labeled breaks we can have more dominated blocks. | |
| 549 if (dominated.length >= 3) { | |
| 550 for (int i = 2; i < dominated.length; i++) { | |
| 551 visitBasicBlock(dominated[i]); | |
| 552 } | |
| 553 } | 565 } |
| 554 } | 566 } |
| 555 | 567 |
| 556 visitBailoutTarget(HBailoutTarget target) { | 568 visitBailoutTarget(HBailoutTarget target) { |
| 557 int inputLength = target.inputs.length; | 569 int inputLength = target.inputs.length; |
| 558 for (HInstruction input in target.inputs) { | 570 for (HInstruction input in target.inputs) { |
| 559 String inputName = variableNames.getName(input); | 571 String inputName = variableNames.getName(input); |
| 560 int position = parameterNames[inputName]; | 572 int position = parameterNames[inputName]; |
| 561 if (position == null) { | 573 if (position == null) { |
| 562 position = parameterNames[inputName] = bailoutArity++; | 574 position = parameterNames[inputName] = bailoutArity++; |
| 563 } | 575 } |
| 564 } | 576 } |
| 565 | 577 |
| 566 if (blocks.isEmpty) { | 578 if (blocks.isEmpty) { |
| 567 if (firstBailoutTarget == null) { | 579 if (firstBailoutTarget == null) { |
| 568 firstBailoutTarget = target; | 580 firstBailoutTarget = target; |
| 569 } else { | 581 } else { |
| 570 hasComplexBailoutTargets = true; | 582 hasComplexBailoutTargets = true; |
| 571 } | 583 } |
| 572 } else { | 584 } else { |
| 573 hasComplexBailoutTargets = true; | 585 hasComplexBailoutTargets = true; |
| 574 blocks.forEach((HBasicBlock block) { | 586 blocks.forEach((HBasicBlock block) { |
| 575 block.bailoutTargets.add(target); | 587 block.bailoutTargets.add(target); |
| 576 }); | 588 }); |
| 577 } | 589 } |
| 578 } | 590 } |
| 579 } | 591 } |
| OLD | NEW |