Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 15192) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
| @@ -60,38 +60,13 @@ |
| compiler.unimplemented('Unknown operator', node: op); |
| } |
| - Element getStaticInterceptor(Selector selector) { |
| - // Check if we have an interceptor method implemented with |
| - // interceptor classes. |
| + /** |
| + * Returns a set of interceptor classes that contain a member whose |
| + * signature matches the given [selector]. |
| + */ |
| + Set<ClassElement> getInterceptedClassesOn(Selector selector) { |
| JavaScriptBackend backend = compiler.backend; |
| - if (backend.shouldInterceptSelector(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 |
| - // method-interceptor, we should generate a get-interceptor automatically. |
| - String mangledName = "get\$$name"; |
| - return compiler.findInterceptor(new SourceString(mangledName)); |
| - } else if (selector.isSetter()) { |
| - String mangledName = "set\$$name"; |
| - return compiler.findInterceptor(new SourceString(mangledName)); |
| - } else { |
| - Element element = compiler.findInterceptor(new SourceString(name)); |
| - if (element != null && element.isFunction()) { |
| - // Only pick the function element with the short name if the |
| - // number of parameters it expects matches the number we're |
| - // passing modulo the receiver. |
| - FunctionElement function = element; |
| - if (function.parameterCount(compiler) == selector.argumentCount + 1) { |
| - return element; |
| - } |
| - } |
| - String longMangledName = "$name\$${selector.argumentCount}"; |
| - return compiler.findInterceptor(new SourceString(longMangledName)); |
| - } |
| + return backend.getInterceptedClassesOn(selector); |
| } |
| Element getOperatorInterceptor(Operator op) { |
| @@ -2409,7 +2384,7 @@ |
| return result; |
| } |
| - Element getInterceptor(Send send, Selector selector) { |
| + Set<ClassElement> getInterceptedClassesOn(Send send, Selector selector) { |
| if (!methodInterceptionEnabled) return null; |
| if (!backend.isInterceptorClass(currentElement.getEnclosingClass()) |
| && send.receiver == null) { |
| @@ -2417,7 +2392,7 @@ |
| // object. |
| return null; |
| } |
| - return interceptors.getStaticInterceptor(selector); |
| + return interceptors.getInterceptedClassesOn(selector); |
| } |
| void generateInstanceGetterWithCompiledReceiver(Send send, |
| @@ -2431,10 +2406,11 @@ |
| : elements.getSelector(send.selector); |
| assert(selector.isGetter()); |
| SourceString getterName = selector.name; |
| - Element interceptor = getInterceptor(send, selector); |
| + Set<ClassElement> interceptedClasses = |
| + getInterceptedClassesOn(send, selector); |
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| - if (interceptor == backend.getInterceptorMethod && interceptor != null) { |
| + if (interceptedClasses != null) { |
|
karlklose
2012/11/21 14:45:53
"|| interceptedClasses.isEmpty" to be sure?
ahe
2012/11/22 13:26:11
An assertion would be more appropriate. The docum
|
| // If we're using an interceptor class, emit a call to the |
| // interceptor method and then the actual dynamic call on the |
| // interceptor object. |
| @@ -2443,7 +2419,7 @@ |
| && send.receiver == null) { |
| instruction = thisInstruction; |
| } else { |
| - pushInvokeInterceptor(interceptor, receiver); |
| + pushInvokeInterceptor(interceptedClasses, receiver); |
| instruction = pop(); |
| } |
| instruction = new HInvokeDynamicGetter( |
| @@ -2504,9 +2480,10 @@ |
| Selector selector = elements.getSelector(send); |
| assert(selector.isSetter()); |
| SourceString setterName = selector.name; |
| - Element interceptor = getInterceptor(send, selector); |
| bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); |
| - if (interceptor != null && interceptor == backend.getInterceptorMethod) { |
| + Set<ClassElement> interceptedClasses = |
| + getInterceptedClassesOn(send, selector); |
| + if (interceptedClasses != null) { |
| // If we're using an interceptor class, emit a call to the |
| // interceptor method and then the actual dynamic call on the |
| // interceptor object. |
| @@ -2515,7 +2492,7 @@ |
| && send.receiver == null) { |
| instruction = thisInstruction; |
| } else { |
| - pushInvokeInterceptor(interceptor, receiver); |
| + pushInvokeInterceptor(interceptedClasses, receiver); |
| instruction = pop(); |
| } |
| instruction = new HInvokeDynamicSetter( |
| @@ -2567,13 +2544,9 @@ |
| } |
| } |
| - void pushInvokeInterceptor(Element element, HInstruction receiver) { |
| - HInstruction interceptor = new HStatic(element); |
| - add(interceptor); |
| - List<HInstruction> inputs = <HInstruction>[interceptor, receiver]; |
| - HInstruction result = new HInvokeStatic(inputs); |
| - result.isSideEffectFree = true; |
| - push(result); |
| + void pushInvokeInterceptor(Set<ClassElement> intercepted, |
| + HInstruction receiver) { |
| + push(new HInterceptor(intercepted, receiver)); |
| } |
| void pushInvokeHelper0(Element helper) { |
| @@ -2793,28 +2766,27 @@ |
| dartMethodName = node.selector.asIdentifier().source; |
| } |
| - Element interceptor = getInterceptor(node, selector); |
| + Set<ClassElement> interceptedClasses = |
| + getInterceptedClassesOn(node, selector); |
| - if (interceptor != null) { |
| - if (interceptor == backend.getInterceptorMethod) { |
| - if (backend.isInterceptorClass(currentElement.getEnclosingClass()) |
| - && node.receiver == null) { |
| - inputs.add(thisInstruction); |
| - inputs.add(localsHandler.readThis()); |
| - } else { |
| - visit(node.receiver); |
| - HInstruction receiver = pop(); |
| - pushInvokeInterceptor(interceptor, receiver); |
| - inputs.add(pop()); |
| - 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. |
| - HInstruction instruction = new HInvokeDynamicMethod(selector, inputs); |
| - pushWithPosition(instruction, node); |
| - return; |
| + if (interceptedClasses != null) { |
| + if (backend.isInterceptorClass(currentElement.getEnclosingClass()) |
| + && node.receiver == null) { |
| + inputs.add(thisInstruction); |
| + inputs.add(localsHandler.readThis()); |
| + } else { |
| + visit(node.receiver); |
| + HInstruction receiver = pop(); |
| + pushInvokeInterceptor(interceptedClasses, receiver); |
| + inputs.add(pop()); |
| + 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. |
| + HInstruction instruction = new HInvokeDynamicMethod(selector, inputs); |
| + pushWithPosition(instruction, node); |
| + return; |
| } |
| Element element = elements[node]; |
| @@ -3865,14 +3837,15 @@ |
| SourceString iteratorName = const SourceString("iterator"); |
| Selector selector = |
| new Selector.call(iteratorName, work.element.getLibrary(), 0); |
| - Element element = interceptors.getStaticInterceptor(selector); |
| + Set<ClassElement> interceptedClasses = |
| + interceptors.getInterceptedClassesOn(selector); |
| visit(node.expression); |
| HInstruction receiver = pop(); |
| - if (element == null) { |
| + if (interceptedClasses == null) { |
| iterator = new HInvokeDynamicMethod(selector, <HInstruction>[receiver]); |
| } else { |
| - pushInvokeInterceptor(element, receiver); |
| - HInvokeStatic interceptor = pop(); |
| + pushInvokeInterceptor(interceptedClasses, receiver); |
| + HInterceptor interceptor = pop(); |
| iterator = new HInvokeDynamicMethod( |
| selector, <HInstruction>[interceptor, receiver]); |
| } |
| @@ -3881,10 +3854,6 @@ |
| HInstruction buildCondition() { |
| SourceString name = const SourceString('hasNext'); |
| Selector selector = new Selector.getter(name, work.element.getLibrary()); |
| - if (interceptors.getStaticInterceptor(selector) != null) { |
| - compiler.internalError("hasNext getter must not be intercepted", |
| - node: node); |
| - } |
| bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| push(new HInvokeDynamicGetter(selector, null, iterator, !hasGetter)); |
| return popBoolified(); |