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 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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 } | 386 } |
| 387 generationState = oldState; | 387 generationState = oldState; |
| 388 } | 388 } |
| 389 | 389 |
| 390 /** | 390 /** |
| 391 * Generate expressions from block information. | 391 * Generate expressions from block information. |
| 392 */ | 392 */ |
| 393 void generateExpression(HExpressionInformation expression) { | 393 void generateExpression(HExpressionInformation expression) { |
| 394 // Currently we only handle sub-expression graphs. | 394 // Currently we only handle sub-expression graphs. |
| 395 assert(expression is HSubExpressionBlockInformation); | 395 assert(expression is HSubExpressionBlockInformation); |
| 396 // [visitSubGraph] will reset the [expectedPrecedence]. Make sure we don't | |
| 397 // need parenthesis. I.e., this only expects to be called for top-level | |
| 398 // expressions, not sub-expressions. | |
| 399 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE | |
| 400 || expectedPrecedence == JSPrecedence.EXPRESSION_PRECEDENCE); | |
| 401 | |
| 396 HSubExpressionBlockInformation expressionSubGraph = expression; | 402 HSubExpressionBlockInformation expressionSubGraph = expression; |
| 397 | 403 |
| 398 int oldState = generationState; | 404 int oldState = generationState; |
| 399 generationState = STATE_FIRST_EXPRESSION; | 405 generationState = STATE_FIRST_EXPRESSION; |
| 400 visitSubGraph(expressionSubGraph.subExpression); | 406 visitSubGraph(expressionSubGraph.subExpression); |
| 401 generationState = oldState; | 407 generationState = oldState; |
| 402 } | 408 } |
| 403 | 409 |
| 404 void generateDeclaration(HExpressionInformation expression) { | 410 void generateDeclaration(HExpressionInformation expression) { |
| 405 // Currently we only handle sub-expression graphs. | 411 // Currently we only handle sub-expression graphs. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 String inputName = variableNames.getName(instruction.checkedInput); | 570 String inputName = variableNames.getName(instruction.checkedInput); |
| 565 if (name != inputName) return false; | 571 if (name != inputName) return false; |
| 566 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 572 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 567 return true; | 573 return true; |
| 568 } | 574 } |
| 569 | 575 |
| 570 void define(HInstruction instruction) { | 576 void define(HInstruction instruction) { |
| 571 if (isGeneratingExpression()) { | 577 if (isGeneratingExpression()) { |
| 572 addExpressionSeparator(); | 578 addExpressionSeparator(); |
| 573 } else { | 579 } else { |
| 580 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE); | |
| 574 addIndentation(); | 581 addIndentation(); |
| 575 } | 582 } |
| 576 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { | 583 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { |
| 577 var name = variableNames.getName(instruction); | 584 var name = variableNames.getName(instruction); |
| 578 if (!handleSimpleUpdateDefinition(instruction, name) | 585 if (!handleSimpleUpdateDefinition(instruction, name) |
| 579 && !handleTypeConversion(instruction, name)) { | 586 && !handleTypeConversion(instruction, name)) { |
| 580 declareInstruction(instruction); | 587 withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, () { |
|
sra1
2012/06/29 02:03:57
It bothers me that there are >200 places in this f
| |
| 581 buffer.add(" = "); | 588 declareInstruction(instruction); |
| 582 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 589 buffer.add(" = "); |
| 590 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | |
| 591 }); | |
| 583 } | 592 } |
| 584 } else { | 593 } else { |
| 585 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 594 visit(instruction, expectedPrecedence); |
| 586 } | 595 } |
| 587 if (!isGeneratingExpression()) buffer.add(';\n'); | 596 if (!isGeneratingExpression()) buffer.add(';\n'); |
| 588 } | 597 } |
| 589 | 598 |
| 590 void use(HInstruction argument, int expectedPrecedenceForArgument) { | 599 void use(HInstruction argument, int expectedPrecedenceForArgument) { |
| 591 if (isGenerateAtUseSite(argument)) { | 600 if (isGenerateAtUseSite(argument)) { |
| 592 visit(argument, expectedPrecedenceForArgument); | 601 visit(argument, expectedPrecedenceForArgument); |
| 593 } else if (argument is HCheck && argument.isControlFlow()) { | 602 } else if (argument is HCheck && argument.isControlFlow()) { |
| 594 // A [HCheck] that has control flow can never be used as an | 603 // A [HCheck] that has control flow can never be used as an |
| 595 // expression and may not have a name. Therefore we just use the | 604 // expression and may not have a name. Therefore we just use the |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 } | 1113 } |
| 1105 } | 1114 } |
| 1106 } | 1115 } |
| 1107 | 1116 |
| 1108 void iterateBasicBlock(HBasicBlock node) { | 1117 void iterateBasicBlock(HBasicBlock node) { |
| 1109 HInstruction instruction = node.first; | 1118 HInstruction instruction = node.first; |
| 1110 while (instruction !== node.last) { | 1119 while (instruction !== node.last) { |
| 1111 if (instruction is HTypeGuard) { | 1120 if (instruction is HTypeGuard) { |
| 1112 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 1121 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1113 } else if (!isGenerateAtUseSite(instruction)) { | 1122 } else if (!isGenerateAtUseSite(instruction)) { |
| 1123 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; | |
| 1114 define(instruction); | 1124 define(instruction); |
| 1115 } | 1125 } |
| 1116 instruction = instruction.next; | 1126 instruction = instruction.next; |
| 1117 } | 1127 } |
| 1118 assignPhisOfSuccessors(node); | 1128 assignPhisOfSuccessors(node); |
| 1119 if (instruction is HLoopBranch && isGeneratingExpression()) { | 1129 if (instruction is HLoopBranch && isGeneratingExpression()) { |
| 1120 addExpressionSeparator(); | 1130 addExpressionSeparator(); |
| 1121 } | 1131 } |
| 1122 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 1132 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1123 } | 1133 } |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1450 int thenKind = analyzeGraphForCodegen(thenGraph); | 1460 int thenKind = analyzeGraphForCodegen(thenGraph); |
| 1451 int elseKind = analyzeGraphForCodegen(elseGraph); | 1461 int elseKind = analyzeGraphForCodegen(elseGraph); |
| 1452 | 1462 |
| 1453 void visitWithoutIndent(HStatementInformation toVisit) { | 1463 void visitWithoutIndent(HStatementInformation toVisit) { |
| 1454 int oldIndent = indent; | 1464 int oldIndent = indent; |
| 1455 indent = 0; | 1465 indent = 0; |
| 1456 generateStatements(toVisit); | 1466 generateStatements(toVisit); |
| 1457 indent = oldIndent; | 1467 indent = oldIndent; |
| 1458 } | 1468 } |
| 1459 | 1469 |
| 1470 void visitExpression(HStatementInformation toVisit) { | |
| 1471 // [generateExpression] only works if the [expectedPrecedence] is a | |
| 1472 // statement or an expression. We therefore have to duplicate some | |
| 1473 // work here. | |
| 1474 assert(toVisit.start == toVisit.end); | |
| 1475 assert(toVisit.start.last is HGoto); | |
| 1476 // Find the expression (there must only be one). | |
| 1477 HInstruction expression = toVisit.start.first; | |
| 1478 while (generateAtUseSite.contains(expression)) { | |
| 1479 expression = expression.next; | |
| 1480 } | |
| 1481 assert(() { | |
| 1482 HInstruction remaining = expression.next; | |
| 1483 while (remaining is !HGoto) { | |
| 1484 if (!generateAtUseSite.contains(remaining)) return false; | |
| 1485 remaining = remaining.next; | |
| 1486 } | |
| 1487 return true; | |
| 1488 }); | |
| 1489 | |
| 1490 int oldState = generationState; | |
| 1491 generationState = STATE_FIRST_EXPRESSION; | |
| 1492 define(expression); | |
| 1493 generationState = oldState; | |
| 1494 } | |
| 1495 | |
| 1460 void visitWithIndent(HStatementInformation toVisit) { | 1496 void visitWithIndent(HStatementInformation toVisit) { |
| 1461 buffer.add('{\n'); | 1497 buffer.add('{\n'); |
| 1462 indent++; | 1498 indent++; |
| 1463 generateStatements(toVisit); | 1499 generateStatements(toVisit); |
| 1464 indent--; | 1500 indent--; |
| 1465 addIndented('}'); | 1501 addIndented('}'); |
| 1466 } | 1502 } |
| 1467 | 1503 |
| 1468 void emitIf() { | 1504 void emitIf() { |
| 1469 addIndented('if ('); | 1505 addIndented('if ('); |
| 1470 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); | 1506 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1471 buffer.add(') '); | 1507 buffer.add(') '); |
| 1472 } | 1508 } |
| 1473 | 1509 |
| 1474 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&']; | 1510 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&']; |
| 1475 void generateAnd(HStatementInformation toVisit, Function condition) { | 1511 void generateAnd(HStatementInformation toVisit, Function condition) { |
| 1476 addIndentation(); | 1512 addIndentation(); |
| 1477 beginExpression(operatorPrecedence.precedence); | 1513 beginExpression(operatorPrecedence.precedence); |
| 1514 var oldPrecedence = expectedPrecedence; | |
| 1515 expectedPrecedence = operatorPrecedence.left; | |
| 1478 condition(); | 1516 condition(); |
| 1479 buffer.add(" && "); | 1517 buffer.add(" && "); |
| 1480 var oldPrecedence = expectedPrecedence; | |
| 1481 expectedPrecedence = operatorPrecedence.right; | 1518 expectedPrecedence = operatorPrecedence.right; |
| 1482 visitWithoutIndent(toVisit); | 1519 visitExpression(toVisit); |
| 1483 expectedPrecedence = oldPrecedence; | 1520 expectedPrecedence = oldPrecedence; |
| 1484 endExpression(operatorPrecedence.precedence); | 1521 endExpression(operatorPrecedence.precedence); |
| 1522 buffer.add(";\n"); | |
| 1485 } | 1523 } |
| 1486 | 1524 |
| 1487 List<HBasicBlock> thenSuccessors = thenGraph.end.successors; | 1525 List<HBasicBlock> thenSuccessors = thenGraph.end.successors; |
| 1488 bool thenGraphHasSuccessor = thenSuccessors.length != 0 | 1526 bool thenGraphHasSuccessor = thenSuccessors.length != 0 |
| 1489 && thenSuccessors[0] !== currentGraph.exit; | 1527 && thenSuccessors[0] !== currentGraph.exit; |
| 1490 | 1528 |
| 1491 switch (thenKind) { | 1529 switch (thenKind) { |
| 1492 case EMPTY: | 1530 case EMPTY: |
| 1493 switch (elseKind) { | 1531 switch (elseKind) { |
| 1494 case EMPTY: | 1532 case EMPTY: |
| (...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3034 startBailoutSwitch(); | 3072 startBailoutSwitch(); |
| 3035 } | 3073 } |
| 3036 } | 3074 } |
| 3037 | 3075 |
| 3038 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 3076 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 3039 if (labeledBlockInfo.body.start.hasGuards()) { | 3077 if (labeledBlockInfo.body.start.hasGuards()) { |
| 3040 endBailoutSwitch(); | 3078 endBailoutSwitch(); |
| 3041 } | 3079 } |
| 3042 } | 3080 } |
| 3043 } | 3081 } |
| OLD | NEW |