Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: frog/leg/ssa/codegen.dart

Issue 9421035: Support break and labeled statements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Update expectations. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/leg/ssa/builder.dart ('k') | frog/leg/ssa/nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 } 219 }
220 } 220 }
221 221
222 visit(HInstruction node, int expectedPrecedence) { 222 visit(HInstruction node, int expectedPrecedence) {
223 int oldPrecedence = this.expectedPrecedence; 223 int oldPrecedence = this.expectedPrecedence;
224 this.expectedPrecedence = expectedPrecedence; 224 this.expectedPrecedence = expectedPrecedence;
225 node.accept(this); 225 node.accept(this);
226 this.expectedPrecedence = oldPrecedence; 226 this.expectedPrecedence = oldPrecedence;
227 } 227 }
228 228
229 void handleLabeledBlock(HBasicBlock node) {
230 HLabeledBlockInformation labeledBlockInfo = node.labeledBlockInformation;
231 if (labeledBlockInfo.start === node) {
232 addIndentation();
233 for (SourceString label in labeledBlockInfo.labels) {
234 addLabel(label);
235 buffer.add(":");
236 }
237 buffer.add("{\n");
238 indent++;
239 } else {
240 assert(labeledBlockInfo.end === node);
241 assert((){
242 // Check that this block is (transitively) dominated by the start block.
243 HBasicBlock block = node;
244 while (block.dominator !== null) {
245 block = block.dominator;
246 if (block === labeledBlockInfo.start) return true;
247 }
248 return false;
249 });
250 indent--;
251 addIndentation();
252 buffer.add("}\n");
253 }
254 }
255
229 visitBasicBlock(HBasicBlock node) { 256 visitBasicBlock(HBasicBlock node) {
230 currentBlock = node; 257 currentBlock = node;
231 258
232 // While loop will be closed by the conditional loop-branch. 259 if (node.hasLabeledBlockInformation()) {
233 // TODO(floitsch): HACK HACK HACK. 260 handleLabeledBlock(node);
234 if (currentBlock.isLoopHeader()) beginLoop(node); 261 } else if (currentBlock.isLoopHeader()) {
262 // While loop will be closed by the conditional loop-branch.
263 // TODO(floitsch): HACK HACK HACK.
264 beginLoop(node);
265 }
235 266
236 HInstruction instruction = node.first; 267 HInstruction instruction = node.first;
237 while (instruction != null) { 268 while (instruction != null) {
238 if (instruction is HGoto || instruction is HExit || instruction is HTry) { 269 if (instruction is HGoto || instruction is HExit || instruction is HTry) {
239 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 270 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
240 return; 271 return;
241 } else if (!instruction.generateAtUseSite()) { 272 } else if (!instruction.generateAtUseSite()) {
242 if (instruction is !HIf && instruction is !HBailoutTarget) { 273 if (instruction is !HIf && instruction is !HBailoutTarget) {
243 addIndentation(); 274 addIndentation();
244 } 275 }
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 // is responsible for visiting the successor. 396 // is responsible for visiting the successor.
366 if (dominated.isEmpty()) return; 397 if (dominated.isEmpty()) return;
367 if (dominated.length > 2) unreachable(); 398 if (dominated.length > 2) unreachable();
368 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { 399 if (dominated.length == 2 && currentBlock !== currentGraph.entry) {
369 unreachable(); 400 unreachable();
370 } 401 }
371 assert(dominated[0] == currentBlock.successors[0]); 402 assert(dominated[0] == currentBlock.successors[0]);
372 visitBasicBlock(dominated[0]); 403 visitBasicBlock(dominated[0]);
373 } 404 }
374 405
406 // Used to write the name of labels.
407 // The default implementation uses the unmodified Dart label name.
408 // Specializations might change this.
409 void addLabel(SourceString label) {
410 buffer.add(label.toString());
411 }
412
413 visitBreak(HBreak node) {
414 assert(currentBlock.successors.length == 1);
415 // No block finishing with a 'break' can have more than
416 // one dominated block (since it has only one successor).
417 // If the successor is dominated by another block, then the other block
418 // is responsible for visiting the successor.
419 List<HBasicBlock> dominated = currentBlock.dominatedBlocks;
420 assert(dominated.isEmpty());
421 // Otherwise we would have bailed out in the builder.
422 addIndentation();
423 buffer.add("break");
424 if (node.label !== null) {
425 buffer.add(" ");
426 addLabel(node.label);
427 }
428 buffer.add(";\n");
429 }
430
375 visitTry(HTry node) { 431 visitTry(HTry node) {
376 addIndentation(); 432 addIndentation();
377 buffer.add('try {\n'); 433 buffer.add('try {\n');
378 indent++; 434 indent++;
379 List<HBasicBlock> successors = node.block.successors; 435 List<HBasicBlock> successors = node.block.successors;
380 visitBasicBlock(successors[0]); 436 visitBasicBlock(successors[0]);
381 indent--; 437 indent--;
382 438
383 if (node.finallyBlock != successors[1]) { 439 if (node.finallyBlock != successors[1]) {
384 // Printing the catch part. 440 // Printing the catch part.
(...skipping 14 matching lines...) Expand all
399 visitBasicBlock(node.finallyBlock); 455 visitBasicBlock(node.finallyBlock);
400 indent--; 456 indent--;
401 } 457 }
402 addIndentation(); 458 addIndentation();
403 buffer.add('}\n'); 459 buffer.add('}\n');
404 460
405 visitBasicBlock(node.joinBlock); 461 visitBasicBlock(node.joinBlock);
406 } 462 }
407 463
408 visitIf(HIf node) { 464 visitIf(HIf node) {
465 List<HBasicBlock> dominated = node.block.dominatedBlocks;
409 startIf(node); 466 startIf(node);
410 assert(!node.generateAtUseSite()); 467 assert(!node.generateAtUseSite());
411 startThen(node); 468 startThen(node);
469 assert(node.thenBlock === dominated[0]);
412 visitBasicBlock(node.thenBlock); 470 visitBasicBlock(node.thenBlock);
471 int preVisitedBlocks = 1;
413 endThen(node); 472 endThen(node);
414 if (node.hasElse) { 473 if (node.hasElse) {
415 startElse(node); 474 startElse(node);
475 assert(node.elseBlock === dominated[1]);
416 visitBasicBlock(node.elseBlock); 476 visitBasicBlock(node.elseBlock);
477 preVisitedBlocks = 2;
417 endElse(node); 478 endElse(node);
418 } 479 }
419 endIf(node); 480 endIf(node);
420 481
421 // Normally the HIf dominates the join-block. In this case there is one 482 // Visit all the dominated blocks that are not part of the then or else
422 // dominated block that we need to visit: 483 // branches. Depending on how the then/else branches terminate
423 // If both the then and else blocks return/throw, then the join-block is 484 // (e.g., return/throw/break) there can be any number of these.
424 // either the exit-block, or there is none.
425 // We can also have the case where the HIf has no else, but the then-branch
426 // terminates. If the code after the 'if' terminates, then the
427 // if could become the dominator of the exit-block, thus having
428 // three dominated blocks: the then, the code after the if, and the exit
429 // block.
430
431 List<HBasicBlock> dominated = node.block.dominatedBlocks;
432 int dominatedCount = dominated.length; 485 int dominatedCount = dominated.length;
433 if (node.hasElse && (dominatedCount == 3 || dominatedCount == 4)) { 486 for (int i = preVisitedBlocks; i < dominatedCount; i++) {
434 // Normal case. The third dominated block is either the join-block or 487 HBasicBlock dominatedBlock = dominated[i];
435 // the exit-block (if both branches terminate). 488 assert(dominatedBlock.dominator === node.block);
436 // If the if dominates 4 blocks, then at least one branch does a 489 visitBasicBlock(dominatedBlock);
437 // conditional return, and the 4th block is the exit-block.
438 assert(dominatedCount != 4 || dominated.last().isExitBlock());
439 visitBasicBlock(dominated[2]);
440 } else if (node.hasElse) {
441 // Both branches terminate, but this HIf is not the dominator of the exit
442 // block.
443 assert(dominatedCount == 2);
444 } else if (!node.hasElse && dominatedCount == 2) {
445 // Normal case. Even if the then-branch terminated there is still
446 // a join-block.
447 assert(!dominated.last().isExitBlock());
448 visitBasicBlock(dominated[1]);
449 } else {
450 // The then-branch terminates, and the code following the if terminates
451 // too. The if happens to dominate the exit-block.
452 assert(!node.hasElse);
453 assert(dominatedCount == 3);
454 assert(dominated.last().isExitBlock());
455 visitBasicBlock(dominated[1]);
456 visitBasicBlock(dominated[2]);
457 } 490 }
458 } 491 }
459 492
460 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 493 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
461 beginExpression(JSPrecedence.CALL_PRECEDENCE); 494 beginExpression(JSPrecedence.CALL_PRECEDENCE);
462 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 495 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
463 buffer.add('.'); 496 buffer.add('.');
464 // Avoid adding the generative constructor name to the list of 497 // Avoid adding the generative constructor name to the list of
465 // seen selectors. 498 // seen selectors.
466 if (node.inputs[0] is HForeignNew) { 499 if (node.inputs[0] is HForeignNew) {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 visitLoopBranch(HLoopBranch node) { 667 visitLoopBranch(HLoopBranch node) {
635 HBasicBlock branchBlock = currentBlock; 668 HBasicBlock branchBlock = currentBlock;
636 handleLoopCondition(node); 669 handleLoopCondition(node);
637 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; 670 List<HBasicBlock> dominated = currentBlock.dominatedBlocks;
638 // For a do while loop, the body has already been visited. 671 // For a do while loop, the body has already been visited.
639 if (!node.isDoWhile()) { 672 if (!node.isDoWhile()) {
640 visitBasicBlock(dominated[0]); 673 visitBasicBlock(dominated[0]);
641 } 674 }
642 endLoop(node.block); 675 endLoop(node.block);
643 visitBasicBlock(branchBlock.successors[1]); 676 visitBasicBlock(branchBlock.successors[1]);
644 // TODO(floitsch): with labeled breaks we can have more dominated blocks. 677 // With labeled breaks we can have more dominated blocks.
645 assert(dominated.length <= 3); 678 if (dominated.length >= 3) {
646 if (dominated.length == 3) { 679 for (int i = 2; i < dominated.length; i++) {
647 // This happens when the body contains a 'return', and the exit-block is 680 visitBasicBlock(dominated[i]);
648 // not dominated by a dominator of the while loop. 681 }
649 assert(dominated[2].isExitBlock());
650 visitBasicBlock(dominated[2]);
651 } 682 }
652 } 683 }
653 684
654 visitNot(HNot node) { 685 visitNot(HNot node) {
655 assert(node.inputs.length == 1); 686 assert(node.inputs.length == 1);
656 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); 687 beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
657 buffer.add('!'); 688 buffer.add('!');
658 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE); 689 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE);
659 endExpression(JSPrecedence.PREFIX_PRECEDENCE); 690 endExpression(JSPrecedence.PREFIX_PRECEDENCE);
660 } 691 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 checkArray(input, '!=='); 1037 checkArray(input, '!==');
1007 buffer.add(')) '); 1038 buffer.add(')) ');
1008 bailout(node, 'Not a string or array'); 1039 bailout(node, 'Not a string or array');
1009 } else { 1040 } else {
1010 unreachable(); 1041 unreachable();
1011 } 1042 }
1012 } 1043 }
1013 1044
1014 void beginLoop(HBasicBlock block) { 1045 void beginLoop(HBasicBlock block) {
1015 addIndentation(); 1046 addIndentation();
1047 for (SourceString label in block.loopInformation.labels) {
1048 buffer.add("${label.stringValue}:");
1049 }
1016 buffer.add('while (true) {\n'); 1050 buffer.add('while (true) {\n');
1017 indent++; 1051 indent++;
1018 } 1052 }
1019 1053
1020 void endLoop(HBasicBlock block) { 1054 void endLoop(HBasicBlock block) {
1021 indent--; 1055 indent--;
1022 addIndentation(); 1056 addIndentation();
1023 buffer.add('}\n'); // Close 'while' loop. 1057 buffer.add('}\n'); // Close 'while' loop.
1024 } 1058 }
1025 1059
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1167 indent++; 1201 indent++;
1168 } 1202 }
1169 1203
1170 void endBailoutSwitch() { 1204 void endBailoutSwitch() {
1171 indent--; // Close 'case'. 1205 indent--; // Close 'case'.
1172 indent--; 1206 indent--;
1173 addIndentation(); 1207 addIndentation();
1174 buffer.add('}\n'); // Close 'switch'. 1208 buffer.add('}\n'); // Close 'switch'.
1175 } 1209 }
1176 1210
1211 // Adds a "$" in front of names of labels from the original source.
1212 // This avoids conflicts with labels introduced by bailouts, which
1213 // starts with a non-"$" character.
1214 void addLabel(SourceString label) {
1215 buffer.add("\$$label");
1216 }
1217
1177 void beginLoop(HBasicBlock block) { 1218 void beginLoop(HBasicBlock block) {
1178 // TODO(ngeoffray): Don't put labels on loops that don't bailout. 1219 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
1179 String newLabel = pushLabel(); 1220 String newLabel = pushLabel();
1180 if (block.hasBailouts()) { 1221 if (block.hasBailouts()) {
1181 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); 1222 startBailoutCase(block.bailouts, const <HBailoutTarget>[]);
1182 } 1223 }
1183 1224
1184 addIndentation(); 1225 addIndentation();
1226 for (SourceString label in block.loopInformation.labels) {
1227 addLabel(label);
1228 buffer.add(":");
1229 }
1185 buffer.add('$newLabel: while (true) {\n'); 1230 buffer.add('$newLabel: while (true) {\n');
1186 indent++; 1231 indent++;
1187 1232
1188 if (block.hasBailouts()) { 1233 if (block.hasBailouts()) {
1189 startBailoutSwitch(); 1234 startBailoutSwitch();
1190 } 1235 }
1191 } 1236 }
1192 1237
1193 void endLoop(HBasicBlock block) { 1238 void endLoop(HBasicBlock block) {
1194 popLabel(); 1239 popLabel();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 startBailoutSwitch(); 1309 startBailoutSwitch();
1265 } 1310 }
1266 } 1311 }
1267 1312
1268 void endElse(HIf node) { 1313 void endElse(HIf node) {
1269 if (node.elseBlock.hasBailouts()) { 1314 if (node.elseBlock.hasBailouts()) {
1270 endBailoutSwitch(); 1315 endBailoutSwitch();
1271 } 1316 }
1272 } 1317 }
1273 } 1318 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/builder.dart ('k') | frog/leg/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698