| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class Interceptors { | 7 class Interceptors { |
| 8 Compiler compiler; | 8 Compiler compiler; |
| 9 Interceptors(Compiler this.compiler); | 9 Interceptors(Compiler this.compiler); |
| 10 | 10 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 if (identical(name, '<<=')) return const SourceString('shl'); | 38 if (identical(name, '<<=')) return const SourceString('shl'); |
| 39 if (identical(name, '>>=')) return const SourceString('shr'); | 39 if (identical(name, '>>=')) return const SourceString('shr'); |
| 40 if (identical(name, '|=')) return const SourceString('or'); | 40 if (identical(name, '|=')) return const SourceString('or'); |
| 41 if (identical(name, '&=')) return const SourceString('and'); | 41 if (identical(name, '&=')) return const SourceString('and'); |
| 42 if (identical(name, '^=')) return const SourceString('xor'); | 42 if (identical(name, '^=')) return const SourceString('xor'); |
| 43 if (identical(name, '++')) return const SourceString('add'); | 43 if (identical(name, '++')) return const SourceString('add'); |
| 44 if (identical(name, '--')) return const SourceString('sub'); | 44 if (identical(name, '--')) return const SourceString('sub'); |
| 45 compiler.unimplemented('Unknown operator', node: op); | 45 compiler.unimplemented('Unknown operator', node: op); |
| 46 } | 46 } |
| 47 | 47 |
| 48 // TODO(karlklose,kasperl): change uses of getStatic[Get|Set]Interceptor to | 48 Element getStaticInterceptor(Selector selector) { |
| 49 // use this function. | 49 String name = selector.name.slowToString(); |
| 50 Element getStaticInterceptorBySelector(Selector selector) { | |
| 51 if (selector.isGetter()) { | 50 if (selector.isGetter()) { |
| 52 // TODO(lrn): If there is no get-interceptor, but there is a | 51 // TODO(lrn): If there is no get-interceptor, but there is a |
| 53 // method-interceptor, we should generate a get-interceptor automatically. | 52 // method-interceptor, we should generate a get-interceptor automatically. |
| 54 return getStaticGetInterceptor(selector.name); | 53 String mangledName = "get\$$name"; |
| 54 return compiler.findInterceptor(new SourceString(mangledName)); |
| 55 } else if (selector.isSetter()) { | 55 } else if (selector.isSetter()) { |
| 56 return getStaticSetInterceptor(selector.name); | 56 String mangledName = "set\$$name"; |
| 57 return compiler.findInterceptor(new SourceString(mangledName)); |
| 57 } else { | 58 } else { |
| 58 return getStaticInterceptor(selector.name, selector.argumentCount); | 59 Element element = compiler.findInterceptor(new SourceString(name)); |
| 60 if (element != null && element.isFunction()) { |
| 61 // Only pick the function element with the short name if the |
| 62 // number of parameters it expects matches the number we're |
| 63 // passing modulo the receiver. |
| 64 FunctionElement function = element; |
| 65 if (function.parameterCount(compiler) == selector.argumentCount + 1) { |
| 66 return element; |
| 67 } |
| 68 } |
| 69 String longMangledName = "$name\$${selector.argumentCount}"; |
| 70 return compiler.findInterceptor(new SourceString(longMangledName)); |
| 59 } | 71 } |
| 60 } | 72 } |
| 61 | 73 |
| 62 Element getStaticInterceptor(SourceString name, int parameters) { | |
| 63 String mangledName = name.slowToString(); | |
| 64 Element element = compiler.findInterceptor(new SourceString(mangledName)); | |
| 65 if (element != null && element.isFunction()) { | |
| 66 // Only pick the function element with the short name if the | |
| 67 // number of parameters it expects matches the number we're | |
| 68 // passing modulo the receiver. | |
| 69 FunctionElement function = element; | |
| 70 if (function.parameterCount(compiler) == parameters + 1) return element; | |
| 71 } | |
| 72 String longMangledName = "$mangledName\$$parameters"; | |
| 73 return compiler.findInterceptor(new SourceString(longMangledName)); | |
| 74 } | |
| 75 | |
| 76 Element getStaticGetInterceptor(SourceString name) { | |
| 77 String mangledName = "get\$${name.slowToString()}"; | |
| 78 return compiler.findInterceptor(new SourceString(mangledName)); | |
| 79 } | |
| 80 | |
| 81 Element getStaticSetInterceptor(SourceString name) { | |
| 82 String mangledName = "set\$${name.slowToString()}"; | |
| 83 return compiler.findInterceptor(new SourceString(mangledName)); | |
| 84 } | |
| 85 | |
| 86 Element getOperatorInterceptor(Operator op) { | 74 Element getOperatorInterceptor(Operator op) { |
| 87 SourceString name = mapOperatorToMethodName(op); | 75 SourceString name = mapOperatorToMethodName(op); |
| 88 return compiler.findHelper(name); | 76 return compiler.findHelper(name); |
| 89 } | 77 } |
| 90 | 78 |
| 91 Element getBoolifiedVersionOf(Element interceptor) { | 79 Element getBoolifiedVersionOf(Element interceptor) { |
| 92 if (interceptor == null) return interceptor; | 80 if (interceptor == null) return interceptor; |
| 93 String boolifiedName = "${interceptor.name.slowToString()}B"; | 81 String boolifiedName = "${interceptor.name.slowToString()}B"; |
| 94 return compiler.findHelper(new SourceString(boolifiedName)); | 82 return compiler.findHelper(new SourceString(boolifiedName)); |
| 95 } | 83 } |
| (...skipping 2181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2277 // TODO(kasperl): This is a convoluted way of checking if we're | 2265 // TODO(kasperl): This is a convoluted way of checking if we're |
| 2278 // generating code for a compound assignment. If we are, we need | 2266 // generating code for a compound assignment. If we are, we need |
| 2279 // to get the selector from the mapping for the AST selector node. | 2267 // to get the selector from the mapping for the AST selector node. |
| 2280 Selector selector = (send.asSendSet() == null) | 2268 Selector selector = (send.asSendSet() == null) |
| 2281 ? elements.getSelector(send) | 2269 ? elements.getSelector(send) |
| 2282 : elements.getSelector(send.selector); | 2270 : elements.getSelector(send.selector); |
| 2283 assert(selector.isGetter()); | 2271 assert(selector.isGetter()); |
| 2284 SourceString getterName = selector.name; | 2272 SourceString getterName = selector.name; |
| 2285 Element staticInterceptor = null; | 2273 Element staticInterceptor = null; |
| 2286 if (elements[send] == null && methodInterceptionEnabled) { | 2274 if (elements[send] == null && methodInterceptionEnabled) { |
| 2287 staticInterceptor = interceptors.getStaticGetInterceptor(getterName); | 2275 staticInterceptor = interceptors.getStaticInterceptor(selector); |
| 2288 } | 2276 } |
| 2289 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | 2277 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| 2290 if (staticInterceptor != null) { | 2278 if (staticInterceptor != null) { |
| 2291 HStatic target = new HStatic(staticInterceptor); | 2279 HStatic target = new HStatic(staticInterceptor); |
| 2292 add(target); | 2280 add(target); |
| 2293 List<HInstruction> inputs = <HInstruction>[target, receiver]; | 2281 List<HInstruction> inputs = <HInstruction>[target, receiver]; |
| 2294 pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter), | 2282 pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter), |
| 2295 send); | 2283 send); |
| 2296 } else { | 2284 } else { |
| 2297 pushWithPosition( | 2285 pushWithPosition( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 | 2328 |
| 2341 void generateInstanceSetterWithCompiledReceiver(Send send, | 2329 void generateInstanceSetterWithCompiledReceiver(Send send, |
| 2342 HInstruction receiver, | 2330 HInstruction receiver, |
| 2343 HInstruction value) { | 2331 HInstruction value) { |
| 2344 assert(Elements.isInstanceSend(send, elements)); | 2332 assert(Elements.isInstanceSend(send, elements)); |
| 2345 Selector selector = elements.getSelector(send); | 2333 Selector selector = elements.getSelector(send); |
| 2346 assert(selector.isSetter()); | 2334 assert(selector.isSetter()); |
| 2347 SourceString setterName = selector.name; | 2335 SourceString setterName = selector.name; |
| 2348 Element staticInterceptor = null; | 2336 Element staticInterceptor = null; |
| 2349 if (elements[send] == null && methodInterceptionEnabled) { | 2337 if (elements[send] == null && methodInterceptionEnabled) { |
| 2350 staticInterceptor = interceptors.getStaticSetInterceptor(setterName); | 2338 staticInterceptor = interceptors.getStaticInterceptor(selector); |
| 2351 } | 2339 } |
| 2352 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); | 2340 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); |
| 2353 if (staticInterceptor != null) { | 2341 if (staticInterceptor != null) { |
| 2354 HStatic target = new HStatic(staticInterceptor); | 2342 HStatic target = new HStatic(staticInterceptor); |
| 2355 add(target); | 2343 add(target); |
| 2356 List<HInstruction> inputs = <HInstruction>[target, receiver, value]; | 2344 List<HInstruction> inputs = <HInstruction>[target, receiver, value]; |
| 2357 addWithPosition(new HInvokeInterceptor(selector, inputs), send); | 2345 addWithPosition(new HInvokeInterceptor(selector, inputs), send); |
| 2358 } else { | 2346 } else { |
| 2359 addWithPosition( | 2347 addWithPosition( |
| 2360 new HInvokeDynamicSetter(selector, null, receiver, value, !hasSetter), | 2348 new HInvokeDynamicSetter(selector, null, receiver, value, !hasSetter), |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 SourceString name = node.selector.asIdentifier().source; | 2598 SourceString name = node.selector.asIdentifier().source; |
| 2611 isNotEquals = identical(name.stringValue, '!='); | 2599 isNotEquals = identical(name.stringValue, '!='); |
| 2612 dartMethodName = Elements.constructOperatorName( | 2600 dartMethodName = Elements.constructOperatorName( |
| 2613 name, node.argumentsNode is Prefix); | 2601 name, node.argumentsNode is Prefix); |
| 2614 } else { | 2602 } else { |
| 2615 dartMethodName = node.selector.asIdentifier().source; | 2603 dartMethodName = node.selector.asIdentifier().source; |
| 2616 } | 2604 } |
| 2617 | 2605 |
| 2618 Element interceptor = null; | 2606 Element interceptor = null; |
| 2619 if (methodInterceptionEnabled && elements[node] == null) { | 2607 if (methodInterceptionEnabled && elements[node] == null) { |
| 2620 interceptor = interceptors.getStaticInterceptor(dartMethodName, | 2608 interceptor = interceptors.getStaticInterceptor(selector); |
| 2621 node.argumentCount()); | |
| 2622 } | 2609 } |
| 2623 if (interceptor != null) { | 2610 if (interceptor != null) { |
| 2624 HStatic target = new HStatic(interceptor); | 2611 HStatic target = new HStatic(interceptor); |
| 2625 add(target); | 2612 add(target); |
| 2626 inputs.add(target); | 2613 inputs.add(target); |
| 2627 visit(node.receiver); | 2614 visit(node.receiver); |
| 2628 inputs.add(pop()); | 2615 inputs.add(pop()); |
| 2629 addGenericSendArgumentsToList(node.arguments, inputs); | 2616 addGenericSendArgumentsToList(node.arguments, inputs); |
| 2630 pushWithPosition(new HInvokeInterceptor(selector, inputs), node); | 2617 pushWithPosition(new HInvokeInterceptor(selector, inputs), node); |
| 2631 return; | 2618 return; |
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3679 // Iterator<E> $iter = <iterable>.iterator() | 3666 // Iterator<E> $iter = <iterable>.iterator() |
| 3680 // while ($iter.hasNext) { | 3667 // while ($iter.hasNext) { |
| 3681 // E <declaredIdentifier> = $iter.next(); | 3668 // E <declaredIdentifier> = $iter.next(); |
| 3682 // <body> | 3669 // <body> |
| 3683 // } | 3670 // } |
| 3684 | 3671 |
| 3685 // The iterator is shared between initializer, condition and body. | 3672 // The iterator is shared between initializer, condition and body. |
| 3686 HInstruction iterator; | 3673 HInstruction iterator; |
| 3687 void buildInitializer() { | 3674 void buildInitializer() { |
| 3688 SourceString iteratorName = const SourceString("iterator"); | 3675 SourceString iteratorName = const SourceString("iterator"); |
| 3689 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); | 3676 Selector selector = |
| 3677 new Selector.call(iteratorName, work.element.getLibrary(), 0); |
| 3678 Element interceptor = interceptors.getStaticInterceptor(selector); |
| 3690 assert(interceptor != null); | 3679 assert(interceptor != null); |
| 3691 visit(node.expression); | 3680 visit(node.expression); |
| 3692 pushInvokeHelper1(interceptor, pop()); | 3681 pushInvokeHelper1(interceptor, pop()); |
| 3693 iterator = pop(); | 3682 iterator = pop(); |
| 3694 } | 3683 } |
| 3695 HInstruction buildCondition() { | 3684 HInstruction buildCondition() { |
| 3696 SourceString name = const SourceString('hasNext'); | 3685 SourceString name = const SourceString('hasNext'); |
| 3697 Selector selector = new Selector.getter(name, work.element.getLibrary()); | 3686 Selector selector = new Selector.getter(name, work.element.getLibrary()); |
| 3698 if (interceptors.getStaticGetInterceptor(name) != null) { | 3687 if (interceptors.getStaticInterceptor(selector) != null) { |
| 3699 compiler.internalError("hasNext getter must not be intercepted", | 3688 compiler.internalError("hasNext getter must not be intercepted", |
| 3700 node: node); | 3689 node: node); |
| 3701 } | 3690 } |
| 3702 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | 3691 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| 3703 push(new HInvokeDynamicGetter(selector, null, iterator, !hasGetter)); | 3692 push(new HInvokeDynamicGetter(selector, null, iterator, !hasGetter)); |
| 3704 return popBoolified(); | 3693 return popBoolified(); |
| 3705 } | 3694 } |
| 3706 void buildBody() { | 3695 void buildBody() { |
| 3707 SourceString name = const SourceString('next'); | 3696 SourceString name = const SourceString('next'); |
| 3708 Selector call = new Selector.call(name, work.element.getLibrary(), 0); | 3697 Selector call = new Selector.call(name, work.element.getLibrary(), 0); |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4771 new HSubGraphBlockInformation(elseBranch.graph)); | 4760 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4772 | 4761 |
| 4773 HBasicBlock conditionStartBlock = conditionBranch.block; | 4762 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4774 conditionStartBlock.setBlockFlow(info, joinBlock); | 4763 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4775 SubGraph conditionGraph = conditionBranch.graph; | 4764 SubGraph conditionGraph = conditionBranch.graph; |
| 4776 HIf branch = conditionGraph.end.last; | 4765 HIf branch = conditionGraph.end.last; |
| 4777 assert(branch is HIf); | 4766 assert(branch is HIf); |
| 4778 branch.blockInformation = conditionStartBlock.blockFlow; | 4767 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4779 } | 4768 } |
| 4780 } | 4769 } |
| OLD | NEW |