| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
| 6 String get name(); | 6 String get name(); |
| 7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
| 8 } | 8 } |
| 9 | 9 |
| 10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 HInstruction visitInstruction(HInstruction node) { | 83 HInstruction visitInstruction(HInstruction node) { |
| 84 return node; | 84 return node; |
| 85 } | 85 } |
| 86 | 86 |
| 87 HInstruction visitBoolify(HBoolify node) { | 87 HInstruction visitBoolify(HBoolify node) { |
| 88 List<HInstruction> inputs = node.inputs; | 88 List<HInstruction> inputs = node.inputs; |
| 89 assert(inputs.length == 1); | 89 assert(inputs.length == 1); |
| 90 HInstruction input = inputs[0]; | 90 HInstruction input = inputs[0]; |
| 91 if (input.isBoolean()) return input; | 91 if (input.isBoolean()) return input; |
| 92 // All values !== true are boolified to false. | 92 // All values !== true are boolified to false. |
| 93 if (input.type.isKnown()) { | 93 if (input.type.isKnown()) return graph.addNewLiteralFalse(); |
| 94 return graph.addConstantBool(false); | |
| 95 } | |
| 96 return node; | 94 return node; |
| 97 } | 95 } |
| 98 | 96 |
| 99 HInstruction visitNot(HNot node) { | 97 HInstruction visitNot(HNot node) { |
| 100 List<HInstruction> inputs = node.inputs; | 98 List<HInstruction> inputs = node.inputs; |
| 101 assert(inputs.length == 1); | 99 assert(inputs.length == 1); |
| 102 HInstruction input = inputs[0]; | 100 HInstruction input = inputs[0]; |
| 103 if (input is HConstant) { | 101 if (input is HLiteral) { |
| 104 HConstant constant = input; | 102 HLiteral literal = input; |
| 105 bool isTrue = constant.constant.isTrue(); | 103 return graph.addNewLiteralBool(literal.value !== true); |
| 106 return graph.addConstantBool(!isTrue); | |
| 107 } | 104 } |
| 108 return node; | 105 return node; |
| 109 } | 106 } |
| 110 | 107 |
| 111 HInstruction visitInvokeBinary(HInvokeBinary node) => node.fold(graph); | 108 HInstruction visitInvokeBinary(HInvokeBinary node) => node.fold(graph); |
| 112 HInstruction visitInvokeUnary(HInvokeUnary node) => node.fold(graph); | 109 HInstruction visitInvokeUnary(HInvokeUnary node) => node.fold(graph); |
| 113 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) | 110 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) |
| 114 => node.fold(graph); | 111 => node.fold(graph); |
| 115 | 112 |
| 116 HInstruction visitAdd(HAdd node) { | 113 HInstruction visitAdd(HAdd node) { |
| 117 // TODO(floitsch): move this code into the compile-time constant handler. | |
| 118 | |
| 119 // String + is defined for all literals. We don't need to know which | 114 // String + is defined for all literals. We don't need to know which |
| 120 // type the right-hand side is. | 115 // literal type the right-hand side is. |
| 121 | 116 |
| 122 if (node.left.isString()) { | 117 if (node.left.isString()) { |
| 123 // First try to eliminate adding the empty string to a string. | 118 // First try to eliminate adding the empty string to a string. |
| 124 if (node.right.isConstantString()) { | 119 if (node.right.isLiteralString()) { |
| 125 HConstant right = node.right; | 120 HLiteral right = node.right; |
| 126 Constant rightStringConstant = right.constant; | 121 DartString rightString = right.value; |
| 127 DartString rightString = rightStringConstant.value; | |
| 128 if (rightString.isEmpty()) { | 122 if (rightString.isEmpty()) { |
| 129 // String has no content, i.e., it's the empty string. | 123 // String has no content, i.e., it's the empty string. |
| 130 return node.left; | 124 return node.left; |
| 131 } | 125 } |
| 132 } | 126 } |
| 133 // Then, if both are constants, try to do the concatenation statically. | 127 // Then, if both are literals, try to do the concatenation statically. |
| 134 if (node.left.isConstantString()) { | 128 if (node.left.isLiteralString()) { |
| 135 HConstant left = node.left; | 129 HLiteral left = node.left; |
| 136 Constant leftStringConstant = left.constant; | 130 DartString leftString = left.value; |
| 137 DartString leftString = leftStringConstant.value; | |
| 138 if (leftString.isEmpty()) { | 131 if (leftString.isEmpty()) { |
| 139 // Left is empty String. | 132 // Left is empty String. |
| 140 if (node.right.isString()) { | 133 if (node.right.isString()) { |
| 141 // Right is already a String, just return that. | 134 // Right is already a String, just return that. |
| 142 return node.right; | 135 return node.right; |
| 143 } | 136 } |
| 144 if (node.right is HConstant) { | 137 if (node.right is HLiteral) { |
| 145 HConstant right = node.right; | 138 HLiteral right = node.right; |
| 146 // Right is a constant, so we can statically convert it to String | 139 // Right is a literal, so we can statically convert it to String |
| 147 // and return that. | 140 // and return that. |
| 148 // Remaining literal types are represented by their Dart value. | 141 // Remaining literal types are represented by their Dart value. |
| 149 if (right.isConstantBoolean() || | 142 assert(right.isLiteralBoolean() || |
| 150 right.isConstantNumber() || | 143 right.isLiteralNumber() || |
| 151 right.isConstantNull()) { | 144 right.isLiteralNull()); |
| 152 PrimitiveConstant rightConstant = right.constant; | 145 String str = right.value.toString(); |
| 153 String str = rightConstant.value.toString(); | 146 return graph.addNewLiteralString(new DartString.literal(str)); |
| 154 return graph.addConstantString(new DartString.literal(str)); | |
| 155 } | |
| 156 } | 147 } |
| 157 } | 148 } |
| 158 // TODO(lrn): Perform concatenation in Dart. | 149 // TODO(lrn): Perform concatenation in Dart. |
| 159 } | 150 } |
| 160 } | 151 } |
| 161 return visitInvokeBinary(node); | 152 return visitInvokeBinary(node); |
| 162 } | 153 } |
| 163 | 154 |
| 155 HInstruction visitEquals(HEquals node) { |
| 156 if (node.left is HLiteral && node.right is HLiteral) { |
| 157 HLiteral op1 = node.left; |
| 158 HLiteral op2 = node.right; |
| 159 if (op1.isLiteralString()) { |
| 160 if (op2.isLiteralString() && op1.value.definitelyEquals(op2.value)) { |
| 161 return graph.addNewLiteralTrue(); |
| 162 } |
| 163 } else { |
| 164 return graph.addNewLiteralBool(op1.value == op2.value); |
| 165 } |
| 166 } else if (node.right.isLiteralNull()) { |
| 167 HStatic target = new HStatic( |
| 168 compiler.builder.interceptors.getEqualsNullInterceptor()); |
| 169 node.block.addBefore(node, target); |
| 170 return new HEquals(target, node.left, node.right); |
| 171 } |
| 172 return node; |
| 173 } |
| 174 |
| 164 HInstruction visitTypeGuard(HTypeGuard node) { | 175 HInstruction visitTypeGuard(HTypeGuard node) { |
| 165 HInstruction value = node.guarded; | 176 HInstruction value = node.guarded; |
| 166 return (value.type.combine(node.type) == value.type) ? value : node; | 177 return (value.type.combine(node.type) == value.type) ? value : node; |
| 167 } | 178 } |
| 168 | 179 |
| 169 HInstruction visitIntegerCheck(HIntegerCheck node) { | 180 HInstruction visitIntegerCheck(HIntegerCheck node) { |
| 170 HInstruction value = node.value; | 181 HInstruction value = node.value; |
| 171 return value.isInteger() ? value : node; | 182 return value.isInteger() ? value : node; |
| 172 } | 183 } |
| 173 } | 184 } |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 } | 636 } |
| 626 } | 637 } |
| 627 if (!canBeMoved) continue; | 638 if (!canBeMoved) continue; |
| 628 | 639 |
| 629 // This is safe because we are running after GVN. | 640 // This is safe because we are running after GVN. |
| 630 // TODO(ngeoffray): ensure GVN has been run. | 641 // TODO(ngeoffray): ensure GVN has been run. |
| 631 set_.add(current); | 642 set_.add(current); |
| 632 } | 643 } |
| 633 } | 644 } |
| 634 } | 645 } |
| OLD | NEW |