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); |