Chromium Code Reviews| 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 } |
|
ngeoffray
2012/03/19 11:42:06
Shouldn't you do: if !(labeledBlockInfo.labels.isE
Lasse Reichstein Nielsen
2012/03/19 12:13:58
It's never empty, so no.
| |
| 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) { |
|
ngeoffray
2012/03/19 11:42:06
Please add a comment that since we're generating s
Lasse Reichstein Nielsen
2012/03/19 12:13:58
Done.
| |
| 457 buffer.add(@' '); | 474 buffer.add(@' '); |
| 458 addImplicitLabel(target); | 475 addImplicitBreakLabel(target); |
| 459 } | 476 } |
| 460 } | 477 } |
| 461 buffer.add(";\n"); | 478 buffer.add(";\n"); |
| 479 } | |
| 480 | |
| 481 visitContinue(HContinue node) { | |
| 482 assert(currentBlock.successors.length == 1); | |
| 483 // No block finishing with a 'break' can have more than | |
|
ngeoffray
2012/03/19 11:42:06
break -> continue
| |
| 484 // one dominated block (since it has only one successor). | |
|
ngeoffray
2012/03/19 11:42:06
more than one -> a ? You're checking that dominate
| |
| 485 // If the successor is dominated by another block, then the other block | |
| 486 // is responsible for visiting the successor. | |
| 487 assert(currentBlock.dominatedBlocks.isEmpty()); | |
| 488 // Otherwise we would have bailed out in the builder. | |
|
ngeoffray
2012/03/19 11:42:06
Should that comment be one line above?
Lasse Reichstein Nielsen
2012/03/19 12:13:58
These comments should all go away, just as they di
| |
| 489 addIndentation(); | |
| 490 buffer.add("break "); | |
|
ngeoffray
2012/03/19 11:42:06
Please add a comment on why this isn't 'continue'.
Lasse Reichstein Nielsen
2012/03/19 12:13:58
Done.
| |
| 491 if (node.label !== null) { | |
| 492 addContinueLabel(node.label); | |
| 493 } else { | |
| 494 addImplicitContinueLabel(node.target); | |
| 495 } | |
| 496 buffer.add(";\n"); | |
| 462 // We never follow the break to its target, even if it dominates the | 497 // We never follow the break to its target, even if it dominates the |
| 463 // break target block. That block is always handled by the structure | 498 // break target block. That block is always handled by the structure |
| 464 // that introduced the break. | 499 // that introduced the break. |
| 465 } | 500 } |
| 466 | 501 |
| 467 visitTry(HTry node) { | 502 visitTry(HTry node) { |
| 468 addIndentation(); | 503 addIndentation(); |
| 469 buffer.add('try {\n'); | 504 buffer.add('try {\n'); |
| 470 indent++; | 505 indent++; |
| 471 List<HBasicBlock> successors = node.block.successors; | 506 List<HBasicBlock> successors = node.block.successors; |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1172 buffer.add(')) '); | 1207 buffer.add(')) '); |
| 1173 bailout(node, 'Not a string or array'); | 1208 bailout(node, 'Not a string or array'); |
| 1174 } else { | 1209 } else { |
| 1175 unreachable(); | 1210 unreachable(); |
| 1176 } | 1211 } |
| 1177 } | 1212 } |
| 1178 | 1213 |
| 1179 void beginLoop(HBasicBlock block) { | 1214 void beginLoop(HBasicBlock block) { |
| 1180 addIndentation(); | 1215 addIndentation(); |
| 1181 for (LabelElement label in block.loopInformation.labels) { | 1216 for (LabelElement label in block.loopInformation.labels) { |
| 1182 addLabel(label); | 1217 addBreakLabel(label); |
|
ngeoffray
2012/03/19 11:42:06
What about continue labels here?
Lasse Reichstein Nielsen
2012/03/19 12:13:58
Continue labels are put as labels on a block surro
| |
| 1183 buffer.add(":"); | 1218 buffer.add(":"); |
| 1184 } | 1219 } |
| 1185 buffer.add('while (true) {\n'); | 1220 buffer.add('while (true) {\n'); |
| 1186 indent++; | 1221 indent++; |
| 1187 } | 1222 } |
| 1188 | 1223 |
| 1189 void endLoop(HBasicBlock block) { | 1224 void endLoop(HBasicBlock block) { |
| 1190 indent--; | 1225 indent--; |
| 1191 addIndentation(); | 1226 addIndentation(); |
| 1192 buffer.add('}\n'); // Close 'while' loop. | 1227 buffer.add('}\n'); // Close 'while' loop. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1336 indent++; | 1371 indent++; |
| 1337 } | 1372 } |
| 1338 | 1373 |
| 1339 void endBailoutSwitch() { | 1374 void endBailoutSwitch() { |
| 1340 indent--; // Close 'case'. | 1375 indent--; // Close 'case'. |
| 1341 indent--; | 1376 indent--; |
| 1342 addIndentation(); | 1377 addIndentation(); |
| 1343 buffer.add('}\n'); // Close 'switch'. | 1378 buffer.add('}\n'); // Close 'switch'. |
| 1344 } | 1379 } |
| 1345 | 1380 |
| 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 | 1381 |
| 1353 void beginLoop(HBasicBlock block) { | 1382 void beginLoop(HBasicBlock block) { |
| 1354 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1383 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| 1355 String newLabel = pushLabel(); | 1384 String newLabel = pushLabel(); |
| 1356 if (block.hasBailouts()) { | 1385 if (block.hasBailouts()) { |
| 1357 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); | 1386 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); |
| 1358 } | 1387 } |
| 1359 | 1388 |
| 1360 addIndentation(); | 1389 addIndentation(); |
| 1361 for (LabelElement label in block.loopInformation.labels) { | 1390 for (SourceString label in block.loopInformation.labels) { |
| 1362 addLabel(label); | 1391 addBreakLabel(label); |
| 1363 buffer.add(":"); | 1392 buffer.add(":"); |
| 1364 } | 1393 } |
| 1365 buffer.add('$newLabel: while (true) {\n'); | 1394 buffer.add('$newLabel: while (true) {\n'); |
| 1366 indent++; | 1395 indent++; |
| 1367 | 1396 |
| 1368 if (block.hasBailouts()) { | 1397 if (block.hasBailouts()) { |
| 1369 startBailoutSwitch(); | 1398 startBailoutSwitch(); |
| 1370 } | 1399 } |
| 1371 } | 1400 } |
| 1372 | 1401 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1444 startBailoutSwitch(); | 1473 startBailoutSwitch(); |
| 1445 } | 1474 } |
| 1446 } | 1475 } |
| 1447 | 1476 |
| 1448 void endElse(HIf node) { | 1477 void endElse(HIf node) { |
| 1449 if (node.elseBlock.hasBailouts()) { | 1478 if (node.elseBlock.hasBailouts()) { |
| 1450 endBailoutSwitch(); | 1479 endBailoutSwitch(); |
| 1451 } | 1480 } |
| 1452 } | 1481 } |
| 1453 } | 1482 } |
| OLD | NEW |