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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2607783002: Implement do-while in Kernel SSA. (Closed)
Patch Set: . Created 3 years, 11 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
« no previous file with comments | « no previous file | tests/compiler/dart2js/kernel/loops_test.dart » ('j') | 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) 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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/kernel/loops_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698