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

Side by Side Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10100001: Refactoring if block-information. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 8 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
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 9
10 String generateMethod(WorkItem work, HGraph graph) { 10 String generateMethod(WorkItem work, HGraph graph) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 parameterNames[element] = function.isNative() 53 parameterNames[element] = function.isNative()
54 ? element.name.slowToString() 54 ? element.name.slowToString()
55 : JsNames.getValid('${element.name.slowToString()}'); 55 : JsNames.getValid('${element.name.slowToString()}');
56 }); 56 });
57 return parameterNames; 57 return parameterNames;
58 } 58 }
59 } 59 }
60 60
61 typedef void ElementAction(Element element); 61 typedef void ElementAction(Element element);
62 62
63 class SsaCodeGenerator implements HVisitor { 63 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
64 /** 64 /**
65 * Current state for generating simple (non-local-control) code. 65 * Current state for generating simple (non-local-control) code.
66 * It is generated as either statements (indented and ';'-terminated), 66 * It is generated as either statements (indented and ';'-terminated),
67 * expressions (comma separated) or declarations (also comma separated, 67 * expressions (comma separated) or declarations (also comma separated,
68 * but expected to be preceeded by a 'var' so it declares its variables); 68 * but expected to be preceeded by a 'var' so it declares its variables);
69 */ 69 */
70 static final int STATE_STATEMENT = 0; 70 static final int STATE_STATEMENT = 0;
71 static final int STATE_FIRST_EXPRESSION = 1; 71 static final int STATE_FIRST_EXPRESSION = 1;
72 static final int STATE_FIRST_DECLARATION = 2; 72 static final int STATE_FIRST_DECLARATION = 2;
73 static final int STATE_EXPRESSION = 3; 73 static final int STATE_EXPRESSION = 3;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 buffer.add(";\n"); 386 buffer.add(";\n");
387 } 387 }
388 388
389 void implicitBreakWithLabel(TargetElement target) { 389 void implicitBreakWithLabel(TargetElement target) {
390 addIndentation(); 390 addIndentation();
391 buffer.add("break "); 391 buffer.add("break ");
392 writeImplicitLabel(target); 392 writeImplicitLabel(target);
393 buffer.add(";\n"); 393 buffer.add(";\n");
394 } 394 }
395 395
396 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 396 bool visitIfInfo(HIfBlockInformation info) {
397 return false;
398 }
399
400 bool visitAndOrInfo(HAndOrBlockInformation info) {
401 return false;
402 }
403
404 bool visitLoopInfo(HLoopInformation info) {
405 bool success = false;
406 SubExpression condition = info.condition;
407 void visitBodyIgnoreLabels() {
408 if (info.body.start.isLabeledBlock()) {
409 HBlockInformation oldInfo = currentBlockInformation;
410 currentBlockInformation = info.body.start.blockInformation;
411 visitSubGraph(info.body);
412 currentBlockInformation = oldInfo;
413 } else {
414 visitSubGraph(info.body);
415 }
416 }
417 if (isCondition(condition)) {
floitsch 2012/04/16 13:26:07 I would prefer bailing out here. if (!isCondition
Lasse Reichstein Nielsen 2012/04/17 12:58:22 Done.
418 switch (info.type) {
floitsch 2012/04/16 13:26:07 I would prefer 'kind' instead of 'type'.
Lasse Reichstein Nielsen 2012/04/17 12:58:22 Done.
419 case HLoopInformation.WHILE_LOOP:
420 case HLoopInformation.FOR_IN_LOOP: {
floitsch 2012/04/16 13:26:07 Afaics there is almost no difference between while
Lasse Reichstein Nielsen 2012/04/17 12:58:22 It can have an update block that isn't just phis.
421 addIndentation();
422 for (LabelElement label in info.labels) {
423 writeLabel(label);
424 buffer.add(":");
425 }
426 bool inlineUpdates =
427 info.updates !== null && isExpression(info.updates);
428 if (inlineUpdates) {
429 buffer.add("for (; ");
430 visitConditionGraph(condition);
431 buffer.add("; ");
432 visitExpressionGraph(info.updates);
433 buffer.add(") {\n");
434 indent++;
435 // The body might be labeled. Ignore this when recursing on the
436 // subgraph.
437 // TODO(lrn): Remove this extra labeling when handling all loops
438 // using subgraphs.
439 visitBodyIgnoreLabels();
440
441 indent--;
442 } else {
443 buffer.add("while (");
444 visitConditionGraph(condition);
445 buffer.add(") {\n");
446 indent++;
447 wrapLoopBodyForContinue(info);
448 if (info.updates !== null) visitSubGraph(info.updates);
449 indent--;
450 }
451 addIndentation();
452 buffer.add("}\n");
453 success = true;
454 break;
455 }
456 case HLoopInformation.FOR_LOOP: {
457 // TODO(lrn): Find a way to put initialization into the for.
458 // It's currently handled before we reach the [HLoopInformation].
459 addIndentation();
460 for (LabelElement label in info.labels) {
461 if (label.isTarget) {
462 writeLabel(label);
463 buffer.add(":");
464 }
465 }
466 buffer.add("for(;");
467 visitConditionGraph(info.condition);
468 buffer.add(";");
469 if (isExpression(info.updates)) {
470 visitExpressionGraph(info.updates);
471 buffer.add(") {\n");
472 indent++;
473
474 visitBodyIgnoreLabels();
475
476 indent--;
477 addIndentation();
478 buffer.add("}\n");
479 } else {
480 addIndentation();
481 buffer.add(") {\n");
482 indent++;
483 wrapLoopBodyForContinue(info);
484 visitSubGraph(info.updates);
485 indent--;
486 buffer.add("}\n");
487 }
488 success = true;
489 break;
490 }
491 case HLoopInformation.DO_WHILE_LOOP:
492 // Currently unhandled.
floitsch 2012/04/16 13:26:07 We don't have fall-throughs. Why didn't this throu
Lasse Reichstein Nielsen 2012/04/17 12:58:22 It's an empty case, so it's joined with the follow
493 default:
floitsch 2012/04/16 13:26:07 Is default an internal error?
Lasse Reichstein Nielsen 2012/04/17 12:58:22 Probably, yes. I'll make it an internal error, and
494 }
495 }
496 if (success) {
floitsch 2012/04/16 13:26:07 Unless wrong you can merge while, for-in and for.
Lasse Reichstein Nielsen 2012/04/17 12:58:22 I'll keep it here, but without the if (I'll return
497 visitBasicBlock(info.joinBlock);
498 return true;
499 }
500 return false;
501 }
502
503 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
397 addIndentation(); 504 addIndentation();
398 Link<Element> continueOverrides = const EmptyLink<Element>(); 505 Link<Element> continueOverrides = const EmptyLink<Element>();
399 // If [labeledBlockInfo.isContinue], the block is an artificial 506 // If [labeledBlockInfo.isContinue], the block is an artificial
400 // block around the body of a loop with an update block, so that 507 // block around the body of a loop with an update block, so that
401 // continues of the loop can be written as breaks of the body 508 // continues of the loop can be written as breaks of the body
402 // block. 509 // block.
403 if (labeledBlockInfo.isContinue) { 510 if (labeledBlockInfo.isContinue) {
404 for (LabelElement label in labeledBlockInfo.labels) { 511 for (LabelElement label in labeledBlockInfo.labels) {
405 if (label.isContinueTarget) { 512 if (label.isContinueTarget) {
406 writeContinueLabel(label); 513 writeContinueLabel(label);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 visitBasicBlock(labeledBlockInfo.joinBlock); 554 visitBasicBlock(labeledBlockInfo.joinBlock);
448 } 555 }
449 if (labeledBlockInfo.isContinue) { 556 if (labeledBlockInfo.isContinue) {
450 while (!continueOverrides.isEmpty()) { 557 while (!continueOverrides.isEmpty()) {
451 continueAction.remove(continueOverrides.head); 558 continueAction.remove(continueOverrides.head);
452 continueOverrides = continueOverrides.tail; 559 continueOverrides = continueOverrides.tail;
453 } 560 }
454 } else { 561 } else {
455 breakAction.remove(labeledBlockInfo.target); 562 breakAction.remove(labeledBlockInfo.target);
456 } 563 }
564 return true;
457 } 565 }
458 566
459 void emitLogicalOperation(HPhi node, String operation) { 567 void emitLogicalOperation(HPhi node, String operation) {
460 JSBinaryOperatorPrecedence operatorPrecedence = 568 JSBinaryOperatorPrecedence operatorPrecedence =
461 JSPrecedence.binary[operation]; 569 JSPrecedence.binary[operation];
462 beginExpression(operatorPrecedence.precedence); 570 beginExpression(operatorPrecedence.precedence);
463 use(node.inputs[0], operatorPrecedence.left); 571 use(node.inputs[0], operatorPrecedence.left);
464 buffer.add(" $operation "); 572 buffer.add(" $operation ");
465 use(node.inputs[1], operatorPrecedence.right); 573 use(node.inputs[1], operatorPrecedence.right);
466 endExpression(operatorPrecedence.precedence); 574 endExpression(operatorPrecedence.precedence);
(...skipping 25 matching lines...) Expand all
492 if (label.isContinueTarget) { 600 if (label.isContinueTarget) {
493 continueAction.remove(label); 601 continueAction.remove(label);
494 } 602 }
495 } 603 }
496 } else { 604 } else {
497 // Loop body contains no continues, so we don't need a break target. 605 // Loop body contains no continues, so we don't need a break target.
498 visitSubGraph(info.body); 606 visitSubGraph(info.body);
499 } 607 }
500 } 608 }
501 609
502 bool handleLoop(HBasicBlock node) {
503 bool success = false;
504 assert(node.isLoopHeader());
505 HLoopInformation info = node.loopInformation;
506 SubExpression condition = info.condition;
507 if (isCondition(condition)) {
508 switch (info.type) {
509 case HLoopInformation.WHILE_LOOP:
510 case HLoopInformation.FOR_IN_LOOP: {
511 addIndentation();
512 for (LabelElement label in info.labels) {
513 writeLabel(label);
514 buffer.add(":");
515 }
516 bool inlineUpdates =
517 info.updates !== null && isExpression(info.updates);
518 if (inlineUpdates) {
519 buffer.add("for (; ");
520 visitConditionGraph(condition);
521 buffer.add("; ");
522 visitExpressionGraph(info.updates);
523 buffer.add(") {\n");
524 indent++;
525 // The body might be labeled. Ignore this when recursing on the
526 // subgraph.
527 // TODO(lrn): Remove this extra labeling when handling all loops
528 // using subgraphs.
529 HBlockInformation oldInfo = currentBlockInformation;
530 currentBlockInformation = info.body.start.labeledBlockInformation;
531 visitSubGraph(info.body);
532 currentBlockInformation = oldInfo;
533
534 indent--;
535 } else {
536 buffer.add("while (");
537 visitConditionGraph(condition);
538 buffer.add(") {\n");
539 indent++;
540 wrapLoopBodyForContinue(info);
541 if (info.updates !== null) visitSubGraph(info.updates);
542 indent--;
543 }
544 addIndentation();
545 buffer.add("}\n");
546 success = true;
547 break;
548 }
549 case HLoopInformation.FOR_LOOP: {
550 // TODO(lrn): Find a way to put initialization into the for.
551 // It's currently handled before we reach the [HLoopInformation].
552 addIndentation();
553 for (LabelElement label in info.labels) {
554 if (label.isTarget) {
555 writeLabel(label);
556 buffer.add(":");
557 }
558 }
559 buffer.add("for(;");
560 visitConditionGraph(info.condition);
561 buffer.add(";");
562 if (isExpression(info.updates)) {
563 visitExpressionGraph(info.updates);
564 buffer.add(") {\n");
565 indent++;
566
567 HBlockInformation oldInfo = currentBlockInformation;
568 currentBlockInformation = info.body.start.labeledBlockInformation;
569 visitSubGraph(info.body);
570 currentBlockInformation = oldInfo;
571
572 indent--;
573 addIndentation();
574 buffer.add("}\n");
575 } else {
576 addIndentation();
577 buffer.add(") {\n");
578 indent++;
579 wrapLoopBodyForContinue(info);
580 visitSubGraph(info.updates);
581 indent--;
582 buffer.add("}\n");
583 }
584 success = true;
585 break;
586 }
587 case HLoopInformation.DO_WHILE_LOOP:
588 // Currently unhandled.
589 default:
590 }
591 }
592 return success;
593 }
594
595 void visitBasicBlock(HBasicBlock node) { 610 void visitBasicBlock(HBasicBlock node) {
596 // Abort traversal if we are leaving the currently active sub-graph. 611 // Abort traversal if we are leaving the currently active sub-graph.
597 if (!subGraph.contains(node)) return; 612 if (!subGraph.contains(node)) return;
598 613
599 // If this node has special behavior attached, handle it. 614 // If this node has special behavior attached, handle it.
600 // If we reach here again while handling the attached information, 615 // If we reach here again while handling the attached information,
601 // e.g., because we call visitSubGraph on a subgraph starting here, 616 // e.g., because we call visitSubGraph on a subgraph starting here,
602 // don't handle it again. 617 // don't handle it again.
603 if (node.hasLabeledBlockInformation() && 618 if (node.blockInformation !== null &&
604 node.labeledBlockInformation !== currentBlockInformation) { 619 node.blockInformation !== currentBlockInformation) {
605 HBlockInformation oldBlockInformation = currentBlockInformation; 620 HBlockInformation oldBlockInformation = currentBlockInformation;
606 currentBlockInformation = node.labeledBlockInformation; 621 currentBlockInformation = node.blockInformation;
607 handleLabeledBlock(currentBlockInformation); 622 bool success = currentBlockInformation.accept(this);
608 currentBlockInformation = oldBlockInformation; 623 currentBlockInformation = oldBlockInformation;
609 return; 624 if (success) return;
625
626 // Even if our special handling didn't succeed, loop blocks
floitsch 2012/04/16 13:26:07 If our special handling didn't succeed, we have to
Lasse Reichstein Nielsen 2012/04/17 12:58:22 Done.
627 // have special treatement in the primitive traversal too.
628 if (node.isLoopHeader()) {
629 beginLoop(node);
630 }
610 } 631 }
611
612 if (node.isLoopHeader() &&
613 node.loopInformation !== currentBlockInformation) {
614 HBlockInformation oldBlockInformation = currentBlockInformation;
615 currentBlockInformation = node.loopInformation;
616 bool prettyLoop = handleLoop(node);
617 currentBlockInformation = oldBlockInformation;
618 if (prettyLoop) {
619 visitBasicBlock(node.loopInformation.joinBlock);
620 return;
621 }
622 beginLoop(node);
623 }
624
625 iterateBasicBlock(node); 632 iterateBasicBlock(node);
626 } 633 }
627 634
628 void iterateBasicBlock(HBasicBlock node) { 635 void iterateBasicBlock(HBasicBlock node) {
629 currentBlock = node; 636 currentBlock = node;
630 HInstruction instruction = node.first; 637 HInstruction instruction = node.first;
631 while (instruction != null) { 638 while (instruction != null) {
632 if (instruction === node.last) { 639 if (instruction === node.last) {
633 for (HBasicBlock successor in node.successors) { 640 for (HBasicBlock successor in node.successors) {
634 int index = successor.predecessors.indexOf(node); 641 int index = successor.predecessors.indexOf(node);
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after
1584 buffer.add(') '); 1591 buffer.add(') ');
1585 bailout(node, 'Not a string'); 1592 bailout(node, 'Not a string');
1586 } else if (node.isMutableArray()) { 1593 } else if (node.isMutableArray()) {
1587 buffer.add('if ('); 1594 buffer.add('if (');
1588 checkObject(input, '!=='); 1595 checkObject(input, '!==');
1589 buffer.add('||'); 1596 buffer.add('||');
1590 checkArray(input, '!=='); 1597 checkArray(input, '!==');
1591 buffer.add('||'); 1598 buffer.add('||');
1592 checkImmutableArray(input); 1599 checkImmutableArray(input);
1593 buffer.add(') '); 1600 buffer.add(') ');
1594 bailout(node, 'Not a mutable array'); 1601 bailout(node, 'Not a mutable array');
1595 } else if (node.isArray()) { 1602 } else if (node.isArray()) {
1596 buffer.add('if ('); 1603 buffer.add('if (');
1597 checkObject(input, '!=='); 1604 checkObject(input, '!==');
1598 buffer.add('||'); 1605 buffer.add('||');
1599 checkArray(input, '!=='); 1606 checkArray(input, '!==');
1600 buffer.add(') '); 1607 buffer.add(') ');
1601 bailout(node, 'Not an array'); 1608 bailout(node, 'Not an array');
1602 } else if (node.isStringOrArray()) { 1609 } else if (node.isStringOrArray()) {
1603 buffer.add('if ('); 1610 buffer.add('if (');
1604 checkString(input, '!=='); 1611 checkString(input, '!==');
1605 buffer.add(' && ('); 1612 buffer.add(' && (');
1606 checkObject(input, '!=='); 1613 checkObject(input, '!==');
1607 buffer.add('||'); 1614 buffer.add('||');
1608 checkArray(input, '!=='); 1615 checkArray(input, '!==');
1609 buffer.add(')) '); 1616 buffer.add(')) ');
1610 bailout(node, 'Not a string or array'); 1617 bailout(node, 'Not a string or array');
1611 } else { 1618 } else {
1612 unreachable(); 1619 unreachable();
1613 } 1620 }
1614 buffer.add(';\n'); 1621 buffer.add(';\n');
1615 } 1622 }
1616 1623
1617 void beginLoop(HBasicBlock block) { 1624 void beginLoop(HBasicBlock block) {
1618 addIndentation(); 1625 addIndentation();
1619 for (LabelElement label in block.loopInformation.labels) { 1626 HLoopInformation info = block.blockInformation;
1627 for (LabelElement label in info.labels) {
1620 writeLabel(label); 1628 writeLabel(label);
1621 buffer.add(":"); 1629 buffer.add(":");
1622 } 1630 }
1623 buffer.add('while (true) {\n'); 1631 buffer.add('while (true) {\n');
1624 indent++; 1632 indent++;
1625 } 1633 }
1626 1634
1627 void endLoop(HBasicBlock block) { 1635 void endLoop(HBasicBlock block) {
1628 indent--; 1636 indent--;
1629 addIndentation(); 1637 addIndentation();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 HBoundsCheck instruction = argument; 1736 HBoundsCheck instruction = argument;
1729 return unwrap(instruction.index); 1737 return unwrap(instruction.index);
1730 } else if (argument is HTypeGuard) { 1738 } else if (argument is HTypeGuard) {
1731 HTypeGuard instruction = argument; 1739 HTypeGuard instruction = argument;
1732 return unwrap(instruction.guarded); 1740 return unwrap(instruction.guarded);
1733 } else { 1741 } else {
1734 return argument; 1742 return argument;
1735 } 1743 }
1736 } 1744 }
1737 1745
1738 bool handleLoop(HBasicBlock node) => false; 1746 bool visitLoopInfo(HLoopInformation info) => false;
1739 1747
1740 void visitTypeGuard(HTypeGuard node) { 1748 void visitTypeGuard(HTypeGuard node) {
1741 indent--; 1749 indent--;
1742 addIndentation(); 1750 addIndentation();
1743 buffer.add('case ${node.state}:\n'); 1751 buffer.add('case ${node.state}:\n');
1744 indent++; 1752 indent++;
1745 addIndentation(); 1753 addIndentation();
1746 buffer.add('state = 0;\n'); 1754 buffer.add('state = 0;\n');
1747 1755
1748 setup.add(' case ${node.state}:\n'); 1756 setup.add(' case ${node.state}:\n');
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 indent++; 1788 indent++;
1781 } 1789 }
1782 1790
1783 void endBailoutSwitch() { 1791 void endBailoutSwitch() {
1784 indent--; // Close 'case'. 1792 indent--; // Close 'case'.
1785 indent--; 1793 indent--;
1786 addIndentation(); 1794 addIndentation();
1787 buffer.add('}\n'); // Close 'switch'. 1795 buffer.add('}\n'); // Close 'switch'.
1788 } 1796 }
1789 1797
1790
1791 void beginLoop(HBasicBlock block) { 1798 void beginLoop(HBasicBlock block) {
1792 // TODO(ngeoffray): Don't put labels on loops that don't bailout. 1799 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
1793 String newLabel = pushLabel(); 1800 String newLabel = pushLabel();
1794 if (block.hasGuards()) { 1801 if (block.hasGuards()) {
1795 startBailoutCase(block.guards, const <HTypeGuard>[]); 1802 startBailoutCase(block.guards, const <HTypeGuard>[]);
1796 } 1803 }
1797 1804
1798 addIndentation(); 1805 addIndentation();
1799 for (SourceString label in block.loopInformation.labels) { 1806 HLoopInformation info = block.blockInformation;
1807 for (SourceString label in info.labels) {
1800 writeLabel(label); 1808 writeLabel(label);
1801 buffer.add(":"); 1809 buffer.add(":");
1802 } 1810 }
1803 buffer.add('$newLabel: while (true) {\n'); 1811 buffer.add('$newLabel: while (true) {\n');
1804 indent++; 1812 indent++;
1805 1813
1806 if (block.hasGuards()) { 1814 if (block.hasGuards()) {
1807 startBailoutSwitch(); 1815 startBailoutSwitch();
1808 } 1816 }
1809 } 1817 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 startBailoutSwitch(); 1890 startBailoutSwitch();
1883 } 1891 }
1884 } 1892 }
1885 1893
1886 void endElse(HIf node) { 1894 void endElse(HIf node) {
1887 if (node.elseBlock.hasGuards()) { 1895 if (node.elseBlock.hasGuards()) {
1888 endBailoutSwitch(); 1896 endBailoutSwitch();
1889 } 1897 }
1890 } 1898 }
1891 } 1899 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698