Index: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/optimize.dart (revision 15265) |
+++ sdk/lib/_internal/compiler/implementation/ssa/optimize.dart (working copy) |
@@ -211,6 +211,22 @@ |
&& node.selector.name == const SourceString('toString')) { |
return node.inputs[1]; |
} |
+ // Check if this call does not need to be intercepted. |
+ HType type = types[input]; |
+ var interceptor = node.inputs[0]; |
+ if (node is HInvokeDynamicMethod |
+ && interceptor is !HThis |
+ && !type.canBePrimitive()) { |
+ // If the type can be null, and the intercepted method can be in |
+ // the object class, keep the interceptor. |
+ if (type.canBeNull() |
+ && interceptor.interceptedClasses.contains(compiler.objectClass)) { |
+ return node; |
+ } |
+ // Change the call to a regular invoke dynamic call. |
+ return new HInvokeDynamicMethod( |
+ node.selector, node.inputs.getRange(1, node.inputs.length - 1)); |
+ } |
return node; |
} |
@@ -250,8 +266,8 @@ |
return node; |
} |
- HInstruction fromInterceptorToDynamicInvocation(HInvokeStatic node, |
- Selector selector) { |
+ HInstruction fromNativeToDynamicInvocation(HInvokeStatic node, |
+ Selector selector) { |
HBoundedType type = types[node.inputs[1]]; |
HInvokeDynamicMethod result = new HInvokeDynamicMethod( |
selector, |
@@ -281,7 +297,7 @@ |
HInstruction visitIndex(HIndex node) { |
if (!node.receiver.canBePrimitive(types)) { |
Selector selector = new Selector.index(); |
- return fromInterceptorToDynamicInvocation(node, selector); |
+ return fromNativeToDynamicInvocation(node, selector); |
} |
return node; |
} |
@@ -289,7 +305,7 @@ |
HInstruction visitIndexAssign(HIndexAssign node) { |
if (!node.receiver.canBePrimitive(types)) { |
Selector selector = new Selector.indexSet(); |
- return fromInterceptorToDynamicInvocation(node, selector); |
+ return fromNativeToDynamicInvocation(node, selector); |
} |
return node; |
} |
@@ -310,7 +326,7 @@ |
// The equals operation is being optimized in visitEquals. |
&& node is! HEquals) { |
Selector selector = new Selector.binaryOperator(operation.name); |
- return fromInterceptorToDynamicInvocation(node, selector); |
+ return fromNativeToDynamicInvocation(node, selector); |
} |
return node; |
} |
@@ -656,6 +672,38 @@ |
} |
return graph.addConstant(constantSystem.createString(folded, node.node)); |
} |
+ |
+ HInstruction visitInterceptor(HInterceptor node) { |
+ if (node.isConstant()) return node; |
+ HType type = types[node.inputs[0]]; |
+ Element constantInterceptor; |
+ if (type.isInteger()) { |
+ constantInterceptor = backend.intInterceptor; |
+ } else if (type.isDouble()) { |
+ constantInterceptor = backend.doubleInterceptor; |
+ } else if (type.isBoolean()) { |
+ constantInterceptor = backend.boolInterceptor; |
+ } else if (type.isString()) { |
+ constantInterceptor = backend.stringInterceptor; |
+ } else if (type.isArray()) { |
+ constantInterceptor = backend.arrayInterceptor; |
+ } else if (type.isNull()) { |
+ constantInterceptor = backend.nullInterceptor; |
+ } else if (type.isNumber()) { |
+ Set<ClassElement> intercepted = node.interceptedClasses; |
+ // If the method being intercepted is not defined in [int] or |
+ // [double] we can safely use the number interceptor. |
+ if (!intercepted.contains(compiler.intClass) |
+ && !intercepted.contains(compiler.doubleClass)) { |
+ constantInterceptor = backend.numberInterceptor; |
+ } |
+ } |
+ |
+ if (constantInterceptor == null) return node; |
+ |
+ ConstantHandler handler = compiler.constantHandler; |
+ return graph.addConstant(handler.compileVariable(constantInterceptor)); |
+ } |
} |
class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { |