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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
6 final JavaScriptBackend backend; | 6 final JavaScriptBackend backend; |
7 SsaCodeGeneratorTask(JavaScriptBackend backend) | 7 SsaCodeGeneratorTask(JavaScriptBackend backend) |
8 : this.backend = backend, | 8 : this.backend = backend, |
9 super(backend.compiler); | 9 super(backend.compiler); |
10 String get name() => 'SSA code generator'; | 10 String get name() => 'SSA code generator'; |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 var operation = instruction.operation.name; | 534 var operation = instruction.operation.name; |
535 declareInstruction(instruction); | 535 declareInstruction(instruction); |
536 buffer.add(' ${operation}= ${value}'); | 536 buffer.add(' ${operation}= ${value}'); |
537 } | 537 } |
538 return true; | 538 return true; |
539 } | 539 } |
540 } | 540 } |
541 return false; | 541 return false; |
542 } | 542 } |
543 | 543 |
| 544 // For simple type checks like i = intTypeCheck(i), we don't have to |
| 545 // emit an assignment, because the intTypeCheck just returns its |
| 546 // argument. |
| 547 bool handleTypeConversion(instruction, name) { |
| 548 if (instruction is !HTypeConversion) return false; |
| 549 String inputName = variableNames.getName(instruction.checkedInput); |
| 550 if (name != inputName) return false; |
| 551 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 552 return true; |
| 553 } |
| 554 |
544 void define(HInstruction instruction) { | 555 void define(HInstruction instruction) { |
545 if (isGeneratingExpression()) { | 556 if (isGeneratingExpression()) { |
546 addExpressionSeparator(); | 557 addExpressionSeparator(); |
547 } else { | 558 } else { |
548 addIndentation(); | 559 addIndentation(); |
549 } | 560 } |
550 if (instruction is !HCheck && variableNames.hasName(instruction)) { | 561 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { |
551 var name = variableNames.getName(instruction); | 562 var name = variableNames.getName(instruction); |
552 if (!handleSimpleUpdateDefinition(instruction, name)) { | 563 if (!handleSimpleUpdateDefinition(instruction, name) |
| 564 && !handleTypeConversion(instruction, name)) { |
553 declareInstruction(instruction); | 565 declareInstruction(instruction); |
554 buffer.add(" = "); | 566 buffer.add(" = "); |
555 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 567 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
556 } | 568 } |
557 } else { | 569 } else { |
558 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 570 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
559 } | 571 } |
560 if (!isGeneratingExpression()) buffer.add(';\n'); | 572 if (!isGeneratingExpression()) buffer.add(';\n'); |
561 } | 573 } |
562 | 574 |
563 void use(HInstruction argument, int expectedPrecedenceForArgument) { | 575 void use(HInstruction argument, int expectedPrecedenceForArgument) { |
564 if (isGenerateAtUseSite(argument)) { | 576 if (isGenerateAtUseSite(argument)) { |
565 visit(argument, expectedPrecedenceForArgument); | 577 visit(argument, expectedPrecedenceForArgument); |
566 } else if (argument is HCheck) { | 578 } else if (argument is HCheck && argument.isControlFlow()) { |
| 579 // A [HCheck] that has control flow can never be used as an |
| 580 // expression and may not have a name. Therefore we just use the |
| 581 // checked instruction. |
567 HCheck check = argument; | 582 HCheck check = argument; |
568 use(argument.checkedInput, expectedPrecedenceForArgument); | 583 use(check.checkedInput, expectedPrecedenceForArgument); |
569 } else { | 584 } else { |
570 buffer.add(variableNames.getName(argument)); | 585 buffer.add(variableNames.getName(argument)); |
571 } | 586 } |
572 } | 587 } |
573 | 588 |
574 visit(HInstruction node, int expectedPrecedenceForNode) { | 589 visit(HInstruction node, int expectedPrecedenceForNode) { |
575 int oldPrecedence = this.expectedPrecedence; | 590 int oldPrecedence = this.expectedPrecedence; |
576 this.expectedPrecedence = expectedPrecedenceForNode; | 591 this.expectedPrecedence = expectedPrecedenceForNode; |
577 node.accept(this); | 592 node.accept(this); |
578 this.expectedPrecedence = oldPrecedence; | 593 this.expectedPrecedence = oldPrecedence; |
(...skipping 1911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2490 } | 2505 } |
2491 | 2506 |
2492 void endGraph(HGraph graph) { | 2507 void endGraph(HGraph graph) { |
2493 if (!graph.entry.hasGuards()) return; | 2508 if (!graph.entry.hasGuards()) return; |
2494 indent--; // Close original case. | 2509 indent--; // Close original case. |
2495 indent--; | 2510 indent--; |
2496 addIndented('}\n'); // Close 'switch'. | 2511 addIndented('}\n'); // Close 'switch'. |
2497 setup.add(' }\n'); | 2512 setup.add(' }\n'); |
2498 } | 2513 } |
2499 | 2514 |
2500 // For instructions that reference a guard or a check, we change that | |
2501 // reference to the instruction they guard against. Therefore, we must | |
2502 // use that instruction when restoring the environment. | |
2503 HInstruction unwrap(argument) { | |
2504 while (argument is HCheck) argument = argument.checkedInput; | |
2505 return argument; | |
2506 } | |
2507 | |
2508 bool visitAndOrInfo(HAndOrBlockInformation info) => false; | 2515 bool visitAndOrInfo(HAndOrBlockInformation info) => false; |
2509 bool visitIfInfo(HIfBlockInformation info) => false; | 2516 bool visitIfInfo(HIfBlockInformation info) => false; |
2510 bool visitLoopInfo(HLoopBlockInformation info) => false; | 2517 bool visitLoopInfo(HLoopBlockInformation info) => false; |
2511 bool visitTryInfo(HTryBlockInformation info) => false; | 2518 bool visitTryInfo(HTryBlockInformation info) => false; |
2512 bool visitSequenceInfo(HStatementSequenceInformation info) => false; | 2519 bool visitSequenceInfo(HStatementSequenceInformation info) => false; |
2513 | 2520 |
2514 void visitTypeGuard(HTypeGuard node) { | 2521 void visitTypeGuard(HTypeGuard node) { |
2515 indent--; | 2522 indent--; |
2516 addIndented('case ${node.state}:\n'); | 2523 addIndented('case ${node.state}:\n'); |
2517 indent++; | 2524 indent++; |
2518 addIndented('state = 0;\n'); | 2525 addIndented('state = 0;\n'); |
2519 | 2526 |
2520 setup.add(' case ${node.state}:\n'); | 2527 setup.add(' case ${node.state}:\n'); |
2521 int i = 0; | 2528 int i = 0; |
2522 for (HInstruction input in node.inputs) { | 2529 for (HInstruction input in node.inputs) { |
2523 HInstruction instruction = unwrap(input); | 2530 setup.add(' ${variableNames.getName(input)} = env$i;\n'); |
2524 setup.add(' ${variableNames.getName(instruction)} = env$i;\n'); | |
2525 i++; | 2531 i++; |
2526 } | 2532 } |
2527 if (i > maxBailoutParameters) maxBailoutParameters = i; | 2533 if (i > maxBailoutParameters) maxBailoutParameters = i; |
2528 setup.add(' break;\n'); | 2534 setup.add(' break;\n'); |
2529 } | 2535 } |
2530 | 2536 |
2531 void startBailoutCase(List<HTypeGuard> bailouts1, | 2537 void startBailoutCase(List<HTypeGuard> bailouts1, |
2532 List<HTypeGuard> bailouts2) { | 2538 List<HTypeGuard> bailouts2) { |
2533 indent--; | 2539 indent--; |
2534 handleBailoutCase(bailouts1); | 2540 handleBailoutCase(bailouts1); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2673 startBailoutSwitch(); | 2679 startBailoutSwitch(); |
2674 } | 2680 } |
2675 } | 2681 } |
2676 | 2682 |
2677 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2683 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
2678 if (labeledBlockInfo.body.start.hasGuards()) { | 2684 if (labeledBlockInfo.body.start.hasGuards()) { |
2679 endBailoutSwitch(); | 2685 endBailoutSwitch(); |
2680 } | 2686 } |
2681 } | 2687 } |
2682 } | 2688 } |
OLD | NEW |