| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 if (operand is HConstant) { | 144 if (operand is HConstant) { |
| 145 UnaryOperation operation = node.operation; | 145 UnaryOperation operation = node.operation; |
| 146 HConstant receiver = operand; | 146 HConstant receiver = operand; |
| 147 Constant folded = operation.fold(receiver.constant); | 147 Constant folded = operation.fold(receiver.constant); |
| 148 if (folded !== null) return graph.addConstant(folded); | 148 if (folded !== null) return graph.addConstant(folded); |
| 149 } | 149 } |
| 150 return node; | 150 return node; |
| 151 } | 151 } |
| 152 | 152 |
| 153 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { | 153 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { |
| 154 if (node.name == const SourceString('length') && | 154 if (node.isLengthGetter()) { |
| 155 node.inputs[1].isConstantString()) { | 155 HInstruction input = node.inputs[1]; |
| 156 HConstant input = node.inputs[1]; | 156 if (input.isConstantString()) { |
| 157 StringConstant constant = input.constant; | 157 StringConstant constant = input.constant; |
| 158 DartString string = constant.value; | 158 return graph.addConstantInt(constant.length); |
| 159 return graph.addConstantInt(string.length); | 159 } else if (input.isConstantList()) { |
| 160 ListConstant constant = input.constant; |
| 161 return graph.addConstantInt(constant.length); |
| 162 } else if (input.isConstantMap()) { |
| 163 MapConstant constant = input.constant; |
| 164 return graph.addConstantInt(constant.length); |
| 165 } |
| 166 } |
| 167 return node; |
| 168 } |
| 169 |
| 170 HInstruction visitInvokeDynamic(HInvokeDynamic node) { |
| 171 HType receiverType = node.receiver.propagatedType; |
| 172 if (receiverType.isNonPrimitive()) { |
| 173 HNonPrimitiveType type = receiverType; |
| 174 Element element = type.lookupMember(node.name); |
| 175 // TODO(ngeoffray): Also fold if it's a getter or variable. |
| 176 if (element != null && element.isFunction()) { |
| 177 FunctionElement method = element; |
| 178 FunctionParameters parameters = method.computeParameters(compiler); |
| 179 if (node.selector.applies(parameters)) { |
| 180 if (parameters.optionalParameterCount == 0) { |
| 181 node.element = element; |
| 182 } |
| 183 // TODO(ngeoffray): If the method has optional parameters, |
| 184 // we should pass the default values here. |
| 185 } |
| 186 } |
| 187 } |
| 188 return node; |
| 189 } |
| 190 |
| 191 HInstruction fromInterceptorToDynamicInvocation( |
| 192 HInvokeStatic node, SourceString methodName) { |
| 193 HNonPrimitiveType type = node.inputs[1].propagatedType; |
| 194 Element element = type.lookupMember(methodName); |
| 195 HInvokeDynamicMethod result = new HInvokeDynamicMethod( |
| 196 node.selector, |
| 197 methodName, |
| 198 node.inputs.getRange(1, node.inputs.length - 1)); |
| 199 result.element = element; |
| 200 return result; |
| 201 } |
| 202 |
| 203 HInstruction visitIndex(HIndex node) { |
| 204 if (node.receiver.isNonPrimitive()) { |
| 205 SourceString methodName = Elements.constructOperatorName( |
| 206 const SourceString('operator'), const SourceString('[]')); |
| 207 return fromInterceptorToDynamicInvocation(node, methodName); |
| 208 } |
| 209 return node; |
| 210 } |
| 211 |
| 212 HInstruction visitIndexAssign(HIndexAssign node) { |
| 213 if (node.receiver.isNonPrimitive()) { |
| 214 SourceString methodName = Elements.constructOperatorName( |
| 215 const SourceString('operator'), const SourceString('[]=')); |
| 216 return fromInterceptorToDynamicInvocation(node, methodName); |
| 160 } | 217 } |
| 161 return node; | 218 return node; |
| 162 } | 219 } |
| 163 | 220 |
| 164 HInstruction visitInvokeBinary(HInvokeBinary node) { | 221 HInstruction visitInvokeBinary(HInvokeBinary node) { |
| 165 HInstruction left = node.left; | 222 HInstruction left = node.left; |
| 166 HInstruction right = node.right; | 223 HInstruction right = node.right; |
| 167 if (left is HConstant && right is HConstant) { | 224 if (left is HConstant && right is HConstant) { |
| 168 BinaryOperation operation = node.operation; | 225 BinaryOperation operation = node.operation; |
| 169 HConstant op1 = left; | 226 HConstant op1 = left; |
| 170 HConstant op2 = right; | 227 HConstant op2 = right; |
| 171 Constant folded = operation.fold(op1.constant, op2.constant); | 228 Constant folded = operation.fold(op1.constant, op2.constant); |
| 172 if (folded !== null) return graph.addConstant(folded); | 229 if (folded !== null) return graph.addConstant(folded); |
| 173 } | 230 } |
| 231 |
| 232 if (left.isNonPrimitive() && node.operation.isUserDefinable()) { |
| 233 SourceString methodName = Elements.constructOperatorName( |
| 234 const SourceString('operator'), node.operation.name); |
| 235 return fromInterceptorToDynamicInvocation(node, methodName); |
| 236 } |
| 174 return node; | 237 return node; |
| 175 } | 238 } |
| 176 | 239 |
| 177 HInstruction visitEquals(HEquals node) { | 240 HInstruction visitEquals(HEquals node) { |
| 178 HInstruction left = node.left; | 241 HInstruction left = node.left; |
| 179 HInstruction right = node.right; | 242 HInstruction right = node.right; |
| 180 if (!left.isConstant() && right.isConstantNull()) { | 243 |
| 181 // TODO(floitsch): cache interceptors. | 244 if (left.isConstant() && right.isConstant()) { |
| 182 HStatic target = new HStatic( | 245 return visitInvokeBinary(node); |
| 183 compiler.builder.interceptors.getEqualsNullInterceptor()); | |
| 184 node.block.addBefore(node,target); | |
| 185 return new HEquals(target, node.left, node.right); | |
| 186 } | 246 } |
| 247 |
| 248 if (right.isConstantNull()) { |
| 249 if (left.propagatedType.isUseful()) { |
| 250 return graph.addConstantBool(false); |
| 251 } else { |
| 252 // TODO(floitsch): cache interceptors. |
| 253 HStatic target = new HStatic( |
| 254 compiler.builder.interceptors.getEqualsNullInterceptor()); |
| 255 node.block.addBefore(node,target); |
| 256 return new HEquals(target, node.left, node.right); |
| 257 } |
| 258 } |
| 259 |
| 260 if (left.isNonPrimitive()) { |
| 261 // If the left-hand side is guaranteed to be a non-primitive |
| 262 // type and and it does not define operator==, we can just emit |
| 263 // an identity check. |
| 264 HNonPrimitiveType type = left.propagatedType; |
| 265 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); |
| 266 if (element === null) { |
| 267 // TODO(floitsch): cache interceptors. |
| 268 HStatic target = new HStatic( |
| 269 compiler.builder.interceptors.getTripleEqualsInterceptor()); |
| 270 return new HIdentity(target, left, right); |
| 271 } |
| 272 } |
| 273 |
| 187 // All other cases are dealt with by the [visitInvokeBinary]. | 274 // All other cases are dealt with by the [visitInvokeBinary]. |
| 188 return visitInvokeBinary(node); | 275 return visitInvokeBinary(node); |
| 189 } | 276 } |
| 190 | 277 |
| 191 HInstruction visitTypeGuard(HTypeGuard node) { | 278 HInstruction visitTypeGuard(HTypeGuard node) { |
| 192 HInstruction value = node.guarded; | 279 HInstruction value = node.guarded; |
| 193 HType combinedType = value.propagatedType.combine(node.propagatedType); | 280 HType combinedType = value.propagatedType.combine(node.propagatedType); |
| 194 return (combinedType == value.propagatedType) ? value : node; | 281 return (combinedType == value.propagatedType) ? value : node; |
| 195 } | 282 } |
| 196 | 283 |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 } | 804 } |
| 718 } | 805 } |
| 719 if (!canBeMoved) continue; | 806 if (!canBeMoved) continue; |
| 720 | 807 |
| 721 // This is safe because we are running after GVN. | 808 // This is safe because we are running after GVN. |
| 722 // TODO(ngeoffray): ensure GVN has been run. | 809 // TODO(ngeoffray): ensure GVN has been run. |
| 723 set_.add(current); | 810 set_.add(current); |
| 724 } | 811 } |
| 725 } | 812 } |
| 726 } | 813 } |
| OLD | NEW |