Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: dart/lib/compiler/implementation/ssa/codegen.dart

Issue 10541173: Generate nested else if (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 static final int STATE_EXPRESSION = 3; 116 static final int STATE_EXPRESSION = 3;
117 static final int STATE_DECLARATION = 4; 117 static final int STATE_DECLARATION = 4;
118 118
119 /** 119 /**
120 * When analyzing a [HStatementGraph] we try to recognize if it has 120 * When analyzing a [HStatementGraph] we try to recognize if it has
121 * the following properties. 121 * the following properties.
122 */ 122 */
123 static final int ONE_STATEMENT = 0; 123 static final int ONE_STATEMENT = 0;
124 static final int ONE_EXPRESSION = 1; 124 static final int ONE_EXPRESSION = 1;
125 static final int EMPTY = 2; 125 static final int EMPTY = 2;
126 static final int MULTIPLE_STATEMENTS = 3; 126 static final int IF_STATEMENT = 3;
127 static final int MULTIPLE_STATEMENTS = 4;
127 128
128 /** 129 /**
129 * Returned by [expressionType] to tell how code can be generated for 130 * Returned by [expressionType] to tell how code can be generated for
130 * a subgraph. 131 * a subgraph.
131 * - [TYPE_STATEMENT] means that the graph must be generated as a statement, 132 * - [TYPE_STATEMENT] means that the graph must be generated as a statement,
132 * which is always possible. 133 * which is always possible.
133 * - [TYPE_EXPRESSION] means that the graph can be generated as an expression, 134 * - [TYPE_EXPRESSION] means that the graph can be generated as an expression,
134 * or possibly several comma-separated expressions. 135 * or possibly several comma-separated expressions.
135 * - [TYPE_DECLARATION] means that the graph can be generated as an 136 * - [TYPE_DECLARATION] means that the graph can be generated as an
136 * expression, and that it only generates expressions of the form 137 * expression, and that it only generates expressions of the form
(...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 // information in [visitTryInfo], or not at all, in the case of the bailout 1309 // information in [visitTryInfo], or not at all, in the case of the bailout
1309 // generator. 1310 // generator.
1310 compiler.internalError('visitTry should not be called', instruction: node); 1311 compiler.internalError('visitTry should not be called', instruction: node);
1311 } 1312 }
1312 1313
1313 /** 1314 /**
1314 * Analyzes the given [graph] to know whether it is empty, or 1315 * Analyzes the given [graph] to know whether it is empty, or
1315 * contains one statement, one expression, or multiple statements. 1316 * contains one statement, one expression, or multiple statements.
1316 */ 1317 */
1317 int analyzeGraphForCodegen(HStatementInformation graph) { 1318 int analyzeGraphForCodegen(HStatementInformation graph) {
1318 HBasicBlock start = graph.start; 1319 return analyzeBlocksForCodegen(graph.start, graph.end);
1319 HBasicBlock end = graph.end; 1320 }
1320 // Only deal with single blocks for now. TODO(ngeoffray): analyze
1321 // all blocks.
1322 if (start !== end) return MULTIPLE_STATEMENTS;
1323 1321
1322 int analyzeBlocksForCodegen(HBasicBlock start, HBasicBlock end) {
1324 int kind = EMPTY; 1323 int kind = EMPTY;
1325 bool updateKind(int newKind) { 1324 bool updateKind(int newKind) {
1326 if (kind != EMPTY) return false; 1325 if (kind != EMPTY) return false;
1327 kind = newKind; 1326 kind = newKind;
1328 return true; 1327 return true;
1329 } 1328 }
1330 1329
1331 for (HInstruction instruction = start.first; 1330 for (HInstruction instruction = start.first;
1332 instruction != start.last; 1331 instruction != start.last;
1333 instruction = instruction.next) { 1332 instruction = instruction.next) {
1334 if (instruction.isStatement()) { 1333 if (instruction.isStatement()) {
1335 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1334 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1336 } else if (!isGenerateAtUseSite(instruction)) { 1335 } else if (!isGenerateAtUseSite(instruction)) {
1337 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS; 1336 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS;
1338 } 1337 }
1339 } 1338 }
1340 1339
1341 HInstruction last = start.last; 1340 HInstruction last = start.last;
1342 if (last is !HGoto) { 1341 if (last is HGoto) {
1343 if (!updateKind(last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) { 1342 if (start !== end) {
1343 int nextKind = analyzeBlocksForCodegen(start.successors[0], end);
1344 if (!updateKind(nextKind)) return MULTIPLE_STATEMENTS;
1345 }
1346 } else if (last is HIf) {
1347 HIf ifInstruction = last;
1348 if (ifInstruction.joinBlock !== null
1349 && analyzeBlocksForCodegen(ifInstruction.joinBlock, end) != EMPTY) {
1344 return MULTIPLE_STATEMENTS; 1350 return MULTIPLE_STATEMENTS;
1345 } 1351 }
1352 int ifKind = controlFlowOperators.contains(ifInstruction)
1353 ? ONE_EXPRESSION
1354 : IF_STATEMENT;
Lasse Reichstein Nielsen 2012/06/15 08:31:01 Maybe (later) consider whether the if-"statement"
1355 if (!updateKind(ifKind)) return MULTIPLE_STATEMENTS;
1356 } else if (start !== end) {
1357 return MULTIPLE_STATEMENTS;
1358 } else if (!updateKind(last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) {
1359 return MULTIPLE_STATEMENTS;
1346 } 1360 }
1347 1361
1348 CopyHandler handler = variableNames.getCopyHandler(start); 1362 CopyHandler handler = variableNames.getCopyHandler(start);
1349 if (handler !== null && !handler.isEmpty()) { 1363 if (handler !== null && !handler.isEmpty()) {
1350 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS; 1364 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS;
1351 if (handler.assignments.length == 1) { 1365 if (handler.assignments.length == 1) {
1352 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1366 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1353 } 1367 }
1354 // If the block has a copy where the destination and source are 1368 // If the block has a copy where the destination and source are
1355 // different, we will emit that copy, and therefore the block is 1369 // different, we will emit that copy, and therefore the block is
(...skipping 13 matching lines...) Expand all
1369 if (!controlFlowOperators.contains(node)) return false; 1383 if (!controlFlowOperators.contains(node)) return false;
1370 HPhi phi = node.joinBlock.phis.first; 1384 HPhi phi = node.joinBlock.phis.first;
1371 bool atUseSite = isGenerateAtUseSite(phi); 1385 bool atUseSite = isGenerateAtUseSite(phi);
1372 // Don't generate a conditional operator in this situation: 1386 // Don't generate a conditional operator in this situation:
1373 // i = condition ? bar() : i; 1387 // i = condition ? bar() : i;
1374 // But generate this instead: 1388 // But generate this instead:
1375 // if (condition) i = bar(); 1389 // if (condition) i = bar();
1376 // Usually, the variable name is longer than 'if' and it takes up 1390 // Usually, the variable name is longer than 'if' and it takes up
1377 // more space to duplicate the name. 1391 // more space to duplicate the name.
1378 if (!atUseSite 1392 if (!atUseSite
1393 && !generatingInlineStatement
1379 && variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) { 1394 && variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) {
1380 return false; 1395 return false;
1381 } 1396 }
1382 if (!atUseSite) define(phi); 1397 if (!atUseSite) define(phi);
1383 visitBasicBlock(node.joinBlock); 1398 visitBasicBlock(node.joinBlock);
1384 return true; 1399 return true;
1385 } 1400 }
1386 1401
1387 void generateIf(HIf node, HIfBlockInformation info) { 1402 void generateIf(HIf node, HIfBlockInformation info) {
1388 HStatementInformation thenGraph = info.thenGraph; 1403 HStatementInformation thenGraph = info.thenGraph;
1389 HStatementInformation elseGraph = info.elseGraph; 1404 HStatementInformation elseGraph = info.elseGraph;
1390 int thenKind = analyzeGraphForCodegen(thenGraph); 1405 int thenKind = analyzeGraphForCodegen(thenGraph);
1391 int elseKind = analyzeGraphForCodegen(elseGraph); 1406 int elseKind = analyzeGraphForCodegen(elseGraph);
1392 1407
1393 void visitWithoutIndent(HStatementInformation toVisit) { 1408 void visitWithoutIndent(HStatementInformation toVisit) {
1394 int oldIndent = indent; 1409 generatingInlineStatement = true;
1395 indent = 0; 1410 visitSubGraph(new SubGraph(toVisit.start, toVisit.end));
1396 generateStatements(toVisit);
1397 indent = oldIndent;
1398 } 1411 }
1399 1412
1400 void visitWithIndent(HStatementInformation toVisit) { 1413 void visitWithIndent(HStatementInformation toVisit) {
1401 buffer.add('{\n'); 1414 buffer.add('{\n');
1402 indent++; 1415 indent++;
1403 generateStatements(toVisit); 1416 visitSubGraph(new SubGraph(toVisit.start, toVisit.end));
1404 indent--; 1417 indent--;
1405 addIndented('}'); 1418 addIndented('}');
1406 } 1419 }
1407 1420
1408 void emitIf() { 1421 void emitIf() {
1409 addIndented('if ('); 1422 addIndented('if (');
1410 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1423 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1411 buffer.add(') '); 1424 buffer.add(') ');
1412 } 1425 }
1413 1426
(...skipping 23 matching lines...) Expand all
1437 use(node.inputs[0], JSPrecedence.STATEMENT_PRECEDENCE); 1450 use(node.inputs[0], JSPrecedence.STATEMENT_PRECEDENCE);
1438 buffer.add(';\n'); 1451 buffer.add(';\n');
1439 } 1452 }
1440 break; 1453 break;
1441 1454
1442 case ONE_EXPRESSION: 1455 case ONE_EXPRESSION:
1443 generateAnd(elseGraph, () { generateNot(node.inputs[0]); }); 1456 generateAnd(elseGraph, () { generateNot(node.inputs[0]); });
1444 break; 1457 break;
1445 1458
1446 case ONE_STATEMENT: 1459 case ONE_STATEMENT:
1460 case IF_STATEMENT:
1447 addIndented('if ('); 1461 addIndented('if (');
1448 generateNot(node.inputs[0]); 1462 generateNot(node.inputs[0]);
1449 buffer.add(') '); 1463 buffer.add(') ');
1450 visitWithoutIndent(elseGraph); 1464 visitWithoutIndent(elseGraph);
1451 break; 1465 break;
1452 1466
1453 case MULTIPLE_STATEMENTS: 1467 case MULTIPLE_STATEMENTS:
1454 addIndented('if ('); 1468 addIndented('if (');
1455 generateNot(node.inputs[0]); 1469 generateNot(node.inputs[0]);
1456 buffer.add(') '); 1470 buffer.add(') ');
(...skipping 12 matching lines...) Expand all
1469 int precedence = operatorPrecedence.left; 1483 int precedence = operatorPrecedence.left;
1470 generateAnd(thenGraph, () { use(node.inputs[0], precedence); }); 1484 generateAnd(thenGraph, () { use(node.inputs[0], precedence); });
1471 } else { 1485 } else {
1472 emitIf(); 1486 emitIf();
1473 visitWithoutIndent(thenGraph); 1487 visitWithoutIndent(thenGraph);
1474 } 1488 }
1475 break; 1489 break;
1476 1490
1477 case ONE_EXPRESSION: 1491 case ONE_EXPRESSION:
1478 case ONE_STATEMENT: 1492 case ONE_STATEMENT:
1493 case IF_STATEMENT:
1479 // TODO(ngeoffray): Generate a conditional. 1494 // TODO(ngeoffray): Generate a conditional.
1480 emitIf(); 1495 emitIf();
1481 visitWithoutIndent(thenGraph); 1496 visitWithoutIndent(thenGraph);
1482 if (thenGraphHasSuccessor) { 1497 if (thenGraphHasSuccessor) {
1483 addIndented('else '); 1498 addIndented('else ');
1484 visitWithoutIndent(elseGraph); 1499 visitWithoutIndent(elseGraph);
1485 } else { 1500 } else {
1486 generateStatements(elseGraph); 1501 generateStatements(elseGraph);
1487 } 1502 }
1488 break; 1503 break;
1489 1504
1490 case MULTIPLE_STATEMENTS: 1505 case MULTIPLE_STATEMENTS:
1491 emitIf(); 1506 emitIf();
1492 visitWithoutIndent(thenGraph); 1507 visitWithoutIndent(thenGraph);
1493 if (thenGraphHasSuccessor) { 1508 if (thenGraphHasSuccessor) {
1494 addIndented('else '); 1509 addIndented('else ');
1495 visitWithIndent(elseGraph); 1510 visitWithIndent(elseGraph);
1496 buffer.add('\n'); 1511 buffer.add('\n');
1497 } else { 1512 } else {
1498 generateStatements(elseGraph); 1513 generateStatements(elseGraph);
1499 } 1514 }
1500 break; 1515 break;
1501 } 1516 }
1502 break; 1517 break;
1503 1518
1504 case MULTIPLE_STATEMENTS: 1519 case MULTIPLE_STATEMENTS:
1520 case IF_STATEMENT:
1505 emitIf(); 1521 emitIf();
1506 visitWithIndent(thenGraph); 1522 visitWithIndent(thenGraph);
1507 1523
1508 switch (elseKind) { 1524 switch (elseKind) {
1509 case EMPTY: 1525 case EMPTY:
1510 buffer.add('\n'); 1526 buffer.add('\n');
1511 break; 1527 break;
1512 1528
1513 case ONE_EXPRESSION: 1529 case ONE_EXPRESSION:
1514 case ONE_STATEMENT: 1530 case ONE_STATEMENT:
1531 case IF_STATEMENT:
1515 if (thenGraphHasSuccessor) { 1532 if (thenGraphHasSuccessor) {
1516 buffer.add(' else '); 1533 buffer.add(' else ');
1517 visitWithoutIndent(elseGraph); 1534 visitWithoutIndent(elseGraph);
1518 } else { 1535 } else {
1519 buffer.add('\n'); 1536 buffer.add('\n');
1520 generateStatements(elseGraph); 1537 generateStatements(elseGraph);
1521 } 1538 }
1522 break; 1539 break;
1523 1540
1524 case MULTIPLE_STATEMENTS: 1541 case MULTIPLE_STATEMENTS:
(...skipping 22 matching lines...) Expand all
1547 return; 1564 return;
1548 } 1565 }
1549 1566
1550 HInstruction condition = node.inputs[0]; 1567 HInstruction condition = node.inputs[0];
1551 HIfBlockInformation info = node.blockInformation.body; 1568 HIfBlockInformation info = node.blockInformation.body;
1552 1569
1553 if (condition.isConstant()) { 1570 if (condition.isConstant()) {
1554 HConstant constant = condition; 1571 HConstant constant = condition;
1555 if (constant.constant.isTrue()) { 1572 if (constant.constant.isTrue()) {
1556 generateStatements(info.thenGraph); 1573 generateStatements(info.thenGraph);
1574 int thenKind = analyzeGraphForCodegen(info.thenGraph);
1575 if (thenKind == EMPTY && generatingInlineStatement) {
1576 generatingInlineStatement = false;
Lasse Reichstein Nielsen 2012/06/15 08:31:01 Explain why you set generatingInlineStatement to f
ngeoffray 2012/06/18 15:43:25 Done.
1577 buffer.add(';\n');
1578 }
1557 } else { 1579 } else {
1558 generateStatements(info.elseGraph); 1580 generateStatements(info.elseGraph);
1581 int elseKind = analyzeGraphForCodegen(info.elseGraph);
1582 if (elseKind == EMPTY && generatingInlineStatement) {
1583 generatingInlineStatement = false;
1584 buffer.add(';\n');
1585 }
1559 } 1586 }
1560 } else { 1587 } else {
1561 generateIf(node, info); 1588 generateIf(node, info);
1562 } 1589 }
1563 1590
1564 HBasicBlock joinBlock = node.joinBlock; 1591 HBasicBlock joinBlock = node.joinBlock;
1565 if (joinBlock !== null && joinBlock.dominator !== node.block) { 1592 if (joinBlock !== null && joinBlock.dominator !== node.block) {
1566 // The join block is dominated by a block in one of the branches. 1593 // The join block is dominated by a block in one of the branches.
1567 // The subgraph traversal never reached it, so we visit it here 1594 // The subgraph traversal never reached it, so we visit it here
1568 // instead. 1595 // instead.
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 world.registerStaticUse(helper); 2022 world.registerStaticUse(helper);
1996 buffer.add('throw '); 2023 buffer.add('throw ');
1997 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 2024 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
1998 beginExpression(JSPrecedence.CALL_PRECEDENCE); 2025 beginExpression(JSPrecedence.CALL_PRECEDENCE);
1999 buffer.add(compiler.namer.isolateAccess(helper)); 2026 buffer.add(compiler.namer.isolateAccess(helper));
2000 visitArguments([null, argument]); 2027 visitArguments([null, argument]);
2001 endExpression(JSPrecedence.CALL_PRECEDENCE); 2028 endExpression(JSPrecedence.CALL_PRECEDENCE);
2002 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 2029 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
2003 } 2030 }
2004 2031
2032 bool generatingInlineStatement = false;
Lasse Reichstein Nielsen 2012/06/15 08:31:01 Move this field to the top of the class, and docum
ngeoffray 2012/06/18 15:43:25 Done.
2005 void addIndentation() { 2033 void addIndentation() {
2006 for (int i = 0; i < indent; i++) { 2034 if (generatingInlineStatement) {
2007 buffer.add(' '); 2035 generatingInlineStatement = false;
2036 } else {
2037 for (int i = 0; i < indent; i++) {
2038 buffer.add(' ');
2039 }
2008 } 2040 }
2009 } 2041 }
2010 2042
2011 void addIndented(String text) { 2043 void addIndented(String text) {
2012 addIndentation(); 2044 addIndentation();
2013 buffer.add(text); 2045 buffer.add(text);
2014 } 2046 }
2015 2047
2016 void visitSwitch(HSwitch node) { 2048 void visitSwitch(HSwitch node) {
2017 // Switches are handled using [visitSwitchInfo]. 2049 // Switches are handled using [visitSwitchInfo].
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
2894 startBailoutSwitch(); 2926 startBailoutSwitch();
2895 } 2927 }
2896 } 2928 }
2897 2929
2898 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2930 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2899 if (labeledBlockInfo.body.start.hasGuards()) { 2931 if (labeledBlockInfo.body.start.hasGuards()) {
2900 endBailoutSwitch(); 2932 endBailoutSwitch();
2901 } 2933 }
2902 } 2934 }
2903 } 2935 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698