Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 14840) |
+++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
@@ -46,6 +46,15 @@ |
} |
Element getStaticInterceptor(Selector selector) { |
+ // Check if we have an interceptor method implemented with |
+ // interceptor classes. |
+ JavaScriptBackend backend = compiler.backend; |
+ if (backend.shouldInterceptSelector(selector)) { |
+ backend.addInterceptedSelector(selector); |
+ return backend.getInterceptorMethod; |
+ } |
+ |
+ // Fall back to the old interceptor mechanism. |
String name = selector.name.slowToString(); |
if (selector.isGetter()) { |
// TODO(lrn): If there is no get-interceptor, but there is a |
@@ -400,8 +409,8 @@ |
}); |
if (closureData.isClosure()) { |
// Inside closure redirect references to itself to [:this:]. |
- HInstruction thisInstruction = new HThis(); |
- builder.add(thisInstruction); |
+ HInstruction thisInstruction = new HThis(closureData.thisElement); |
+ builder.graph.entry.addAtEntry(thisInstruction); |
updateLocal(closureData.closureElement, thisInstruction); |
} else if (element.isInstanceMember() |
|| element.isGenerativeConstructor()) { |
@@ -410,8 +419,10 @@ |
// context. |
ClassElement cls = element.getEnclosingClass(); |
DartType type = cls.computeType(builder.compiler); |
- HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type)); |
- builder.add(thisInstruction); |
+ HInstruction thisInstruction = new HThis(closureData.thisElement, |
+ new HBoundedType.nonNull(type)); |
+ thisInstruction.sourceElement = closureData.thisElement; |
+ builder.graph.entry.addAtEntry(thisInstruction); |
directLocals[closureData.thisElement] = thisInstruction; |
} |
} |
@@ -2270,17 +2281,35 @@ |
: elements.getSelector(send.selector); |
assert(selector.isGetter()); |
SourceString getterName = selector.name; |
- Element staticInterceptor = null; |
+ Element interceptor = null; |
if (elements[send] == null && methodInterceptionEnabled) { |
- staticInterceptor = interceptors.getStaticInterceptor(selector); |
+ interceptor = interceptors.getStaticInterceptor(selector); |
} |
bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
- if (staticInterceptor != null) { |
- HStatic target = new HStatic(staticInterceptor); |
- add(target); |
- List<HInstruction> inputs = <HInstruction>[target, receiver]; |
- pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter), |
- send); |
+ if (interceptor != null) { |
+ if (interceptor == backend.getInterceptorMethod) { |
+ // If we're using an interceptor class, emit a call to the |
+ // interceptor method and then the actual dynamic call on the |
+ // interceptor object. |
+ HStatic target = new HStatic(interceptor); |
+ add(target); |
+ HInstruction instruction = |
+ new HInvokeStatic(<HInstruction>[target, receiver]); |
+ add(instruction); |
+ instruction = new HInvokeDynamicGetter( |
+ selector, null, instruction, !hasGetter); |
+ // Add the receiver as an argument to the getter call on the |
+ // interceptor. |
+ instruction.inputs.add(receiver); |
+ pushWithPosition(instruction, send); |
+ } else { |
+ // Use the old, deprecated interceptor mechanism. |
+ HStatic target = new HStatic(interceptor); |
+ add(target); |
+ List<HInstruction> inputs = <HInstruction>[target, receiver]; |
+ pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter), |
+ send); |
+ } |
} else { |
pushWithPosition( |
new HInvokeDynamicGetter(selector, null, receiver, !hasGetter), send); |
@@ -2608,13 +2637,34 @@ |
interceptor = interceptors.getStaticInterceptor(selector); |
} |
if (interceptor != null) { |
- HStatic target = new HStatic(interceptor); |
- add(target); |
- inputs.add(target); |
- visit(node.receiver); |
- inputs.add(pop()); |
- addGenericSendArgumentsToList(node.arguments, inputs); |
- pushWithPosition(new HInvokeInterceptor(selector, inputs), node); |
+ // TODO(ngeoffray): The receiver never being null is currently the |
+ // case, but should be updated once we start implementing more of |
+ // the interceptors class. |
+ assert(node.receiver != null); |
+ if (interceptor == backend.getInterceptorMethod) { |
+ HStatic target = new HStatic(interceptor); |
+ add(target); |
+ visit(node.receiver); |
+ HInstruction receiver = pop(); |
+ HInstruction instruction = |
+ new HInvokeStatic(<HInstruction>[target, receiver]); |
+ add(instruction); |
+ inputs.add(instruction); |
+ inputs.add(receiver); |
+ addDynamicSendArgumentsToList(node, inputs); |
+ // The first entry in the inputs list is the interceptor. The |
+ // second is the receiver, and the others are the arguments. |
+ instruction = new HInvokeDynamicMethod(selector, inputs); |
+ pushWithPosition(instruction, node); |
+ } else { |
+ HStatic target = new HStatic(interceptor); |
+ add(target); |
+ inputs.add(target); |
+ visit(node.receiver); |
+ inputs.add(pop()); |
+ addGenericSendArgumentsToList(node.arguments, inputs); |
+ pushWithPosition(new HInvokeInterceptor(selector, inputs), node); |
+ } |
return; |
} |