| 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 |