OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../closure.dart'; | 7 import '../closure.dart'; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 var enclosing = constructor.enclosingClass; | 227 var enclosing = constructor.enclosingClass; |
228 if (backend.classNeedsRti(astAdapter.getElement(enclosing))) { | 228 if (backend.classNeedsRti(astAdapter.getElement(enclosing))) { |
229 ClassElement clsElement = | 229 ClassElement clsElement = |
230 astAdapter.getElement(constructor).enclosingElement; | 230 astAdapter.getElement(constructor).enclosingElement; |
231 enclosing.typeParameters.forEach((ir.TypeParameter typeParameter) { | 231 enclosing.typeParameters.forEach((ir.TypeParameter typeParameter) { |
232 var typeParamElement = astAdapter.getElement(typeParameter); | 232 var typeParamElement = astAdapter.getElement(typeParameter); |
233 HParameterValue param = | 233 HParameterValue param = |
234 addParameter(typeParamElement, commonMasks.nonNullType); | 234 addParameter(typeParamElement, commonMasks.nonNullType); |
235 // This is a little bit wacky (and n^2) until we make the localsHandler | 235 // This is a little bit wacky (and n^2) until we make the localsHandler |
236 // take Kernel DartTypes instead of just the AST DartTypes. | 236 // take Kernel DartTypes instead of just the AST DartTypes. |
237 var typeVariableType = clsElement | 237 var typeVariableType = clsElement.typeVariables |
238 .typeVariables | |
239 .firstWhere((TypeVariableType i) => i.name == typeParameter.name); | 238 .firstWhere((TypeVariableType i) => i.name == typeParameter.name); |
240 localsHandler.directLocals[ | 239 localsHandler.directLocals[ |
241 localsHandler.getTypeVariableAsLocal(typeVariableType)] = param; | 240 localsHandler.getTypeVariableAsLocal(typeVariableType)] = param; |
242 }); | 241 }); |
243 } | 242 } |
244 } | 243 } |
245 | 244 |
246 /// Builds generative constructors. | 245 /// Builds generative constructors. |
247 /// | 246 /// |
248 /// Generative constructors are built in two stages. | 247 /// Generative constructors are built in two stages. |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 whileStatement.condition.accept(this); | 775 whileStatement.condition.accept(this); |
777 return popBoolified(); | 776 return popBoolified(); |
778 } | 777 } |
779 | 778 |
780 loopHandler.handleLoop(whileStatement, () {}, buildCondition, () {}, () { | 779 loopHandler.handleLoop(whileStatement, () {}, buildCondition, () {}, () { |
781 whileStatement.body.accept(this); | 780 whileStatement.body.accept(this); |
782 }); | 781 }); |
783 } | 782 } |
784 | 783 |
785 @override | 784 @override |
| 785 visitDoStatement(ir.DoStatement doStatement) { |
| 786 // TODO(efortuna): I think this can be rewritten using |
| 787 // LoopHandler.handleLoop with some tricks about when the "update" happens. |
| 788 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 789 localsHandler.startLoop(astAdapter.getNode(doStatement)); |
| 790 JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement); |
| 791 HLoopInformation loopInfo = current.loopInformation; |
| 792 HBasicBlock loopEntryBlock = current; |
| 793 HBasicBlock bodyEntryBlock = current; |
| 794 JumpTarget target = |
| 795 elements.getTargetDefinition(astAdapter.getNode(doStatement)); |
| 796 bool hasContinues = target != null && target.isContinueTarget; |
| 797 if (hasContinues) { |
| 798 // Add extra block to hang labels on. |
| 799 // It doesn't currently work if they are on the same block as the |
| 800 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| 801 // SubGraph that starts at the same block again, so the HLoopInfo is |
| 802 // either handled twice, or it's handled after the labeled block info, |
| 803 // both of which generate the wrong code. |
| 804 // Using a separate block is just a simple workaround. |
| 805 bodyEntryBlock = openNewBlock(); |
| 806 } |
| 807 localsHandler.enterLoopBody(astAdapter.getNode(doStatement)); |
| 808 doStatement.body.accept(this); |
| 809 |
| 810 // If there are no continues we could avoid the creation of the condition |
| 811 // block. This could also lead to a block having multiple entries and exits. |
| 812 HBasicBlock bodyExitBlock; |
| 813 bool isAbortingBody = false; |
| 814 if (current != null) { |
| 815 bodyExitBlock = close(new HGoto()); |
| 816 } else { |
| 817 isAbortingBody = true; |
| 818 bodyExitBlock = lastOpenedBlock; |
| 819 } |
| 820 |
| 821 SubExpression conditionExpression; |
| 822 bool loopIsDegenerate = isAbortingBody && !hasContinues; |
| 823 if (!loopIsDegenerate) { |
| 824 HBasicBlock conditionBlock = addNewBlock(); |
| 825 |
| 826 List<LocalsHandler> continueHandlers = <LocalsHandler>[]; |
| 827 jumpHandler |
| 828 .forEachContinue((HContinue instruction, LocalsHandler locals) { |
| 829 instruction.block.addSuccessor(conditionBlock); |
| 830 continueHandlers.add(locals); |
| 831 }); |
| 832 |
| 833 if (!isAbortingBody) { |
| 834 bodyExitBlock.addSuccessor(conditionBlock); |
| 835 } |
| 836 |
| 837 if (!continueHandlers.isEmpty) { |
| 838 if (!isAbortingBody) continueHandlers.add(localsHandler); |
| 839 localsHandler = |
| 840 savedLocals.mergeMultiple(continueHandlers, conditionBlock); |
| 841 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 842 List<LabelDefinition> labels = jumpHandler.labels; |
| 843 HSubGraphBlockInformation bodyInfo = |
| 844 new HSubGraphBlockInformation(bodyGraph); |
| 845 HLabeledBlockInformation info; |
| 846 if (!labels.isEmpty) { |
| 847 info = |
| 848 new HLabeledBlockInformation(bodyInfo, labels, isContinue: true); |
| 849 } else { |
| 850 info = new HLabeledBlockInformation.implicit(bodyInfo, target, |
| 851 isContinue: true); |
| 852 } |
| 853 bodyEntryBlock.setBlockFlow(info, conditionBlock); |
| 854 } |
| 855 open(conditionBlock); |
| 856 |
| 857 doStatement.condition.accept(this); |
| 858 assert(!isAborted()); |
| 859 HInstruction conditionInstruction = popBoolified(); |
| 860 HBasicBlock conditionEndBlock = close( |
| 861 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); |
| 862 |
| 863 HBasicBlock avoidCriticalEdge = addNewBlock(); |
| 864 conditionEndBlock.addSuccessor(avoidCriticalEdge); |
| 865 open(avoidCriticalEdge); |
| 866 close(new HGoto()); |
| 867 avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge. |
| 868 |
| 869 conditionExpression = |
| 870 new SubExpression(conditionBlock, conditionEndBlock); |
| 871 |
| 872 // Avoid a critical edge from the condition to the loop-exit body. |
| 873 HBasicBlock conditionExitBlock = addNewBlock(); |
| 874 open(conditionExitBlock); |
| 875 close(new HGoto()); |
| 876 conditionEndBlock.addSuccessor(conditionExitBlock); |
| 877 |
| 878 loopHandler.endLoop( |
| 879 loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler); |
| 880 |
| 881 loopEntryBlock.postProcessLoopHeader(); |
| 882 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); |
| 883 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( |
| 884 HLoopBlockInformation.DO_WHILE_LOOP, |
| 885 null, |
| 886 wrapExpressionGraph(conditionExpression), |
| 887 wrapStatementGraph(bodyGraph), |
| 888 null, |
| 889 loopEntryBlock.loopInformation.target, |
| 890 loopEntryBlock.loopInformation.labels, |
| 891 sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement))); |
| 892 loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
| 893 loopInfo.loopBlockInformation = loopBlockInfo; |
| 894 } else { |
| 895 // Since the loop has no back edge, we remove the loop information on the |
| 896 // header. |
| 897 loopEntryBlock.loopInformation = null; |
| 898 |
| 899 if (jumpHandler.hasAnyBreak()) { |
| 900 // Null branchBlock because the body of the do-while loop always aborts, |
| 901 // so we never get to the condition. |
| 902 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler); |
| 903 |
| 904 // Since the body of the loop has a break, we attach a synthesized label |
| 905 // to the body. |
| 906 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 907 JumpTarget target = |
| 908 elements.getTargetDefinition(astAdapter.getNode(doStatement)); |
| 909 LabelDefinition label = target.addLabel(null, 'loop'); |
| 910 label.setBreakTarget(); |
| 911 HLabeledBlockInformation info = new HLabeledBlockInformation( |
| 912 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); |
| 913 loopEntryBlock.setBlockFlow(info, current); |
| 914 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
| 915 HBasicBlock block = breakInstruction.block; |
| 916 block.addAtExit(new HBreak.toLabel(label)); |
| 917 block.remove(breakInstruction); |
| 918 }); |
| 919 } |
| 920 } |
| 921 jumpHandler.close(); |
| 922 } |
| 923 |
| 924 @override |
786 void visitIfStatement(ir.IfStatement ifStatement) { | 925 void visitIfStatement(ir.IfStatement ifStatement) { |
787 handleIf( | 926 handleIf( |
788 visitCondition: () => ifStatement.condition.accept(this), | 927 visitCondition: () => ifStatement.condition.accept(this), |
789 visitThen: () => ifStatement.then.accept(this), | 928 visitThen: () => ifStatement.then.accept(this), |
790 visitElse: () => ifStatement.otherwise?.accept(this)); | 929 visitElse: () => ifStatement.otherwise?.accept(this)); |
791 } | 930 } |
792 | 931 |
793 @override | 932 @override |
794 void visitAsExpression(ir.AsExpression asExpression) { | 933 void visitAsExpression(ir.AsExpression asExpression) { |
795 asExpression.operand.accept(this); | 934 asExpression.operand.accept(this); |
(...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2338 kernelBuilder.open(exitBlock); | 2477 kernelBuilder.open(exitBlock); |
2339 enterBlock.setBlockFlow( | 2478 enterBlock.setBlockFlow( |
2340 new HTryBlockInformation( | 2479 new HTryBlockInformation( |
2341 kernelBuilder.wrapStatementGraph(bodyGraph), | 2480 kernelBuilder.wrapStatementGraph(bodyGraph), |
2342 exception, | 2481 exception, |
2343 kernelBuilder.wrapStatementGraph(catchGraph), | 2482 kernelBuilder.wrapStatementGraph(catchGraph), |
2344 kernelBuilder.wrapStatementGraph(finallyGraph)), | 2483 kernelBuilder.wrapStatementGraph(finallyGraph)), |
2345 exitBlock); | 2484 exitBlock); |
2346 } | 2485 } |
2347 } | 2486 } |
OLD | NEW |