| 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 SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 8 | 8 |
| 9 String generate(WorkItem work, HGraph graph) { | 9 String generate(WorkItem work, HGraph graph) { |
| 10 return measure(() { | 10 return measure(() { |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 visit(HInstruction node, int expectedPrecedence) { | 240 visit(HInstruction node, int expectedPrecedence) { |
| 241 int oldPrecedence = this.expectedPrecedence; | 241 int oldPrecedence = this.expectedPrecedence; |
| 242 this.expectedPrecedence = expectedPrecedence; | 242 this.expectedPrecedence = expectedPrecedence; |
| 243 node.accept(this); | 243 node.accept(this); |
| 244 this.expectedPrecedence = oldPrecedence; | 244 this.expectedPrecedence = oldPrecedence; |
| 245 } | 245 } |
| 246 | 246 |
| 247 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 247 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 248 addIndentation(); | 248 addIndentation(); |
| 249 for (LabelElement label in labeledBlockInfo.labels) { | 249 for (LabelElement label in labeledBlockInfo.labels) { |
| 250 addLabel(label); | 250 if (labeledBlockInfo.isContinue) { |
| 251 addContinueLabel(label); |
| 252 } else { |
| 253 addBreakLabel(label); |
| 254 } |
| 251 buffer.add(':'); | 255 buffer.add(':'); |
| 252 } | 256 } |
| 253 TargetElement target = labeledBlockInfo.target; | 257 TargetElement target = labeledBlockInfo.target; |
| 254 if (target.isSwitch) { | 258 if (target.isSwitch) { |
| 255 addImplicitLabel(target); | 259 addImplicitBreakLabel(target); |
| 256 buffer.add(@':'); | 260 buffer.add(@':'); |
| 257 } | 261 } |
| 262 if (labeledBlockInfo.isContinue) { |
| 263 addImplicitContinueLabel(target); |
| 264 buffer.add(':'); |
| 265 } |
| 258 buffer.add('{\n'); | 266 buffer.add('{\n'); |
| 259 indent++; | 267 indent++; |
| 260 | 268 |
| 261 visitSubGraph(labeledBlockInfo.body); | 269 visitSubGraph(labeledBlockInfo.body); |
| 262 | 270 |
| 263 indent--; | 271 indent--; |
| 264 addIndentation(); | 272 addIndentation(); |
| 265 buffer.add('}\n'); | 273 buffer.add('}\n'); |
| 266 | 274 |
| 267 if (labeledBlockInfo.joinBlock !== null) { | 275 if (labeledBlockInfo.joinBlock !== null) { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 if (dominated.isEmpty()) return; | 434 if (dominated.isEmpty()) return; |
| 427 if (dominated.length > 2) unreachable(); | 435 if (dominated.length > 2) unreachable(); |
| 428 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { | 436 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { |
| 429 unreachable(); | 437 unreachable(); |
| 430 } | 438 } |
| 431 assert(dominated[0] == currentBlock.successors[0]); | 439 assert(dominated[0] == currentBlock.successors[0]); |
| 432 visitBasicBlock(dominated[0]); | 440 visitBasicBlock(dominated[0]); |
| 433 } | 441 } |
| 434 | 442 |
| 435 // Used to write the name of labels. | 443 // Used to write the name of labels. |
| 436 // The default implementation uses the unmodified Dart label name. | 444 void addBreakLabel(LabelElement label) { |
| 437 // Specializations might change this. | |
| 438 void addLabel(LabelElement label) { | |
| 439 buffer.add(@'$'); | 445 buffer.add(@'$'); |
| 440 buffer.add(label.labelName); | 446 buffer.add(label.labelName); |
| 441 } | 447 } |
| 442 | 448 |
| 443 void addImplicitLabel(TargetElement target) { | 449 void addContinueLabel(LabelElement label) { |
| 444 buffer.add('\$${target.nestingLevel}'); | 450 buffer.add(@'c$'); |
| 451 buffer.add(label.labelName); |
| 452 } |
| 453 |
| 454 void addImplicitBreakLabel(TargetElement target) { |
| 455 buffer.add(@'$'); |
| 456 buffer.add('${target.nestingLevel}'); |
| 457 } |
| 458 |
| 459 void addImplicitContinueLabel(TargetElement target) { |
| 460 buffer.add(@'c$'); |
| 461 buffer.add('${target.nestingLevel}'); |
| 445 } | 462 } |
| 446 | 463 |
| 447 visitBreak(HBreak node) { | 464 visitBreak(HBreak node) { |
| 448 assert(currentBlock.successors.length == 1); | 465 assert(currentBlock.successors.length == 1); |
| 449 addIndentation(); | 466 addIndentation(); |
| 450 buffer.add("break"); | 467 buffer.add("break"); |
| 451 if (node.label !== null) { | 468 if (node.label !== null) { |
| 452 buffer.add(" "); | 469 buffer.add(" "); |
| 453 addLabel(node.label); | 470 addBreakLabel(node.label); |
| 454 } else { | 471 } else { |
| 455 TargetElement target = node.target; | 472 TargetElement target = node.target; |
| 456 if (target.isSwitch) { | 473 if (target.isSwitch) { |
| 474 // We are wrapping switches in a labeled block so that we can |
| 475 // break from them even when they are implemented as if/else chains. |
| 476 // For that reason, we need to use a labeled break targeting the |
| 477 // "implicit" label we gave to the block. |
| 457 buffer.add(@' '); | 478 buffer.add(@' '); |
| 458 addImplicitLabel(target); | 479 addImplicitBreakLabel(target); |
| 459 } | 480 } |
| 460 } | 481 } |
| 461 buffer.add(";\n"); | 482 buffer.add(";\n"); |
| 462 // We never follow the break to its target, even if it dominates the | 483 } |
| 463 // break target block. That block is always handled by the structure | 484 |
| 464 // that introduced the break. | 485 visitContinue(HContinue node) { |
| 486 assert(currentBlock.successors.length == 1); |
| 487 addIndentation(); |
| 488 // We currently implement "continue" in a loop as a break of a block |
| 489 // containing the loop body. If we ever implement for-loops as such, |
| 490 // we should use a real continue. |
| 491 buffer.add("break "); |
| 492 if (node.label !== null) { |
| 493 addContinueLabel(node.label); |
| 494 } else { |
| 495 addImplicitContinueLabel(node.target); |
| 496 } |
| 497 buffer.add(";\n"); |
| 465 } | 498 } |
| 466 | 499 |
| 467 visitTry(HTry node) { | 500 visitTry(HTry node) { |
| 468 addIndentation(); | 501 addIndentation(); |
| 469 buffer.add('try {\n'); | 502 buffer.add('try {\n'); |
| 470 indent++; | 503 indent++; |
| 471 List<HBasicBlock> successors = node.block.successors; | 504 List<HBasicBlock> successors = node.block.successors; |
| 472 visitBasicBlock(successors[0]); | 505 visitBasicBlock(successors[0]); |
| 473 indent--; | 506 indent--; |
| 474 | 507 |
| (...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 buffer.add(')) '); | 1205 buffer.add(')) '); |
| 1173 bailout(node, 'Not a string or array'); | 1206 bailout(node, 'Not a string or array'); |
| 1174 } else { | 1207 } else { |
| 1175 unreachable(); | 1208 unreachable(); |
| 1176 } | 1209 } |
| 1177 } | 1210 } |
| 1178 | 1211 |
| 1179 void beginLoop(HBasicBlock block) { | 1212 void beginLoop(HBasicBlock block) { |
| 1180 addIndentation(); | 1213 addIndentation(); |
| 1181 for (LabelElement label in block.loopInformation.labels) { | 1214 for (LabelElement label in block.loopInformation.labels) { |
| 1182 addLabel(label); | 1215 addBreakLabel(label); |
| 1183 buffer.add(":"); | 1216 buffer.add(":"); |
| 1184 } | 1217 } |
| 1185 buffer.add('while (true) {\n'); | 1218 buffer.add('while (true) {\n'); |
| 1186 indent++; | 1219 indent++; |
| 1187 } | 1220 } |
| 1188 | 1221 |
| 1189 void endLoop(HBasicBlock block) { | 1222 void endLoop(HBasicBlock block) { |
| 1190 indent--; | 1223 indent--; |
| 1191 addIndentation(); | 1224 addIndentation(); |
| 1192 buffer.add('}\n'); // Close 'while' loop. | 1225 buffer.add('}\n'); // Close 'while' loop. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 indent++; | 1369 indent++; |
| 1337 } | 1370 } |
| 1338 | 1371 |
| 1339 void endBailoutSwitch() { | 1372 void endBailoutSwitch() { |
| 1340 indent--; // Close 'case'. | 1373 indent--; // Close 'case'. |
| 1341 indent--; | 1374 indent--; |
| 1342 addIndentation(); | 1375 addIndentation(); |
| 1343 buffer.add('}\n'); // Close 'switch'. | 1376 buffer.add('}\n'); // Close 'switch'. |
| 1344 } | 1377 } |
| 1345 | 1378 |
| 1346 // Adds a "$" in front of names of labels from the original source. | |
| 1347 // This avoids conflicts with labels introduced by bailouts, which | |
| 1348 // starts with a non-"$" character. | |
| 1349 void addLabel(LabelElement label) { | |
| 1350 buffer.add("\$${label.labelName}"); | |
| 1351 } | |
| 1352 | 1379 |
| 1353 void beginLoop(HBasicBlock block) { | 1380 void beginLoop(HBasicBlock block) { |
| 1354 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1381 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| 1355 String newLabel = pushLabel(); | 1382 String newLabel = pushLabel(); |
| 1356 if (block.hasBailouts()) { | 1383 if (block.hasBailouts()) { |
| 1357 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); | 1384 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); |
| 1358 } | 1385 } |
| 1359 | 1386 |
| 1360 addIndentation(); | 1387 addIndentation(); |
| 1361 for (LabelElement label in block.loopInformation.labels) { | 1388 for (SourceString label in block.loopInformation.labels) { |
| 1362 addLabel(label); | 1389 addBreakLabel(label); |
| 1363 buffer.add(":"); | 1390 buffer.add(":"); |
| 1364 } | 1391 } |
| 1365 buffer.add('$newLabel: while (true) {\n'); | 1392 buffer.add('$newLabel: while (true) {\n'); |
| 1366 indent++; | 1393 indent++; |
| 1367 | 1394 |
| 1368 if (block.hasBailouts()) { | 1395 if (block.hasBailouts()) { |
| 1369 startBailoutSwitch(); | 1396 startBailoutSwitch(); |
| 1370 } | 1397 } |
| 1371 } | 1398 } |
| 1372 | 1399 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1444 startBailoutSwitch(); | 1471 startBailoutSwitch(); |
| 1445 } | 1472 } |
| 1446 } | 1473 } |
| 1447 | 1474 |
| 1448 void endElse(HIf node) { | 1475 void endElse(HIf node) { |
| 1449 if (node.elseBlock.hasBailouts()) { | 1476 if (node.elseBlock.hasBailouts()) { |
| 1450 endBailoutSwitch(); | 1477 endBailoutSwitch(); |
| 1451 } | 1478 } |
| 1452 } | 1479 } |
| 1453 } | 1480 } |
| OLD | NEW |