| Index: pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
|
| index 0bcc9df4e7306a36a7030bf8a3cf8678404b6d31..e7226103f74b8cd56a5047aef9ff51a9db0240ff 100644
|
| --- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
|
| @@ -52,7 +52,15 @@ class UnsugarVisitor extends RecursiveVisitor {
|
|
|
| UnsugarVisitor(this._glue);
|
|
|
| + bool methodUsesReceiverArgument(FunctionElement function) {
|
| + assert(_glue.isInterceptedMethod(function));
|
| + ClassElement clazz = function.enclosingClass.declaration;
|
| + return _glue.isInterceptorClass(clazz) ||
|
| + _glue.isUsedAsMixin(clazz);
|
| + }
|
| +
|
| void rewrite(FunctionDefinition function) {
|
| + thisParameter = function.thisParameter;
|
| bool inInterceptedMethod = _glue.isInterceptedMethod(function.element);
|
|
|
| if (function.element.name == '==' &&
|
| @@ -64,7 +72,6 @@ class UnsugarVisitor extends RecursiveVisitor {
|
| }
|
|
|
| if (inInterceptedMethod) {
|
| - thisParameter = function.thisParameter;
|
| ThisParameterLocal holder = thisParameter.hint;
|
| explicitReceiverParameter = new Parameter(
|
| new ExplicitReceiverParameterEntity(
|
| @@ -75,7 +82,7 @@ class UnsugarVisitor extends RecursiveVisitor {
|
| // Set all parent pointers.
|
| _parentVisitor.visit(function);
|
|
|
| - if (inInterceptedMethod) {
|
| + if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) {
|
| explicitReceiverParameter.substituteFor(thisParameter);
|
| }
|
|
|
| @@ -235,8 +242,13 @@ class UnsugarVisitor extends RecursiveVisitor {
|
| /// The type propagation pass will later narrow the set of interceptors
|
| /// based on the input type, and the let sinking pass will propagate the
|
| /// getInterceptor call closer to its use when this is profitable.
|
| - Interceptor getInterceptorFor(Primitive prim, Selector selector,
|
| - SourceInformation sourceInformation) {
|
| + Primitive getInterceptorFor(Primitive prim, Selector selector,
|
| + SourceInformation sourceInformation) {
|
| + if (prim == explicitReceiverParameter) {
|
| + // If the receiver is the explicit receiver, we are calling a method in
|
| + // the same interceptor.
|
| + return thisParameter;
|
| + }
|
| assert(prim is! Interceptor);
|
| Interceptor interceptor = interceptors[prim];
|
| if (interceptor == null) {
|
| @@ -255,37 +267,24 @@ class UnsugarVisitor extends RecursiveVisitor {
|
| }
|
|
|
| processInvokeMethod(InvokeMethod node) {
|
| - Selector selector = node.selector;
|
| - if (!_glue.isInterceptedSelector(selector)) return;
|
| -
|
| - Primitive receiver = node.receiver.definition;
|
| - Primitive newReceiver;
|
| -
|
| - if (receiver == explicitReceiverParameter) {
|
| - // If the receiver is the explicit receiver, we are calling a method in
|
| - // the same interceptor:
|
| - // Change 'receiver.foo()' to 'this.foo(receiver)'.
|
| - newReceiver = thisParameter;
|
| - } else {
|
| - newReceiver = getInterceptorFor(
|
| - receiver, node.selector, node.sourceInformation);
|
| + if (_glue.isInterceptedSelector(node.selector)) {
|
| + // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`.
|
| + Primitive receiver = node.receiver.definition;
|
| + Primitive newReceiver =
|
| + getInterceptorFor(receiver, node.selector, node.sourceInformation);
|
| + node.arguments.insert(0, node.receiver);
|
| + node.receiver = new Reference<Primitive>(newReceiver);
|
| }
|
| -
|
| - node.arguments.insert(0, node.receiver);
|
| - node.receiver = new Reference<Primitive>(newReceiver);
|
| }
|
|
|
| processInvokeMethodDirectly(InvokeMethodDirectly node) {
|
| if (_glue.isInterceptedMethod(node.target)) {
|
| - Primitive nullPrim = nullConstant;
|
| - insertLetPrim(nullPrim, node);
|
| + // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`.
|
| + Primitive receiver = node.receiver.definition;
|
| + Primitive newReceiver =
|
| + getInterceptorFor(receiver, node.selector, node.sourceInformation);
|
| node.arguments.insert(0, node.receiver);
|
| - // TODO(sra): `null` is not adequate. Interceptors project the class
|
| - // hierarchy onto an interceptor hierarchy. A super call that does a
|
| - // method call will use the javascript 'this' parameter to avoid calling
|
| - // getInterceptor again, so the receiver must be the interceptor (likely
|
| - // `this`), not `null`.
|
| - node.receiver = new Reference<Primitive>(nullPrim);
|
| + node.receiver = new Reference<Primitive>(newReceiver);
|
| }
|
| }
|
|
|
|
|