| 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 import 'dart:math' as math; | 5 import 'dart:math' as math; |
| 6 import 'dart:collection' show Queue; |
| 6 import '../common.dart'; | 7 import '../common.dart'; |
| 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 8 import '../common/tasks.dart' show CompilerTask; | 9 import '../common/tasks.dart' show CompilerTask; |
| 9 import '../constants/constant_system.dart'; | 10 import '../constants/constant_system.dart'; |
| 10 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
| 11 import '../common_elements.dart' show CommonElements; | 12 import '../common_elements.dart' show CommonElements; |
| 12 import '../elements/elements.dart' | 13 import '../elements/elements.dart' |
| 13 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst; | 14 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst; |
| 14 import '../elements/entities.dart'; | 15 import '../elements/entities.dart'; |
| 15 import '../elements/types.dart'; | 16 import '../elements/types.dart'; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 | 200 |
| 200 HGraph currentGraph; | 201 HGraph currentGraph; |
| 201 | 202 |
| 202 // Records a block-information that is being handled specially. | 203 // Records a block-information that is being handled specially. |
| 203 // Used to break bad recursion. | 204 // Used to break bad recursion. |
| 204 HBlockInformation currentBlockInformation; | 205 HBlockInformation currentBlockInformation; |
| 205 // The subgraph is used to delimit traversal for some constructions, e.g., | 206 // The subgraph is used to delimit traversal for some constructions, e.g., |
| 206 // if branches. | 207 // if branches. |
| 207 SubGraph subGraph; | 208 SubGraph subGraph; |
| 208 | 209 |
| 210 // Pending blocks than need to be visited as part of current subgraph. |
| 211 Queue<HBasicBlock> blockQueue; |
| 212 |
| 209 SsaCodeGenerator( | 213 SsaCodeGenerator( |
| 210 this._options, | 214 this._options, |
| 211 this._emitter, | 215 this._emitter, |
| 212 this._nativeEnqueuer, | 216 this._nativeEnqueuer, |
| 213 this._helpers, | 217 this._helpers, |
| 214 this._checkedModeHelpers, | 218 this._checkedModeHelpers, |
| 215 this._nativeData, | 219 this._nativeData, |
| 216 this._interceptorData, | 220 this._interceptorData, |
| 217 this._oneShotInterceptorData, | 221 this._oneShotInterceptorData, |
| 218 this._rtiSubstitutions, | 222 this._rtiSubstitutions, |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 var declarationList = new js.VariableDeclarationList(declarations) | 416 var declarationList = new js.VariableDeclarationList(declarations) |
| 413 .withSourceInformation(sourceInformation); | 417 .withSourceInformation(sourceInformation); |
| 414 ; | 418 ; |
| 415 insertStatementAtStart(new js.ExpressionStatement(declarationList)); | 419 insertStatementAtStart(new js.ExpressionStatement(declarationList)); |
| 416 } | 420 } |
| 417 } | 421 } |
| 418 | 422 |
| 419 visitGraph(HGraph graph) { | 423 visitGraph(HGraph graph) { |
| 420 preGenerateMethod(graph); | 424 preGenerateMethod(graph); |
| 421 currentGraph = graph; | 425 currentGraph = graph; |
| 422 subGraph = new SubGraph(graph.entry, graph.exit); | 426 visitSubGraph(new SubGraph(graph.entry, graph.exit)); |
| 423 visitBasicBlock(graph.entry); | |
| 424 handleDelayedVariableDeclarations(graph.sourceInformation); | 427 handleDelayedVariableDeclarations(graph.sourceInformation); |
| 425 } | 428 } |
| 426 | 429 |
| 427 void visitSubGraph(SubGraph newSubGraph) { | 430 void visitSubGraph(SubGraph newSubGraph) { |
| 428 SubGraph oldSubGraph = subGraph; | 431 SubGraph oldSubGraph = subGraph; |
| 432 Queue<HBasicBlock> oldBlockQueue = blockQueue; |
| 429 subGraph = newSubGraph; | 433 subGraph = newSubGraph; |
| 430 visitBasicBlock(subGraph.start); | 434 blockQueue = new Queue<HBasicBlock>(); |
| 435 enterSubGraph(subGraph.start); |
| 436 blockQueue = oldBlockQueue; |
| 431 subGraph = oldSubGraph; | 437 subGraph = oldSubGraph; |
| 432 } | 438 } |
| 433 | 439 |
| 434 /** | 440 /** |
| 435 * Check whether a sub-graph can be generated as an expression, or even | 441 * Check whether a sub-graph can be generated as an expression, or even |
| 436 * as a declaration, or if it has to fall back to being generated as | 442 * as a declaration, or if it has to fall back to being generated as |
| 437 * a statement. | 443 * a statement. |
| 438 * Expressions are anything that doesn't generate control flow constructs. | 444 * Expressions are anything that doesn't generate control flow constructs. |
| 439 * Declarations must only generate assignments on the form "id = expression", | 445 * Declarations must only generate assignments on the form "id = expression", |
| 440 * and not, e.g., expressions where the value isn't assigned, or where it's | 446 * and not, e.g., expressions where the value isn't assigned, or where it's |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 // the same block, don't handle it again. | 1200 // the same block, don't handle it again. |
| 1195 // When the structure graph is complete, we will be able to have | 1201 // When the structure graph is complete, we will be able to have |
| 1196 // different structures starting on the same basic block (e.g., an | 1202 // different structures starting on the same basic block (e.g., an |
| 1197 // "if" and its condition). | 1203 // "if" and its condition). |
| 1198 if (identical(info, currentBlockInformation)) return false; | 1204 if (identical(info, currentBlockInformation)) return false; |
| 1199 | 1205 |
| 1200 HBlockInformation oldBlockInformation = currentBlockInformation; | 1206 HBlockInformation oldBlockInformation = currentBlockInformation; |
| 1201 currentBlockInformation = info; | 1207 currentBlockInformation = info; |
| 1202 bool success = info.accept(this); | 1208 bool success = info.accept(this); |
| 1203 currentBlockInformation = oldBlockInformation; | 1209 currentBlockInformation = oldBlockInformation; |
| 1210 |
| 1204 if (success) { | 1211 if (success) { |
| 1205 HBasicBlock continuation = block.continuation; | 1212 HBasicBlock continuation = block.continuation; |
| 1206 if (continuation != null) { | 1213 if (continuation != null) { |
| 1207 visitBasicBlock(continuation); | 1214 continueSubGraph(continuation); |
| 1208 } | 1215 } |
| 1209 } | 1216 } |
| 1210 return success; | 1217 return success; |
| 1211 } | 1218 } |
| 1212 | 1219 |
| 1213 void visitBasicBlock(HBasicBlock node) { | 1220 void enterSubGraph(HBasicBlock node) { |
| 1221 assert(blockQueue.isEmpty); |
| 1222 assert(node != null); |
| 1223 continueSubGraph(node); |
| 1224 while (blockQueue.isNotEmpty) { |
| 1225 node = blockQueue.removeFirst(); |
| 1226 assert(node.isLive); |
| 1227 assert(subGraph.contains(node)); |
| 1228 |
| 1229 // If this node has block-structure based information attached, |
| 1230 // try using that to traverse from here. |
| 1231 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) { |
| 1232 continue; |
| 1233 } |
| 1234 |
| 1235 iterateBasicBlock(node); |
| 1236 } |
| 1237 } |
| 1238 |
| 1239 void continueSubGraph(HBasicBlock node) { |
| 1214 if (!node.isLive) return; | 1240 if (!node.isLive) return; |
| 1215 | 1241 // Don't follow edges out of the current sub-graph. |
| 1216 // Abort traversal if we are leaving the currently active sub-graph. | |
| 1217 if (!subGraph.contains(node)) return; | 1242 if (!subGraph.contains(node)) return; |
| 1218 | 1243 blockQueue.add(node); |
| 1219 // If this node has block-structure based information attached, | |
| 1220 // try using that to traverse from here. | |
| 1221 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) { | |
| 1222 return; | |
| 1223 } | |
| 1224 iterateBasicBlock(node); | |
| 1225 } | 1244 } |
| 1226 | 1245 |
| 1227 void emitAssignment(String destination, String source) { | 1246 void emitAssignment(String destination, String source) { |
| 1228 assignVariable(destination, new js.VariableUse(source), null); | 1247 assignVariable(destination, new js.VariableUse(source), null); |
| 1229 } | 1248 } |
| 1230 | 1249 |
| 1231 /** | 1250 /** |
| 1232 * Sequentialize a list of conceptually parallel copies. Parallel | 1251 * Sequentialize a list of conceptually parallel copies. Parallel |
| 1233 * copies may contain cycles, that this method breaks. | 1252 * copies may contain cycles, that this method breaks. |
| 1234 */ | 1253 */ |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 if (dominated.isEmpty) return; | 1496 if (dominated.isEmpty) return; |
| 1478 if (dominated.length > 2) { | 1497 if (dominated.length > 2) { |
| 1479 throw new SpannableAssertionFailure( | 1498 throw new SpannableAssertionFailure( |
| 1480 node, 'dominated.length = ${dominated.length}'); | 1499 node, 'dominated.length = ${dominated.length}'); |
| 1481 } | 1500 } |
| 1482 if (dominated.length == 2 && block != currentGraph.entry) { | 1501 if (dominated.length == 2 && block != currentGraph.entry) { |
| 1483 throw new SpannableAssertionFailure( | 1502 throw new SpannableAssertionFailure( |
| 1484 node, 'node.block != currentGraph.entry'); | 1503 node, 'node.block != currentGraph.entry'); |
| 1485 } | 1504 } |
| 1486 assert(dominated[0] == block.successors[0]); | 1505 assert(dominated[0] == block.successors[0]); |
| 1487 visitBasicBlock(dominated[0]); | 1506 continueSubGraph(dominated.first); |
| 1488 } | 1507 } |
| 1489 | 1508 |
| 1490 visitLoopBranch(HLoopBranch node) { | 1509 visitLoopBranch(HLoopBranch node) { |
| 1491 assert(node.block == subGraph.end); | 1510 assert(node.block == subGraph.end); |
| 1492 // We are generating code for a loop condition. | 1511 // We are generating code for a loop condition. |
| 1493 // If we are generating the subgraph as an expression, the | 1512 // If we are generating the subgraph as an expression, the |
| 1494 // condition will be generated as the expression. | 1513 // condition will be generated as the expression. |
| 1495 // Otherwise, we don't generate the expression, and leave that | 1514 // Otherwise, we don't generate the expression, and leave that |
| 1496 // to the code that called [visitSubGraph]. | 1515 // to the code that called [visitSubGraph]. |
| 1497 if (isGeneratingExpression) { | 1516 if (isGeneratingExpression) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 } | 1575 } |
| 1557 } | 1576 } |
| 1558 } | 1577 } |
| 1559 | 1578 |
| 1560 visitExitTry(HExitTry node) { | 1579 visitExitTry(HExitTry node) { |
| 1561 // An [HExitTry] is used to represent the control flow graph of a | 1580 // An [HExitTry] is used to represent the control flow graph of a |
| 1562 // try/catch block, ie the try body is always a predecessor | 1581 // try/catch block, ie the try body is always a predecessor |
| 1563 // of the catch and finally. Here, we continue visiting the try | 1582 // of the catch and finally. Here, we continue visiting the try |
| 1564 // body by visiting the block that contains the user-level control | 1583 // body by visiting the block that contains the user-level control |
| 1565 // flow instruction. | 1584 // flow instruction. |
| 1566 visitBasicBlock(node.bodyTrySuccessor); | 1585 continueSubGraph(node.bodyTrySuccessor); |
| 1567 } | 1586 } |
| 1568 | 1587 |
| 1569 visitTry(HTry node) { | 1588 visitTry(HTry node) { |
| 1570 // We should never get here. Try/catch/finally is always handled using block | 1589 // We should never get here. Try/catch/finally is always handled using block |
| 1571 // information in [visitTryInfo]. | 1590 // information in [visitTryInfo]. |
| 1572 throw new SpannableAssertionFailure(node, 'visitTry should not be called.'); | 1591 throw new SpannableAssertionFailure(node, 'visitTry should not be called.'); |
| 1573 } | 1592 } |
| 1574 | 1593 |
| 1575 bool tryControlFlowOperation(HIf node) { | 1594 bool tryControlFlowOperation(HIf node) { |
| 1576 if (!controlFlowOperators.contains(node)) return false; | 1595 if (!controlFlowOperators.contains(node)) return false; |
| 1577 HPhi phi = node.joinBlock.phis.first; | 1596 HPhi phi = node.joinBlock.phis.first; |
| 1578 bool atUseSite = isGenerateAtUseSite(phi); | 1597 bool atUseSite = isGenerateAtUseSite(phi); |
| 1579 // Don't generate a conditional operator in this situation: | 1598 // Don't generate a conditional operator in this situation: |
| 1580 // i = condition ? bar() : i; | 1599 // i = condition ? bar() : i; |
| 1581 // But generate this instead: | 1600 // But generate this instead: |
| 1582 // if (condition) i = bar(); | 1601 // if (condition) i = bar(); |
| 1583 // Usually, the variable name is longer than 'if' and it takes up | 1602 // Usually, the variable name is longer than 'if' and it takes up |
| 1584 // more space to duplicate the name. | 1603 // more space to duplicate the name. |
| 1585 if (!atUseSite && | 1604 if (!atUseSite && |
| 1586 variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) { | 1605 variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) { |
| 1587 return false; | 1606 return false; |
| 1588 } | 1607 } |
| 1589 if (!atUseSite) define(phi); | 1608 if (!atUseSite) define(phi); |
| 1590 visitBasicBlock(node.joinBlock); | 1609 continueSubGraph(node.joinBlock); |
| 1591 return true; | 1610 return true; |
| 1592 } | 1611 } |
| 1593 | 1612 |
| 1594 void generateIf(HIf node, HIfBlockInformation info) { | 1613 void generateIf(HIf node, HIfBlockInformation info) { |
| 1595 use(node.inputs[0]); | 1614 use(node.inputs[0]); |
| 1596 js.Expression test = pop(); | 1615 js.Expression test = pop(); |
| 1597 | 1616 |
| 1598 HStatementInformation thenGraph = info.thenGraph; | 1617 HStatementInformation thenGraph = info.thenGraph; |
| 1599 HStatementInformation elseGraph = info.elseGraph; | 1618 HStatementInformation elseGraph = info.elseGraph; |
| 1600 js.Statement thenPart = | 1619 js.Statement thenPart = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 } | 1657 } |
| 1639 } else { | 1658 } else { |
| 1640 generateIf(node, info); | 1659 generateIf(node, info); |
| 1641 } | 1660 } |
| 1642 | 1661 |
| 1643 HBasicBlock joinBlock = node.joinBlock; | 1662 HBasicBlock joinBlock = node.joinBlock; |
| 1644 if (joinBlock != null && !identical(joinBlock.dominator, node.block)) { | 1663 if (joinBlock != null && !identical(joinBlock.dominator, node.block)) { |
| 1645 // The join block is dominated by a block in one of the branches. | 1664 // The join block is dominated by a block in one of the branches. |
| 1646 // The subgraph traversal never reached it, so we visit it here | 1665 // The subgraph traversal never reached it, so we visit it here |
| 1647 // instead. | 1666 // instead. |
| 1648 visitBasicBlock(joinBlock); | 1667 continueSubGraph(joinBlock); |
| 1649 } | 1668 } |
| 1650 | 1669 |
| 1651 // Visit all the dominated blocks that are not part of the then or else | 1670 // Visit all the dominated blocks that are not part of the then or else |
| 1652 // branches, and is not the join block. | 1671 // branches, and is not the join block. |
| 1653 // Depending on how the then/else branches terminate | 1672 // Depending on how the then/else branches terminate |
| 1654 // (e.g., return/throw/break) there can be any number of these. | 1673 // (e.g., return/throw/break) there can be any number of these. |
| 1655 List<HBasicBlock> dominated = node.block.dominatedBlocks; | 1674 List<HBasicBlock> dominated = node.block.dominatedBlocks; |
| 1656 for (int i = 2; i < dominated.length; i++) { | 1675 for (int i = 2; i < dominated.length; i++) { |
| 1657 visitBasicBlock(dominated[i]); | 1676 continueSubGraph(dominated[i]); |
| 1658 } | 1677 } |
| 1659 } | 1678 } |
| 1660 | 1679 |
| 1661 void visitInterceptor(HInterceptor node) { | 1680 void visitInterceptor(HInterceptor node) { |
| 1662 if (node.isConditionalConstantInterceptor) { | 1681 if (node.isConditionalConstantInterceptor) { |
| 1663 assert(node.inputs.length == 2); | 1682 assert(node.inputs.length == 2); |
| 1664 use(node.receiver); | 1683 use(node.receiver); |
| 1665 js.Expression receiverExpression = pop(); | 1684 js.Expression receiverExpression = pop(); |
| 1666 use(node.conditionalConstantInterceptor); | 1685 use(node.conditionalConstantInterceptor); |
| 1667 js.Expression constant = pop(); | 1686 js.Expression constant = pop(); |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3012 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { | 3031 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { |
| 3013 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls); | 3032 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls); |
| 3014 }); | 3033 }); |
| 3015 } | 3034 } |
| 3016 | 3035 |
| 3017 @override | 3036 @override |
| 3018 void visitRef(HRef node) { | 3037 void visitRef(HRef node) { |
| 3019 visit(node.value); | 3038 visit(node.value); |
| 3020 } | 3039 } |
| 3021 } | 3040 } |
| OLD | NEW |