| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 19046)
|
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy)
|
| @@ -325,9 +325,10 @@
|
| }
|
|
|
| // If this method is an intercepted method, add the extra
|
| - // parameter to it, that is the actual receiver.
|
| + // parameter to it, that is the actual receiver for intercepted
|
| + // classes, or the same as [:this:] for non-intercepted classes.
|
| ClassElement cls = element.getEnclosingClass();
|
| - if (builder.backend.isInterceptorClass(cls)) {
|
| + if (builder.backend.isInterceptedMethod(element)) {
|
| HType type = HType.UNKNOWN;
|
| if (cls == builder.backend.jsArrayClass) {
|
| type = HType.READABLE_ARRAY;
|
| @@ -348,7 +349,10 @@
|
| HParameterValue value = new HParameterValue(parameter);
|
| builder.graph.entry.addAfter(
|
| directLocals[closureData.thisElement], value);
|
| - directLocals[closureData.thisElement] = value;
|
| + if (builder.backend.isInterceptorClass(cls.declaration)) {
|
| + // Only use the extra parameter in intercepted classes.
|
| + directLocals[closureData.thisElement] = value;
|
| + }
|
| value.instructionType = type;
|
| }
|
| }
|
| @@ -895,6 +899,18 @@
|
| // check at the beginning of the method. This is to avoid having
|
| // call sites do the null check.
|
| if (name == const SourceString('==')) {
|
| + if (functionElement.getEnclosingClass() == compiler.objectClass) {
|
| + // We special case [Object.operator==] because we know the
|
| + // receiver is not null and therefore can just do an identity
|
| + // check on [:this:]. The interceptor classes have their own
|
| + // synthesized [:operator==:] method.
|
| + HInstruction parameter = parameters.values.first;
|
| + HIdentity identity = new HIdentity(graph.thisInstruction, parameter);
|
| + add(identity);
|
| + HReturn ret = new HReturn(identity);
|
| + close(ret).addSuccessor(graph.exit);
|
| + return closeFunction();
|
| + }
|
| handleIf(
|
| function,
|
| () {
|
| @@ -2351,13 +2367,9 @@
|
| }
|
|
|
| /**
|
| - * Returns a set of interceptor classes that contain a member whose
|
| - * signature matches the given [selector].
|
| + * Returns a set of interceptor classes that contain the given
|
| + * [selector].
|
| */
|
| - Set<ClassElement> getInterceptedClassesOn(Selector selector) {
|
| - return backend.getInterceptedClassesOn(selector);
|
| - }
|
| -
|
| void generateInstanceGetterWithCompiledReceiver(Send send,
|
| HInstruction receiver) {
|
| assert(Elements.isInstanceSend(send, elements));
|
| @@ -2369,7 +2381,8 @@
|
| : elements.getSelector(send.selector);
|
| assert(selector.isGetter());
|
| SourceString getterName = selector.name;
|
| - Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
|
| + Set<ClassElement> interceptedClasses =
|
| + backend.getInterceptedClassesOn(getterName);
|
|
|
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
|
| HInstruction instruction;
|
| @@ -2444,7 +2457,8 @@
|
| assert(selector.isSetter());
|
| SourceString setterName = selector.name;
|
| bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
|
| - Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
|
| + Set<ClassElement> interceptedClasses =
|
| + backend.getInterceptedClassesOn(setterName);
|
| if (interceptedClasses != null) {
|
| // If we're using an interceptor class, emit a call to the
|
| // getInterceptor method and then the actual dynamic call on the
|
| @@ -3101,10 +3115,11 @@
|
| argumentNamesInstruction,
|
| HType.UNKNOWN);
|
|
|
| - var inputs = <HInstruction>[
|
| - target,
|
| - self,
|
| - pop()];
|
| + var inputs = <HInstruction>[target, self];
|
| + if (backend.isInterceptedMethod(element)) {
|
| + inputs.add(self);
|
| + }
|
| + inputs.add(pop());
|
| push(new HInvokeSuper(inputs));
|
| }
|
|
|
| @@ -3126,6 +3141,9 @@
|
| HInstruction context = localsHandler.readThis();
|
| add(target);
|
| var inputs = <HInstruction>[target, context];
|
| + if (backend.isInterceptedMethod(element)) {
|
| + inputs.add(context);
|
| + }
|
| if (node.isPropertyAccess) {
|
| push(new HInvokeSuper(inputs));
|
| } else if (element.isFunction() || element.isGenerativeConstructor()) {
|
| @@ -3565,7 +3583,8 @@
|
| Selector selector,
|
| HInstruction receiver,
|
| List<HInstruction> arguments) {
|
| - Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
|
| + Set<ClassElement> interceptedClasses =
|
| + backend.getInterceptedClassesOn(selector.name);
|
| List<HInstruction> inputs = <HInstruction>[];
|
| bool isIntercepted = interceptedClasses != null;
|
| if (isIntercepted) {
|
| @@ -3919,7 +3938,8 @@
|
| SourceString iteratorName = const SourceString("iterator");
|
| Selector selector =
|
| new Selector.getter(iteratorName, currentElement.getLibrary());
|
| - Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
|
| + Set<ClassElement> interceptedClasses =
|
| + backend.getInterceptedClassesOn(selector.name);
|
| visit(node.expression);
|
| HInstruction receiver = pop();
|
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
|
|
|