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