| OLD | NEW |
| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 204 } |
| 205 return node; | 205 return node; |
| 206 } | 206 } |
| 207 | 207 |
| 208 HInstruction handleInterceptorCall(HInvokeDynamic node) { | 208 HInstruction handleInterceptorCall(HInvokeDynamic node) { |
| 209 HInstruction input = node.inputs[1]; | 209 HInstruction input = node.inputs[1]; |
| 210 if (input.isString(types) | 210 if (input.isString(types) |
| 211 && node.selector.name == const SourceString('toString')) { | 211 && node.selector.name == const SourceString('toString')) { |
| 212 return node.inputs[1]; | 212 return node.inputs[1]; |
| 213 } | 213 } |
| 214 // Check if this call does not need to be intercepted. | |
| 215 HType type = types[input]; | |
| 216 var interceptor = node.inputs[0]; | |
| 217 if (node is HInvokeDynamicMethod | |
| 218 && interceptor is !HThis | |
| 219 && !type.canBePrimitive()) { | |
| 220 // If the type can be null, and the intercepted method can be in | |
| 221 // the object class, keep the interceptor. | |
| 222 if (type.canBeNull() | |
| 223 && interceptor.interceptedClasses.contains(compiler.objectClass)) { | |
| 224 return node; | |
| 225 } | |
| 226 // Change the call to a regular invoke dynamic call. | |
| 227 return new HInvokeDynamicMethod( | |
| 228 node.selector, node.inputs.getRange(1, node.inputs.length - 1)); | |
| 229 } | |
| 230 return node; | 214 return node; |
| 231 } | 215 } |
| 232 | 216 |
| 233 bool isFixedSizeListConstructor(HInvokeStatic node) { | 217 bool isFixedSizeListConstructor(HInvokeStatic node) { |
| 234 Element element = node.target.element; | 218 Element element = node.target.element; |
| 235 return element.getEnclosingClass() == compiler.listClass | 219 return element.getEnclosingClass() == compiler.listClass |
| 236 && node.inputs.length == 2 | 220 && node.inputs.length == 2 |
| 237 && node.inputs[1].isInteger(types); | 221 && node.inputs[1].isInteger(types); |
| 238 } | 222 } |
| 239 | 223 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 259 node.element = element; | 243 node.element = element; |
| 260 } | 244 } |
| 261 // TODO(ngeoffray): If the method has optional parameters, | 245 // TODO(ngeoffray): If the method has optional parameters, |
| 262 // we should pass the default values here. | 246 // we should pass the default values here. |
| 263 } | 247 } |
| 264 } | 248 } |
| 265 } | 249 } |
| 266 return node; | 250 return node; |
| 267 } | 251 } |
| 268 | 252 |
| 269 HInstruction fromNativeToDynamicInvocation(HInvokeStatic node, | 253 HInstruction fromInterceptorToDynamicInvocation(HInvokeStatic node, |
| 270 Selector selector) { | 254 Selector selector) { |
| 271 HBoundedType type = types[node.inputs[1]]; | 255 HBoundedType type = types[node.inputs[1]]; |
| 272 HInvokeDynamicMethod result = new HInvokeDynamicMethod( | 256 HInvokeDynamicMethod result = new HInvokeDynamicMethod( |
| 273 selector, | 257 selector, |
| 274 node.inputs.getRange(1, node.inputs.length - 1)); | 258 node.inputs.getRange(1, node.inputs.length - 1)); |
| 275 if (type.isExact()) { | 259 if (type.isExact()) { |
| 276 HBoundedType concrete = type; | 260 HBoundedType concrete = type; |
| 277 result.element = concrete.lookupMember(selector.name); | 261 result.element = concrete.lookupMember(selector.name); |
| 278 } | 262 } |
| 279 return result; | 263 return result; |
| 280 } | 264 } |
| 281 | 265 |
| 282 HInstruction visitIntegerCheck(HIntegerCheck node) { | 266 HInstruction visitIntegerCheck(HIntegerCheck node) { |
| 283 HInstruction value = node.value; | 267 HInstruction value = node.value; |
| 284 if (value.isInteger(types)) return value; | 268 if (value.isInteger(types)) return value; |
| 285 if (value.isConstant()) { | 269 if (value.isConstant()) { |
| 286 HConstant constantInstruction = value; | 270 HConstant constantInstruction = value; |
| 287 assert(!constantInstruction.constant.isInt()); | 271 assert(!constantInstruction.constant.isInt()); |
| 288 if (!constantSystem.isInt(constantInstruction.constant)) { | 272 if (!constantSystem.isInt(constantInstruction.constant)) { |
| 289 // -0.0 is a double but will pass the runtime integer check. | 273 // -0.0 is a double but will pass the runtime integer check. |
| 290 node.alwaysFalse = true; | 274 node.alwaysFalse = true; |
| 291 } | 275 } |
| 292 } | 276 } |
| 293 return node; | 277 return node; |
| 294 } | 278 } |
| 295 | 279 |
| 296 | 280 |
| 297 HInstruction visitIndex(HIndex node) { | 281 HInstruction visitIndex(HIndex node) { |
| 298 if (!node.receiver.canBePrimitive(types)) { | 282 if (!node.receiver.canBePrimitive(types)) { |
| 299 Selector selector = new Selector.index(); | 283 Selector selector = new Selector.index(); |
| 300 return fromNativeToDynamicInvocation(node, selector); | 284 return fromInterceptorToDynamicInvocation(node, selector); |
| 301 } | 285 } |
| 302 return node; | 286 return node; |
| 303 } | 287 } |
| 304 | 288 |
| 305 HInstruction visitIndexAssign(HIndexAssign node) { | 289 HInstruction visitIndexAssign(HIndexAssign node) { |
| 306 if (!node.receiver.canBePrimitive(types)) { | 290 if (!node.receiver.canBePrimitive(types)) { |
| 307 Selector selector = new Selector.indexSet(); | 291 Selector selector = new Selector.indexSet(); |
| 308 return fromNativeToDynamicInvocation(node, selector); | 292 return fromInterceptorToDynamicInvocation(node, selector); |
| 309 } | 293 } |
| 310 return node; | 294 return node; |
| 311 } | 295 } |
| 312 | 296 |
| 313 HInstruction visitInvokeBinary(HInvokeBinary node) { | 297 HInstruction visitInvokeBinary(HInvokeBinary node) { |
| 314 HInstruction left = node.left; | 298 HInstruction left = node.left; |
| 315 HInstruction right = node.right; | 299 HInstruction right = node.right; |
| 316 BinaryOperation operation = node.operation(constantSystem); | 300 BinaryOperation operation = node.operation(constantSystem); |
| 317 if (left is HConstant && right is HConstant) { | 301 if (left is HConstant && right is HConstant) { |
| 318 HConstant op1 = left; | 302 HConstant op1 = left; |
| 319 HConstant op2 = right; | 303 HConstant op2 = right; |
| 320 Constant folded = operation.fold(op1.constant, op2.constant); | 304 Constant folded = operation.fold(op1.constant, op2.constant); |
| 321 if (folded != null) return graph.addConstant(folded); | 305 if (folded != null) return graph.addConstant(folded); |
| 322 } | 306 } |
| 323 | 307 |
| 324 if (!left.canBePrimitive(types) | 308 if (!left.canBePrimitive(types) |
| 325 && operation.isUserDefinable() | 309 && operation.isUserDefinable() |
| 326 // The equals operation is being optimized in visitEquals. | 310 // The equals operation is being optimized in visitEquals. |
| 327 && node is! HEquals) { | 311 && node is! HEquals) { |
| 328 Selector selector = new Selector.binaryOperator(operation.name); | 312 Selector selector = new Selector.binaryOperator(operation.name); |
| 329 return fromNativeToDynamicInvocation(node, selector); | 313 return fromInterceptorToDynamicInvocation(node, selector); |
| 330 } | 314 } |
| 331 return node; | 315 return node; |
| 332 } | 316 } |
| 333 | 317 |
| 334 bool allUsersAreBoolifies(HInstruction instruction) { | 318 bool allUsersAreBoolifies(HInstruction instruction) { |
| 335 List<HInstruction> users = instruction.usedBy; | 319 List<HInstruction> users = instruction.usedBy; |
| 336 int length = users.length; | 320 int length = users.length; |
| 337 for (int i = 0; i < length; i++) { | 321 for (int i = 0; i < length; i++) { |
| 338 if (users[i] is! HBoolify) return false; | 322 if (users[i] is! HBoolify) return false; |
| 339 } | 323 } |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 for (int i = 0; i < node.inputs.length; i++) { | 649 for (int i = 0; i < node.inputs.length; i++) { |
| 666 HInstruction part = node.inputs[i]; | 650 HInstruction part = node.inputs[i]; |
| 667 if (!part.isConstant()) return node; | 651 if (!part.isConstant()) return node; |
| 668 HConstant constant = part; | 652 HConstant constant = part; |
| 669 if (!constant.constant.isPrimitive()) return node; | 653 if (!constant.constant.isPrimitive()) return node; |
| 670 PrimitiveConstant primitive = constant.constant; | 654 PrimitiveConstant primitive = constant.constant; |
| 671 folded = new DartString.concat(folded, primitive.toDartString()); | 655 folded = new DartString.concat(folded, primitive.toDartString()); |
| 672 } | 656 } |
| 673 return graph.addConstant(constantSystem.createString(folded, node.node)); | 657 return graph.addConstant(constantSystem.createString(folded, node.node)); |
| 674 } | 658 } |
| 675 | |
| 676 HInstruction visitInterceptor(HInterceptor node) { | |
| 677 if (node.isConstant()) return node; | |
| 678 HType type = types[node.inputs[0]]; | |
| 679 Element constantInterceptor; | |
| 680 if (type.isInteger()) { | |
| 681 constantInterceptor = backend.intInterceptor; | |
| 682 } else if (type.isDouble()) { | |
| 683 constantInterceptor = backend.doubleInterceptor; | |
| 684 } else if (type.isBoolean()) { | |
| 685 constantInterceptor = backend.boolInterceptor; | |
| 686 } else if (type.isString()) { | |
| 687 constantInterceptor = backend.stringInterceptor; | |
| 688 } else if (type.isArray()) { | |
| 689 constantInterceptor = backend.arrayInterceptor; | |
| 690 } else if (type.isNull()) { | |
| 691 constantInterceptor = backend.nullInterceptor; | |
| 692 } else if (type.isNumber()) { | |
| 693 Set<ClassElement> intercepted = node.interceptedClasses; | |
| 694 // If the method being intercepted is not defined in [int] or | |
| 695 // [double] we can safely use the number interceptor. | |
| 696 if (!intercepted.contains(compiler.intClass) | |
| 697 && !intercepted.contains(compiler.doubleClass)) { | |
| 698 constantInterceptor = backend.numberInterceptor; | |
| 699 } | |
| 700 } | |
| 701 | |
| 702 if (constantInterceptor == null) return node; | |
| 703 | |
| 704 ConstantHandler handler = compiler.constantHandler; | |
| 705 return graph.addConstant(handler.compileVariable(constantInterceptor)); | |
| 706 } | |
| 707 } | 659 } |
| 708 | 660 |
| 709 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { | 661 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { |
| 710 final HTypeMap types; | 662 final HTypeMap types; |
| 711 final ConstantSystem constantSystem; | 663 final ConstantSystem constantSystem; |
| 712 final Set<HInstruction> boundsChecked; | 664 final Set<HInstruction> boundsChecked; |
| 713 final WorkItem work; | 665 final WorkItem work; |
| 714 final String name = "SsaCheckInserter"; | 666 final String name = "SsaCheckInserter"; |
| 715 HGraph graph; | 667 HGraph graph; |
| 716 Element lengthInterceptor; | 668 Element lengthInterceptor; |
| (...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 } | 1353 } |
| 1402 | 1354 |
| 1403 // For other fields having setters in the generative constructor body, set | 1355 // For other fields having setters in the generative constructor body, set |
| 1404 // the type to UNKNOWN to avoid relying on the type set in the initializer | 1356 // the type to UNKNOWN to avoid relying on the type set in the initializer |
| 1405 // list. | 1357 // list. |
| 1406 allSetters.forEach((Element element) { | 1358 allSetters.forEach((Element element) { |
| 1407 backend.registerFieldConstructor(element, HType.UNKNOWN); | 1359 backend.registerFieldConstructor(element, HType.UNKNOWN); |
| 1408 }); | 1360 }); |
| 1409 } | 1361 } |
| 1410 } | 1362 } |
| OLD | NEW |