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

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

Issue 10383062: Avoid inserting new temporaries because of HTypeConversion nodes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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 buildJavaScriptFunction(FunctionElement element, 10 String buildJavaScriptFunction(FunctionElement element,
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 if (!isGeneratingDeclaration()) { 510 if (!isGeneratingDeclaration()) {
511 delayedVarDecl = delayedVarDecl.prepend(variableName); 511 delayedVarDecl = delayedVarDecl.prepend(variableName);
512 } 512 }
513 } else { 513 } else {
514 buffer.add("var "); 514 buffer.add("var ");
515 buffer.add(variableName); 515 buffer.add(variableName);
516 } 516 }
517 } 517 }
518 518
519 void define(HInstruction instruction) { 519 void define(HInstruction instruction) {
520 String name = temporary(instruction); 520 bool needsVar = !instruction.usedBy.isEmpty();
521 declareVariable(name); 521 if (needsVar) {
522 buffer.add(" = "); 522 if (instruction.returnsInput()) {
Lasse Reichstein Nielsen 2012/05/08 12:39:08 Use single if with '&&'.
ngeoffray 2012/05/08 16:09:12 Done.
523 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); 523 HInstruction input = instruction.input;
524 // We only need a new var if [input] is generated at use site
525 // but is not a trivial code motion invariant instruction (eg
floitsch 2012/05/08 13:21:42 "like for". There is enough space.
ngeoffray 2012/05/08 16:09:12 Done.
526 // parameters or this).
527 //
528 // For example:
529 // Foo a = this;
530 // print(a);
531 // print(a);
532 //
533 // In checked mode does not need a new variable:
floitsch 2012/05/08 13:21:42 In checked mode no new variable is needed:
ngeoffray 2012/05/08 16:09:12 Done.
534 // FooTypeCheck(this);
535 // print(this);
536 // print(this);
537 //
538 // But for this example:
539 // Foo a = foo();
540 // print(a);
541 // print(a);
542 //
543 // We need a new variable:
544 // var a = FooTypeCheck(foo());
545 // print(a);
546 // print(a);
547 needsVar = isGenerateAtUseSite(input) && !input.isCodeMotionInvariant();
floitsch 2012/05/08 13:21:42 If I understand correctly it is crucial that 'defi
ngeoffray 2012/05/08 16:09:12 Done.
548 }
549 }
550 if (needsVar) {
551 String name = temporary(instruction);
552 declareVariable(name);
553 buffer.add(" = ");
554 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
555 } else {
556 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
557 }
524 } 558 }
525 559
526 void use(HInstruction argument, int expectedPrecedenceForArgument) { 560 void use(HInstruction argument, int expectedPrecedenceForArgument) {
527 if (isGenerateAtUseSite(argument)) { 561 if (argument.returnsInput()) {
562 HInstruction input = argument.input;
563 if (isGenerateAtUseSite(argument) && isGenerateAtUseSite(input)) {
564 // If both instructions can be generated at use site, we can
565 // just visit [argument].
566 //
567 // For example:
568 // Foo a = foo();
569 // print(a);
570 //
571 // In checked mode will turn into:
572 // print(FooTypeCheck(foo()));
573 visit(argument, expectedPrecedenceForArgument);
574 } else if (isGenerateAtUseSite(input) && !input.isCodeMotionInvariant()) {
Lasse Reichstein Nielsen 2012/05/08 12:39:08 Please explain the use of isCodeMotionInvariant.
ngeoffray 2012/05/08 16:09:12 Done.
575 // If [argument] cannot be generated at use site, but [input]
576 // can, use the temporary of [argument].
577 //
578 // For example:
579 // Foo a = foo();
580 // print(a);
581 // print(a);
582 //
583 // In checked mode will turn into:
584 // var a = FooTypeCheck(foo());
585 // print(a);
586 // print(a);
587 buffer.add(temporary(argument));
588 } else {
589 // Otherwise we just use [input].
Lasse Reichstein Nielsen 2012/05/08 12:39:08 Please give example of output here too. What happe
ngeoffray 2012/05/08 16:09:12 Done.
590 use(input, expectedPrecedenceForArgument);
591 }
592 } else if (isGenerateAtUseSite(argument)) {
528 visit(argument, expectedPrecedenceForArgument); 593 visit(argument, expectedPrecedenceForArgument);
529 } else if (argument is HIntegerCheck) {
530 HIntegerCheck instruction = argument;
531 use(instruction.value, expectedPrecedenceForArgument);
532 } else if (argument is HBoundsCheck) {
533 HBoundsCheck instruction = argument;
534 use(instruction.index, expectedPrecedenceForArgument);
535 } else if (argument is HTypeGuard) {
536 HTypeGuard instruction = argument;
537 use(instruction.guarded, expectedPrecedenceForArgument);
538 } else { 594 } else {
539 buffer.add(temporary(argument)); 595 buffer.add(temporary(argument));
540 } 596 }
541 } 597 }
542 598
543 visit(HInstruction node, int expectedPrecedenceForNode) { 599 visit(HInstruction node, int expectedPrecedenceForNode) {
544 int oldPrecedence = this.expectedPrecedence; 600 int oldPrecedence = this.expectedPrecedence;
545 this.expectedPrecedence = expectedPrecedenceForNode; 601 this.expectedPrecedence = expectedPrecedenceForNode;
546 node.accept(this); 602 node.accept(this);
547 this.expectedPrecedence = oldPrecedence; 603 this.expectedPrecedence = oldPrecedence;
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 } 1112 }
1057 } 1113 }
1058 1114
1059 void iterateBasicBlock(HBasicBlock node) { 1115 void iterateBasicBlock(HBasicBlock node) {
1060 HInstruction instruction = node.first; 1116 HInstruction instruction = node.first;
1061 while (instruction != null) { 1117 while (instruction != null) {
1062 if (instruction === node.last) { 1118 if (instruction === node.last) {
1063 assignPhisOfAllSuccessors(node); 1119 assignPhisOfAllSuccessors(node);
1064 } 1120 }
1065 1121
1066 if (instruction is HGoto || instruction is HExit || instruction is HTry) { 1122 if (isGenerateAtUseSite(instruction)) {
1067 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1123 if (instruction is HIf) {
1068 return; 1124 HIf hif = instruction;
1069 } else if (!isGenerateAtUseSite(instruction)) { 1125 // The "if" is implementing part of a logical expression.
1070 if (instruction is !HIf 1126 // Skip directly forward to to its latest successor, since everything
1071 && instruction is !HTypeGuard 1127 // in-between must also be generateAtUseSite.
1072 && instruction is !HLoopBranch 1128 assert(hif.trueBranch.id < hif.falseBranch.id);
1073 && !isGeneratingExpression()) { 1129 visitBasicBlock(hif.falseBranch);
1074 addIndentation();
1075 } 1130 }
1076 if (isGeneratingExpression()) { 1131 } else if (instruction is HControlFlow) {
1132 if (instruction is HLoopBranch && isGeneratingExpression()) {
1077 addExpressionSeparator(); 1133 addExpressionSeparator();
1078 } 1134 }
1079 if (instruction.usedBy.isEmpty() 1135 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1080 || instruction is HTypeGuard 1136 } else if (instruction is HTypeGuard) {
1081 || instruction is HCheck) { 1137 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1082 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1138 } else {
1083 } else { 1139 isGeneratingExpression() ? addExpressionSeparator() : addIndentation();
Lasse Reichstein Nielsen 2012/05/08 12:39:08 Use if. Please don't (try) to be clever with the c
ngeoffray 2012/05/08 16:09:12 Done.
1084 define(instruction); 1140 define(instruction);
1085 } 1141 if (!isGeneratingExpression()) buffer.add(';\n');
1086 // Control flow instructions, and some other instructions,
1087 // know how to handle ';'.
1088 if (instruction is !HControlFlow
1089 && instruction is !HTypeGuard
1090 && !isGeneratingExpression()) {
1091 buffer.add(';\n');
1092 }
1093 } else if (instruction is HIf) {
1094 HIf hif = instruction;
1095 // The "if" is implementing part of a logical expression.
1096 // Skip directly forward to to its latest successor, since everything
1097 // in-between must also be generateAtUseSite.
1098 assert(hif.trueBranch.id < hif.falseBranch.id);
1099 visitBasicBlock(hif.falseBranch);
1100 return;
1101 } 1142 }
1102 instruction = instruction.next; 1143 instruction = instruction.next;
1103 } 1144 }
1104 } 1145 }
1105 1146
1106 visitInvokeBinary(HInvokeBinary node, String op) { 1147 visitInvokeBinary(HInvokeBinary node, String op) {
1107 if (node.builtin) { 1148 if (node.builtin) {
1108 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; 1149 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op];
1109 beginExpression(operatorPrecedences.precedence); 1150 beginExpression(operatorPrecedences.precedence);
1110 use(node.left, operatorPrecedences.left); 1151 use(node.left, operatorPrecedences.left);
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 String operation = logicalOperations[node]; 1652 String operation = logicalOperations[node];
1612 if (operation !== null) { 1653 if (operation !== null) {
1613 emitLogicalOperation(node, operation); 1654 emitLogicalOperation(node, operation);
1614 } else { 1655 } else {
1615 HPhi canonicalPhi = phiEquivalence.getRepresentative(node); 1656 HPhi canonicalPhi = phiEquivalence.getRepresentative(node);
1616 buffer.add('${temporary(canonicalPhi)}'); 1657 buffer.add('${temporary(canonicalPhi)}');
1617 } 1658 }
1618 } 1659 }
1619 1660
1620 visitReturn(HReturn node) { 1661 visitReturn(HReturn node) {
1662 addIndentation();
1621 assert(node.inputs.length == 1); 1663 assert(node.inputs.length == 1);
1622 HInstruction input = node.inputs[0]; 1664 HInstruction input = node.inputs[0];
1623 if (input.isConstantNull()) { 1665 if (input.isConstantNull()) {
1624 buffer.add('return;\n'); 1666 buffer.add('return;\n');
1625 } else { 1667 } else {
1626 buffer.add('return '); 1668 buffer.add('return ');
1627 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1669 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1628 buffer.add(';\n'); 1670 buffer.add(';\n');
1629 } 1671 }
1630 } 1672 }
1631 1673
1632 visitThis(HThis node) { 1674 visitThis(HThis node) {
1633 buffer.add('this'); 1675 buffer.add('this');
1634 } 1676 }
1635 1677
1636 visitThrow(HThrow node) { 1678 visitThrow(HThrow node) {
1679 addIndentation();
1637 if (node.isRethrow) { 1680 if (node.isRethrow) {
1638 buffer.add('throw '); 1681 buffer.add('throw ');
1639 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1682 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1640 } else { 1683 } else {
1641 generateThrowWithHelper('captureStackTrace', node.inputs[0]); 1684 generateThrowWithHelper('captureStackTrace', node.inputs[0]);
1642 } 1685 }
1643 buffer.add(';\n'); 1686 buffer.add(';\n');
1644 } 1687 }
1645 1688
1646 visitBoundsCheck(HBoundsCheck node) { 1689 visitBoundsCheck(HBoundsCheck node) {
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
2026 buffer.add(".${name.slowToString()} === '${arguments.head}'"); 2069 buffer.add(".${name.slowToString()} === '${arguments.head}'");
2027 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2070 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2028 }); 2071 });
2029 } 2072 }
2030 if (node.nullOk) { 2073 if (node.nullOk) {
2031 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); 2074 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE);
2032 } 2075 }
2033 } 2076 }
2034 2077
2035 void visitTypeConversion(HTypeConversion node) { 2078 void visitTypeConversion(HTypeConversion node) {
2079 HInstruction input = node.inputs[0];
Lasse Reichstein Nielsen 2012/05/08 12:39:08 node.input? Why extract input here, when it's only
ngeoffray 2012/05/08 16:09:12 Done.
2036 if (node.checked) { 2080 if (node.checked) {
2037 Element element = node.type.computeType(compiler).element; 2081 Element element = node.type.computeType(compiler).element;
2038 compiler.registerIsCheck(element); 2082 compiler.registerIsCheck(element);
2039 SourceString helper; 2083 SourceString helper;
2040 String additionalArgument; 2084 String additionalArgument;
2041 bool nativeCheck = 2085 bool nativeCheck =
2042 compiler.emitter.nativeEmitter.requiresNativeIsCheck(element); 2086 compiler.emitter.nativeEmitter.requiresNativeIsCheck(element);
2043 beginExpression(JSPrecedence.CALL_PRECEDENCE); 2087 beginExpression(JSPrecedence.CALL_PRECEDENCE);
2044 2088
2045 if (element == compiler.stringClass) { 2089 if (element == compiler.stringClass) {
(...skipping 27 matching lines...) Expand all
2073 } else if (nativeCheck) { 2117 } else if (nativeCheck) {
2074 helper = const SourceString('callTypeCheck'); 2118 helper = const SourceString('callTypeCheck');
2075 } else { 2119 } else {
2076 helper = const SourceString('propertyTypeCheck'); 2120 helper = const SourceString('propertyTypeCheck');
2077 } 2121 }
2078 } 2122 }
2079 Element helperElement = compiler.findHelper(helper); 2123 Element helperElement = compiler.findHelper(helper);
2080 compiler.registerStaticUse(helperElement); 2124 compiler.registerStaticUse(helperElement);
2081 buffer.add(compiler.namer.isolateAccess(helperElement)); 2125 buffer.add(compiler.namer.isolateAccess(helperElement));
2082 buffer.add('('); 2126 buffer.add('(');
2083 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 2127 use(input, JSPrecedence.EXPRESSION_PRECEDENCE);
2084 if (additionalArgument !== null) buffer.add(", '$additionalArgument'"); 2128 if (additionalArgument !== null) buffer.add(", '$additionalArgument'");
2085 buffer.add(')'); 2129 buffer.add(')');
2086 endExpression(JSPrecedence.CALL_PRECEDENCE); 2130 endExpression(JSPrecedence.CALL_PRECEDENCE);
2087 } else { 2131 } else {
2088 use(node.inputs[0], expectedPrecedence); 2132 visit(input, expectedPrecedence);
2089 } 2133 }
2090 } 2134 }
2091 } 2135 }
2092 2136
2093 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { 2137 class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
2094 SsaOptimizedCodeGenerator(compiler, work, parameters, parameterNames) 2138 SsaOptimizedCodeGenerator(compiler, work, parameters, parameterNames)
2095 : super(compiler, work, parameters, parameterNames); 2139 : super(compiler, work, parameters, parameterNames);
2096 2140
2097 void beginGraph(HGraph graph) {} 2141 void beginGraph(HGraph graph) {}
2098 void endGraph(HGraph graph) {} 2142 void endGraph(HGraph graph) {}
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
2487 startBailoutSwitch(); 2531 startBailoutSwitch();
2488 } 2532 }
2489 } 2533 }
2490 2534
2491 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2535 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2492 if (labeledBlockInfo.body.start.hasGuards()) { 2536 if (labeledBlockInfo.body.start.hasGuards()) {
2493 endBailoutSwitch(); 2537 endBailoutSwitch();
2494 } 2538 }
2495 } 2539 }
2496 } 2540 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen_helpers.dart » ('j') | lib/compiler/implementation/ssa/nodes.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698