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 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 Map<Element, HInstruction> fieldValues) { | 810 Map<Element, HInstruction> fieldValues) { |
811 constructors.addLast(constructor); | 811 constructors.addLast(constructor); |
812 | 812 |
813 List<HInstruction> compiledArguments = new List<HInstruction>(); | 813 List<HInstruction> compiledArguments = new List<HInstruction>(); |
814 bool succeeded = addStaticSendArgumentsToList(selector, | 814 bool succeeded = addStaticSendArgumentsToList(selector, |
815 arguments, | 815 arguments, |
816 constructor, | 816 constructor, |
817 compiledArguments); | 817 compiledArguments); |
818 if (!succeeded) { | 818 if (!succeeded) { |
819 // Non-matching super and redirects are compile-time errors and thus | 819 // Non-matching super and redirects are compile-time errors and thus |
820 // checked by the resolver. | 820 // checked by the resolver. |
821 compiler.internalError( | 821 compiler.internalError( |
822 "Parameters and arguments didn't match for super/redirect call", | 822 "Parameters and arguments didn't match for super/redirect call", |
823 element: constructor); | 823 element: constructor); |
824 } | 824 } |
825 | 825 |
826 int index = 0; | 826 int index = 0; |
827 FunctionParameters parameters = constructor.computeParameters(compiler); | 827 FunctionParameters parameters = constructor.computeParameters(compiler); |
828 parameters.forEachParameter((Element parameter) { | 828 parameters.forEachParameter((Element parameter) { |
829 HInstruction argument = compiledArguments[index++]; | 829 HInstruction argument = compiledArguments[index++]; |
830 localsHandler.updateLocal(parameter, argument); | 830 localsHandler.updateLocal(parameter, argument); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 | 1023 |
1024 void goto(HBasicBlock from, HBasicBlock to) { | 1024 void goto(HBasicBlock from, HBasicBlock to) { |
1025 from.close(new HGoto()); | 1025 from.close(new HGoto()); |
1026 from.addSuccessor(to); | 1026 from.addSuccessor(to); |
1027 } | 1027 } |
1028 | 1028 |
1029 bool isAborted() { | 1029 bool isAborted() { |
1030 return current === null; | 1030 return current === null; |
1031 } | 1031 } |
1032 | 1032 |
| 1033 /** |
| 1034 * Creates a new block, transitions to it from any current block, and |
| 1035 * opens the new block. |
| 1036 */ |
| 1037 HBasicBlock openNewBlock() { |
| 1038 HBasicBlock newBlock = addNewBlock(); |
| 1039 if (!isAborted()) goto(current, newBlock); |
| 1040 open(newBlock); |
| 1041 return newBlock; |
| 1042 } |
| 1043 |
1033 void add(HInstruction instruction) { | 1044 void add(HInstruction instruction) { |
1034 current.add(instruction); | 1045 current.add(instruction); |
1035 } | 1046 } |
1036 | 1047 |
1037 void push(HInstruction instruction) { | 1048 void push(HInstruction instruction) { |
1038 add(instruction); | 1049 add(instruction); |
1039 stack.add(instruction); | 1050 stack.add(instruction); |
1040 } | 1051 } |
1041 | 1052 |
1042 HInstruction pop() { | 1053 HInstruction pop() { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 // loop-entry: | 1154 // loop-entry: |
1144 // if (!<condition>) goto loop-exit; | 1155 // if (!<condition>) goto loop-exit; |
1145 // <body> | 1156 // <body> |
1146 // <updates> | 1157 // <updates> |
1147 // goto loop-entry; | 1158 // goto loop-entry; |
1148 // loop-exit: | 1159 // loop-exit: |
1149 | 1160 |
1150 localsHandler.startLoop(loop); | 1161 localsHandler.startLoop(loop); |
1151 | 1162 |
1152 // The initializer. | 1163 // The initializer. |
1153 HBasicBlock initializerBlock = graph.addNewBlock(); | 1164 HBasicBlock initializerBlock = openNewBlock(); |
1154 goto(current, initializerBlock); | |
1155 open(initializerBlock); | |
1156 initialize(); | 1165 initialize(); |
1157 assert(!isAborted()); | 1166 assert(!isAborted()); |
1158 SubGraph initializerGraph = new SubGraph(initializerBlock, current); | 1167 SubGraph initializerGraph = new SubGraph(initializerBlock, current); |
1159 | 1168 |
1160 JumpHandler jumpHandler = beginLoopHeader(loop); | 1169 JumpHandler jumpHandler = beginLoopHeader(loop); |
1161 HBasicBlock conditionBlock = current; | 1170 HBasicBlock conditionBlock = current; |
1162 HLoopInformation loopInfo = current.loopInformation; | 1171 HLoopInformation loopInfo = current.blockInformation; |
1163 // The initializer graph is currently unused due to the way we | 1172 // The initializer graph is currently unused due to the way we |
1164 // generate code. | 1173 // generate code. |
1165 loopInfo.initializer = initializerGraph; | 1174 loopInfo.initializer = initializerGraph; |
1166 | 1175 |
1167 HInstruction conditionInstruction = condition(); | 1176 HInstruction conditionInstruction = condition(); |
1168 HBasicBlock conditionExitBlock = | 1177 HBasicBlock conditionExitBlock = |
1169 close(new HLoopBranch(conditionInstruction)); | 1178 close(new HLoopBranch(conditionInstruction)); |
1170 loopInfo.condition = new SubExpression(conditionBlock, | 1179 loopInfo.condition = new SubExpression(conditionBlock, |
1171 conditionExitBlock, | 1180 conditionExitBlock, |
1172 conditionInstruction); | 1181 conditionInstruction); |
(...skipping 27 matching lines...) Expand all Loading... |
1200 continueLocals.add(localsHandler); | 1209 continueLocals.add(localsHandler); |
1201 | 1210 |
1202 open(updateBlock); | 1211 open(updateBlock); |
1203 | 1212 |
1204 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); | 1213 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); |
1205 | 1214 |
1206 HLabeledBlockInformation labelInfo; | 1215 HLabeledBlockInformation labelInfo; |
1207 List<LabelElement> labels = jumpHandler.labels(); | 1216 List<LabelElement> labels = jumpHandler.labels(); |
1208 TargetElement target = elements[loop]; | 1217 TargetElement target = elements[loop]; |
1209 if (!labels.isEmpty()) { | 1218 if (!labels.isEmpty()) { |
1210 beginBodyBlock.labeledBlockInformation = | 1219 beginBodyBlock.blockInformation = |
1211 new HLabeledBlockInformation(bodyGraph, updateBlock, | 1220 new HLabeledBlockInformation(bodyGraph, updateBlock, |
1212 jumpHandler.labels(), isContinue: true); | 1221 jumpHandler.labels(), isContinue: true); |
1213 } else if (target !== null && target.isContinueTarget) { | 1222 } else if (target !== null && target.isContinueTarget) { |
1214 beginBodyBlock.labeledBlockInformation = | 1223 beginBodyBlock.blockInformation = |
1215 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, | 1224 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, |
1216 target, isContinue: true); | 1225 target, isContinue: true); |
1217 } | 1226 } |
1218 | 1227 |
1219 localsHandler.enterLoopUpdates(loop); | 1228 localsHandler.enterLoopUpdates(loop); |
1220 | 1229 |
1221 update(); | 1230 update(); |
1222 | 1231 |
1223 HBasicBlock updateEndBlock = close(new HGoto()); | 1232 HBasicBlock updateEndBlock = close(new HGoto()); |
1224 // The back-edge completing the cycle. | 1233 // The back-edge completing the cycle. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 () {}, | 1282 () {}, |
1274 buildCondition, | 1283 buildCondition, |
1275 () {}, | 1284 () {}, |
1276 () { visit(node.body); }); | 1285 () { visit(node.body); }); |
1277 } | 1286 } |
1278 | 1287 |
1279 visitDoWhile(DoWhile node) { | 1288 visitDoWhile(DoWhile node) { |
1280 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1289 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1281 localsHandler.startLoop(node); | 1290 localsHandler.startLoop(node); |
1282 JumpHandler jumpHandler = beginLoopHeader(node); | 1291 JumpHandler jumpHandler = beginLoopHeader(node); |
1283 HLoopInformation loopInfo = current.loopInformation; | 1292 HLoopInformation loopInfo = current.blockInformation; |
1284 HBasicBlock loopEntryBlock = current; | 1293 HBasicBlock loopEntryBlock = current; |
1285 HBasicBlock bodyEntryBlock = current; | 1294 HBasicBlock bodyEntryBlock = current; |
1286 TargetElement target = elements[node]; | 1295 TargetElement target = elements[node]; |
1287 bool hasContinues = target !== null && target.isContinueTarget; | 1296 bool hasContinues = target !== null && target.isContinueTarget; |
1288 if (hasContinues) { | 1297 if (hasContinues) { |
1289 // Add extra block to hang labels on. | 1298 // Add extra block to hang labels on. |
1290 // It doesn't currently work if they are on the same block as the | 1299 // It doesn't currently work if they are on the same block as the |
1291 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1300 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
1292 // SubGraph that starts at the same block again, so the HLoopInfo is | 1301 // SubGraph that starts at the same block again, so the HLoopInfo is |
1293 // either handled twice, or it's handled after the labeled block info, | 1302 // either handled twice, or it's handled after the labeled block info, |
1294 // both of which generate the wrong code. | 1303 // both of which generate the wrong code. |
1295 // Using a separate block is just a simple workaround. | 1304 // Using a separate block is just a simple workaround. |
1296 bodyEntryBlock = graph.addNewBlock(); | 1305 bodyEntryBlock = openNewBlock(); |
1297 goto(current, bodyEntryBlock); | |
1298 open(bodyEntryBlock); | |
1299 } | 1306 } |
1300 localsHandler.enterLoopBody(node); | 1307 localsHandler.enterLoopBody(node); |
1301 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); | 1308 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); |
1302 | 1309 |
1303 // If there are no continues we could avoid the creation of the condition | 1310 // If there are no continues we could avoid the creation of the condition |
1304 // block. This could also lead to a block having multiple entries and exits. | 1311 // block. This could also lead to a block having multiple entries and exits. |
1305 HBasicBlock bodyExitBlock = close(new HGoto()); | 1312 HBasicBlock bodyExitBlock = close(new HGoto()); |
1306 HBasicBlock conditionBlock = addNewBlock(); | 1313 HBasicBlock conditionBlock = addNewBlock(); |
1307 | 1314 |
1308 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1315 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
1309 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1316 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
1310 instruction.block.addSuccessor(conditionBlock); | 1317 instruction.block.addSuccessor(conditionBlock); |
1311 continueLocals.add(locals); | 1318 continueLocals.add(locals); |
1312 }); | 1319 }); |
1313 bodyExitBlock.addSuccessor(conditionBlock); | 1320 bodyExitBlock.addSuccessor(conditionBlock); |
1314 if (!continueLocals.isEmpty()) { | 1321 if (!continueLocals.isEmpty()) { |
1315 continueLocals.add(localsHandler); | 1322 continueLocals.add(localsHandler); |
1316 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); | 1323 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); |
1317 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1324 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
1318 List<LabelElement> labels = jumpHandler.labels(); | 1325 List<LabelElement> labels = jumpHandler.labels(); |
1319 if (!labels.isEmpty()) { | 1326 if (!labels.isEmpty()) { |
1320 bodyEntryBlock.labeledBlockInformation = | 1327 bodyEntryBlock.blockInformation = |
1321 new HLabeledBlockInformation(bodyGraph, | 1328 new HLabeledBlockInformation(bodyGraph, |
1322 conditionBlock, | 1329 conditionBlock, |
1323 labels, | 1330 labels, |
1324 isContinue: true); | 1331 isContinue: true); |
1325 } else { | 1332 } else { |
1326 bodyEntryBlock.labeledBlockInformation = | 1333 bodyEntryBlock.blockInformation = |
1327 new HLabeledBlockInformation.implicit(bodyGraph, | 1334 new HLabeledBlockInformation.implicit(bodyGraph, |
1328 conditionBlock, | 1335 conditionBlock, |
1329 target, | 1336 target, |
1330 isContinue: true); | 1337 isContinue: true); |
1331 } | 1338 } |
1332 } | 1339 } |
1333 open(conditionBlock); | 1340 open(conditionBlock); |
1334 | 1341 |
1335 visit(node.condition); | 1342 visit(node.condition); |
1336 assert(!isAborted()); | 1343 assert(!isAborted()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 visitIdentifier(Identifier node) { | 1395 visitIdentifier(Identifier node) { |
1389 if (node.isThis()) { | 1396 if (node.isThis()) { |
1390 stack.add(localsHandler.readThis()); | 1397 stack.add(localsHandler.readThis()); |
1391 } else { | 1398 } else { |
1392 compiler.internalError("SsaBuilder.visitIdentifier on non-this", | 1399 compiler.internalError("SsaBuilder.visitIdentifier on non-this", |
1393 node: node); | 1400 node: node); |
1394 } | 1401 } |
1395 } | 1402 } |
1396 | 1403 |
1397 visitIf(If node) { | 1404 visitIf(If node) { |
1398 visit(node.condition); | 1405 handleIf(() => visit(node.condition), |
1399 Function visitElse; | 1406 () => visit(node.thenPart), |
1400 if (node.elsePart != null) { | 1407 node.elsePart != null ? () => visit(node.elsePart) : null); |
1401 visitElse = () { | |
1402 visit(node.elsePart); | |
1403 }; | |
1404 } | |
1405 handleIf(() => visit(node.thenPart), visitElse); | |
1406 } | 1408 } |
1407 | 1409 |
1408 void handleIf(void visitThen(), void visitElse()) { | 1410 void handleIf(void visitCondition(), void visitThen(), void visitElse()) { |
| 1411 HBasicBlock conditionStartBlock = openNewBlock(); |
| 1412 visitCondition(); |
| 1413 SubExpression conditionGraph = |
| 1414 new SubExpression(conditionStartBlock, lastOpenedBlock, stack.last()); |
1409 bool hasElse = visitElse != null; | 1415 bool hasElse = visitElse != null; |
1410 HIf condition = new HIf(popBoolified(), hasElse); | 1416 HInstruction condition = popBoolified(); |
1411 HBasicBlock conditionBlock = close(condition); | 1417 HIf branch = new HIf(condition, hasElse); |
| 1418 HBasicBlock conditionBlock = close(branch); |
1412 | 1419 |
1413 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1420 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1414 | 1421 |
1415 // The then part. | 1422 // The then part. |
1416 HBasicBlock thenBlock = addNewBlock(); | 1423 HBasicBlock thenBlock = addNewBlock(); |
1417 conditionBlock.addSuccessor(thenBlock); | 1424 conditionBlock.addSuccessor(thenBlock); |
1418 open(thenBlock); | 1425 open(thenBlock); |
1419 visitThen(); | 1426 visitThen(); |
1420 SubGraph thenGraph = new SubGraph(thenBlock, lastOpenedBlock); | 1427 SubGraph thenGraph = new SubGraph(thenBlock, lastOpenedBlock); |
1421 thenBlock = current; | 1428 thenBlock = current; |
(...skipping 27 matching lines...) Expand all Loading... |
1449 // with the set of locals we got after visiting the then | 1456 // with the set of locals we got after visiting the then |
1450 // part of the if. | 1457 // part of the if. |
1451 open(joinBlock); | 1458 open(joinBlock); |
1452 if (joinBlock.predecessors.length == 2) { | 1459 if (joinBlock.predecessors.length == 2) { |
1453 localsHandler.mergeWith(thenLocals, joinBlock); | 1460 localsHandler.mergeWith(thenLocals, joinBlock); |
1454 } else if (thenBlock !== null) { | 1461 } else if (thenBlock !== null) { |
1455 // The only predecessor is the then branch. | 1462 // The only predecessor is the then branch. |
1456 localsHandler = thenLocals; | 1463 localsHandler = thenLocals; |
1457 } | 1464 } |
1458 } | 1465 } |
1459 condition.blockInformation = | 1466 HIfBlockInformation info = new HIfBlockInformation(conditionGraph, |
1460 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); | 1467 thenGraph, |
| 1468 elseGraph, |
| 1469 joinBlock); |
| 1470 conditionStartBlock.blockInformation = info; |
| 1471 branch.blockInformation = info; |
1461 } | 1472 } |
1462 | 1473 |
1463 void visitLogicalAndOr(Send node, Operator op) { | 1474 void visitLogicalAndOr(Send node, Operator op) { |
1464 handleLogicalAndOr(() { visit(node.receiver); }, | 1475 handleLogicalAndOr(() { visit(node.receiver); }, |
1465 () { visit(node.argumentsNode); }, | 1476 () { visit(node.argumentsNode); }, |
1466 isAnd: (const SourceString("&&") == op.source)); | 1477 isAnd: (const SourceString("&&") == op.source)); |
1467 } | 1478 } |
1468 | 1479 |
1469 | 1480 |
1470 void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) { | 1481 void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) { |
1471 // x && y is transformed into: | 1482 // x && y is transformed into: |
1472 // t0 = boolify(x); | 1483 // t0 = boolify(x); |
1473 // if (t0) t1 = boolify(y); | 1484 // if (t0) t1 = boolify(y); |
1474 // result = phi(t0, t1); | 1485 // result = phi(t0, t1); |
1475 // | 1486 // |
1476 // x || y is transformed into: | 1487 // x || y is transformed into: |
1477 // t0 = boolify(x); | 1488 // t0 = boolify(x); |
1478 // if (not(t0)) t1 = boolify(y); | 1489 // if (not(t0)) t1 = boolify(y); |
1479 // result = phi(t0, t1); | 1490 // result = phi(t0, t1); |
| 1491 HBasicBlock leftBlock = openNewBlock(); |
1480 left(); | 1492 left(); |
1481 HInstruction boolifiedLeft = popBoolified(); | 1493 HInstruction boolifiedLeft = popBoolified(); |
1482 HInstruction condition; | 1494 HInstruction condition; |
1483 if (isAnd) { | 1495 if (isAnd) { |
1484 condition = boolifiedLeft; | 1496 condition = boolifiedLeft; |
1485 } else { | 1497 } else { |
1486 condition = new HNot(boolifiedLeft); | 1498 condition = new HNot(boolifiedLeft); |
1487 add(condition); | 1499 add(condition); |
1488 } | 1500 } |
| 1501 SubExpression leftGraph = |
| 1502 new SubExpression(leftBlock, lastOpenedBlock, boolifiedLeft); |
1489 HIf branch = new HIf(condition, false); | 1503 HIf branch = new HIf(condition, false); |
1490 HBasicBlock leftBlock = close(branch); | 1504 leftBlock = close(branch); |
1491 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1505 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1492 | 1506 |
1493 HBasicBlock rightBlock = addNewBlock(); | 1507 HBasicBlock rightBlock = addNewBlock(); |
1494 leftBlock.addSuccessor(rightBlock); | 1508 leftBlock.addSuccessor(rightBlock); |
1495 open(rightBlock); | 1509 open(rightBlock); |
1496 | 1510 |
1497 right(); | 1511 right(); |
1498 HInstruction boolifiedRight = popBoolified(); | 1512 HInstruction boolifiedRight = popBoolified(); |
1499 SubGraph rightGraph = new SubGraph(rightBlock, current); | 1513 SubExpression rightGraph = |
| 1514 new SubExpression(rightBlock, current, boolifiedRight); |
1500 rightBlock = close(new HGoto()); | 1515 rightBlock = close(new HGoto()); |
1501 | 1516 |
1502 HBasicBlock joinBlock = addNewBlock(); | 1517 HBasicBlock joinBlock = addNewBlock(); |
1503 leftBlock.addSuccessor(joinBlock); | 1518 leftBlock.addSuccessor(joinBlock); |
1504 rightBlock.addSuccessor(joinBlock); | 1519 rightBlock.addSuccessor(joinBlock); |
1505 open(joinBlock); | 1520 open(joinBlock); |
1506 | 1521 |
| 1522 leftGraph.start.blockInformation = |
| 1523 new HAndOrBlockInformation(isAnd, leftGraph, rightGraph, joinBlock); |
1507 branch.blockInformation = | 1524 branch.blockInformation = |
1508 new HIfBlockInformation(branch, rightGraph, null, joinBlock); | 1525 new HIfBlockInformation(leftGraph, rightGraph, null, joinBlock); |
1509 | 1526 |
1510 localsHandler.mergeWith(savedLocals, joinBlock); | 1527 localsHandler.mergeWith(savedLocals, joinBlock); |
1511 HPhi result = new HPhi.manyInputs(null, | 1528 HPhi result = new HPhi.manyInputs(null, |
1512 <HInstruction>[boolifiedLeft, boolifiedRight]); | 1529 <HInstruction>[boolifiedLeft, boolifiedRight]); |
1513 joinBlock.addPhi(result); | 1530 joinBlock.addPhi(result); |
1514 stack.add(result); | 1531 stack.add(result); |
1515 } | 1532 } |
1516 | 1533 |
1517 void visitLogicalNot(Send node) { | 1534 void visitLogicalNot(Send node) { |
1518 assert(node.argumentsNode is Prefix); | 1535 assert(node.argumentsNode is Prefix); |
(...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2577 // A different target statement only happens if the body is itself | 2594 // A different target statement only happens if the body is itself |
2578 // a break or continue for a different target. In that case, this | 2595 // a break or continue for a different target. In that case, this |
2579 // label is also always unused. | 2596 // label is also always unused. |
2580 visit(body); | 2597 visit(body); |
2581 return; | 2598 return; |
2582 } | 2599 } |
2583 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 2600 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
2584 assert(targetElement.isBreakTarget); | 2601 assert(targetElement.isBreakTarget); |
2585 JumpHandler handler = new JumpHandler(this, targetElement); | 2602 JumpHandler handler = new JumpHandler(this, targetElement); |
2586 // Introduce a new basic block. | 2603 // Introduce a new basic block. |
2587 HBasicBlock entryBlock = graph.addNewBlock(); | 2604 HBasicBlock entryBlock = openNewBlock(); |
2588 goto(current, entryBlock); | |
2589 open(entryBlock); | |
2590 hackAroundPossiblyAbortingBody(node, () { visit(body); }); | 2605 hackAroundPossiblyAbortingBody(node, () { visit(body); }); |
2591 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); | 2606 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
2592 | 2607 |
2593 HBasicBlock joinBlock = graph.addNewBlock(); | 2608 HBasicBlock joinBlock = graph.addNewBlock(); |
2594 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 2609 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
2595 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 2610 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
2596 breakInstruction.block.addSuccessor(joinBlock); | 2611 breakInstruction.block.addSuccessor(joinBlock); |
2597 breakLocals.add(locals); | 2612 breakLocals.add(locals); |
2598 }); | 2613 }); |
2599 bool hasBreak = breakLocals.length > 0; | 2614 bool hasBreak = breakLocals.length > 0; |
2600 if (!isAborted()) { | 2615 if (!isAborted()) { |
2601 goto(current, joinBlock); | 2616 goto(current, joinBlock); |
2602 breakLocals.add(localsHandler); | 2617 breakLocals.add(localsHandler); |
2603 } | 2618 } |
2604 open(joinBlock); | 2619 open(joinBlock); |
2605 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); | 2620 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); |
2606 | 2621 |
2607 if (hasBreak) { | 2622 if (hasBreak) { |
2608 // There was at least one reachable break, so the label is needed. | 2623 // There was at least one reachable break, so the label is needed. |
2609 HLabeledBlockInformation blockInfo = | 2624 entryBlock.blockInformation = |
2610 new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); | 2625 new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); |
2611 entryBlock.labeledBlockInformation = blockInfo; | |
2612 } | 2626 } |
2613 handler.close(); | 2627 handler.close(); |
2614 } | 2628 } |
2615 | 2629 |
2616 visitLiteralMap(LiteralMap node) { | 2630 visitLiteralMap(LiteralMap node) { |
2617 if (node.isConst()) { | 2631 if (node.isConst()) { |
2618 ConstantHandler handler = compiler.constantHandler; | 2632 ConstantHandler handler = compiler.constantHandler; |
2619 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 2633 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
2620 stack.add(graph.addConstant(constant)); | 2634 stack.add(graph.addConstant(constant)); |
2621 return; | 2635 return; |
(...skipping 19 matching lines...) Expand all Loading... |
2641 visit(node.key); | 2655 visit(node.key); |
2642 } | 2656 } |
2643 | 2657 |
2644 visitNamedArgument(NamedArgument node) { | 2658 visitNamedArgument(NamedArgument node) { |
2645 visit(node.expression); | 2659 visit(node.expression); |
2646 } | 2660 } |
2647 | 2661 |
2648 visitSwitchStatement(SwitchStatement node) { | 2662 visitSwitchStatement(SwitchStatement node) { |
2649 work.allowSpeculativeOptimization = false; | 2663 work.allowSpeculativeOptimization = false; |
2650 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 2664 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
2651 HBasicBlock startBlock = graph.addNewBlock(); | 2665 HBasicBlock startBlock = openNewBlock(); |
2652 goto(current, startBlock); | |
2653 open(startBlock); | |
2654 visit(node.expression); | 2666 visit(node.expression); |
2655 HInstruction expression = pop(); | 2667 HInstruction expression = pop(); |
2656 if (node.cases.isEmpty()) { | 2668 if (node.cases.isEmpty()) { |
2657 return; | 2669 return; |
2658 } | 2670 } |
2659 Link<Node> cases = node.cases.nodes; | 2671 Link<Node> cases = node.cases.nodes; |
2660 | 2672 |
2661 JumpHandler jumpHandler = createJumpHandler(node); | 2673 JumpHandler jumpHandler = createJumpHandler(node); |
2662 | 2674 |
2663 buildSwitchCases(cases, expression); | 2675 buildSwitchCases(cases, expression); |
(...skipping 19 matching lines...) Expand all Loading... |
2683 open(joinBlock); | 2695 open(joinBlock); |
2684 if (caseLocals.length == 1) { | 2696 if (caseLocals.length == 1) { |
2685 localsHandler = caseLocals[0]; | 2697 localsHandler = caseLocals[0]; |
2686 } else { | 2698 } else { |
2687 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | 2699 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); |
2688 } | 2700 } |
2689 } else { | 2701 } else { |
2690 // The joinblock is not used. | 2702 // The joinblock is not used. |
2691 joinBlock = null; | 2703 joinBlock = null; |
2692 } | 2704 } |
2693 startBlock.labeledBlockInformation = new HLabeledBlockInformation.implicit( | 2705 startBlock.blockInformation = new HLabeledBlockInformation.implicit( |
2694 new SubGraph(startBlock, lastBlock), | 2706 new SubGraph(startBlock, lastBlock), |
2695 joinBlock, | 2707 joinBlock, |
2696 elements[node]); | 2708 elements[node]); |
2697 jumpHandler.close(); | 2709 jumpHandler.close(); |
2698 } | 2710 } |
2699 | 2711 |
2700 | 2712 |
2701 // Recursively build an if/else structure to match the cases. | 2713 // Recursively build an if/else structure to match the cases. |
2702 buildSwitchCases(Link<Node> cases, HInstruction expression) { | 2714 buildSwitchCases(Link<Node> cases, HInstruction expression) { |
2703 SwitchCase node = cases.head; | 2715 SwitchCase node = cases.head; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2748 left(); | 2760 left(); |
2749 return; | 2761 return; |
2750 } | 2762 } |
2751 | 2763 |
2752 void right() { | 2764 void right() { |
2753 buildTests(remainingExpressions.tail); | 2765 buildTests(remainingExpressions.tail); |
2754 } | 2766 } |
2755 handleLogicalAndOr(left, right, isAnd: false); | 2767 handleLogicalAndOr(left, right, isAnd: false); |
2756 } | 2768 } |
2757 | 2769 |
2758 buildTests(expressions); | |
2759 HInstruction result = popBoolified(); | |
2760 | |
2761 if (node.isDefaultCase) { | 2770 if (node.isDefaultCase) { |
2762 // Don't actually use the condition result. | 2771 buildTests(expressions); |
2763 // This must be final case, so don't check for abort. | 2772 // Throw away the test result. We always execute the default case. |
| 2773 pop(); |
2764 visit(node.statements); | 2774 visit(node.statements); |
2765 } else { | 2775 } else { |
2766 stack.add(result); | |
2767 if (cases.tail.isEmpty()) { | 2776 if (cases.tail.isEmpty()) { |
2768 handleIf(() { visit(node.statements); }, null); | 2777 handleIf(() { buildTests(expressions); }, |
| 2778 () { visit(node.statements); }, |
| 2779 null); |
2769 } else { | 2780 } else { |
2770 handleIf(() { visitStatementsAndAbort(); }, | 2781 handleIf(() { buildTests(expressions); }, |
| 2782 () { visitStatementsAndAbort(); }, |
2771 () { buildSwitchCases(cases.tail, expression); }); | 2783 () { buildSwitchCases(cases.tail, expression); }); |
2772 } | 2784 } |
2773 } | 2785 } |
2774 } | 2786 } |
2775 | 2787 |
2776 visitSwitchCase(SwitchCase node) { | 2788 visitSwitchCase(SwitchCase node) { |
2777 unreachable(); | 2789 unreachable(); |
2778 } | 2790 } |
2779 | 2791 |
2780 visitTryStatement(TryStatement node) { | 2792 visitTryStatement(TryStatement node) { |
2781 work.allowSpeculativeOptimization = false; | 2793 work.allowSpeculativeOptimization = false; |
2782 HBasicBlock enterBlock = graph.addNewBlock(); | 2794 HBasicBlock enterBlock = openNewBlock(); |
2783 close(new HGoto()).addSuccessor(enterBlock); | |
2784 open(enterBlock); | |
2785 HTry tryInstruction = new HTry(); | 2795 HTry tryInstruction = new HTry(); |
2786 List<HBasicBlock> blocks = <HBasicBlock>[]; | 2796 List<HBasicBlock> blocks = <HBasicBlock>[]; |
2787 blocks.add(close(tryInstruction)); | 2797 blocks.add(close(tryInstruction)); |
2788 | 2798 |
2789 HBasicBlock tryBody = graph.addNewBlock(); | 2799 HBasicBlock tryBody = graph.addNewBlock(); |
2790 enterBlock.addSuccessor(tryBody); | 2800 enterBlock.addSuccessor(tryBody); |
2791 open(tryBody); | 2801 open(tryBody); |
2792 visit(node.tryBlock); | 2802 visit(node.tryBlock); |
2793 if (!isAborted()) blocks.add(close(new HGoto())); | 2803 if (!isAborted()) blocks.add(close(new HGoto())); |
2794 | 2804 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2842 localsHandler.updateLocal(elements[trace], traceInstruction); | 2852 localsHandler.updateLocal(elements[trace], traceInstruction); |
2843 } | 2853 } |
2844 visit(catchBlock); | 2854 visit(catchBlock); |
2845 } | 2855 } |
2846 | 2856 |
2847 void visitElse() { | 2857 void visitElse() { |
2848 if (link.isEmpty()) { | 2858 if (link.isEmpty()) { |
2849 close(new HThrow(exception, isRethrow: true)); | 2859 close(new HThrow(exception, isRethrow: true)); |
2850 } else { | 2860 } else { |
2851 CatchBlock newBlock = link.head; | 2861 CatchBlock newBlock = link.head; |
2852 pushCondition(newBlock); | 2862 handleIf(() { pushCondition(newBlock); }, |
2853 handleIf(visitThen, visitElse); | 2863 visitThen, visitElse); |
2854 } | 2864 } |
2855 } | 2865 } |
2856 | 2866 |
2857 CatchBlock firstBlock = link.head; | 2867 CatchBlock firstBlock = link.head; |
2858 pushCondition(firstBlock); | 2868 handleIf(() { pushCondition(firstBlock); }, visitThen, visitElse); |
2859 handleIf(visitThen, visitElse); | |
2860 if (!isAborted()) blocks.add(close(new HGoto())); | 2869 if (!isAborted()) blocks.add(close(new HGoto())); |
2861 rethrowableException = oldRethrowableException; | 2870 rethrowableException = oldRethrowableException; |
2862 } | 2871 } |
2863 | 2872 |
2864 if (node.finallyBlock != null) { | 2873 if (node.finallyBlock != null) { |
2865 HBasicBlock finallyBlock = graph.addNewBlock(); | 2874 HBasicBlock finallyBlock = graph.addNewBlock(); |
2866 enterBlock.addSuccessor(finallyBlock); | 2875 enterBlock.addSuccessor(finallyBlock); |
2867 open(finallyBlock); | 2876 open(finallyBlock); |
2868 visit(node.finallyBlock); | 2877 visit(node.finallyBlock); |
2869 if (!isAborted()) blocks.add(close(new HGoto())); | 2878 if (!isAborted()) blocks.add(close(new HGoto())); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2904 // calling [add] does not work as it asserts that the instruction | 2913 // calling [add] does not work as it asserts that the instruction |
2905 // isn't a control flow instruction. So we inline parts of [add]. | 2914 // isn't a control flow instruction. So we inline parts of [add]. |
2906 current.addAfter(current.last, new HThrow(message)); | 2915 current.addAfter(current.last, new HThrow(message)); |
2907 if (isExpression) { | 2916 if (isExpression) { |
2908 stack.add(graph.addConstantNull()); | 2917 stack.add(graph.addConstantNull()); |
2909 } | 2918 } |
2910 } | 2919 } |
2911 | 2920 |
2912 /** HACK HACK HACK */ | 2921 /** HACK HACK HACK */ |
2913 void hackAroundPossiblyAbortingBody(Node statement, void body()) { | 2922 void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
2914 stack.add(graph.addConstantBool(true)); | 2923 visitCondition() { |
| 2924 stack.add(graph.addConstantBool(true)); |
| 2925 } |
2915 buildBody() { | 2926 buildBody() { |
2916 // TODO(lrn): Make sure to take continue into account. | 2927 // TODO(lrn): Make sure to take continue into account. |
2917 body(); | 2928 body(); |
2918 if (isAborted()) { | 2929 if (isAborted()) { |
2919 compiler.reportWarning(statement, "aborting loop body"); | 2930 compiler.reportWarning(statement, "aborting loop body"); |
2920 } | 2931 } |
2921 } | 2932 } |
2922 handleIf(buildBody, null); | 2933 handleIf(visitCondition, buildBody, null); |
2923 } | 2934 } |
2924 } | 2935 } |
2925 | 2936 |
2926 /** | 2937 /** |
2927 * Visitor that handles generation of string literals (LiteralString, | 2938 * Visitor that handles generation of string literals (LiteralString, |
2928 * StringInterpolation), and otherwise delegates to the given visitor for | 2939 * StringInterpolation), and otherwise delegates to the given visitor for |
2929 * non-literal subexpressions. | 2940 * non-literal subexpressions. |
2930 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 2941 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
2931 * expressions as well. | 2942 * expressions as well. |
2932 */ | 2943 */ |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3074 false, | 3085 false, |
3075 <HInstruction>[target, input])); | 3086 <HInstruction>[target, input])); |
3076 return builder.pop(); | 3087 return builder.pop(); |
3077 } | 3088 } |
3078 | 3089 |
3079 HInstruction result() { | 3090 HInstruction result() { |
3080 flushLiterals(); | 3091 flushLiterals(); |
3081 return prefix; | 3092 return prefix; |
3082 } | 3093 } |
3083 } | 3094 } |
OLD | NEW |