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. | |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
I.e., this only expects to be called for top-level
floitsch
2012/06/27 11:18:24
Done.
| |
| 398 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE | |
| 399 || expectedPrecedence == JSPrecedence.EXPRESSION_PRECEDENCE); | |
| 400 | |
| 396 HSubExpressionBlockInformation expressionSubGraph = expression; | 401 HSubExpressionBlockInformation expressionSubGraph = expression; |
| 397 | 402 |
| 398 int oldState = generationState; | 403 int oldState = generationState; |
| 399 generationState = STATE_FIRST_EXPRESSION; | 404 generationState = STATE_FIRST_EXPRESSION; |
| 400 visitSubGraph(expressionSubGraph.subExpression); | 405 visitSubGraph(expressionSubGraph.subExpression); |
| 401 generationState = oldState; | 406 generationState = oldState; |
| 402 } | 407 } |
| 403 | 408 |
| 404 void generateDeclaration(HExpressionInformation expression) { | 409 void generateDeclaration(HExpressionInformation expression) { |
| 405 // Currently we only handle sub-expression graphs. | 410 // 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); | 569 String inputName = variableNames.getName(instruction.checkedInput); |
| 565 if (name != inputName) return false; | 570 if (name != inputName) return false; |
| 566 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 571 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 567 return true; | 572 return true; |
| 568 } | 573 } |
| 569 | 574 |
| 570 void define(HInstruction instruction) { | 575 void define(HInstruction instruction) { |
| 571 if (isGeneratingExpression()) { | 576 if (isGeneratingExpression()) { |
| 572 addExpressionSeparator(); | 577 addExpressionSeparator(); |
| 573 } else { | 578 } else { |
| 579 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE); | |
| 574 addIndentation(); | 580 addIndentation(); |
| 575 } | 581 } |
| 576 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { | 582 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { |
| 577 var name = variableNames.getName(instruction); | 583 var name = variableNames.getName(instruction); |
| 578 if (!handleSimpleUpdateDefinition(instruction, name) | 584 if (!handleSimpleUpdateDefinition(instruction, name) |
| 579 && !handleTypeConversion(instruction, name)) { | 585 && !handleTypeConversion(instruction, name)) { |
| 580 declareInstruction(instruction); | 586 withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, () { |
| 581 buffer.add(" = "); | 587 declareInstruction(instruction); |
| 582 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 588 buffer.add(" = "); |
| 589 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | |
| 590 }); | |
| 583 } | 591 } |
| 584 } else { | 592 } else { |
| 585 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 593 visit(instruction, expectedPrecedence); |
| 586 } | 594 } |
| 587 if (!isGeneratingExpression()) buffer.add(';\n'); | 595 if (!isGeneratingExpression()) buffer.add(';\n'); |
| 588 } | 596 } |
| 589 | 597 |
| 590 void use(HInstruction argument, int expectedPrecedenceForArgument) { | 598 void use(HInstruction argument, int expectedPrecedenceForArgument) { |
| 591 if (isGenerateAtUseSite(argument)) { | 599 if (isGenerateAtUseSite(argument)) { |
| 592 visit(argument, expectedPrecedenceForArgument); | 600 visit(argument, expectedPrecedenceForArgument); |
| 593 } else if (argument is HCheck && argument.isControlFlow()) { | 601 } else if (argument is HCheck && argument.isControlFlow()) { |
| 594 // A [HCheck] that has control flow can never be used as an | 602 // 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 | 603 // 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 } | 1112 } |
| 1105 } | 1113 } |
| 1106 } | 1114 } |
| 1107 | 1115 |
| 1108 void iterateBasicBlock(HBasicBlock node) { | 1116 void iterateBasicBlock(HBasicBlock node) { |
| 1109 HInstruction instruction = node.first; | 1117 HInstruction instruction = node.first; |
| 1110 while (instruction !== node.last) { | 1118 while (instruction !== node.last) { |
| 1111 if (instruction is HTypeGuard) { | 1119 if (instruction is HTypeGuard) { |
| 1112 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 1120 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1113 } else if (!isGenerateAtUseSite(instruction)) { | 1121 } else if (!isGenerateAtUseSite(instruction)) { |
| 1122 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; | |
| 1114 define(instruction); | 1123 define(instruction); |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
Won't a "define" always expect to be at the "state
floitsch
2012/06/27 11:18:24
No. 'define' is called from visitExpression below.
| |
| 1115 } | 1124 } |
| 1116 instruction = instruction.next; | 1125 instruction = instruction.next; |
| 1117 } | 1126 } |
| 1118 assignPhisOfSuccessors(node); | 1127 assignPhisOfSuccessors(node); |
| 1119 if (instruction is HLoopBranch && isGeneratingExpression()) { | 1128 if (instruction is HLoopBranch && isGeneratingExpression()) { |
| 1120 addExpressionSeparator(); | 1129 addExpressionSeparator(); |
| 1121 } | 1130 } |
| 1122 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 1131 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1123 } | 1132 } |
| 1124 | 1133 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1450 int thenKind = analyzeGraphForCodegen(thenGraph); | 1459 int thenKind = analyzeGraphForCodegen(thenGraph); |
| 1451 int elseKind = analyzeGraphForCodegen(elseGraph); | 1460 int elseKind = analyzeGraphForCodegen(elseGraph); |
| 1452 | 1461 |
| 1453 void visitWithoutIndent(HStatementInformation toVisit) { | 1462 void visitWithoutIndent(HStatementInformation toVisit) { |
| 1454 int oldIndent = indent; | 1463 int oldIndent = indent; |
| 1455 indent = 0; | 1464 indent = 0; |
| 1456 generateStatements(toVisit); | 1465 generateStatements(toVisit); |
| 1457 indent = oldIndent; | 1466 indent = oldIndent; |
| 1458 } | 1467 } |
| 1459 | 1468 |
| 1469 void visitExpression(HStatementInformation toVisit) { | |
| 1470 // [generateExpression] only works if the [expectedPrecedence] is a | |
| 1471 // statement or an expression. We therefore have to duplicate some | |
| 1472 // work here. | |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
Have you considered making a visitSubGraph that ta
floitsch
2012/06/27 11:18:24
Without the asserts we only have 8 lines here. The
| |
| 1473 assert(toVisit.start == toVisit.end); | |
| 1474 assert(toVisit.start.last is HGoto); | |
| 1475 // Find the expression (there must only be one). | |
| 1476 HInstruction expression = toVisit.start.first; | |
| 1477 while (generateAtUseSite.contains(expression)) { | |
| 1478 expression = expression.next; | |
| 1479 } | |
| 1480 assert(() { | |
| 1481 HInstruction remaining = expression.next; | |
| 1482 while (remaining is !HGoto) { | |
| 1483 if (generateAtUseSite.contains(remaining)) return false; | |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
Shouldn't this test be negated?
floitsch
2012/06/27 11:18:24
Done.
| |
| 1484 remaining = remaining.next; | |
| 1485 } | |
| 1486 return true; | |
| 1487 }); | |
| 1488 | |
| 1489 int oldState = generationState; | |
| 1490 generationState = STATE_FIRST_EXPRESSION; | |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
x
floitsch
2012/06/27 11:18:24
Done.
| |
| 1491 define(expression); | |
| 1492 generationState = oldState; | |
| 1493 } | |
| 1494 | |
| 1460 void visitWithIndent(HStatementInformation toVisit) { | 1495 void visitWithIndent(HStatementInformation toVisit) { |
| 1461 buffer.add('{\n'); | 1496 buffer.add('{\n'); |
| 1462 indent++; | 1497 indent++; |
| 1463 generateStatements(toVisit); | 1498 generateStatements(toVisit); |
| 1464 indent--; | 1499 indent--; |
| 1465 addIndented('}'); | 1500 addIndented('}'); |
| 1466 } | 1501 } |
| 1467 | 1502 |
| 1468 void emitIf() { | 1503 void emitIf() { |
| 1469 addIndented('if ('); | 1504 addIndented('if ('); |
| 1470 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); | 1505 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1471 buffer.add(') '); | 1506 buffer.add(') '); |
| 1472 } | 1507 } |
| 1473 | 1508 |
| 1474 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&']; | 1509 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&']; |
| 1475 void generateAnd(HStatementInformation toVisit, Function condition) { | 1510 void generateAnd(HStatementInformation toVisit, Function condition) { |
| 1476 addIndentation(); | 1511 addIndentation(); |
| 1477 beginExpression(operatorPrecedence.precedence); | 1512 beginExpression(operatorPrecedence.precedence); |
| 1478 condition(); | 1513 condition(); |
|
Lasse Reichstein Nielsen
2012/06/27 08:53:58
Shouldn't this be executed in a scope where expect
floitsch
2012/06/27 11:18:24
Done.
| |
| 1479 buffer.add(" && "); | 1514 buffer.add(" && "); |
| 1480 var oldPrecedence = expectedPrecedence; | 1515 var oldPrecedence = expectedPrecedence; |
| 1481 expectedPrecedence = operatorPrecedence.right; | 1516 expectedPrecedence = operatorPrecedence.right; |
| 1482 visitWithoutIndent(toVisit); | 1517 visitExpression(toVisit); |
| 1483 expectedPrecedence = oldPrecedence; | 1518 expectedPrecedence = oldPrecedence; |
| 1484 endExpression(operatorPrecedence.precedence); | 1519 endExpression(operatorPrecedence.precedence); |
| 1520 buffer.add(";\n"); | |
| 1485 } | 1521 } |
| 1486 | 1522 |
| 1487 List<HBasicBlock> thenSuccessors = thenGraph.end.successors; | 1523 List<HBasicBlock> thenSuccessors = thenGraph.end.successors; |
| 1488 bool thenGraphHasSuccessor = thenSuccessors.length != 0 | 1524 bool thenGraphHasSuccessor = thenSuccessors.length != 0 |
| 1489 && thenSuccessors[0] !== currentGraph.exit; | 1525 && thenSuccessors[0] !== currentGraph.exit; |
| 1490 | 1526 |
| 1491 switch (thenKind) { | 1527 switch (thenKind) { |
| 1492 case EMPTY: | 1528 case EMPTY: |
| 1493 switch (elseKind) { | 1529 switch (elseKind) { |
| 1494 case EMPTY: | 1530 case EMPTY: |
| (...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3002 startBailoutSwitch(); | 3038 startBailoutSwitch(); |
| 3003 } | 3039 } |
| 3004 } | 3040 } |
| 3005 | 3041 |
| 3006 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 3042 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 3007 if (labeledBlockInfo.body.start.hasGuards()) { | 3043 if (labeledBlockInfo.body.start.hasGuards()) { |
| 3008 endBailoutSwitch(); | 3044 endBailoutSwitch(); |
| 3009 } | 3045 } |
| 3010 } | 3046 } |
| 3011 } | 3047 } |
| OLD | NEW |