Index: sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart |
index e4a4ad825268f78016408b3c07a567ed5a23077c..601b07431da8abab19b53984f8b4f7f3087bd044 100644 |
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart |
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart |
@@ -186,7 +186,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor |
if (interceptedClasses.contains(backend.jsNumberClass) |
&& !(interceptedClasses.contains(backend.jsDoubleClass) |
|| interceptedClasses.contains(backend.jsIntClass))) { |
- for (var user in node.usedBy) { |
+ for (HInstruction user in node.usedBy) { |
if (user is! HInvoke) continue; |
Set<ClassElement> intercepted = |
backend.getInterceptedClassesOn(user.selector.name); |
@@ -200,7 +200,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor |
} |
} else { |
interceptedClasses = new Set<ClassElement>(); |
- for (var user in node.usedBy) { |
+ for (HInstruction user in node.usedBy) { |
if (user is HIs) { |
// Is-checks can be performed on any intercepted class. |
interceptedClasses.addAll(backend.interceptedClasses); |
@@ -215,8 +215,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor |
HInstruction receiver = node.receiver; |
if (canUseSelfForInterceptor(receiver, interceptedClasses)) { |
- node.block.rewrite(node, receiver); |
- return false; |
+ return rewriteToUseSelfAsInterceptor(node, receiver); |
} |
// Try computing a constant interceptor. |
@@ -254,6 +253,50 @@ class SsaSimplifyInterceptors extends HBaseVisitor |
return true; |
} |
+ bool rewriteToUseSelfAsInterceptor(HInterceptor node, HInstruction receiver) { |
+ List<HInstruction> users = node.usedBy.toList(); |
floitsch
2013/12/19 10:29:16
Add comment explaining that we need to get the lis
|
+ |
+ node.block.rewrite(node, receiver); |
+ |
+ // We have just rewritten: |
+ // |
+ // m = getInterceptor(a) |
+ // m.foo$1(a, x) |
+ // --> |
+ // m = getInterceptor(a) |
+ // a.foo$1(a, x) |
+ // |
+ // For the rewritten calls, if the selector matches only methods that ignore |
+ // the explicit receiver parameter, replace occurences of the receiver |
+ // argument with a dummy receiver '0': |
+ // |
+ // a.foo$1(a, x) --> a.foo$1(0, x) |
+ // |
+ JavaScriptBackend backend = compiler.backend; |
+ for (HInstruction user in users) { |
+ if (user is HInvokeDynamic) { |
+ HInvokeDynamic invoke = user; |
+ if (invoke.receiver == receiver && |
+ !backend.isInterceptedMixinSelector(invoke.selector)) { |
+ HInstruction receiverArgument = invoke.inputs[1]; |
+ // TODO(15720): The test here should be |
+ // |
+ // invoke.receiver.nonCheck() == receiverArgument.nonCheck() |
+ // |
+ if (invoke.receiver == receiverArgument) { // recognize a.foo(a,...) |
+ Constant constant = new DummyReceiverConstant( |
+ receiverArgument.instructionType); |
+ HConstant dummy = graph.addConstant(constant, compiler); |
+ receiverArgument.usedBy.remove(invoke); |
+ invoke.inputs[1] = dummy; |
+ dummy.usedBy.add(invoke); |
+ } |
+ } |
+ } |
+ } |
+ return false; |
+ } |
+ |
bool visitOneShotInterceptor(HOneShotInterceptor node) { |
HInstruction constant = tryComputeConstantInterceptor( |
node.inputs[1], node.interceptedClasses); |