Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| index 264334af9fc924e9a14b6a3c8d9a86de49e92c54..3d75f89100574fcec53ad91d33478ff4954f262d 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| @@ -250,21 +250,25 @@ class LocalsHandler { |
| HType cachedTypeOfThis; |
| - HType computeTypeOfThis() { |
| - Element element = closureData.thisElement; |
| - ClassElement cls = element.enclosingElement.getEnclosingClass(); |
| - Compiler compiler = builder.compiler; |
| - DartType type = cls.computeType(compiler); |
| - if (compiler.world.isUsedAsMixin(cls)) { |
| - // If the enclosing class is used as a mixin, [:this:] can be |
| - // of the class that mixins the enclosing class. These two |
| - // classes do not have a subclass relationship, so, for |
| - // simplicity, we mark the type as an interface type. |
| - cachedTypeOfThis = new HType.nonNullSubtype(type, compiler); |
| - } else { |
| - cachedTypeOfThis = new HType.nonNullSubclass(type, compiler); |
| + HType getTypeOfThis() { |
| + HType result = cachedTypeOfThis; |
| + if (result == null) { |
| + Element element = closureData.thisElement; |
| + ClassElement cls = element.enclosingElement.getEnclosingClass(); |
| + Compiler compiler = builder.compiler; |
| + DartType type = cls.computeType(compiler); |
| + if (compiler.world.isUsedAsMixin(cls)) { |
| + // If the enclosing class is used as a mixin, [:this:] can be |
| + // of the class that mixins the enclosing class. These two |
| + // classes do not have a subclass relationship, so, for |
| + // simplicity, we mark the type as an interface type. |
| + result = new HType.nonNullSubtype(type, compiler); |
| + } else { |
| + result = new HType.nonNullSubclass(type, compiler); |
| + } |
| + cachedTypeOfThis = result; |
| } |
| - return cachedTypeOfThis; |
| + return result; |
| } |
| /** |
| @@ -320,7 +324,7 @@ class LocalsHandler { |
| // not have any thisElement if the closure was created inside a static |
| // context. |
| HThis thisInstruction = new HThis( |
| - closureData.thisElement, computeTypeOfThis()); |
| + closureData.thisElement, getTypeOfThis()); |
| builder.graph.thisInstruction = thisInstruction; |
| builder.graph.entry.addAtEntry(thisInstruction); |
| directLocals[closureData.thisElement] = thisInstruction; |
| @@ -435,10 +439,7 @@ class LocalsHandler { |
| HInstruction readThis() { |
| HInstruction res = readLocal(closureData.thisElement); |
| if (res.guaranteedType == null) { |
| - if (cachedTypeOfThis == null) { |
| - computeTypeOfThis(); |
| - } |
| - res.guaranteedType = cachedTypeOfThis; |
| + res.guaranteedType = getTypeOfThis(); |
| } |
| return res; |
| } |
| @@ -2789,9 +2790,25 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| } |
| + bool isThisSend(Send send) { |
| + Node receiver = send.receiver; |
| + if (receiver == null) return true; |
| + Identifier identifier = receiver.asIdentifier(); |
| + return identifier != null && identifier.isThis(); |
| + } |
| + |
| visitDynamicSend(Send node) { |
| Selector selector = elements.getSelector(node); |
| + // TODO(kasperl): It would be much better to try to get the |
| + // guaranteed type of the receiver after we've evaluated it, but |
| + // because of the way inlining currently works that is hard to do |
| + // with re-evaluating the receiver. |
| + if (isThisSend(node)) { |
| + HType receiverType = localsHandler.getTypeOfThis(); |
| + selector = receiverType.refine(selector, compiler); |
| + } |
| + |
| SourceString dartMethodName; |
| bool isNotEquals = false; |
| if (node.isIndex && !node.arguments.tail.isEmpty) { |
| @@ -2806,9 +2823,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| dartMethodName = node.selector.asIdentifier().source; |
| } |
| - Element element = elements[node]; |
| + Element element = compiler.world.locateSingleElement(selector); |
| bool isClosureCall = false; |
| - if (element != null && compiler.world.hasNoOverridingMember(element)) { |
| + if (element != null) { |
| if (tryInlineMethod(element, selector, node.arguments, node)) { |
| if (element.isGetter()) { |
| // If the element is a getter, we are doing a closure call |
| @@ -3932,12 +3949,12 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| if (interceptedClasses == null) { |
| iterator = |
| - new HInvokeDynamicGetter(selector, null, receiver, hasGetter); |
| + new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); |
|
ngeoffray
2013/02/18 08:35:34
change the constructor to have a named argument? T
|
| } else { |
| HInterceptor interceptor = |
| invokeInterceptor(interceptedClasses, receiver, null); |
| iterator = |
| - new HInvokeDynamicGetter(selector, null, interceptor, hasGetter); |
| + new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter); |
| // Add the receiver as an argument to the getter call on the |
| // interceptor. |
| iterator.inputs.add(receiver); |
| @@ -3956,7 +3973,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| SourceString name = const SourceString('current'); |
| Selector call = new Selector.getter(name, currentElement.getLibrary()); |
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); |
| - push(new HInvokeDynamicGetter(call, null, iterator, hasGetter)); |
| + push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter)); |
| Element variable; |
| if (node.declaredIdentifier.asSend() != null) { |