| 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 |