| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 | 10 |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 jsNode.endSourcePosition = endSourcePosition; | 330 jsNode.endSourcePosition = endSourcePosition; |
| 331 return jsNode; | 331 return jsNode; |
| 332 } | 332 } |
| 333 | 333 |
| 334 visitTypeGuard(HTypeGuard node); | 334 visitTypeGuard(HTypeGuard node); |
| 335 visitBailoutTarget(HBailoutTarget node); | 335 visitBailoutTarget(HBailoutTarget node); |
| 336 | 336 |
| 337 beginGraph(HGraph graph); | 337 beginGraph(HGraph graph); |
| 338 endGraph(HGraph graph); | 338 endGraph(HGraph graph); |
| 339 | 339 |
| 340 beginLoop(HBasicBlock block); | |
| 341 endLoop(HBasicBlock block); | |
| 342 handleLoopCondition(HLoopBranch node); | |
| 343 | |
| 344 preLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 340 preLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 345 startLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 341 startLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 346 endLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 342 endLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 347 | 343 |
| 348 void preGenerateMethod(HGraph graph) { | 344 void preGenerateMethod(HGraph graph) { |
| 349 new SsaInstructionMerger(types, generateAtUseSite).visitGraph(graph); | 345 new SsaInstructionMerger(types, generateAtUseSite).visitGraph(graph); |
| 350 new SsaConditionMerger( | 346 new SsaConditionMerger( |
| 351 types, generateAtUseSite, controlFlowOperators).visitGraph(graph); | 347 types, generateAtUseSite, controlFlowOperators).visitGraph(graph); |
| 352 SsaLiveIntervalBuilder intervalBuilder = | 348 SsaLiveIntervalBuilder intervalBuilder = |
| 353 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); | 349 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); |
| (...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 // } else { | 948 // } else { |
| 953 // break; | 949 // break; |
| 954 // } | 950 // } |
| 955 // } while (true); | 951 // } while (true); |
| 956 HBasicBlock avoidEdge = info.end.successors[0]; | 952 HBasicBlock avoidEdge = info.end.successors[0]; |
| 957 js.Block updateBody = new js.Block.empty(); | 953 js.Block updateBody = new js.Block.empty(); |
| 958 currentContainer = updateBody; | 954 currentContainer = updateBody; |
| 959 assignPhisOfSuccessors(avoidEdge); | 955 assignPhisOfSuccessors(avoidEdge); |
| 960 bool hasPhiUpdates = !updateBody.statements.isEmpty; | 956 bool hasPhiUpdates = !updateBody.statements.isEmpty; |
| 961 currentContainer = body; | 957 currentContainer = body; |
| 962 if (hasPhiUpdates || !isConditionExpression || info.updates != null) { | 958 visitBodyIgnoreLabels(info); |
| 963 wrapLoopBodyForContinue(info); | |
| 964 } else { | |
| 965 visitBodyIgnoreLabels(info); | |
| 966 } | |
| 967 if (info.updates != null) { | 959 if (info.updates != null) { |
| 968 generateStatements(info.updates); | 960 generateStatements(info.updates); |
| 969 } | 961 } |
| 970 if (isConditionExpression) { | 962 if (isConditionExpression) { |
| 971 push(generateExpression(condition)); | 963 push(generateExpression(condition)); |
| 972 } else { | 964 } else { |
| 973 generateStatements(condition); | 965 generateStatements(condition); |
| 974 use(condition.conditionExpression); | 966 use(condition.conditionExpression); |
| 975 } | 967 } |
| 976 js.Expression jsCondition = pop(); | 968 js.Expression jsCondition = pop(); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 return success; | 1110 return success; |
| 1119 } | 1111 } |
| 1120 | 1112 |
| 1121 void visitBasicBlock(HBasicBlock node) { | 1113 void visitBasicBlock(HBasicBlock node) { |
| 1122 // Abort traversal if we are leaving the currently active sub-graph. | 1114 // Abort traversal if we are leaving the currently active sub-graph. |
| 1123 if (!subGraph.contains(node)) return; | 1115 if (!subGraph.contains(node)) return; |
| 1124 | 1116 |
| 1125 currentBlock = node; | 1117 currentBlock = node; |
| 1126 // If this node has block-structure based information attached, | 1118 // If this node has block-structure based information attached, |
| 1127 // try using that to traverse from here. | 1119 // try using that to traverse from here. |
| 1128 if (node.blockFlow != null && | 1120 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) { |
| 1129 handleBlockFlow(node.blockFlow)) { | |
| 1130 return; | 1121 return; |
| 1131 } | 1122 } |
| 1132 // Flow based traversal. | |
| 1133 if (node.isLoopHeader() && | |
| 1134 !identical(node.loopInformation.loopBlockInformation, currentBlockInform
ation)) { | |
| 1135 beginLoop(node); | |
| 1136 } | |
| 1137 iterateBasicBlock(node); | 1123 iterateBasicBlock(node); |
| 1138 } | 1124 } |
| 1139 | 1125 |
| 1140 void emitAssignment(String destination, String source) { | 1126 void emitAssignment(String destination, String source) { |
| 1141 assignVariable(destination, new js.VariableUse(source)); | 1127 assignVariable(destination, new js.VariableUse(source)); |
| 1142 } | 1128 } |
| 1143 | 1129 |
| 1144 /** | 1130 /** |
| 1145 * Sequentialize a list of conceptually parallel copies. Parallel | 1131 * Sequentialize a list of conceptually parallel copies. Parallel |
| 1146 * copies may contain cycles, that this method breaks. | 1132 * copies may contain cycles, that this method breaks. |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 instruction: node); | 1342 instruction: node); |
| 1357 } | 1343 } |
| 1358 if (dominated.length == 2 && !identical(currentBlock, currentGraph.entry)) { | 1344 if (dominated.length == 2 && !identical(currentBlock, currentGraph.entry)) { |
| 1359 compiler.internalError('currentBlock !== currentGraph.entry', | 1345 compiler.internalError('currentBlock !== currentGraph.entry', |
| 1360 instruction: node); | 1346 instruction: node); |
| 1361 } | 1347 } |
| 1362 assert(dominated[0] == currentBlock.successors[0]); | 1348 assert(dominated[0] == currentBlock.successors[0]); |
| 1363 visitBasicBlock(dominated[0]); | 1349 visitBasicBlock(dominated[0]); |
| 1364 } | 1350 } |
| 1365 | 1351 |
| 1352 visitLoopBranch(HLoopBranch node) { |
| 1353 assert(node.block == subGraph.end); |
| 1354 // We are generating code for a loop condition. |
| 1355 // If we are generating the subgraph as an expression, the |
| 1356 // condition will be generated as the expression. |
| 1357 // Otherwise, we don't generate the expression, and leave that |
| 1358 // to the code that called [visitSubGraph]. |
| 1359 if (isGeneratingExpression) { |
| 1360 use(node.inputs[0]); |
| 1361 } |
| 1362 } |
| 1363 |
| 1366 /** | 1364 /** |
| 1367 * Checks if [map] contains an [ElementAction] for [element], and | 1365 * Checks if [map] contains an [ElementAction] for [element], and |
| 1368 * if so calls that action and returns true. | 1366 * if so calls that action and returns true. |
| 1369 * Otherwise returns false. | 1367 * Otherwise returns false. |
| 1370 */ | 1368 */ |
| 1371 bool tryCallAction(Map<Element, ElementAction> map, Element element) { | 1369 bool tryCallAction(Map<Element, ElementAction> map, Element element) { |
| 1372 ElementAction action = map[element]; | 1370 ElementAction action = map[element]; |
| 1373 if (action == null) return false; | 1371 if (action == null) return false; |
| 1374 action(element); | 1372 action(element); |
| 1375 return true; | 1373 return true; |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 assert(isGenerateAtUseSite(node)); | 1824 assert(isGenerateAtUseSite(node)); |
| 1827 generateConstant(node.constant); | 1825 generateConstant(node.constant); |
| 1828 DartType type = node.constant.computeType(compiler); | 1826 DartType type = node.constant.computeType(compiler); |
| 1829 if (node.constant is ConstructedConstant) { | 1827 if (node.constant is ConstructedConstant) { |
| 1830 ConstantHandler handler = compiler.constantHandler; | 1828 ConstantHandler handler = compiler.constantHandler; |
| 1831 handler.registerCompileTimeConstant(node.constant); | 1829 handler.registerCompileTimeConstant(node.constant); |
| 1832 } | 1830 } |
| 1833 world.registerInstantiatedClass(type.element); | 1831 world.registerInstantiatedClass(type.element); |
| 1834 } | 1832 } |
| 1835 | 1833 |
| 1836 visitLoopBranch(HLoopBranch node) { | |
| 1837 if (subGraph != null && identical(node.block, subGraph.end)) { | |
| 1838 // We are generating code for a loop condition. | |
| 1839 // If doing this as part of a SubGraph traversal, the | |
| 1840 // calling code will handle the control flow logic. | |
| 1841 | |
| 1842 // If we are generating the subgraph as an expression, the | |
| 1843 // condition will be generated as the expression. | |
| 1844 // Otherwise, we don't generate the expression, and leave that | |
| 1845 // to the code that called [visitSubGraph]. | |
| 1846 if (isGeneratingExpression) { | |
| 1847 use(node.inputs[0]); | |
| 1848 } | |
| 1849 return; | |
| 1850 } | |
| 1851 HBasicBlock branchBlock = currentBlock; | |
| 1852 handleLoopCondition(node); | |
| 1853 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | |
| 1854 if (!node.isDoWhile()) { | |
| 1855 // For a do while loop, the body has already been visited. | |
| 1856 visitBasicBlock(dominated[0]); | |
| 1857 } | |
| 1858 endLoop(node.block); | |
| 1859 | |
| 1860 // If the branch does not dominate the code after the loop, the | |
| 1861 // dominator will visit it. | |
| 1862 if (!identical(branchBlock.successors[1].dominator, branchBlock)) return; | |
| 1863 | |
| 1864 visitBasicBlock(branchBlock.successors[1]); | |
| 1865 // With labeled breaks we can have more dominated blocks. | |
| 1866 if (dominated.length >= 3) { | |
| 1867 for (int i = 2; i < dominated.length; i++) { | |
| 1868 visitBasicBlock(dominated[i]); | |
| 1869 } | |
| 1870 } | |
| 1871 } | |
| 1872 | |
| 1873 visitNot(HNot node) { | 1834 visitNot(HNot node) { |
| 1874 assert(node.inputs.length == 1); | 1835 assert(node.inputs.length == 1); |
| 1875 generateNot(node.inputs[0]); | 1836 generateNot(node.inputs[0]); |
| 1876 attachLocationToLast(node); | 1837 attachLocationToLast(node); |
| 1877 } | 1838 } |
| 1878 | 1839 |
| 1879 void generateNot(HInstruction input) { | 1840 void generateNot(HInstruction input) { |
| 1880 bool canGenerateOptimizedComparison(HInstruction instruction) { | 1841 bool canGenerateOptimizedComparison(HInstruction instruction) { |
| 1881 if (instruction is !HRelational) return false; | 1842 if (instruction is !HRelational) return false; |
| 1882 HRelational relational = instruction; | 1843 HRelational relational = instruction; |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2648 pushStatement(new js.If.noElse(test, then), node); | 2609 pushStatement(new js.If.noElse(test, then), node); |
| 2649 } else { | 2610 } else { |
| 2650 compiler.internalError('Unexpected type guard', instruction: input); | 2611 compiler.internalError('Unexpected type guard', instruction: input); |
| 2651 } | 2612 } |
| 2652 } | 2613 } |
| 2653 | 2614 |
| 2654 void visitBailoutTarget(HBailoutTarget target) { | 2615 void visitBailoutTarget(HBailoutTarget target) { |
| 2655 // Do nothing. Bailout targets are only used in the non-optimized version. | 2616 // Do nothing. Bailout targets are only used in the non-optimized version. |
| 2656 } | 2617 } |
| 2657 | 2618 |
| 2658 void beginLoop(HBasicBlock block) { | |
| 2659 oldContainerStack.add(currentContainer); | |
| 2660 currentContainer = new js.Block.empty(); | |
| 2661 } | |
| 2662 | |
| 2663 void endLoop(HBasicBlock block) { | |
| 2664 js.Statement body = currentContainer; | |
| 2665 currentContainer = oldContainerStack.removeLast(); | |
| 2666 body = unwrapStatement(body); | |
| 2667 js.While loop = new js.While(newLiteralBool(true), body); | |
| 2668 | |
| 2669 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader; | |
| 2670 HLoopInformation info = header.loopInformation; | |
| 2671 attachLocationRange(loop, | |
| 2672 info.loopBlockInformation.sourcePosition, | |
| 2673 info.loopBlockInformation.endSourcePosition); | |
| 2674 pushStatement(wrapIntoLabels(loop, info.labels)); | |
| 2675 } | |
| 2676 | |
| 2677 void handleLoopCondition(HLoopBranch node) { | |
| 2678 use(node.inputs[0]); | |
| 2679 js.Expression test = new js.Prefix('!', pop()); | |
| 2680 js.Statement then = new js.Break(null); | |
| 2681 pushStatement(new js.If.noElse(test, then), node); | |
| 2682 } | |
| 2683 | |
| 2684 | |
| 2685 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2619 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2686 } | 2620 } |
| 2687 | 2621 |
| 2688 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2622 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2689 } | 2623 } |
| 2690 | 2624 |
| 2691 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2625 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2692 } | 2626 } |
| 2693 } | 2627 } |
| 2694 | 2628 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2788 } | 2722 } |
| 2789 } | 2723 } |
| 2790 | 2724 |
| 2791 visitParameterValue(HParameterValue node) { | 2725 visitParameterValue(HParameterValue node) { |
| 2792 // Nothing to do, parameters are dealt with specially in a bailout | 2726 // Nothing to do, parameters are dealt with specially in a bailout |
| 2793 // method. | 2727 // method. |
| 2794 } | 2728 } |
| 2795 | 2729 |
| 2796 bool visitAndOrInfo(HAndOrBlockInformation info) => false; | 2730 bool visitAndOrInfo(HAndOrBlockInformation info) => false; |
| 2797 | 2731 |
| 2732 visitLoopBranch(HLoopBranch node) { |
| 2733 HBasicBlock header = node.isDoWhile() |
| 2734 ? node.block.successors[0] |
| 2735 : node.block; |
| 2736 if (header.hasBailoutTargets()) { |
| 2737 // The graph visitor in [visitLoopInfo] does not handle the |
| 2738 // condition. We must instead manually emit it here. |
| 2739 handleLoopCondition(node); |
| 2740 // We must also visit the body from here. |
| 2741 // For a do while loop, the body has already been visited. |
| 2742 if (!node.isDoWhile()) { |
| 2743 visitBasicBlock(node.block.dominatedBlocks[0]); |
| 2744 } |
| 2745 } else { |
| 2746 super.visitLoopBranch(node); |
| 2747 } |
| 2748 } |
| 2749 |
| 2750 |
| 2798 bool visitIfInfo(HIfBlockInformation info) { | 2751 bool visitIfInfo(HIfBlockInformation info) { |
| 2799 if (info.thenGraph.start.hasBailoutTargets()) return false; | 2752 if (info.thenGraph.start.hasBailoutTargets()) return false; |
| 2800 if (info.elseGraph.start.hasBailoutTargets()) return false; | 2753 if (info.elseGraph.start.hasBailoutTargets()) return false; |
| 2801 return super.visitIfInfo(info); | 2754 return super.visitIfInfo(info); |
| 2802 } | 2755 } |
| 2803 | 2756 |
| 2804 bool visitLoopInfo(HLoopBlockInformation info) { | 2757 bool visitLoopInfo(HLoopBlockInformation info) { |
| 2805 if (info.start.hasBailoutTargets()) return false; | 2758 // Always emit with block flow traversal. |
| 2806 if (info.loopHeader.hasBailoutTargets()) return false; | 2759 if (info.loopHeader.hasBailoutTargets()) { |
| 2760 // If there are any bailout targets in the loop, we cannot use |
| 2761 // the pretty [SsaCodeGenerator.visitLoopInfo] printer. |
| 2762 if (info.initializer != null) { |
| 2763 generateStatements(info.initializer); |
| 2764 } |
| 2765 beginLoop(info.loopHeader); |
| 2766 generateStatements(info.condition); |
| 2767 generateStatements(info.body); |
| 2768 if (info.updates != null) { |
| 2769 generateStatements(info.updates); |
| 2770 } |
| 2771 endLoop(info.end); |
| 2772 return true; |
| 2773 } |
| 2807 return super.visitLoopInfo(info); | 2774 return super.visitLoopInfo(info); |
| 2808 } | 2775 } |
| 2809 | 2776 |
| 2810 bool visitTryInfo(HTryBlockInformation info) => false; | 2777 bool visitTryInfo(HTryBlockInformation info) => false; |
| 2811 bool visitSequenceInfo(HStatementSequenceInformation info) => false; | 2778 bool visitSequenceInfo(HStatementSequenceInformation info) => false; |
| 2812 | 2779 |
| 2813 void visitTypeGuard(HTypeGuard node) { | 2780 void visitTypeGuard(HTypeGuard node) { |
| 2814 // Do nothing. Type guards are only used in the optimized version. | 2781 // Do nothing. Type guards are only used in the optimized version. |
| 2815 } | 2782 } |
| 2816 | 2783 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 if (leftType.canBeNull() && rightType.canBeNull()) { | 2995 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 3029 if (left.isConstantNull() || right.isConstantNull() || | 2996 if (left.isConstantNull() || right.isConstantNull() || |
| 3030 (leftType.isPrimitive() && leftType == rightType)) { | 2997 (leftType.isPrimitive() && leftType == rightType)) { |
| 3031 return '=='; | 2998 return '=='; |
| 3032 } | 2999 } |
| 3033 return null; | 3000 return null; |
| 3034 } else { | 3001 } else { |
| 3035 return '==='; | 3002 return '==='; |
| 3036 } | 3003 } |
| 3037 } | 3004 } |
| OLD | NEW |