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

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

Issue 9956172: Revert "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) {
11 return measure(() { 11 return measure(() {
12 compiler.tracer.traceGraph("codegen", graph); 12 compiler.tracer.traceGraph("codegen", graph);
13 Map<Element, String> parameterNames = getParameterNames(work); 13 Map<Element, String> parameterNames = getParameterNames(work);
14 String parameters = Strings.join(parameterNames.getValues(), ', '); 14 String parameters = Strings.join(parameterNames.getValues(), ', ');
15 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( 15 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator(
16 compiler, work, parameters, parameterNames); 16 compiler, work, parameters, parameterNames);
17 codegen.visitGraph(graph); 17 codegen.visitGraph(graph);
18 18
19 FunctionElement element = work.element; 19 FunctionElement element = work.element;
20 String code; 20 String code;
21 if (element.isInstanceMember() 21 if (element.isInstanceMember()
22 && element.enclosingElement.isClass() 22 && element.enclosingElement.isClass()
23 && element.enclosingElement.isNative() 23 && element.enclosingElement.isNative()
24 && native.isOverriddenMethod(element, 24 && native.isOverriddenMethod(element,
25 element.enclosingElement, 25 element.enclosingElement,
26 compiler.emitter.nativeEmitter)) { 26 compiler.emitter.nativeEmitter)) {
27 // Record that this method is overridden. In case of optional 27 // Record that this method is overridden. In case of optional
28 // arguments, the emitter will generate stubs to handle them, 28 // arguments, the emitter will generate stubs to handle them,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 parameterNames[element] = function.isNative() 73 parameterNames[element] = function.isNative()
74 ? element.name.slowToString() 74 ? element.name.slowToString()
75 : JsNames.getValid('${element.name.slowToString()}'); 75 : JsNames.getValid('${element.name.slowToString()}');
76 }); 76 });
77 return parameterNames; 77 return parameterNames;
78 } 78 }
79 } 79 }
80 80
81 typedef void ElementAction(Element element); 81 typedef void ElementAction(Element element);
82 82
83 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { 83 class SsaCodeGenerator implements HVisitor {
84 /** 84 /**
85 * Current state for generating simple (non-local-control) code. 85 * Current state for generating simple (non-local-control) code.
86 * It is generated as either statements (indented and ';'-terminated), 86 * It is generated as either statements (indented and ';'-terminated),
87 * expressions (comma separated) or declarations (also comma separated, 87 * expressions (comma separated) or declarations (also comma separated,
88 * but expected to be preceeded by a 'var' so it declares its variables); 88 * but expected to be preceeded by a 'var' so it declares its variables);
89 */ 89 */
90 static final int STATE_STATEMENT = 0; 90 static final int STATE_STATEMENT = 0;
91 static final int STATE_FIRST_EXPRESSION = 1; 91 static final int STATE_FIRST_EXPRESSION = 1;
92 static final int STATE_FIRST_DECLARATION = 2; 92 static final int STATE_FIRST_DECLARATION = 2;
93 static final int STATE_EXPRESSION = 3; 93 static final int STATE_EXPRESSION = 3;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 buffer.add(";\n"); 406 buffer.add(";\n");
407 } 407 }
408 408
409 void implicitBreakWithLabel(TargetElement target) { 409 void implicitBreakWithLabel(TargetElement target) {
410 addIndentation(); 410 addIndentation();
411 buffer.add("break "); 411 buffer.add("break ");
412 writeImplicitLabel(target); 412 writeImplicitLabel(target);
413 buffer.add(";\n"); 413 buffer.add(";\n");
414 } 414 }
415 415
416 bool visitIfInfo(HIfBlockInformation info) { 416 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
417 return false;
418 }
419
420 bool visitAndOrInfo(HAndOrBlockInformation info) {
421 return false;
422 }
423
424 bool visitLoopInfo(HLoopInformation info) {
425 SubExpression condition = info.condition;
426 void visitBodyIgnoreLabels() {
427 if (info.body.start.isLabeledBlock()) {
428 HBlockInformation oldInfo = currentBlockInformation;
429 currentBlockInformation = info.body.start.blockInformation;
430 visitSubGraph(info.body);
431 currentBlockInformation = oldInfo;
432 } else {
433 visitSubGraph(info.body);
434 }
435 }
436
437 if (!isCondition(condition)) {
438 return false;
439 }
440 switch (info.kind) {
441 case HLoopInformation.WHILE_LOOP:
442 case HLoopInformation.FOR_IN_LOOP: {
443 addIndentation();
444 for (LabelElement label in info.labels) {
445 writeLabel(label);
446 buffer.add(":");
447 }
448 bool inlineUpdates =
449 info.updates !== null && isExpression(info.updates);
450 if (inlineUpdates) {
451 buffer.add("for (; ");
452 visitConditionGraph(condition);
453 buffer.add("; ");
454 visitExpressionGraph(info.updates);
455 buffer.add(") {\n");
456 indent++;
457 // The body might be labeled. Ignore this when recursing on the
458 // subgraph.
459 // TODO(lrn): Remove this extra labeling when handling all loops
460 // using subgraphs.
461 visitBodyIgnoreLabels();
462
463 indent--;
464 } else {
465 buffer.add("while (");
466 visitConditionGraph(condition);
467 buffer.add(") {\n");
468 indent++;
469 wrapLoopBodyForContinue(info);
470 if (info.updates !== null) visitSubGraph(info.updates);
471 indent--;
472 }
473 addIndentation();
474 buffer.add("}\n");
475 break;
476 }
477 case HLoopInformation.FOR_LOOP: {
478 // TODO(lrn): Find a way to put initialization into the for.
479 // It's currently handled before we reach the [HLoopInformation].
480 addIndentation();
481 for (LabelElement label in info.labels) {
482 if (label.isTarget) {
483 writeLabel(label);
484 buffer.add(":");
485 }
486 }
487 buffer.add("for(;");
488 visitConditionGraph(info.condition);
489 buffer.add(";");
490 if (isExpression(info.updates)) {
491 visitExpressionGraph(info.updates);
492 buffer.add(") {\n");
493 indent++;
494
495 visitBodyIgnoreLabels();
496
497 indent--;
498 addIndentation();
499 buffer.add("}\n");
500 } else {
501 addIndentation();
502 buffer.add(") {\n");
503 indent++;
504 wrapLoopBodyForContinue(info);
505 visitSubGraph(info.updates);
506 indent--;
507 buffer.add("}\n");
508 }
509 break;
510 }
511 case HLoopInformation.DO_WHILE_LOOP:
512 // Currently unhandled.
513 return false;
514 default:
515 compiler.internalError(
516 'Unexpected loop kind: ${info.kind}',
517 instruction: condition.expression);
518 }
519 visitBasicBlock(info.joinBlock);
520 return true;
521 }
522
523 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
524 addIndentation(); 417 addIndentation();
525 Link<Element> continueOverrides = const EmptyLink<Element>(); 418 Link<Element> continueOverrides = const EmptyLink<Element>();
526 // If [labeledBlockInfo.isContinue], the block is an artificial 419 // If [labeledBlockInfo.isContinue], the block is an artificial
527 // block around the body of a loop with an update block, so that 420 // block around the body of a loop with an update block, so that
528 // continues of the loop can be written as breaks of the body 421 // continues of the loop can be written as breaks of the body
529 // block. 422 // block.
530 if (labeledBlockInfo.isContinue) { 423 if (labeledBlockInfo.isContinue) {
531 for (LabelElement label in labeledBlockInfo.labels) { 424 for (LabelElement label in labeledBlockInfo.labels) {
532 if (label.isContinueTarget) { 425 if (label.isContinueTarget) {
533 writeContinueLabel(label); 426 writeContinueLabel(label);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 visitBasicBlock(labeledBlockInfo.joinBlock); 467 visitBasicBlock(labeledBlockInfo.joinBlock);
575 } 468 }
576 if (labeledBlockInfo.isContinue) { 469 if (labeledBlockInfo.isContinue) {
577 while (!continueOverrides.isEmpty()) { 470 while (!continueOverrides.isEmpty()) {
578 continueAction.remove(continueOverrides.head); 471 continueAction.remove(continueOverrides.head);
579 continueOverrides = continueOverrides.tail; 472 continueOverrides = continueOverrides.tail;
580 } 473 }
581 } else { 474 } else {
582 breakAction.remove(labeledBlockInfo.target); 475 breakAction.remove(labeledBlockInfo.target);
583 } 476 }
584 return true;
585 } 477 }
586 478
587 void emitLogicalOperation(HPhi node, String operation) { 479 void emitLogicalOperation(HPhi node, String operation) {
588 JSBinaryOperatorPrecedence operatorPrecedence = 480 JSBinaryOperatorPrecedence operatorPrecedence =
589 JSPrecedence.binary[operation]; 481 JSPrecedence.binary[operation];
590 beginExpression(operatorPrecedence.precedence); 482 beginExpression(operatorPrecedence.precedence);
591 use(node.inputs[0], operatorPrecedence.left); 483 use(node.inputs[0], operatorPrecedence.left);
592 buffer.add(" $operation "); 484 buffer.add(" $operation ");
593 use(node.inputs[1], operatorPrecedence.right); 485 use(node.inputs[1], operatorPrecedence.right);
594 endExpression(operatorPrecedence.precedence); 486 endExpression(operatorPrecedence.precedence);
(...skipping 25 matching lines...) Expand all
620 if (label.isContinueTarget) { 512 if (label.isContinueTarget) {
621 continueAction.remove(label); 513 continueAction.remove(label);
622 } 514 }
623 } 515 }
624 } else { 516 } else {
625 // Loop body contains no continues, so we don't need a break target. 517 // Loop body contains no continues, so we don't need a break target.
626 visitSubGraph(info.body); 518 visitSubGraph(info.body);
627 } 519 }
628 } 520 }
629 521
522 bool handleLoop(HBasicBlock node) {
523 bool success = false;
524 assert(node.isLoopHeader());
525 HLoopInformation info = node.loopInformation;
526 SubExpression condition = info.condition;
527 if (isCondition(condition)) {
528 switch (info.type) {
529 case HLoopInformation.WHILE_LOOP:
530 case HLoopInformation.FOR_IN_LOOP: {
531 addIndentation();
532 for (LabelElement label in info.labels) {
533 writeLabel(label);
534 buffer.add(":");
535 }
536 bool inlineUpdates =
537 info.updates !== null && isExpression(info.updates);
538 if (inlineUpdates) {
539 buffer.add("for (; ");
540 visitConditionGraph(condition);
541 buffer.add("; ");
542 visitExpressionGraph(info.updates);
543 buffer.add(") {\n");
544 indent++;
545 // The body might be labeled. Ignore this when recursing on the
546 // subgraph.
547 // TODO(lrn): Remove this extra labeling when handling all loops
548 // using subgraphs.
549 HBlockInformation oldInfo = currentBlockInformation;
550 currentBlockInformation = info.body.start.labeledBlockInformation;
551 visitSubGraph(info.body);
552 currentBlockInformation = oldInfo;
553
554 indent--;
555 } else {
556 buffer.add("while (");
557 visitConditionGraph(condition);
558 buffer.add(") {\n");
559 indent++;
560 wrapLoopBodyForContinue(info);
561 if (info.updates !== null) visitSubGraph(info.updates);
562 indent--;
563 }
564 addIndentation();
565 buffer.add("}\n");
566 success = true;
567 break;
568 }
569 case HLoopInformation.FOR_LOOP: {
570 // TODO(lrn): Find a way to put initialization into the for.
571 // It's currently handled before we reach the [HLoopInformation].
572 addIndentation();
573 for (LabelElement label in info.labels) {
574 if (label.isTarget) {
575 writeLabel(label);
576 buffer.add(":");
577 }
578 }
579 buffer.add("for(;");
580 visitConditionGraph(info.condition);
581 buffer.add(";");
582 if (isExpression(info.updates)) {
583 visitExpressionGraph(info.updates);
584 buffer.add(") {\n");
585 indent++;
586
587 HBlockInformation oldInfo = currentBlockInformation;
588 currentBlockInformation = info.body.start.labeledBlockInformation;
589 visitSubGraph(info.body);
590 currentBlockInformation = oldInfo;
591
592 indent--;
593 addIndentation();
594 buffer.add("}\n");
595 } else {
596 addIndentation();
597 buffer.add(") {\n");
598 indent++;
599 wrapLoopBodyForContinue(info);
600 visitSubGraph(info.updates);
601 indent--;
602 buffer.add("}\n");
603 }
604 success = true;
605 break;
606 }
607 case HLoopInformation.DO_WHILE_LOOP:
608 // Currently unhandled.
609 default:
610 }
611 }
612 return success;
613 }
614
630 void visitBasicBlock(HBasicBlock node) { 615 void visitBasicBlock(HBasicBlock node) {
631 // Abort traversal if we are leaving the currently active sub-graph. 616 // Abort traversal if we are leaving the currently active sub-graph.
632 if (!subGraph.contains(node)) return; 617 if (!subGraph.contains(node)) return;
633 618
634 // If this node has special behavior attached, handle it. 619 // If this node has special behavior attached, handle it.
635 // If we reach here again while handling the attached information, 620 // If we reach here again while handling the attached information,
636 // e.g., because we call visitSubGraph on a subgraph starting here, 621 // e.g., because we call visitSubGraph on a subgraph starting here,
637 // don't handle it again. 622 // don't handle it again.
638 if (node.blockInformation !== null && 623 if (node.hasLabeledBlockInformation() &&
639 node.blockInformation !== currentBlockInformation) { 624 node.labeledBlockInformation !== currentBlockInformation) {
640 HBlockInformation oldBlockInformation = currentBlockInformation; 625 HBlockInformation oldBlockInformation = currentBlockInformation;
641 currentBlockInformation = node.blockInformation; 626 currentBlockInformation = node.labeledBlockInformation;
642 bool success = currentBlockInformation.accept(this); 627 handleLabeledBlock(currentBlockInformation);
643 currentBlockInformation = oldBlockInformation; 628 currentBlockInformation = oldBlockInformation;
644 if (success) return; 629 return;
630 }
645 631
646 // If our special handling didn't succeed, we have to emit a generic 632 if (node.isLoopHeader() &&
647 // version. This still requires special handling for loop-blocks 633 node.loopInformation !== currentBlockInformation) {
648 if (node.isLoopHeader()) { 634 HBlockInformation oldBlockInformation = currentBlockInformation;
649 beginLoop(node); 635 currentBlockInformation = node.loopInformation;
636 bool prettyLoop = handleLoop(node);
637 currentBlockInformation = oldBlockInformation;
638 if (prettyLoop) {
639 visitBasicBlock(node.loopInformation.joinBlock);
640 return;
650 } 641 }
642 beginLoop(node);
651 } 643 }
644
652 iterateBasicBlock(node); 645 iterateBasicBlock(node);
653 } 646 }
654 647
655 void iterateBasicBlock(HBasicBlock node) { 648 void iterateBasicBlock(HBasicBlock node) {
656 currentBlock = node; 649 currentBlock = node;
657 HInstruction instruction = node.first; 650 HInstruction instruction = node.first;
658 while (instruction != null) { 651 while (instruction != null) {
659 if (instruction === node.last) { 652 if (instruction === node.last) {
660 for (HBasicBlock successor in node.successors) { 653 for (HBasicBlock successor in node.successors) {
661 int index = successor.predecessors.indexOf(node); 654 int index = successor.predecessors.indexOf(node);
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after
1614 buffer.add(') '); 1607 buffer.add(') ');
1615 bailout(node, 'Not a string'); 1608 bailout(node, 'Not a string');
1616 } else if (node.isMutableArray()) { 1609 } else if (node.isMutableArray()) {
1617 buffer.add('if ('); 1610 buffer.add('if (');
1618 checkObject(input, '!=='); 1611 checkObject(input, '!==');
1619 buffer.add('||'); 1612 buffer.add('||');
1620 checkArray(input, '!=='); 1613 checkArray(input, '!==');
1621 buffer.add('||'); 1614 buffer.add('||');
1622 checkImmutableArray(input); 1615 checkImmutableArray(input);
1623 buffer.add(') '); 1616 buffer.add(') ');
1624 bailout(node, 'Not a mutable array'); 1617 bailout(node, 'Not a mutable array');
1625 } else if (node.isArray()) { 1618 } else if (node.isArray()) {
1626 buffer.add('if ('); 1619 buffer.add('if (');
1627 checkObject(input, '!=='); 1620 checkObject(input, '!==');
1628 buffer.add('||'); 1621 buffer.add('||');
1629 checkArray(input, '!=='); 1622 checkArray(input, '!==');
1630 buffer.add(') '); 1623 buffer.add(') ');
1631 bailout(node, 'Not an array'); 1624 bailout(node, 'Not an array');
1632 } else if (node.isStringOrArray()) { 1625 } else if (node.isStringOrArray()) {
1633 buffer.add('if ('); 1626 buffer.add('if (');
1634 checkString(input, '!=='); 1627 checkString(input, '!==');
1635 buffer.add(' && ('); 1628 buffer.add(' && (');
1636 checkObject(input, '!=='); 1629 checkObject(input, '!==');
1637 buffer.add('||'); 1630 buffer.add('||');
1638 checkArray(input, '!=='); 1631 checkArray(input, '!==');
1639 buffer.add(')) '); 1632 buffer.add(')) ');
1640 bailout(node, 'Not a string or array'); 1633 bailout(node, 'Not a string or array');
1641 } else { 1634 } else {
1642 unreachable(); 1635 unreachable();
1643 } 1636 }
1644 buffer.add(';\n'); 1637 buffer.add(';\n');
1645 } 1638 }
1646 1639
1647 void beginLoop(HBasicBlock block) { 1640 void beginLoop(HBasicBlock block) {
1648 addIndentation(); 1641 addIndentation();
1649 HLoopInformation info = block.blockInformation; 1642 for (LabelElement label in block.loopInformation.labels) {
1650 for (LabelElement label in info.labels) {
1651 writeLabel(label); 1643 writeLabel(label);
1652 buffer.add(":"); 1644 buffer.add(":");
1653 } 1645 }
1654 buffer.add('while (true) {\n'); 1646 buffer.add('while (true) {\n');
1655 indent++; 1647 indent++;
1656 } 1648 }
1657 1649
1658 void endLoop(HBasicBlock block) { 1650 void endLoop(HBasicBlock block) {
1659 indent--; 1651 indent--;
1660 addIndentation(); 1652 addIndentation();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1759 HBoundsCheck instruction = argument; 1751 HBoundsCheck instruction = argument;
1760 return unwrap(instruction.index); 1752 return unwrap(instruction.index);
1761 } else if (argument is HTypeGuard) { 1753 } else if (argument is HTypeGuard) {
1762 HTypeGuard instruction = argument; 1754 HTypeGuard instruction = argument;
1763 return unwrap(instruction.guarded); 1755 return unwrap(instruction.guarded);
1764 } else { 1756 } else {
1765 return argument; 1757 return argument;
1766 } 1758 }
1767 } 1759 }
1768 1760
1769 bool visitLoopInfo(HLoopInformation info) => false; 1761 bool handleLoop(HBasicBlock node) => false;
1770 1762
1771 void visitTypeGuard(HTypeGuard node) { 1763 void visitTypeGuard(HTypeGuard node) {
1772 indent--; 1764 indent--;
1773 addIndentation(); 1765 addIndentation();
1774 buffer.add('case ${node.state}:\n'); 1766 buffer.add('case ${node.state}:\n');
1775 indent++; 1767 indent++;
1776 addIndentation(); 1768 addIndentation();
1777 buffer.add('state = 0;\n'); 1769 buffer.add('state = 0;\n');
1778 1770
1779 setup.add(' case ${node.state}:\n'); 1771 setup.add(' case ${node.state}:\n');
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 indent++; 1803 indent++;
1812 } 1804 }
1813 1805
1814 void endBailoutSwitch() { 1806 void endBailoutSwitch() {
1815 indent--; // Close 'case'. 1807 indent--; // Close 'case'.
1816 indent--; 1808 indent--;
1817 addIndentation(); 1809 addIndentation();
1818 buffer.add('}\n'); // Close 'switch'. 1810 buffer.add('}\n'); // Close 'switch'.
1819 } 1811 }
1820 1812
1813
1821 void beginLoop(HBasicBlock block) { 1814 void beginLoop(HBasicBlock block) {
1822 // TODO(ngeoffray): Don't put labels on loops that don't bailout. 1815 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
1823 String newLabel = pushLabel(); 1816 String newLabel = pushLabel();
1824 if (block.hasGuards()) { 1817 if (block.hasGuards()) {
1825 startBailoutCase(block.guards, const <HTypeGuard>[]); 1818 startBailoutCase(block.guards, const <HTypeGuard>[]);
1826 } 1819 }
1827 1820
1828 addIndentation(); 1821 addIndentation();
1829 HLoopInformation loopInformation = block.blockInformation; 1822 for (LabelElement label in block.loopInformation.labels) {
1830 for (LabelElement label in loopInformation.labels) {
1831 writeLabel(label); 1823 writeLabel(label);
1832 buffer.add(":"); 1824 buffer.add(":");
1833 } 1825 }
1834 buffer.add('$newLabel: while (true) {\n'); 1826 buffer.add('$newLabel: while (true) {\n');
1835 indent++; 1827 indent++;
1836 1828
1837 if (block.hasGuards()) { 1829 if (block.hasGuards()) {
1838 startBailoutSwitch(); 1830 startBailoutSwitch();
1839 } 1831 }
1840 } 1832 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1913 startBailoutSwitch(); 1905 startBailoutSwitch();
1914 } 1906 }
1915 } 1907 }
1916 1908
1917 void endElse(HIf node) { 1909 void endElse(HIf node) {
1918 if (node.elseBlock.hasGuards()) { 1910 if (node.elseBlock.hasGuards()) {
1919 endBailoutSwitch(); 1911 endBailoutSwitch();
1920 } 1912 }
1921 } 1913 }
1922 } 1914 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/builder.dart ('k') | lib/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698