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; | 9 import '../common/codegen.dart' show CodegenRegistry; |
10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 constructor.function.namedParameters.toList() | 602 constructor.function.namedParameters.toList() |
603 ..sort(namedOrdering) | 603 ..sort(namedOrdering) |
604 ..forEach(handleParameter); | 604 ..forEach(handleParameter); |
605 | 605 |
606 // Set the locals handler state as if we were inlining the constructor. | 606 // Set the locals handler state as if we were inlining the constructor. |
607 ConstructorEntity astElement = _elementMap.getConstructor(constructor); | 607 ConstructorEntity astElement = _elementMap.getConstructor(constructor); |
608 ClosureRepresentationInfo oldClosureData = localsHandler.closureData; | 608 ClosureRepresentationInfo oldClosureData = localsHandler.closureData; |
609 ClosureRepresentationInfo newClosureData = | 609 ClosureRepresentationInfo newClosureData = |
610 closureDataLookup.getClosureRepresentationInfo(astElement); | 610 closureDataLookup.getClosureRepresentationInfo(astElement); |
611 if (astElement is ConstructorElement) { | 611 if (astElement is ConstructorElement) { |
612 // TODO(johnniwinther): Support constructor (body) entities. | 612 // TODO(redemption): Support constructor (body) entities. |
613 ResolvedAst resolvedAst = astElement.resolvedAst; | 613 ResolvedAst resolvedAst = astElement.resolvedAst; |
614 localsHandler.closureData = newClosureData; | 614 localsHandler.closureData = newClosureData; |
615 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 615 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
616 localsHandler.enterScope( | 616 localsHandler.enterScope( |
617 closureDataLookup.getClosureAnalysisInfo(resolvedAst.node), | 617 closureDataLookup.getClosureAnalysisInfo(resolvedAst.node), |
618 forGenerativeConstructorBody: | 618 forGenerativeConstructorBody: |
619 astElement.isGenerativeConstructorBody); | 619 astElement.isGenerativeConstructorBody); |
620 } | 620 } |
621 } | 621 } |
622 inlinedFrom(astElement, () { | 622 inlinedFrom(astElement, () { |
(...skipping 29 matching lines...) Expand all Loading... |
652 if (!backend.operatorEqHandlesNullArgument(method)) { | 652 if (!backend.operatorEqHandlesNullArgument(method)) { |
653 handleIf( | 653 handleIf( |
654 visitCondition: () { | 654 visitCondition: () { |
655 HParameterValue parameter = parameters.values.first; | 655 HParameterValue parameter = parameters.values.first; |
656 push(new HIdentity(parameter, graph.addConstantNull(closedWorld), | 656 push(new HIdentity(parameter, graph.addConstantNull(closedWorld), |
657 null, commonMasks.boolType)); | 657 null, commonMasks.boolType)); |
658 }, | 658 }, |
659 visitThen: () { | 659 visitThen: () { |
660 closeAndGotoExit(new HReturn( | 660 closeAndGotoExit(new HReturn( |
661 graph.addConstantBool(false, closedWorld), | 661 graph.addConstantBool(false, closedWorld), |
662 // TODO(johnniwinther): Provider source information like | 662 // TODO(redemption): Provider source information like |
663 // `sourceInformationBuilder.buildImplicitReturn(method)`. | 663 // `sourceInformationBuilder.buildImplicitReturn(method)`. |
664 null)); | 664 null)); |
665 }, | 665 }, |
666 visitElse: null, | 666 visitElse: null, |
667 // TODO(27394): Add sourceInformation via | 667 // TODO(27394): Add sourceInformation via |
668 // `sourceInformationBuilder.buildIf(?)`. | 668 // `sourceInformationBuilder.buildIf(?)`. |
669 ); | 669 ); |
670 } | 670 } |
671 } | 671 } |
672 functionNode.body.accept(this); | 672 functionNode.body.accept(this); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 } | 904 } |
905 | 905 |
906 void buildBody() { | 906 void buildBody() { |
907 forStatement.body.accept(this); | 907 forStatement.body.accept(this); |
908 } | 908 } |
909 | 909 |
910 loopHandler.handleLoop( | 910 loopHandler.handleLoop( |
911 forStatement, | 911 forStatement, |
912 localsMap.getClosureRepresentationInfoForLoop( | 912 localsMap.getClosureRepresentationInfoForLoop( |
913 closureDataLookup, forStatement), | 913 closureDataLookup, forStatement), |
| 914 localsMap.getJumpTargetForFor(forStatement), |
914 buildInitializer, | 915 buildInitializer, |
915 buildCondition, | 916 buildCondition, |
916 buildUpdate, | 917 buildUpdate, |
917 buildBody); | 918 buildBody); |
918 } | 919 } |
919 | 920 |
920 @override | 921 @override |
921 void visitForInStatement(ir.ForInStatement forInStatement) { | 922 void visitForInStatement(ir.ForInStatement forInStatement) { |
922 if (forInStatement.isAsync) { | 923 if (forInStatement.isAsync) { |
923 _buildAsyncForIn(forInStatement); | 924 _buildAsyncForIn(forInStatement); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 HInstruction addInstruction = | 1034 HInstruction addInstruction = |
1034 new HAdd(index, one, null, commonMasks.positiveIntType); | 1035 new HAdd(index, one, null, commonMasks.positiveIntType); |
1035 add(addInstruction); | 1036 add(addInstruction); |
1036 localsHandler.updateLocal(indexVariable, addInstruction); | 1037 localsHandler.updateLocal(indexVariable, addInstruction); |
1037 } | 1038 } |
1038 | 1039 |
1039 loopHandler.handleLoop( | 1040 loopHandler.handleLoop( |
1040 forInStatement, | 1041 forInStatement, |
1041 localsMap.getClosureRepresentationInfoForLoop( | 1042 localsMap.getClosureRepresentationInfoForLoop( |
1042 closureDataLookup, forInStatement), | 1043 closureDataLookup, forInStatement), |
| 1044 localsMap.getJumpTargetForForIn(forInStatement), |
1043 buildInitializer, | 1045 buildInitializer, |
1044 buildCondition, | 1046 buildCondition, |
1045 buildUpdate, | 1047 buildUpdate, |
1046 buildBody); | 1048 buildBody); |
1047 } | 1049 } |
1048 | 1050 |
1049 _buildForInIterator(ir.ForInStatement forInStatement) { | 1051 _buildForInIterator(ir.ForInStatement forInStatement) { |
1050 // Generate a structure equivalent to: | 1052 // Generate a structure equivalent to: |
1051 // Iterator<E> $iter = <iterable>.iterator; | 1053 // Iterator<E> $iter = <iterable>.iterator; |
1052 // while ($iter.moveNext()) { | 1054 // while ($iter.moveNext()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1084 if (loopVariableLocal is! SyntheticLocal) { | 1086 if (loopVariableLocal is! SyntheticLocal) { |
1085 value.sourceElement ??= loopVariableLocal; | 1087 value.sourceElement ??= loopVariableLocal; |
1086 } | 1088 } |
1087 forInStatement.body.accept(this); | 1089 forInStatement.body.accept(this); |
1088 } | 1090 } |
1089 | 1091 |
1090 loopHandler.handleLoop( | 1092 loopHandler.handleLoop( |
1091 forInStatement, | 1093 forInStatement, |
1092 localsMap.getClosureRepresentationInfoForLoop( | 1094 localsMap.getClosureRepresentationInfoForLoop( |
1093 closureDataLookup, forInStatement), | 1095 closureDataLookup, forInStatement), |
| 1096 localsMap.getJumpTargetForForIn(forInStatement), |
1094 buildInitializer, | 1097 buildInitializer, |
1095 buildCondition, | 1098 buildCondition, |
1096 () {}, | 1099 () {}, |
1097 buildBody); | 1100 buildBody); |
1098 } | 1101 } |
1099 | 1102 |
1100 void _buildAsyncForIn(ir.ForInStatement forInStatement) { | 1103 void _buildAsyncForIn(ir.ForInStatement forInStatement) { |
1101 // The async-for is implemented with a StreamIterator. | 1104 // The async-for is implemented with a StreamIterator. |
1102 HInstruction streamIterator; | 1105 HInstruction streamIterator; |
1103 | 1106 |
(...skipping 27 matching lines...) Expand all Loading... |
1131 | 1134 |
1132 void buildUpdate() {} | 1135 void buildUpdate() {} |
1133 | 1136 |
1134 // Creates a synthetic try/finally block in case anything async goes amiss. | 1137 // Creates a synthetic try/finally block in case anything async goes amiss. |
1135 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); | 1138 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); |
1136 // Build fake try body: | 1139 // Build fake try body: |
1137 loopHandler.handleLoop( | 1140 loopHandler.handleLoop( |
1138 forInStatement, | 1141 forInStatement, |
1139 localsMap.getClosureRepresentationInfoForLoop( | 1142 localsMap.getClosureRepresentationInfoForLoop( |
1140 closureDataLookup, forInStatement), | 1143 closureDataLookup, forInStatement), |
| 1144 localsMap.getJumpTargetForForIn(forInStatement), |
1141 buildInitializer, | 1145 buildInitializer, |
1142 buildCondition, | 1146 buildCondition, |
1143 buildUpdate, | 1147 buildUpdate, |
1144 buildBody); | 1148 buildBody); |
1145 | 1149 |
1146 void finalizerFunction() { | 1150 void finalizerFunction() { |
1147 _pushDynamicInvocation(forInStatement, null, [streamIterator], | 1151 _pushDynamicInvocation(forInStatement, null, [streamIterator], |
1148 selector: Selectors.cancel); | 1152 selector: Selectors.cancel); |
1149 add(new HAwait(pop(), closedWorld.commonMasks.dynamicType)); | 1153 add(new HAwait(pop(), closedWorld.commonMasks.dynamicType)); |
1150 } | 1154 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 assert(isReachable); | 1186 assert(isReachable); |
1183 HInstruction buildCondition() { | 1187 HInstruction buildCondition() { |
1184 whileStatement.condition.accept(this); | 1188 whileStatement.condition.accept(this); |
1185 return popBoolified(); | 1189 return popBoolified(); |
1186 } | 1190 } |
1187 | 1191 |
1188 loopHandler.handleLoop( | 1192 loopHandler.handleLoop( |
1189 whileStatement, | 1193 whileStatement, |
1190 localsMap.getClosureRepresentationInfoForLoop( | 1194 localsMap.getClosureRepresentationInfoForLoop( |
1191 closureDataLookup, whileStatement), | 1195 closureDataLookup, whileStatement), |
| 1196 localsMap.getJumpTargetForWhile(whileStatement), |
1192 () {}, | 1197 () {}, |
1193 buildCondition, | 1198 buildCondition, |
1194 () {}, () { | 1199 () {}, () { |
1195 whileStatement.body.accept(this); | 1200 whileStatement.body.accept(this); |
1196 }); | 1201 }); |
1197 } | 1202 } |
1198 | 1203 |
1199 @override | 1204 @override |
1200 visitDoStatement(ir.DoStatement doStatement) { | 1205 visitDoStatement(ir.DoStatement doStatement) { |
1201 // TODO(efortuna): I think this can be rewritten using | 1206 // TODO(efortuna): I think this can be rewritten using |
1202 // LoopHandler.handleLoop with some tricks about when the "update" happens. | 1207 // LoopHandler.handleLoop with some tricks about when the "update" happens. |
1203 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1208 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1204 LoopClosureRepresentationInfo loopClosureInfo = localsMap | 1209 LoopClosureRepresentationInfo loopClosureInfo = localsMap |
1205 .getClosureRepresentationInfoForLoop(closureDataLookup, doStatement); | 1210 .getClosureRepresentationInfoForLoop(closureDataLookup, doStatement); |
1206 localsHandler.startLoop(loopClosureInfo); | 1211 localsHandler.startLoop(loopClosureInfo); |
1207 JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement); | 1212 JumpTarget target = localsMap.getJumpTargetForDo(doStatement); |
| 1213 JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement, target); |
1208 HLoopInformation loopInfo = current.loopInformation; | 1214 HLoopInformation loopInfo = current.loopInformation; |
1209 HBasicBlock loopEntryBlock = current; | 1215 HBasicBlock loopEntryBlock = current; |
1210 HBasicBlock bodyEntryBlock = current; | 1216 HBasicBlock bodyEntryBlock = current; |
1211 JumpTarget target = localsMap.getJumpTarget(doStatement); | |
1212 bool hasContinues = target != null && target.isContinueTarget; | 1217 bool hasContinues = target != null && target.isContinueTarget; |
1213 if (hasContinues) { | 1218 if (hasContinues) { |
1214 // Add extra block to hang labels on. | 1219 // Add extra block to hang labels on. |
1215 // It doesn't currently work if they are on the same block as the | 1220 // It doesn't currently work if they are on the same block as the |
1216 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1221 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
1217 // SubGraph that starts at the same block again, so the HLoopInfo is | 1222 // SubGraph that starts at the same block again, so the HLoopInfo is |
1218 // either handled twice, or it's handled after the labeled block info, | 1223 // either handled twice, or it's handled after the labeled block info, |
1219 // both of which generate the wrong code. | 1224 // both of which generate the wrong code. |
1220 // Using a separate block is just a simple workaround. | 1225 // Using a separate block is just a simple workaround. |
1221 bodyEntryBlock = openNewBlock(); | 1226 bodyEntryBlock = openNewBlock(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 loopEntryBlock.postProcessLoopHeader(); | 1302 loopEntryBlock.postProcessLoopHeader(); |
1298 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); | 1303 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); |
1299 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( | 1304 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( |
1300 HLoopBlockInformation.DO_WHILE_LOOP, | 1305 HLoopBlockInformation.DO_WHILE_LOOP, |
1301 null, | 1306 null, |
1302 wrapExpressionGraph(conditionExpression), | 1307 wrapExpressionGraph(conditionExpression), |
1303 wrapStatementGraph(bodyGraph), | 1308 wrapStatementGraph(bodyGraph), |
1304 null, | 1309 null, |
1305 loopEntryBlock.loopInformation.target, | 1310 loopEntryBlock.loopInformation.target, |
1306 loopEntryBlock.loopInformation.labels, | 1311 loopEntryBlock.loopInformation.labels, |
1307 // TODO(johnniwinther): Provide source information like: | 1312 // TODO(redemption): Provide source information like: |
1308 // sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement)) | 1313 // sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement)) |
1309 null); | 1314 null); |
1310 loopEntryBlock.setBlockFlow(loopBlockInfo, current); | 1315 loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
1311 loopInfo.loopBlockInformation = loopBlockInfo; | 1316 loopInfo.loopBlockInformation = loopBlockInfo; |
1312 } else { | 1317 } else { |
1313 // Since the loop has no back edge, we remove the loop information on the | 1318 // Since the loop has no back edge, we remove the loop information on the |
1314 // header. | 1319 // header. |
1315 loopEntryBlock.loopInformation = null; | 1320 loopEntryBlock.loopInformation = null; |
1316 | 1321 |
1317 if (jumpHandler.hasAnyBreak()) { | 1322 if (jumpHandler.hasAnyBreak()) { |
1318 // Null branchBlock because the body of the do-while loop always aborts, | 1323 // Null branchBlock because the body of the do-while loop always aborts, |
1319 // so we never get to the condition. | 1324 // so we never get to the condition. |
1320 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler); | 1325 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler); |
1321 | 1326 |
1322 // Since the body of the loop has a break, we attach a synthesized label | 1327 // Since the body of the loop has a break, we attach a synthesized label |
1323 // to the body. | 1328 // to the body. |
1324 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1329 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
1325 JumpTarget target = localsMap.getJumpTarget(doStatement); | 1330 JumpTarget target = localsMap.getJumpTargetForDo(doStatement); |
1326 LabelDefinition label = target.addLabel(null, 'loop'); | 1331 LabelDefinition label = |
1327 label.setBreakTarget(); | 1332 target.addLabel(null, 'loop', isBreakTarget: true); |
1328 HLabeledBlockInformation info = new HLabeledBlockInformation( | 1333 HLabeledBlockInformation info = new HLabeledBlockInformation( |
1329 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); | 1334 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); |
1330 loopEntryBlock.setBlockFlow(info, current); | 1335 loopEntryBlock.setBlockFlow(info, current); |
1331 jumpHandler.forEachBreak((HBreak breakInstruction, _) { | 1336 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
1332 HBasicBlock block = breakInstruction.block; | 1337 HBasicBlock block = breakInstruction.block; |
1333 block.addAtExit(new HBreak.toLabel(label)); | 1338 block.addAtExit(new HBreak.toLabel(label)); |
1334 block.remove(breakInstruction); | 1339 block.remove(breakInstruction); |
1335 }); | 1340 }); |
1336 } | 1341 } |
1337 } | 1342 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 handleIf(visitCondition: buildCondition, visitThen: fail); | 1444 handleIf(visitCondition: buildCondition, visitThen: fail); |
1440 } | 1445 } |
1441 | 1446 |
1442 /// Creates a [JumpHandler] for a statement. The node must be a jump | 1447 /// Creates a [JumpHandler] for a statement. The node must be a jump |
1443 /// target. If there are no breaks or continues targeting the statement, | 1448 /// target. If there are no breaks or continues targeting the statement, |
1444 /// a special "null handler" is returned. | 1449 /// a special "null handler" is returned. |
1445 /// | 1450 /// |
1446 /// [isLoopJump] is true when the jump handler is for a loop. This is used | 1451 /// [isLoopJump] is true when the jump handler is for a loop. This is used |
1447 /// to distinguish the synthesized loop created for a switch statement with | 1452 /// to distinguish the synthesized loop created for a switch statement with |
1448 /// continue statements from simple switch statements. | 1453 /// continue statements from simple switch statements. |
1449 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { | 1454 JumpHandler createJumpHandler(ir.TreeNode node, JumpTarget target, |
1450 JumpTarget target = localsMap.getJumpTarget(node); | 1455 {bool isLoopJump: false}) { |
1451 if (target == null) { | 1456 if (target == null) { |
1452 // No breaks or continues to this node. | 1457 // No breaks or continues to this node. |
1453 return new NullJumpHandler(reporter); | 1458 return new NullJumpHandler(reporter); |
1454 } | 1459 } |
1455 if (isLoopJump && node is ir.SwitchStatement) { | 1460 if (isLoopJump && node is ir.SwitchStatement) { |
1456 return new KernelSwitchCaseJumpHandler(this, target, node, localsMap); | 1461 return new KernelSwitchCaseJumpHandler(this, target, node, localsMap); |
1457 } | 1462 } |
1458 | 1463 |
1459 return new JumpHandler(this, target); | 1464 return new JumpHandler(this, target); |
1460 } | 1465 } |
1461 | 1466 |
1462 @override | 1467 @override |
1463 void visitBreakStatement(ir.BreakStatement breakStatement) { | 1468 void visitBreakStatement(ir.BreakStatement breakStatement) { |
1464 assert(!isAborted()); | 1469 assert(!isAborted()); |
1465 handleInTryStatement(); | 1470 handleInTryStatement(); |
1466 JumpTarget target = localsMap.getJumpTarget(breakStatement.target); | 1471 JumpTarget target = localsMap.getJumpTargetForBreak(breakStatement); |
1467 assert(target != null); | 1472 assert(target != null); |
1468 JumpHandler handler = jumpTargets[target]; | 1473 JumpHandler handler = jumpTargets[target]; |
1469 assert(handler != null); | 1474 assert(handler != null); |
1470 if (handler.labels.isNotEmpty) { | 1475 if (handler.labels.isNotEmpty) { |
1471 handler.generateBreak(handler.labels.first); | 1476 handler.generateBreak(handler.labels.first); |
1472 } else { | 1477 } else { |
1473 handler.generateBreak(); | 1478 handler.generateBreak(); |
1474 } | 1479 } |
1475 } | 1480 } |
1476 | 1481 |
1477 @override | 1482 @override |
1478 void visitLabeledStatement(ir.LabeledStatement labeledStatement) { | 1483 void visitLabeledStatement(ir.LabeledStatement labeledStatement) { |
1479 ir.Statement body = labeledStatement.body; | 1484 ir.Statement body = labeledStatement.body; |
1480 if (body is ir.WhileStatement || | 1485 if (body is ir.WhileStatement || |
1481 body is ir.DoStatement || | 1486 body is ir.DoStatement || |
1482 body is ir.ForStatement || | 1487 body is ir.ForStatement || |
1483 body is ir.ForInStatement || | 1488 body is ir.ForInStatement || |
1484 body is ir.SwitchStatement) { | 1489 body is ir.SwitchStatement) { |
1485 // loops and switches handle breaks on their own | 1490 // loops and switches handle breaks on their own |
1486 body.accept(this); | 1491 body.accept(this); |
1487 return; | 1492 return; |
1488 } | 1493 } |
1489 JumpHandler handler = createJumpHandler(labeledStatement); | 1494 JumpHandler handler = createJumpHandler( |
| 1495 labeledStatement, localsMap.getJumpTargetForLabel(labeledStatement)); |
1490 | 1496 |
1491 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 1497 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
1492 | 1498 |
1493 HBasicBlock newBlock = openNewBlock(); | 1499 HBasicBlock newBlock = openNewBlock(); |
1494 body.accept(this); | 1500 body.accept(this); |
1495 SubGraph bodyGraph = new SubGraph(newBlock, lastOpenedBlock); | 1501 SubGraph bodyGraph = new SubGraph(newBlock, lastOpenedBlock); |
1496 | 1502 |
1497 HBasicBlock joinBlock = graph.addNewBlock(); | 1503 HBasicBlock joinBlock = graph.addNewBlock(); |
1498 List<LocalsHandler> breakHandlers = <LocalsHandler>[]; | 1504 List<LocalsHandler> breakHandlers = <LocalsHandler>[]; |
1499 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1505 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
(...skipping 29 matching lines...) Expand all Loading... |
1529 constants[caseExpression] = constant; | 1535 constants[caseExpression] = constant; |
1530 } | 1536 } |
1531 } | 1537 } |
1532 return constants; | 1538 return constants; |
1533 } | 1539 } |
1534 | 1540 |
1535 @override | 1541 @override |
1536 void visitContinueSwitchStatement( | 1542 void visitContinueSwitchStatement( |
1537 ir.ContinueSwitchStatement switchStatement) { | 1543 ir.ContinueSwitchStatement switchStatement) { |
1538 handleInTryStatement(); | 1544 handleInTryStatement(); |
1539 JumpTarget target = localsMap.getJumpTarget(switchStatement.target); | 1545 JumpTarget target = |
| 1546 localsMap.getJumpTargetForContinueSwitch(switchStatement); |
1540 assert(target != null); | 1547 assert(target != null); |
1541 JumpHandler handler = jumpTargets[target]; | 1548 JumpHandler handler = jumpTargets[target]; |
1542 assert(handler != null); | 1549 assert(handler != null); |
1543 assert(target.labels.isNotEmpty); | 1550 assert(target.labels.isNotEmpty); |
1544 handler.generateContinue(target.labels.first); | 1551 handler.generateContinue(target.labels.first); |
1545 } | 1552 } |
1546 | 1553 |
1547 @override | 1554 @override |
1548 void visitSwitchStatement(ir.SwitchStatement switchStatement) { | 1555 void visitSwitchStatement(ir.SwitchStatement switchStatement) { |
1549 // The switch case indices must match those computed in | 1556 // The switch case indices must match those computed in |
1550 // [KernelSwitchCaseJumpHandler]. | 1557 // [KernelSwitchCaseJumpHandler]. |
1551 bool hasContinue = false; | 1558 bool hasContinue = false; |
1552 Map<ir.SwitchCase, int> caseIndex = new Map<ir.SwitchCase, int>(); | 1559 Map<ir.SwitchCase, int> caseIndex = new Map<ir.SwitchCase, int>(); |
1553 int switchIndex = 1; | 1560 int switchIndex = 1; |
1554 bool hasDefault = false; | 1561 bool hasDefault = false; |
1555 for (ir.SwitchCase switchCase in switchStatement.cases) { | 1562 for (ir.SwitchCase switchCase in switchStatement.cases) { |
1556 if (_isDefaultCase(switchCase)) { | 1563 if (_isDefaultCase(switchCase)) { |
1557 hasDefault = true; | 1564 hasDefault = true; |
1558 } | 1565 } |
1559 if (SwitchContinueAnalysis.containsContinue(switchCase.body)) { | 1566 if (SwitchContinueAnalysis.containsContinue(switchCase.body)) { |
1560 hasContinue = true; | 1567 hasContinue = true; |
1561 } | 1568 } |
1562 caseIndex[switchCase] = switchIndex; | 1569 caseIndex[switchCase] = switchIndex; |
1563 switchIndex++; | 1570 switchIndex++; |
1564 } | 1571 } |
1565 | 1572 |
1566 JumpHandler jumpHandler = createJumpHandler(switchStatement); | 1573 JumpHandler jumpHandler = createJumpHandler( |
| 1574 switchStatement, localsMap.getJumpTargetForSwitch(switchStatement)); |
1567 if (!hasContinue) { | 1575 if (!hasContinue) { |
1568 // If the switch statement has no switch cases targeted by continue | 1576 // If the switch statement has no switch cases targeted by continue |
1569 // statements we encode the switch statement directly. | 1577 // statements we encode the switch statement directly. |
1570 _buildSimpleSwitchStatement(switchStatement, jumpHandler); | 1578 _buildSimpleSwitchStatement(switchStatement, jumpHandler); |
1571 } else { | 1579 } else { |
1572 _buildComplexSwitchStatement( | 1580 _buildComplexSwitchStatement( |
1573 switchStatement, jumpHandler, caseIndex, hasDefault); | 1581 switchStatement, jumpHandler, caseIndex, hasDefault); |
1574 } | 1582 } |
1575 } | 1583 } |
1576 | 1584 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 // case 1: s_1; break l; | 1657 // case 1: s_1; break l; |
1650 // case 2: s_2; target = i; continue l; | 1658 // case 2: s_2; target = i; continue l; |
1651 // ... | 1659 // ... |
1652 // case n: s_n; target = j; continue l; | 1660 // case n: s_n; target = j; continue l; |
1653 // } | 1661 // } |
1654 // } | 1662 // } |
1655 // | 1663 // |
1656 // This is because JS does not have this same "continue label" semantics so | 1664 // This is because JS does not have this same "continue label" semantics so |
1657 // we encode it in the form of a state machine. | 1665 // we encode it in the form of a state machine. |
1658 | 1666 |
1659 JumpTarget switchTarget = localsMap.getJumpTarget(switchStatement); | 1667 JumpTarget switchTarget = localsMap.getJumpTargetForSwitch(switchStatement); |
1660 localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld)); | 1668 localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld)); |
1661 | 1669 |
1662 var switchCases = switchStatement.cases; | 1670 var switchCases = switchStatement.cases; |
1663 if (!hasDefault) { | 1671 if (!hasDefault) { |
1664 // Use null as the marker for a synthetic default clause. | 1672 // Use null as the marker for a synthetic default clause. |
1665 // The synthetic default is added because otherwise there would be no | 1673 // The synthetic default is added because otherwise there would be no |
1666 // good place to give a default value to the local. | 1674 // good place to give a default value to the local. |
1667 switchCases = new List<ir.SwitchCase>.from(switchCases); | 1675 switchCases = new List<ir.SwitchCase>.from(switchCases); |
1668 switchCases.add(null); | 1676 switchCases.add(null); |
1669 } | 1677 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1718 getConstants, | 1726 getConstants, |
1719 (_) => false, // No case is default. | 1727 (_) => false, // No case is default. |
1720 buildSwitchCase); | 1728 buildSwitchCase); |
1721 } | 1729 } |
1722 | 1730 |
1723 void buildLoop() { | 1731 void buildLoop() { |
1724 loopHandler.handleLoop( | 1732 loopHandler.handleLoop( |
1725 switchStatement, | 1733 switchStatement, |
1726 localsMap.getClosureRepresentationInfoForLoop( | 1734 localsMap.getClosureRepresentationInfoForLoop( |
1727 closureDataLookup, switchStatement), | 1735 closureDataLookup, switchStatement), |
| 1736 switchTarget, |
1728 () {}, | 1737 () {}, |
1729 buildCondition, | 1738 buildCondition, |
1730 () {}, | 1739 () {}, |
1731 buildSwitch); | 1740 buildSwitch); |
1732 } | 1741 } |
1733 | 1742 |
1734 if (hasDefault) { | 1743 if (hasDefault) { |
1735 buildLoop(); | 1744 buildLoop(); |
1736 } else { | 1745 } else { |
1737 // If the switch statement has no default case, surround the loop with | 1746 // If the switch statement has no default case, surround the loop with |
(...skipping 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3487 enterBlock.setBlockFlow( | 3496 enterBlock.setBlockFlow( |
3488 new HTryBlockInformation( | 3497 new HTryBlockInformation( |
3489 kernelBuilder.wrapStatementGraph(bodyGraph), | 3498 kernelBuilder.wrapStatementGraph(bodyGraph), |
3490 exception, | 3499 exception, |
3491 kernelBuilder.wrapStatementGraph(catchGraph), | 3500 kernelBuilder.wrapStatementGraph(catchGraph), |
3492 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3501 kernelBuilder.wrapStatementGraph(finallyGraph)), |
3493 exitBlock); | 3502 exitBlock); |
3494 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3503 kernelBuilder.inTryStatement = previouslyInTryStatement; |
3495 } | 3504 } |
3496 } | 3505 } |
OLD | NEW |