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 |