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 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 List<LabelElement> labels() { | 778 List<LabelElement> labels() { |
779 List<LabelElement> result = null; | 779 List<LabelElement> result = null; |
780 for (LabelElement element in target.labels) { | 780 for (LabelElement element in target.labels) { |
781 if (result === null) result = <LabelElement>[]; | 781 if (result === null) result = <LabelElement>[]; |
782 result.add(element); | 782 result.add(element); |
783 } | 783 } |
784 return (result === null) ? const <LabelElement>[] : result; | 784 return (result === null) ? const <LabelElement>[] : result; |
785 } | 785 } |
786 } | 786 } |
787 | 787 |
788 class SsaBuilder implements Visitor { | 788 class SsaBuilder extends ResolvedVisitor implements Visitor { |
789 final SsaBuilderTask builder; | 789 final SsaBuilderTask builder; |
790 TreeElements elements; | |
791 final Interceptors interceptors; | 790 final Interceptors interceptors; |
792 final WorkItem work; | 791 final WorkItem work; |
793 bool methodInterceptionEnabled; | 792 bool methodInterceptionEnabled; |
794 HGraph graph; | 793 HGraph graph; |
795 LocalsHandler localsHandler; | 794 LocalsHandler localsHandler; |
796 HInstruction rethrowableException; | 795 HInstruction rethrowableException; |
797 | 796 |
798 Map<TargetElement, JumpHandler> jumpTargets; | 797 Map<TargetElement, JumpHandler> jumpTargets; |
799 | 798 |
800 /** | 799 /** |
(...skipping 16 matching lines...) Expand all Loading... |
817 | 816 |
818 LibraryElement get currentLibrary() => work.element.getLibrary(); | 817 LibraryElement get currentLibrary() => work.element.getLibrary(); |
819 Compiler get compiler() => builder.compiler; | 818 Compiler get compiler() => builder.compiler; |
820 CodeEmitterTask get emitter() => builder.emitter; | 819 CodeEmitterTask get emitter() => builder.emitter; |
821 | 820 |
822 SsaBuilder(SsaBuilderTask builder, WorkItem work) | 821 SsaBuilder(SsaBuilderTask builder, WorkItem work) |
823 : this.builder = builder, | 822 : this.builder = builder, |
824 this.work = work, | 823 this.work = work, |
825 interceptors = builder.interceptors, | 824 interceptors = builder.interceptors, |
826 methodInterceptionEnabled = true, | 825 methodInterceptionEnabled = true, |
827 elements = work.resolutionTree, | |
828 graph = new HGraph(), | 826 graph = new HGraph(), |
829 stack = new List<HInstruction>(), | 827 stack = new List<HInstruction>(), |
830 activationVariables = new Map<Element, HParameterValue>(), | 828 activationVariables = new Map<Element, HParameterValue>(), |
831 jumpTargets = new Map<TargetElement, JumpHandler>() { | 829 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 830 super(work.resolutionTree) { |
832 localsHandler = new LocalsHandler(this); | 831 localsHandler = new LocalsHandler(this); |
833 } | 832 } |
834 | 833 |
835 void disableMethodInterception() { | 834 void disableMethodInterception() { |
836 assert(methodInterceptionEnabled); | 835 assert(methodInterceptionEnabled); |
837 methodInterceptionEnabled = false; | 836 methodInterceptionEnabled = false; |
838 } | 837 } |
839 | 838 |
840 void enableMethodInterception() { | 839 void enableMethodInterception() { |
841 assert(!methodInterceptionEnabled); | 840 assert(!methodInterceptionEnabled); |
(...skipping 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1897 if (checked !== value) { | 1896 if (checked !== value) { |
1898 pop(); | 1897 pop(); |
1899 stack.add(checked); | 1898 stack.add(checked); |
1900 } | 1899 } |
1901 localsHandler.updateLocal(element, checked); | 1900 localsHandler.updateLocal(element, checked); |
1902 } | 1901 } |
1903 } | 1902 } |
1904 | 1903 |
1905 visitOperatorSend(node) { | 1904 visitOperatorSend(node) { |
1906 assert(node.selector is Operator); | 1905 assert(node.selector is Operator); |
| 1906 if (!methodInterceptionEnabled) { |
| 1907 visitDynamicSend(node); |
| 1908 return; |
| 1909 } |
| 1910 |
1907 Operator op = node.selector; | 1911 Operator op = node.selector; |
1908 if (const SourceString("[]") == op.source) { | 1912 if (const SourceString("[]") == op.source) { |
1909 HStatic target = new HStatic(interceptors.getIndexInterceptor()); | 1913 HStatic target = new HStatic(interceptors.getIndexInterceptor()); |
1910 add(target); | 1914 add(target); |
1911 visit(node.receiver); | 1915 visit(node.receiver); |
1912 HInstruction receiver = pop(); | 1916 HInstruction receiver = pop(); |
1913 visit(node.argumentsNode); | 1917 visit(node.argumentsNode); |
1914 HInstruction index = pop(); | 1918 HInstruction index = pop(); |
1915 push(new HIndex(target, receiver, index)); | 1919 push(new HIndex(target, receiver, index)); |
1916 } else if (const SourceString("&&") == op.source || | 1920 } else if (const SourceString("&&") == op.source || |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2239 visit(closure); | 2243 visit(closure); |
2240 List<HInstruction> inputs = <HInstruction>[pop()]; | 2244 List<HInstruction> inputs = <HInstruction>[pop()]; |
2241 String invocationName = compiler.namer.closureInvocationName( | 2245 String invocationName = compiler.namer.closureInvocationName( |
2242 new Selector(SelectorKind.INVOCATION, | 2246 new Selector(SelectorKind.INVOCATION, |
2243 parameters.requiredParameterCount)); | 2247 parameters.requiredParameterCount)); |
2244 push(new HForeign(new DartString.literal('#.$invocationName'), | 2248 push(new HForeign(new DartString.literal('#.$invocationName'), |
2245 const LiteralDartString('var'), | 2249 const LiteralDartString('var'), |
2246 inputs)); | 2250 inputs)); |
2247 } | 2251 } |
2248 | 2252 |
2249 handleForeignSend(Send node) { | 2253 visitForeignSend(Send node) { |
2250 Element element = elements[node]; | 2254 Element element = elements[node]; |
2251 if (element.name == const SourceString('JS')) { | 2255 if (element.name == const SourceString('JS')) { |
2252 handleForeignJs(node); | 2256 handleForeignJs(node); |
2253 } else if (element.name == const SourceString('UNINTERCEPTED')) { | 2257 } else if (element.name == const SourceString('UNINTERCEPTED')) { |
2254 handleForeignUnintercepted(node); | 2258 handleForeignUnintercepted(node); |
2255 } else if (element.name == const SourceString('JS_HAS_EQUALS')) { | 2259 } else if (element.name == const SourceString('JS_HAS_EQUALS')) { |
2256 handleForeignJsHasEquals(node); | 2260 handleForeignJsHasEquals(node); |
2257 } else if (element.name == const SourceString('JS_CURRENT_ISOLATE')) { | 2261 } else if (element.name == const SourceString('JS_CURRENT_ISOLATE')) { |
2258 handleForeignJsCurrentIsolate(node); | 2262 handleForeignJsCurrentIsolate(node); |
2259 } else if (element.name == const SourceString('JS_CALL_IN_ISOLATE')) { | 2263 } else if (element.name == const SourceString('JS_CALL_IN_ISOLATE')) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2394 if (element.kind == ElementKind.GETTER) { | 2398 if (element.kind == ElementKind.GETTER) { |
2395 target = new HInvokeStatic(Selector.GETTER, inputs); | 2399 target = new HInvokeStatic(Selector.GETTER, inputs); |
2396 add(target); | 2400 add(target); |
2397 inputs = <HInstruction>[target]; | 2401 inputs = <HInstruction>[target]; |
2398 } | 2402 } |
2399 addDynamicSendArgumentsToList(node, inputs); | 2403 addDynamicSendArgumentsToList(node, inputs); |
2400 push(new HInvokeClosure(selector, inputs)); | 2404 push(new HInvokeClosure(selector, inputs)); |
2401 } | 2405 } |
2402 } | 2406 } |
2403 | 2407 |
2404 visitSend(Send node) { | 2408 visitGetterSend(Send node) { |
2405 if (node.isSuperCall) { | 2409 generateGetter(node, elements[node]); |
2406 visitSuperSend(node); | 2410 } |
2407 } else if (node.isOperator && methodInterceptionEnabled) { | 2411 |
2408 visitOperatorSend(node); | 2412 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
2409 } else if (node.isPropertyAccess) { | 2413 internalError(String reason, [Node node]) { |
2410 generateGetter(node, elements[node]); | 2414 compiler.internalError(reason, node: node); |
2411 } else if (Elements.isClosureSend(node, elements)) { | |
2412 visitClosureSend(node); | |
2413 } else { | |
2414 Element element = elements[node]; | |
2415 if (element === null) { | |
2416 // Example: f() with 'f' unbound. | |
2417 // This can only happen inside an instance method. | |
2418 visitDynamicSend(node); | |
2419 } else if (element.kind == ElementKind.CLASS) { | |
2420 compiler.internalError("Cannot generate code for send", node: node); | |
2421 } else if (element.isInstanceMember()) { | |
2422 // Example: f() with 'f' bound to instance method. | |
2423 visitDynamicSend(node); | |
2424 } else if (element.kind === ElementKind.FOREIGN) { | |
2425 handleForeignSend(node); | |
2426 } else if (!element.isInstanceMember()) { | |
2427 // Example: A.f() or f() with 'f' bound to a static function. | |
2428 // Also includes new A() or new A.named() which is treated like a | |
2429 // static call to a factory. | |
2430 visitStaticSend(node); | |
2431 } else { | |
2432 compiler.internalError("Cannot generate code for send", node: node); | |
2433 } | |
2434 } | |
2435 } | 2415 } |
2436 | 2416 |
2437 // TODO(karlklose): share with resolver. | 2417 // TODO(karlklose): share with resolver. |
2438 TypeAnnotation getTypeAnnotationFromSend(Send send) { | 2418 TypeAnnotation getTypeAnnotationFromSend(Send send) { |
2439 if (send.selector is TypeAnnotation) { | 2419 if (send.selector is TypeAnnotation) { |
2440 return send.selector; | 2420 return send.selector; |
2441 } else if (send.selector is Send) { | 2421 } else if (send.selector is Send) { |
2442 Send selector = send.selector; | 2422 Send selector = send.selector; |
2443 if (selector.receiver is TypeAnnotation) { | 2423 if (selector.receiver is TypeAnnotation) { |
2444 return selector.receiver; | 2424 return selector.receiver; |
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3413 <HInstruction>[target, input], | 3393 <HInstruction>[target, input], |
3414 HType.STRING)); | 3394 HType.STRING)); |
3415 return builder.pop(); | 3395 return builder.pop(); |
3416 } | 3396 } |
3417 | 3397 |
3418 HInstruction result(Node node) { | 3398 HInstruction result(Node node) { |
3419 flushLiterals(node); | 3399 flushLiterals(node); |
3420 return prefix; | 3400 return prefix; |
3421 } | 3401 } |
3422 } | 3402 } |
OLD | NEW |