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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 8 | 8 |
| 9 | 9 |
| 10 String generateMethod(WorkItem work, HGraph graph) { | 10 String generateMethod(WorkItem work, HGraph graph) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 final StringBuffer buffer; | 78 final StringBuffer buffer; |
| 79 final String parameters; | 79 final String parameters; |
| 80 | 80 |
| 81 final Map<Element, String> parameterNames; | 81 final Map<Element, String> parameterNames; |
| 82 final Map<int, String> names; | 82 final Map<int, String> names; |
| 83 final Map<String, int> prefixes; | 83 final Map<String, int> prefixes; |
| 84 final Set<HInstruction> generateAtUseSite; | 84 final Set<HInstruction> generateAtUseSite; |
| 85 final Map<HPhi, String> logicalOperations; | 85 final Map<HPhi, String> logicalOperations; |
| 86 final Map<Element, ElementAction> breakAction; | 86 final Map<Element, ElementAction> breakAction; |
| 87 final Map<Element, ElementAction> continueAction; | 87 final Map<Element, ElementAction> continueAction; |
| 88 final Equivalence<HPhi> phiEquivalence; | |
| 88 | 89 |
| 89 Element equalsNullElement; | 90 Element equalsNullElement; |
| 90 int indent = 0; | 91 int indent = 0; |
| 91 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; | 92 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; |
| 92 HGraph currentGraph; | 93 HGraph currentGraph; |
| 93 /** | 94 /** |
| 94 * Whether the code-generation should try to generate an expression | 95 * Whether the code-generation should try to generate an expression |
| 95 * instead of a sequence of statements. | 96 * instead of a sequence of statements. |
| 96 */ | 97 */ |
| 97 int generationState = STATE_STATEMENT; | 98 int generationState = STATE_STATEMENT; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 118 SsaCodeGenerator(this.compiler, | 119 SsaCodeGenerator(this.compiler, |
| 119 this.work, | 120 this.work, |
| 120 this.parameters, | 121 this.parameters, |
| 121 this.parameterNames) | 122 this.parameterNames) |
| 122 : names = new Map<int, String>(), | 123 : names = new Map<int, String>(), |
| 123 prefixes = new Map<String, int>(), | 124 prefixes = new Map<String, int>(), |
| 124 buffer = new StringBuffer(), | 125 buffer = new StringBuffer(), |
| 125 generateAtUseSite = new Set<HInstruction>(), | 126 generateAtUseSite = new Set<HInstruction>(), |
| 126 logicalOperations = new Map<HPhi, String>(), | 127 logicalOperations = new Map<HPhi, String>(), |
| 127 breakAction = new Map<Element, ElementAction>(), | 128 breakAction = new Map<Element, ElementAction>(), |
| 128 continueAction = new Map<Element, ElementAction>() { | 129 continueAction = new Map<Element, ElementAction>(), |
| 130 phiEquivalence = new Equivalence<HPhi>() { | |
| 129 | 131 |
| 130 for (final name in parameterNames.getValues()) { | 132 for (final name in parameterNames.getValues()) { |
| 131 prefixes[name] = 0; | 133 prefixes[name] = 0; |
| 132 } | 134 } |
| 133 | 135 |
| 134 equalsNullElement = | 136 equalsNullElement = |
| 135 compiler.builder.interceptors.getEqualsNullInterceptor(); | 137 compiler.builder.interceptors.getEqualsNullInterceptor(); |
| 136 } | 138 } |
| 137 | 139 |
| 138 abstract visitTypeGuard(HTypeGuard node); | 140 abstract visitTypeGuard(HTypeGuard node); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 160 void endExpression(int precedence) { | 162 void endExpression(int precedence) { |
| 161 if (precedence < expectedPrecedence) { | 163 if (precedence < expectedPrecedence) { |
| 162 buffer.add(')'); | 164 buffer.add(')'); |
| 163 } | 165 } |
| 164 } | 166 } |
| 165 | 167 |
| 166 void preGenerateMethod(HGraph graph) { | 168 void preGenerateMethod(HGraph graph) { |
| 167 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); | 169 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); |
| 168 new SsaConditionMerger(generateAtUseSite, | 170 new SsaConditionMerger(generateAtUseSite, |
| 169 logicalOperations).visitGraph(graph); | 171 logicalOperations).visitGraph(graph); |
| 172 new PhiEquivalator(phiEquivalence, logicalOperations).analyzeGraph(graph); | |
| 170 } | 173 } |
| 171 | 174 |
| 172 visitGraph(HGraph graph) { | 175 visitGraph(HGraph graph) { |
| 173 preGenerateMethod(graph); | 176 preGenerateMethod(graph); |
| 174 currentGraph = graph; | 177 currentGraph = graph; |
| 175 indent++; // We are already inside a function. | 178 indent++; // We are already inside a function. |
| 176 subGraph = new SubGraph(graph.entry, graph.exit); | 179 subGraph = new SubGraph(graph.entry, graph.exit); |
| 177 beginGraph(graph); | 180 beginGraph(graph); |
| 178 visitBasicBlock(graph.entry); | 181 visitBasicBlock(graph.entry); |
| 179 if (!delayedVarDecl.isEmpty()) { | 182 if (!delayedVarDecl.isEmpty()) { |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 | 566 |
| 564 HBlockInformation oldInfo = currentBlockInformation; | 567 HBlockInformation oldInfo = currentBlockInformation; |
| 565 currentBlockInformation = info.body.start.labeledBlockInformation; | 568 currentBlockInformation = info.body.start.labeledBlockInformation; |
| 566 visitSubGraph(info.body); | 569 visitSubGraph(info.body); |
| 567 currentBlockInformation = oldInfo; | 570 currentBlockInformation = oldInfo; |
| 568 | 571 |
| 569 indent--; | 572 indent--; |
| 570 addIndentation(); | 573 addIndentation(); |
| 571 buffer.add("}\n"); | 574 buffer.add("}\n"); |
| 572 } else { | 575 } else { |
| 576 addIndentation(); | |
| 573 buffer.add(") {\n"); | 577 buffer.add(") {\n"); |
| 574 indent++; | 578 indent++; |
| 575 wrapLoopBodyForContinue(info); | 579 wrapLoopBodyForContinue(info); |
| 576 visitSubGraph(info.updates); | 580 visitSubGraph(info.updates); |
| 577 indent--; | 581 indent--; |
| 578 buffer.add("}\n"); | 582 buffer.add("}\n"); |
| 579 } | 583 } |
| 580 success = true; | 584 success = true; |
| 581 break; | 585 break; |
| 582 } | 586 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 HInstruction instruction = node.first; | 630 HInstruction instruction = node.first; |
| 627 while (instruction != null) { | 631 while (instruction != null) { |
| 628 if (instruction === node.last) { | 632 if (instruction === node.last) { |
| 629 for (HBasicBlock successor in node.successors) { | 633 for (HBasicBlock successor in node.successors) { |
| 630 int index = successor.predecessors.indexOf(node); | 634 int index = successor.predecessors.indexOf(node); |
| 631 successor.forEachPhi((HPhi phi) { | 635 successor.forEachPhi((HPhi phi) { |
| 632 bool isLogicalOperation = logicalOperations.containsKey(phi); | 636 bool isLogicalOperation = logicalOperations.containsKey(phi); |
| 633 // In case the phi is being generated by another | 637 // In case the phi is being generated by another |
| 634 // instruction. | 638 // instruction. |
| 635 if (isLogicalOperation && isGenerateAtUseSite(phi)) return; | 639 if (isLogicalOperation && isGenerateAtUseSite(phi)) return; |
| 640 HPhi canonicalPhi = phiEquivalence.getRepresentative(phi); | |
| 641 HInstruction input = phi.inputs[index]; | |
| 642 if (input is HPhi) { | |
| 643 HPhi inputPhi = input; | |
| 644 HPhi canonicalInput = phiEquivalence.getRepresentative(inputPhi); | |
| 645 // If we use the same variable, we don't need to create an | |
| 646 // assingment. | |
|
floitsch
2012/04/11 11:44:39
assignment
Lasse Reichstein Nielsen
2012/04/11 11:55:26
Done.
| |
| 647 if (canonicalInput == canonicalPhi) { | |
| 648 assert(!isLogicalOperation); | |
| 649 return; | |
| 650 } | |
| 651 } | |
| 636 if (isGeneratingExpression()) { | 652 if (isGeneratingExpression()) { |
| 637 addExpressionSeparator(); | 653 addExpressionSeparator(); |
| 638 } else { | 654 } else { |
| 639 addIndentation(); | 655 addIndentation(); |
| 640 } | 656 } |
| 641 if (!temporaryExists(phi)) { | 657 if (!temporaryExists(canonicalPhi)) { |
| 642 declareVariable(temporary(phi)); | 658 declareVariable(temporary(canonicalPhi)); |
| 643 } else { | 659 } else { |
| 644 buffer.add(temporary(phi)); | 660 buffer.add(temporary(canonicalPhi)); |
| 645 } | 661 } |
| 646 buffer.add(" = "); | 662 buffer.add(" = "); |
| 647 if (isLogicalOperation) { | 663 if (isLogicalOperation) { |
| 648 emitLogicalOperation(phi, logicalOperations[phi]); | 664 emitLogicalOperation(phi, logicalOperations[phi]); |
| 649 } else { | 665 } else { |
| 650 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE); | 666 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 651 } | 667 } |
| 652 if (!isGeneratingExpression()) { | 668 if (!isGeneratingExpression()) { |
| 653 buffer.add(';\n'); | 669 buffer.add(';\n'); |
| 654 } | 670 } |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1172 visitParameterValue(HParameterValue node) { | 1188 visitParameterValue(HParameterValue node) { |
| 1173 assert(isGenerateAtUseSite(node)); | 1189 assert(isGenerateAtUseSite(node)); |
| 1174 buffer.add(parameterNames[node.element]); | 1190 buffer.add(parameterNames[node.element]); |
| 1175 } | 1191 } |
| 1176 | 1192 |
| 1177 visitPhi(HPhi node) { | 1193 visitPhi(HPhi node) { |
| 1178 String operation = logicalOperations[node]; | 1194 String operation = logicalOperations[node]; |
| 1179 if (operation !== null) { | 1195 if (operation !== null) { |
| 1180 emitLogicalOperation(node, operation); | 1196 emitLogicalOperation(node, operation); |
| 1181 } else { | 1197 } else { |
| 1182 buffer.add('${temporary(node)}'); | 1198 HPhi canonicalPhi = phiEquivalence.getRepresentative(node); |
| 1199 buffer.add('${temporary(canonicalPhi)}'); | |
| 1183 } | 1200 } |
| 1184 } | 1201 } |
| 1185 | 1202 |
| 1186 visitReturn(HReturn node) { | 1203 visitReturn(HReturn node) { |
| 1187 assert(node.inputs.length == 1); | 1204 assert(node.inputs.length == 1); |
| 1188 HInstruction input = node.inputs[0]; | 1205 HInstruction input = node.inputs[0]; |
| 1189 if (input.isConstantNull()) { | 1206 if (input.isConstantNull()) { |
| 1190 buffer.add('return;\n'); | 1207 buffer.add('return;\n'); |
| 1191 } else { | 1208 } else { |
| 1192 buffer.add('return '); | 1209 buffer.add('return '); |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1861 startBailoutSwitch(); | 1878 startBailoutSwitch(); |
| 1862 } | 1879 } |
| 1863 } | 1880 } |
| 1864 | 1881 |
| 1865 void endElse(HIf node) { | 1882 void endElse(HIf node) { |
| 1866 if (node.elseBlock.hasGuards()) { | 1883 if (node.elseBlock.hasGuards()) { |
| 1867 endBailoutSwitch(); | 1884 endBailoutSwitch(); |
| 1868 } | 1885 } |
| 1869 } | 1886 } |
| 1870 } | 1887 } |
| OLD | NEW |