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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 | 999 |
1000 void goto(HBasicBlock from, HBasicBlock to) { | 1000 void goto(HBasicBlock from, HBasicBlock to) { |
1001 from.close(new HGoto()); | 1001 from.close(new HGoto()); |
1002 from.addSuccessor(to); | 1002 from.addSuccessor(to); |
1003 } | 1003 } |
1004 | 1004 |
1005 bool isAborted() { | 1005 bool isAborted() { |
1006 return current === null; | 1006 return current === null; |
1007 } | 1007 } |
1008 | 1008 |
1009 /** | |
1010 * Creates a new block, transitions to it from any current block, and | |
1011 * opens the new block. | |
1012 */ | |
1013 HBasicBlock openNewBlock() { | |
1014 HBasicBlock newBlock = addNewBlock(); | |
1015 if (!isAborted()) goto(current, newBlock); | |
1016 open(newBlock); | |
1017 return newBlock; | |
1018 } | |
1019 | |
1009 void add(HInstruction instruction) { | 1020 void add(HInstruction instruction) { |
1010 current.add(instruction); | 1021 current.add(instruction); |
1011 } | 1022 } |
1012 | 1023 |
1013 void push(HInstruction instruction) { | 1024 void push(HInstruction instruction) { |
1014 add(instruction); | 1025 add(instruction); |
1015 stack.add(instruction); | 1026 stack.add(instruction); |
1016 } | 1027 } |
1017 | 1028 |
1018 HInstruction pop() { | 1029 HInstruction pop() { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1115 // loop-entry: | 1126 // loop-entry: |
1116 // if (!<condition>) goto loop-exit; | 1127 // if (!<condition>) goto loop-exit; |
1117 // <body> | 1128 // <body> |
1118 // <updates> | 1129 // <updates> |
1119 // goto loop-entry; | 1130 // goto loop-entry; |
1120 // loop-exit: | 1131 // loop-exit: |
1121 | 1132 |
1122 localsHandler.startLoop(loop); | 1133 localsHandler.startLoop(loop); |
1123 | 1134 |
1124 // The initializer. | 1135 // The initializer. |
1125 HBasicBlock initializerBlock = graph.addNewBlock(); | 1136 HBasicBlock initializerBlock = openNewBlock(); |
1126 goto(current, initializerBlock); | |
1127 open(initializerBlock); | |
1128 initialize(); | 1137 initialize(); |
1129 assert(!isAborted()); | 1138 assert(!isAborted()); |
1130 SubGraph initializerGraph = new SubGraph(initializerBlock, current); | 1139 SubGraph initializerGraph = new SubGraph(initializerBlock, current); |
1131 | 1140 |
1132 JumpHandler jumpHandler = beginLoopHeader(loop); | 1141 JumpHandler jumpHandler = beginLoopHeader(loop); |
1133 HBasicBlock conditionBlock = current; | 1142 HBasicBlock conditionBlock = current; |
1134 HLoopInformation loopInfo = current.loopInformation; | 1143 HLoopInformation loopInfo = current.blockInformation; |
1135 // The initializer graph is currently unused due to the way we | 1144 // The initializer graph is currently unused due to the way we |
1136 // generate code. | 1145 // generate code. |
1137 loopInfo.initializer = initializerGraph; | 1146 loopInfo.initializer = initializerGraph; |
1138 | 1147 |
1139 HInstruction conditionInstruction = condition(); | 1148 HInstruction conditionInstruction = condition(); |
1140 HBasicBlock conditionExitBlock = | 1149 HBasicBlock conditionExitBlock = |
1141 close(new HLoopBranch(conditionInstruction)); | 1150 close(new HLoopBranch(conditionInstruction)); |
1142 loopInfo.condition = new SubExpression(conditionBlock, | 1151 loopInfo.condition = new SubExpression(conditionBlock, |
1143 conditionExitBlock, | 1152 conditionExitBlock, |
1144 conditionInstruction); | 1153 conditionInstruction); |
(...skipping 27 matching lines...) Expand all Loading... | |
1172 continueLocals.add(localsHandler); | 1181 continueLocals.add(localsHandler); |
1173 | 1182 |
1174 open(updateBlock); | 1183 open(updateBlock); |
1175 | 1184 |
1176 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); | 1185 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); |
1177 | 1186 |
1178 HLabeledBlockInformation labelInfo; | 1187 HLabeledBlockInformation labelInfo; |
1179 List<LabelElement> labels = jumpHandler.labels(); | 1188 List<LabelElement> labels = jumpHandler.labels(); |
1180 TargetElement target = elements[loop]; | 1189 TargetElement target = elements[loop]; |
1181 if (!labels.isEmpty()) { | 1190 if (!labels.isEmpty()) { |
1182 beginBodyBlock.labeledBlockInformation = | 1191 beginBodyBlock.blockInformation = |
1183 new HLabeledBlockInformation(bodyGraph, updateBlock, | 1192 new HLabeledBlockInformation(bodyGraph, updateBlock, |
1184 jumpHandler.labels(), isContinue: true); | 1193 jumpHandler.labels(), isContinue: true); |
1185 } else if (target !== null && target.isContinueTarget) { | 1194 } else if (target !== null && target.isContinueTarget) { |
1186 beginBodyBlock.labeledBlockInformation = | 1195 beginBodyBlock.blockInformation = |
1187 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, | 1196 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, |
1188 target, isContinue: true); | 1197 target, isContinue: true); |
1189 } | 1198 } |
1190 | 1199 |
1191 localsHandler.enterLoopUpdates(loop); | 1200 localsHandler.enterLoopUpdates(loop); |
1192 | 1201 |
1193 update(); | 1202 update(); |
1194 | 1203 |
1195 HBasicBlock updateEndBlock = close(new HGoto()); | 1204 HBasicBlock updateEndBlock = close(new HGoto()); |
1196 // The back-edge completing the cycle. | 1205 // The back-edge completing the cycle. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1245 () {}, | 1254 () {}, |
1246 buildCondition, | 1255 buildCondition, |
1247 () {}, | 1256 () {}, |
1248 () { visit(node.body); }); | 1257 () { visit(node.body); }); |
1249 } | 1258 } |
1250 | 1259 |
1251 visitDoWhile(DoWhile node) { | 1260 visitDoWhile(DoWhile node) { |
1252 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1261 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1253 localsHandler.startLoop(node); | 1262 localsHandler.startLoop(node); |
1254 JumpHandler jumpHandler = beginLoopHeader(node); | 1263 JumpHandler jumpHandler = beginLoopHeader(node); |
1255 HLoopInformation loopInfo = current.loopInformation; | 1264 HLoopInformation loopInfo = current.blockInformation; |
1256 HBasicBlock loopEntryBlock = current; | 1265 HBasicBlock loopEntryBlock = current; |
1257 HBasicBlock bodyEntryBlock = current; | 1266 HBasicBlock bodyEntryBlock = current; |
1258 TargetElement target = elements[node]; | 1267 TargetElement target = elements[node]; |
1259 bool hasContinues = target !== null && target.isContinueTarget; | 1268 bool hasContinues = target !== null && target.isContinueTarget; |
1260 if (hasContinues) { | 1269 if (hasContinues) { |
1261 // Add extra block to hang labels on. | 1270 // Add extra block to hang labels on. |
1262 // It doesn't currently work if they are on the same block as the | 1271 // It doesn't currently work if they are on the same block as the |
1263 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1272 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
1264 // SubGraph that starts at the same block again, so the HLoopInfo is | 1273 // SubGraph that starts at the same block again, so the HLoopInfo is |
1265 // either handled twice, or it's handled after the labeled block info, | 1274 // either handled twice, or it's handled after the labeled block info, |
1266 // both of which generate the wrong code. | 1275 // both of which generate the wrong code. |
1267 // Using a separate block is just a simple workaround. | 1276 // Using a separate block is just a simple workaround. |
1268 bodyEntryBlock = graph.addNewBlock(); | 1277 bodyEntryBlock = openNewBlock(); |
1269 goto(current, bodyEntryBlock); | |
1270 open(bodyEntryBlock); | |
1271 } | 1278 } |
1272 localsHandler.enterLoopBody(node); | 1279 localsHandler.enterLoopBody(node); |
1273 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); | 1280 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); |
1274 | 1281 |
1275 // If there are no continues we could avoid the creation of the condition | 1282 // If there are no continues we could avoid the creation of the condition |
1276 // block. This could also lead to a block having multiple entries and exits. | 1283 // block. This could also lead to a block having multiple entries and exits. |
1277 HBasicBlock bodyExitBlock = close(new HGoto()); | 1284 HBasicBlock bodyExitBlock = close(new HGoto()); |
1278 HBasicBlock conditionBlock = addNewBlock(); | 1285 HBasicBlock conditionBlock = addNewBlock(); |
1279 | 1286 |
1280 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1287 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
1281 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1288 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
1282 instruction.block.addSuccessor(conditionBlock); | 1289 instruction.block.addSuccessor(conditionBlock); |
1283 continueLocals.add(locals); | 1290 continueLocals.add(locals); |
1284 }); | 1291 }); |
1285 bodyExitBlock.addSuccessor(conditionBlock); | 1292 bodyExitBlock.addSuccessor(conditionBlock); |
1286 if (!continueLocals.isEmpty()) { | 1293 if (!continueLocals.isEmpty()) { |
1287 continueLocals.add(localsHandler); | 1294 continueLocals.add(localsHandler); |
1288 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); | 1295 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); |
1289 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1296 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
1290 List<LabelElement> labels = jumpHandler.labels(); | 1297 List<LabelElement> labels = jumpHandler.labels(); |
1291 if (!labels.isEmpty()) { | 1298 if (!labels.isEmpty()) { |
1292 bodyEntryBlock.labeledBlockInformation = | 1299 bodyEntryBlock.blockInformation = |
1293 new HLabeledBlockInformation(bodyGraph, | 1300 new HLabeledBlockInformation(bodyGraph, |
1294 conditionBlock, | 1301 conditionBlock, |
1295 labels, | 1302 labels, |
1296 isContinue: true); | 1303 isContinue: true); |
1297 } else { | 1304 } else { |
1298 bodyEntryBlock.labeledBlockInformation = | 1305 bodyEntryBlock.blockInformation = |
1299 new HLabeledBlockInformation.implicit(bodyGraph, | 1306 new HLabeledBlockInformation.implicit(bodyGraph, |
1300 conditionBlock, | 1307 conditionBlock, |
1301 target, | 1308 target, |
1302 isContinue: true); | 1309 isContinue: true); |
1303 } | 1310 } |
1304 } | 1311 } |
1305 open(conditionBlock); | 1312 open(conditionBlock); |
1306 | 1313 |
1307 visit(node.condition); | 1314 visit(node.condition); |
1308 assert(!isAborted()); | 1315 assert(!isAborted()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1359 | 1366 |
1360 visitIdentifier(Identifier node) { | 1367 visitIdentifier(Identifier node) { |
1361 if (node.isThis()) { | 1368 if (node.isThis()) { |
1362 stack.add(localsHandler.readThis()); | 1369 stack.add(localsHandler.readThis()); |
1363 } else { | 1370 } else { |
1364 compiler.internalError("SsaBuilder.visitIdentifier on non-this", | 1371 compiler.internalError("SsaBuilder.visitIdentifier on non-this", |
1365 node: node); | 1372 node: node); |
1366 } | 1373 } |
1367 } | 1374 } |
1368 | 1375 |
1369 visitIf(If node) { | 1376 visitIf(If node) { |
ngeoffray
2012/04/17 07:44:20
You can remove the five lines below
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Well spotted.
| |
1370 visit(node.condition); | |
1371 Function visitElse; | 1377 Function visitElse; |
1372 if (node.elsePart != null) { | 1378 if (node.elsePart != null) { |
1373 visitElse = () { | 1379 visitElse = () { |
1374 visit(node.elsePart); | 1380 visit(node.elsePart); |
1375 }; | 1381 }; |
1376 } | 1382 } |
1377 handleIf(() => visit(node.thenPart), visitElse); | 1383 handleIf(() => visit(node.condition), |
1384 () => visit(node.thenPart), | |
1385 node.elsePart != null ? () => visit(node.elsePart) : null); | |
1378 } | 1386 } |
1379 | 1387 |
1380 void handleIf(void visitThen(), void visitElse()) { | 1388 void handleIf(void visitCondition(), void visitThen(), void visitElse()) { |
1389 HBasicBlock conditionStartBlock = openNewBlock(); | |
1390 visitCondition(); | |
1391 SubExpression conditionGraph = | |
1392 new SubExpression(conditionStartBlock, lastOpenedBlock, stack.last()); | |
1381 bool hasElse = visitElse != null; | 1393 bool hasElse = visitElse != null; |
1382 HIf condition = new HIf(popBoolified(), hasElse); | 1394 HInstruction condition = popBoolified(); |
1383 HBasicBlock conditionBlock = close(condition); | 1395 HBasicBlock conditionBlock = close(new HIf(condition, hasElse)); |
1384 | 1396 |
1385 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1397 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1386 | 1398 |
1387 // The then part. | 1399 // The then part. |
1388 HBasicBlock thenBlock = addNewBlock(); | 1400 HBasicBlock thenBlock = addNewBlock(); |
1389 conditionBlock.addSuccessor(thenBlock); | 1401 conditionBlock.addSuccessor(thenBlock); |
1390 open(thenBlock); | 1402 open(thenBlock); |
1391 visitThen(); | 1403 visitThen(); |
1392 SubGraph thenGraph = new SubGraph(thenBlock, lastOpenedBlock); | 1404 SubGraph thenGraph = new SubGraph(thenBlock, lastOpenedBlock); |
1393 thenBlock = current; | 1405 thenBlock = current; |
(...skipping 27 matching lines...) Expand all Loading... | |
1421 // with the set of locals we got after visiting the then | 1433 // with the set of locals we got after visiting the then |
1422 // part of the if. | 1434 // part of the if. |
1423 open(joinBlock); | 1435 open(joinBlock); |
1424 if (joinBlock.predecessors.length == 2) { | 1436 if (joinBlock.predecessors.length == 2) { |
1425 localsHandler.mergeWith(thenLocals, joinBlock); | 1437 localsHandler.mergeWith(thenLocals, joinBlock); |
1426 } else if (thenBlock !== null) { | 1438 } else if (thenBlock !== null) { |
1427 // The only predecessor is the then branch. | 1439 // The only predecessor is the then branch. |
1428 localsHandler = thenLocals; | 1440 localsHandler = thenLocals; |
1429 } | 1441 } |
1430 } | 1442 } |
1431 condition.blockInformation = | 1443 HIfBlockInformation info = new HIfBlockInformation(conditionGraph, |
1432 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); | 1444 thenGraph, |
1445 elseGraph, | |
1446 joinBlock); | |
1447 conditionStartBlock.blockInformation = info; | |
1448 conditionBlock.last.blockInformation = info; | |
1433 } | 1449 } |
1434 | 1450 |
1435 void visitLogicalAndOr(Send node, Operator op) { | 1451 void visitLogicalAndOr(Send node, Operator op) { |
1436 handleLogicalAndOr(() { visit(node.receiver); }, | 1452 handleLogicalAndOr(() { visit(node.receiver); }, |
1437 () { visit(node.argumentsNode); }, | 1453 () { visit(node.argumentsNode); }, |
1438 isAnd: (const SourceString("&&") == op.source)); | 1454 isAnd: (const SourceString("&&") == op.source)); |
1439 } | 1455 } |
1440 | 1456 |
1441 | 1457 |
1442 void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) { | 1458 void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) { |
1443 // x && y is transformed into: | 1459 // x && y is transformed into: |
1444 // t0 = boolify(x); | 1460 // t0 = boolify(x); |
1445 // if (t0) t1 = boolify(y); | 1461 // if (t0) t1 = boolify(y); |
1446 // result = phi(t0, t1); | 1462 // result = phi(t0, t1); |
1447 // | 1463 // |
1448 // x || y is transformed into: | 1464 // x || y is transformed into: |
1449 // t0 = boolify(x); | 1465 // t0 = boolify(x); |
1450 // if (not(t0)) t1 = boolify(y); | 1466 // if (not(t0)) t1 = boolify(y); |
1451 // result = phi(t0, t1); | 1467 // result = phi(t0, t1); |
1468 HBasicBlock leftBlock = openNewBlock(); | |
1452 left(); | 1469 left(); |
1453 HInstruction boolifiedLeft = popBoolified(); | 1470 HInstruction boolifiedLeft = popBoolified(); |
1454 HInstruction condition; | 1471 HInstruction condition; |
1455 if (isAnd) { | 1472 if (isAnd) { |
1456 condition = boolifiedLeft; | 1473 condition = boolifiedLeft; |
1457 } else { | 1474 } else { |
1458 condition = new HNot(boolifiedLeft); | 1475 condition = new HNot(boolifiedLeft); |
1459 add(condition); | 1476 add(condition); |
1460 } | 1477 } |
1478 SubExpression leftGraph = | |
1479 new SubExpression(leftBlock, lastOpenedBlock, boolifiedLeft); | |
1461 HIf branch = new HIf(condition, false); | 1480 HIf branch = new HIf(condition, false); |
1462 HBasicBlock leftBlock = close(branch); | 1481 leftBlock = close(branch); |
1463 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1482 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
1464 | 1483 |
1465 HBasicBlock rightBlock = addNewBlock(); | 1484 HBasicBlock rightBlock = addNewBlock(); |
1466 leftBlock.addSuccessor(rightBlock); | 1485 leftBlock.addSuccessor(rightBlock); |
1467 open(rightBlock); | 1486 open(rightBlock); |
1468 | 1487 |
1469 right(); | 1488 right(); |
1470 HInstruction boolifiedRight = popBoolified(); | 1489 HInstruction boolifiedRight = popBoolified(); |
1471 SubGraph rightGraph = new SubGraph(rightBlock, current); | 1490 SubExpression rightGraph = |
1491 new SubExpression(rightBlock, current, boolifiedRight); | |
1472 rightBlock = close(new HGoto()); | 1492 rightBlock = close(new HGoto()); |
1473 | 1493 |
1474 HBasicBlock joinBlock = addNewBlock(); | 1494 HBasicBlock joinBlock = addNewBlock(); |
1475 leftBlock.addSuccessor(joinBlock); | 1495 leftBlock.addSuccessor(joinBlock); |
1476 rightBlock.addSuccessor(joinBlock); | 1496 rightBlock.addSuccessor(joinBlock); |
1477 open(joinBlock); | 1497 open(joinBlock); |
1478 | 1498 |
1499 leftGraph.start.blockInformation = | |
1500 new HAndOrBlockInformation(isAnd, leftGraph, rightGraph, joinBlock); | |
1479 branch.blockInformation = | 1501 branch.blockInformation = |
1480 new HIfBlockInformation(branch, rightGraph, null, joinBlock); | 1502 new HIfBlockInformation(leftGraph, rightGraph, null, joinBlock); |
1481 | 1503 |
1482 localsHandler.mergeWith(savedLocals, joinBlock); | 1504 localsHandler.mergeWith(savedLocals, joinBlock); |
1483 HPhi result = new HPhi.manyInputs(null, | 1505 HPhi result = new HPhi.manyInputs(null, |
1484 <HInstruction>[boolifiedLeft, boolifiedRight]); | 1506 <HInstruction>[boolifiedLeft, boolifiedRight]); |
1485 joinBlock.addPhi(result); | 1507 joinBlock.addPhi(result); |
1486 stack.add(result); | 1508 stack.add(result); |
1487 } | 1509 } |
1488 | 1510 |
1489 void visitLogicalNot(Send node) { | 1511 void visitLogicalNot(Send node) { |
1490 assert(node.argumentsNode is Prefix); | 1512 assert(node.argumentsNode is Prefix); |
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2527 // A different target statement only happens if the body is itself | 2549 // A different target statement only happens if the body is itself |
2528 // a break or continue for a different target. In that case, this | 2550 // a break or continue for a different target. In that case, this |
2529 // label is also always unused. | 2551 // label is also always unused. |
2530 visit(body); | 2552 visit(body); |
2531 return; | 2553 return; |
2532 } | 2554 } |
2533 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 2555 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
2534 assert(targetElement.isBreakTarget); | 2556 assert(targetElement.isBreakTarget); |
2535 JumpHandler handler = new JumpHandler(this, targetElement); | 2557 JumpHandler handler = new JumpHandler(this, targetElement); |
2536 // Introduce a new basic block. | 2558 // Introduce a new basic block. |
2537 HBasicBlock entryBlock = graph.addNewBlock(); | 2559 HBasicBlock entryBlock = openNewBlock(); |
2538 goto(current, entryBlock); | |
2539 open(entryBlock); | |
2540 hackAroundPossiblyAbortingBody(node, () { visit(body); }); | 2560 hackAroundPossiblyAbortingBody(node, () { visit(body); }); |
2541 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); | 2561 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
2542 | 2562 |
2543 HBasicBlock joinBlock = graph.addNewBlock(); | 2563 HBasicBlock joinBlock = graph.addNewBlock(); |
2544 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 2564 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
2545 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 2565 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
2546 breakInstruction.block.addSuccessor(joinBlock); | 2566 breakInstruction.block.addSuccessor(joinBlock); |
2547 breakLocals.add(locals); | 2567 breakLocals.add(locals); |
2548 }); | 2568 }); |
2549 bool hasBreak = breakLocals.length > 0; | 2569 bool hasBreak = breakLocals.length > 0; |
2550 if (!isAborted()) { | 2570 if (!isAborted()) { |
2551 goto(current, joinBlock); | 2571 goto(current, joinBlock); |
2552 breakLocals.add(localsHandler); | 2572 breakLocals.add(localsHandler); |
2553 } | 2573 } |
2554 open(joinBlock); | 2574 open(joinBlock); |
2555 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); | 2575 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); |
2556 | 2576 |
2557 if (hasBreak) { | 2577 if (hasBreak) { |
2558 // There was at least one reachable break, so the label is needed. | 2578 // There was at least one reachable break, so the label is needed. |
2559 HLabeledBlockInformation blockInfo = | 2579 entryBlock.blockInformation = |
2560 new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); | 2580 new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); |
2561 entryBlock.labeledBlockInformation = blockInfo; | |
2562 } | 2581 } |
2563 handler.close(); | 2582 handler.close(); |
2564 } | 2583 } |
2565 | 2584 |
2566 visitLiteralMap(LiteralMap node) { | 2585 visitLiteralMap(LiteralMap node) { |
2567 if (node.isConst()) { | 2586 if (node.isConst()) { |
2568 ConstantHandler handler = compiler.constantHandler; | 2587 ConstantHandler handler = compiler.constantHandler; |
2569 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 2588 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
2570 stack.add(graph.addConstant(constant)); | 2589 stack.add(graph.addConstant(constant)); |
2571 return; | 2590 return; |
(...skipping 19 matching lines...) Expand all Loading... | |
2591 visit(node.key); | 2610 visit(node.key); |
2592 } | 2611 } |
2593 | 2612 |
2594 visitNamedArgument(NamedArgument node) { | 2613 visitNamedArgument(NamedArgument node) { |
2595 visit(node.expression); | 2614 visit(node.expression); |
2596 } | 2615 } |
2597 | 2616 |
2598 visitSwitchStatement(SwitchStatement node) { | 2617 visitSwitchStatement(SwitchStatement node) { |
2599 work.allowSpeculativeOptimization = false; | 2618 work.allowSpeculativeOptimization = false; |
2600 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 2619 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
2601 HBasicBlock startBlock = graph.addNewBlock(); | 2620 HBasicBlock startBlock = openNewBlock(); |
2602 goto(current, startBlock); | |
2603 open(startBlock); | |
2604 visit(node.expression); | 2621 visit(node.expression); |
2605 HInstruction expression = pop(); | 2622 HInstruction expression = pop(); |
2606 if (node.cases.isEmpty()) { | 2623 if (node.cases.isEmpty()) { |
2607 return; | 2624 return; |
2608 } | 2625 } |
2609 Link<Node> cases = node.cases.nodes; | 2626 Link<Node> cases = node.cases.nodes; |
2610 | 2627 |
2611 JumpHandler jumpHandler = createJumpHandler(node); | 2628 JumpHandler jumpHandler = createJumpHandler(node); |
2612 | 2629 |
2613 buildSwitchCases(cases, expression); | 2630 buildSwitchCases(cases, expression); |
(...skipping 19 matching lines...) Expand all Loading... | |
2633 open(joinBlock); | 2650 open(joinBlock); |
2634 if (caseLocals.length == 1) { | 2651 if (caseLocals.length == 1) { |
2635 localsHandler = caseLocals[0]; | 2652 localsHandler = caseLocals[0]; |
2636 } else { | 2653 } else { |
2637 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | 2654 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); |
2638 } | 2655 } |
2639 } else { | 2656 } else { |
2640 // The joinblock is not used. | 2657 // The joinblock is not used. |
2641 joinBlock = null; | 2658 joinBlock = null; |
2642 } | 2659 } |
2643 startBlock.labeledBlockInformation = new HLabeledBlockInformation.implicit( | 2660 startBlock.blockInformation = new HLabeledBlockInformation.implicit( |
2644 new SubGraph(startBlock, lastBlock), | 2661 new SubGraph(startBlock, lastBlock), |
2645 joinBlock, | 2662 joinBlock, |
2646 elements[node]); | 2663 elements[node]); |
2647 jumpHandler.close(); | 2664 jumpHandler.close(); |
2648 } | 2665 } |
2649 | 2666 |
2650 | 2667 |
2651 // Recursively build an if/else structure to match the cases. | 2668 // Recursively build an if/else structure to match the cases. |
2652 buildSwitchCases(Link<Node> cases, HInstruction expression) { | 2669 buildSwitchCases(Link<Node> cases, HInstruction expression) { |
2653 SwitchCase node = cases.head; | 2670 SwitchCase node = cases.head; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2698 left(); | 2715 left(); |
2699 return; | 2716 return; |
2700 } | 2717 } |
2701 | 2718 |
2702 void right() { | 2719 void right() { |
2703 buildTests(expressions.tail); | 2720 buildTests(expressions.tail); |
2704 } | 2721 } |
2705 handleLogicalAndOr(left, right, isAnd: false); | 2722 handleLogicalAndOr(left, right, isAnd: false); |
2706 } | 2723 } |
2707 | 2724 |
2708 buildTests(expressions); | |
2709 HInstruction result = popBoolified(); | |
2710 | |
2711 if (node.isDefaultCase) { | 2725 if (node.isDefaultCase) { |
2712 // Don't actually use the condition result. | 2726 // Don't actually bother testing the expressions. |
ngeoffray
2012/04/17 07:44:20
The comment and the line below don't seem to match
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Reworded.
| |
2713 // This must be final case, so don't check for abort. | 2727 buildTests(expressions); |
2728 pop(); | |
2714 visit(node.statements); | 2729 visit(node.statements); |
2715 } else { | 2730 } else { |
2716 stack.add(result); | |
2717 if (cases.tail.isEmpty()) { | 2731 if (cases.tail.isEmpty()) { |
2718 handleIf(() { visit(node.statements); }, null); | 2732 handleIf(() { buildTests(expressions); }, |
2733 () { visit(node.statements); }, | |
2734 null); | |
2719 } else { | 2735 } else { |
2720 handleIf(() { visitStatementsAndAbort(); }, | 2736 handleIf(() { buildTests(expressions); }, |
2737 () { visitStatementsAndAbort(); }, | |
2721 () { buildSwitchCases(cases.tail, expression); }); | 2738 () { buildSwitchCases(cases.tail, expression); }); |
2722 } | 2739 } |
2723 } | 2740 } |
2724 } | 2741 } |
2725 | 2742 |
2726 visitSwitchCase(SwitchCase node) { | 2743 visitSwitchCase(SwitchCase node) { |
2727 unreachable(); | 2744 unreachable(); |
2728 } | 2745 } |
2729 | 2746 |
2730 visitTryStatement(TryStatement node) { | 2747 visitTryStatement(TryStatement node) { |
2731 work.allowSpeculativeOptimization = false; | 2748 work.allowSpeculativeOptimization = false; |
2732 HBasicBlock enterBlock = graph.addNewBlock(); | 2749 HBasicBlock enterBlock = openNewBlock(); |
2733 close(new HGoto()).addSuccessor(enterBlock); | |
2734 open(enterBlock); | |
2735 HTry tryInstruction = new HTry(); | 2750 HTry tryInstruction = new HTry(); |
2736 List<HBasicBlock> blocks = <HBasicBlock>[]; | 2751 List<HBasicBlock> blocks = <HBasicBlock>[]; |
2737 blocks.add(close(tryInstruction)); | 2752 blocks.add(close(tryInstruction)); |
2738 | 2753 |
2739 HBasicBlock tryBody = graph.addNewBlock(); | 2754 HBasicBlock tryBody = graph.addNewBlock(); |
2740 enterBlock.addSuccessor(tryBody); | 2755 enterBlock.addSuccessor(tryBody); |
2741 open(tryBody); | 2756 open(tryBody); |
2742 visit(node.tryBlock); | 2757 visit(node.tryBlock); |
2743 if (!isAborted()) blocks.add(close(new HGoto())); | 2758 if (!isAborted()) blocks.add(close(new HGoto())); |
2744 | 2759 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2792 localsHandler.updateLocal(elements[trace], traceInstruction); | 2807 localsHandler.updateLocal(elements[trace], traceInstruction); |
2793 } | 2808 } |
2794 visit(catchBlock); | 2809 visit(catchBlock); |
2795 } | 2810 } |
2796 | 2811 |
2797 void visitElse() { | 2812 void visitElse() { |
2798 if (link.isEmpty()) { | 2813 if (link.isEmpty()) { |
2799 close(new HThrow(exception, isRethrow: true)); | 2814 close(new HThrow(exception, isRethrow: true)); |
2800 } else { | 2815 } else { |
2801 CatchBlock newBlock = link.head; | 2816 CatchBlock newBlock = link.head; |
2802 pushCondition(newBlock); | 2817 handleIf(() { pushCondition(newBlock); }, |
2803 handleIf(visitThen, visitElse); | 2818 visitThen, visitElse); |
2804 } | 2819 } |
2805 } | 2820 } |
2806 | 2821 |
2807 CatchBlock firstBlock = link.head; | 2822 CatchBlock firstBlock = link.head; |
2808 pushCondition(firstBlock); | 2823 handleIf(() { pushCondition(firstBlock); }, visitThen, visitElse); |
2809 handleIf(visitThen, visitElse); | |
2810 if (!isAborted()) blocks.add(close(new HGoto())); | 2824 if (!isAborted()) blocks.add(close(new HGoto())); |
2811 rethrowableException = oldRethrowableException; | 2825 rethrowableException = oldRethrowableException; |
2812 } | 2826 } |
2813 | 2827 |
2814 if (node.finallyBlock != null) { | 2828 if (node.finallyBlock != null) { |
2815 HBasicBlock finallyBlock = graph.addNewBlock(); | 2829 HBasicBlock finallyBlock = graph.addNewBlock(); |
2816 enterBlock.addSuccessor(finallyBlock); | 2830 enterBlock.addSuccessor(finallyBlock); |
2817 open(finallyBlock); | 2831 open(finallyBlock); |
2818 visit(node.finallyBlock); | 2832 visit(node.finallyBlock); |
2819 if (!isAborted()) blocks.add(close(new HGoto())); | 2833 if (!isAborted()) blocks.add(close(new HGoto())); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2854 // calling [add] does not work as it asserts that the instruction | 2868 // calling [add] does not work as it asserts that the instruction |
2855 // isn't a control flow instruction. So we inline parts of [add]. | 2869 // isn't a control flow instruction. So we inline parts of [add]. |
2856 current.addAfter(current.last, new HThrow(message)); | 2870 current.addAfter(current.last, new HThrow(message)); |
2857 if (isExpression) { | 2871 if (isExpression) { |
2858 stack.add(graph.addConstantNull()); | 2872 stack.add(graph.addConstantNull()); |
2859 } | 2873 } |
2860 } | 2874 } |
2861 | 2875 |
2862 /** HACK HACK HACK */ | 2876 /** HACK HACK HACK */ |
2863 void hackAroundPossiblyAbortingBody(Node statement, void body()) { | 2877 void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
2864 stack.add(graph.addConstantBool(true)); | 2878 visitCondition() { |
2879 stack.add(graph.addConstantBool(true)); | |
2880 } | |
2865 buildBody() { | 2881 buildBody() { |
2866 // TODO(lrn): Make sure to take continue into account. | 2882 // TODO(lrn): Make sure to take continue into account. |
2867 body(); | 2883 body(); |
2868 if (isAborted()) { | 2884 if (isAborted()) { |
2869 compiler.reportWarning(statement, "aborting loop body"); | 2885 compiler.reportWarning(statement, "aborting loop body"); |
2870 } | 2886 } |
2871 } | 2887 } |
2872 handleIf(buildBody, null); | 2888 handleIf(visitCondition, buildBody, null); |
2873 } | 2889 } |
2874 } | 2890 } |
2875 | 2891 |
2876 /** | 2892 /** |
2877 * Visitor that handles generation of string literals (LiteralString, | 2893 * Visitor that handles generation of string literals (LiteralString, |
2878 * StringInterpolation), and otherwise delegates to the given visitor for | 2894 * StringInterpolation), and otherwise delegates to the given visitor for |
2879 * non-literal subexpressions. | 2895 * non-literal subexpressions. |
2880 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 2896 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
2881 * expressions as well. | 2897 * expressions as well. |
2882 */ | 2898 */ |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3024 false, | 3040 false, |
3025 <HInstruction>[target, input])); | 3041 <HInstruction>[target, input])); |
3026 return builder.pop(); | 3042 return builder.pop(); |
3027 } | 3043 } |
3028 | 3044 |
3029 HInstruction result() { | 3045 HInstruction result() { |
3030 flushLiterals(); | 3046 flushLiterals(); |
3031 return prefix; | 3047 return prefix; |
3032 } | 3048 } |
3033 } | 3049 } |
OLD | NEW |