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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 visit(argument); | 204 visit(argument); |
| 205 } else { | 205 } else { |
| 206 buffer.add(temporary(argument)); | 206 buffer.add(temporary(argument)); |
| 207 } | 207 } |
| 208 } | 208 } |
| 209 | 209 |
| 210 visit(HInstruction node) { | 210 visit(HInstruction node) { |
| 211 return node.accept(this); | 211 return node.accept(this); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void handleLabeledBlock(HBasicBlock node) { | |
| 215 HLabeledBlockInformation labeledBlockInfo = node.labeledBlockInformation; | |
| 216 if (labeledBlockInfo.start === node) { | |
| 217 addIndentation(); | |
| 218 for (SourceString label in labeledBlockInfo.labels) { | |
| 219 addLabel(label); | |
| 220 buffer.add(":"); | |
| 221 } | |
| 222 buffer.add("{\n"); | |
| 223 indent++; | |
| 224 } else { | |
| 225 assert(labeledBlockInfo.end === node); | |
| 226 assert((){ | |
| 227 // Check that this block is (transitively) dominated by the start block. | |
| 228 HBasicBlock block = node; | |
| 229 while (block.dominator !== null) { | |
| 230 block = block.dominator; | |
| 231 if (block === labeledBlockInfo.start) return true; | |
| 232 } | |
| 233 return false; | |
| 234 }); | |
| 235 indent--; | |
| 236 addIndentation(); | |
| 237 buffer.add("}\n"); | |
| 238 } | |
| 239 } | |
| 240 | |
| 214 visitBasicBlock(HBasicBlock node) { | 241 visitBasicBlock(HBasicBlock node) { |
| 215 currentBlock = node; | 242 currentBlock = node; |
| 216 | 243 |
| 217 // While loop will be closed by the conditional loop-branch. | 244 if (node.hasLabeledBlockInformation()) { |
| 218 // TODO(floitsch): HACK HACK HACK. | 245 handleLabeledBlock(node); |
| 219 if (currentBlock.isLoopHeader()) beginLoop(node); | 246 } else if (currentBlock.isLoopHeader()) { |
| 247 // While loop will be closed by the conditional loop-branch. | |
| 248 // TODO(floitsch): HACK HACK HACK. | |
| 249 beginLoop(node); | |
| 250 } | |
| 220 | 251 |
| 221 HInstruction instruction = node.first; | 252 HInstruction instruction = node.first; |
| 222 while (instruction != null) { | 253 while (instruction != null) { |
| 223 if (instruction is HGoto || instruction is HExit || instruction is HTry) { | 254 if (instruction is HGoto || instruction is HExit || instruction is HTry) { |
| 224 visit(instruction); | 255 visit(instruction); |
| 225 return; | 256 return; |
| 226 } else if (!instruction.generateAtUseSite()) { | 257 } else if (!instruction.generateAtUseSite()) { |
| 227 if (instruction is !HIf && instruction is !HBailoutTarget) { | 258 if (instruction is !HIf && instruction is !HBailoutTarget) { |
| 228 addIndentation(); | 259 addIndentation(); |
| 229 } | 260 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 // is responsible for visiting the successor. | 374 // is responsible for visiting the successor. |
| 344 if (dominated.isEmpty()) return; | 375 if (dominated.isEmpty()) return; |
| 345 if (dominated.length > 2) unreachable(); | 376 if (dominated.length > 2) unreachable(); |
| 346 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { | 377 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { |
| 347 unreachable(); | 378 unreachable(); |
| 348 } | 379 } |
| 349 assert(dominated[0] == currentBlock.successors[0]); | 380 assert(dominated[0] == currentBlock.successors[0]); |
| 350 visitBasicBlock(dominated[0]); | 381 visitBasicBlock(dominated[0]); |
| 351 } | 382 } |
| 352 | 383 |
| 384 void addLabel(SourceString label) { | |
|
floitsch
2012/02/20 19:01:54
to many addLabels and similar: sometimes with pref
Lasse Reichstein Nielsen
2012/02/21 13:53:56
There are two addLabels, one for optimized code (a
| |
| 385 buffer.add(label.toString()); | |
| 386 } | |
| 387 | |
| 388 visitBreak(HBreak node) { | |
| 389 assert(currentBlock.successors.length == 1); | |
| 390 addIndentation(); | |
| 391 buffer.add("break"); | |
| 392 if (node.label !== null) { | |
| 393 buffer.add(" "); | |
| 394 addLabel(node.label); | |
| 395 } | |
| 396 buffer.add(";\n"); | |
| 397 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | |
| 398 // No block finishing with a 'throw' can have more than | |
|
floitsch
2012/02/20 19:01:54
s/throw/break.
Lasse Reichstein Nielsen
2012/02/21 13:53:56
Done.
| |
| 399 // one dominated block (since it has only one successor). | |
| 400 // If the successor is dominated by another block, then the other block | |
| 401 // is responsible for visiting the successor. | |
| 402 if (dominated.isEmpty()) return; | |
| 403 if (dominated.length > 2) unreachable(); | |
| 404 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { | |
| 405 unreachable(); | |
| 406 } | |
| 407 assert(dominated[0] == currentBlock.successors[0]); | |
| 408 visitBasicBlock(dominated[0]); | |
| 409 } | |
| 410 | |
| 353 visitTry(HTry node) { | 411 visitTry(HTry node) { |
| 354 addIndentation(); | 412 addIndentation(); |
| 355 buffer.add('try {\n'); | 413 buffer.add('try {\n'); |
| 356 indent++; | 414 indent++; |
| 357 List<HBasicBlock> successors = node.block.successors; | 415 List<HBasicBlock> successors = node.block.successors; |
| 358 visitBasicBlock(successors[0]); | 416 visitBasicBlock(successors[0]); |
| 359 indent--; | 417 indent--; |
| 360 | 418 |
| 361 if (node.finallyBlock != successors[1]) { | 419 if (node.finallyBlock != successors[1]) { |
| 362 // Printing the catch part. | 420 // Printing the catch part. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 } else if (!node.hasElse && dominatedCount == 2) { | 478 } else if (!node.hasElse && dominatedCount == 2) { |
| 421 // Normal case. Even if the then-branch terminated there is still | 479 // Normal case. Even if the then-branch terminated there is still |
| 422 // a join-block. | 480 // a join-block. |
| 423 assert(!dominated.last().isExitBlock()); | 481 assert(!dominated.last().isExitBlock()); |
| 424 visitBasicBlock(dominated[1]); | 482 visitBasicBlock(dominated[1]); |
| 425 } else { | 483 } else { |
| 426 // The then-branch terminates, and the code following the if terminates | 484 // The then-branch terminates, and the code following the if terminates |
| 427 // too. The if happens to dominate the exit-block. | 485 // too. The if happens to dominate the exit-block. |
| 428 assert(!node.hasElse); | 486 assert(!node.hasElse); |
| 429 assert(dominatedCount == 3); | 487 assert(dominatedCount == 3); |
| 430 assert(dominated.last().isExitBlock()); | |
| 431 visitBasicBlock(dominated[1]); | 488 visitBasicBlock(dominated[1]); |
|
floitsch
2012/02/20 19:01:54
This doesn't look right. It seems that the if can
Lasse Reichstein Nielsen
2012/02/21 13:53:56
You are right. All this complication has been redu
| |
| 432 visitBasicBlock(dominated[2]); | 489 visitBasicBlock(dominated[2]); |
| 433 } | 490 } |
| 434 } | 491 } |
| 435 | 492 |
| 436 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 493 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 437 use(node.receiver); | 494 use(node.receiver); |
| 438 buffer.add('.'); | 495 buffer.add('.'); |
| 439 // Avoid adding the generative constructor name to the list of | 496 // Avoid adding the generative constructor name to the list of |
| 440 // seen selectors. | 497 // seen selectors. |
| 441 if (node.inputs[0] is HForeignNew) { | 498 if (node.inputs[0] is HForeignNew) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 visitLoopBranch(HLoopBranch node) { | 629 visitLoopBranch(HLoopBranch node) { |
| 573 HBasicBlock branchBlock = currentBlock; | 630 HBasicBlock branchBlock = currentBlock; |
| 574 handleLoopCondition(node); | 631 handleLoopCondition(node); |
| 575 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | 632 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; |
| 576 // For a do while loop, the body has already been visited. | 633 // For a do while loop, the body has already been visited. |
| 577 if (!node.isDoWhile()) { | 634 if (!node.isDoWhile()) { |
| 578 visitBasicBlock(dominated[0]); | 635 visitBasicBlock(dominated[0]); |
| 579 } | 636 } |
| 580 endLoop(node.block); | 637 endLoop(node.block); |
| 581 visitBasicBlock(branchBlock.successors[1]); | 638 visitBasicBlock(branchBlock.successors[1]); |
| 582 // TODO(floitsch): with labeled breaks we can have more dominated blocks. | 639 // With labeled breaks we can have more dominated blocks. |
| 583 assert(dominated.length <= 3); | 640 if (dominated.length >= 3) { |
| 584 if (dominated.length == 3) { | 641 for (int i = 2; i < dominated.length; i++) { |
| 585 // This happens when the body contains a 'return', and the exit-block is | 642 visitBasicBlock(dominated[i]); |
| 586 // not dominated by a dominator of the while loop. | 643 } |
| 587 assert(dominated[2].isExitBlock()); | |
| 588 visitBasicBlock(dominated[2]); | |
| 589 } | 644 } |
| 590 } | 645 } |
| 591 | 646 |
| 592 visitNot(HNot node) { | 647 visitNot(HNot node) { |
| 593 assert(node.inputs.length == 1); | 648 assert(node.inputs.length == 1); |
| 594 buffer.add('(!'); | 649 buffer.add('(!'); |
| 595 use(node.inputs[0]); | 650 use(node.inputs[0]); |
| 596 buffer.add(')'); | 651 buffer.add(')'); |
| 597 } | 652 } |
| 598 | 653 |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 889 checkArray(input, '!=='); | 944 checkArray(input, '!=='); |
| 890 buffer.add(') '); | 945 buffer.add(') '); |
| 891 bailout(node, 'Not a string or array'); | 946 bailout(node, 'Not a string or array'); |
| 892 } else { | 947 } else { |
| 893 unreachable(); | 948 unreachable(); |
| 894 } | 949 } |
| 895 } | 950 } |
| 896 | 951 |
| 897 void beginLoop(HBasicBlock block) { | 952 void beginLoop(HBasicBlock block) { |
| 898 addIndentation(); | 953 addIndentation(); |
| 954 for (SourceString label in block.loopInformation.labels) { | |
| 955 buffer.add("${label.stringValue}:"); | |
| 956 } | |
| 899 buffer.add('while (true) {\n'); | 957 buffer.add('while (true) {\n'); |
| 900 indent++; | 958 indent++; |
| 901 } | 959 } |
| 902 | 960 |
| 903 void endLoop(HBasicBlock block) { | 961 void endLoop(HBasicBlock block) { |
| 904 indent--; | 962 indent--; |
| 905 addIndentation(); | 963 addIndentation(); |
| 906 buffer.add('}\n'); // Close 'while' loop. | 964 buffer.add('}\n'); // Close 'while' loop. |
| 907 } | 965 } |
| 908 | 966 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1050 indent++; | 1108 indent++; |
| 1051 } | 1109 } |
| 1052 | 1110 |
| 1053 void endBailoutSwitch() { | 1111 void endBailoutSwitch() { |
| 1054 indent--; // Close 'case'. | 1112 indent--; // Close 'case'. |
| 1055 indent--; | 1113 indent--; |
| 1056 addIndentation(); | 1114 addIndentation(); |
| 1057 buffer.add('}\n'); // Close 'switch'. | 1115 buffer.add('}\n'); // Close 'switch'. |
| 1058 } | 1116 } |
| 1059 | 1117 |
| 1118 void addLabel(SourceString label) { | |
| 1119 buffer.add("\$$label"); | |
| 1120 } | |
| 1121 | |
| 1060 void beginLoop(HBasicBlock block) { | 1122 void beginLoop(HBasicBlock block) { |
| 1061 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1123 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| 1062 String newLabel = pushLabel(); | 1124 String newLabel = pushLabel(); |
| 1063 if (block.hasBailouts()) { | 1125 if (block.hasBailouts()) { |
| 1064 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); | 1126 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); |
| 1065 } | 1127 } |
| 1066 | 1128 |
| 1067 addIndentation(); | 1129 addIndentation(); |
| 1130 for (SourceString label in block.loopInformation.labels) { | |
| 1131 addLabel(label); | |
| 1132 buffer.add(":"); | |
| 1133 } | |
| 1068 buffer.add('$newLabel: while (true) {\n'); | 1134 buffer.add('$newLabel: while (true) {\n'); |
| 1069 indent++; | 1135 indent++; |
| 1070 | 1136 |
| 1071 if (block.hasBailouts()) { | 1137 if (block.hasBailouts()) { |
| 1072 startBailoutSwitch(); | 1138 startBailoutSwitch(); |
| 1073 } | 1139 } |
| 1074 } | 1140 } |
| 1075 | 1141 |
| 1076 void endLoop(HBasicBlock block) { | 1142 void endLoop(HBasicBlock block) { |
| 1077 popLabel(); | 1143 popLabel(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1145 startBailoutSwitch(); | 1211 startBailoutSwitch(); |
| 1146 } | 1212 } |
| 1147 } | 1213 } |
| 1148 | 1214 |
| 1149 void endElse(HIf node) { | 1215 void endElse(HIf node) { |
| 1150 if (node.elseBlock.hasBailouts()) { | 1216 if (node.elseBlock.hasBailouts()) { |
| 1151 endBailoutSwitch(); | 1217 endBailoutSwitch(); |
| 1152 } | 1218 } |
| 1153 } | 1219 } |
| 1154 } | 1220 } |
| OLD | NEW |