| 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 893 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |