Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 visit(send.receiver); | 813 visit(send.receiver); |
| 814 receiver = pop(); | 814 receiver = pop(); |
| 815 } | 815 } |
| 816 add(new HInvokeDynamicSetter(null, jsSetterName, receiver, value)); | 816 add(new HInvokeDynamicSetter(null, jsSetterName, receiver, value)); |
| 817 stack.add(value); | 817 stack.add(value); |
| 818 } else { | 818 } else { |
| 819 stack.add(updateDefinition(send, value)); | 819 stack.add(updateDefinition(send, value)); |
| 820 } | 820 } |
| 821 } | 821 } |
| 822 | 822 |
| 823 visitOperatorSend(node) { | |
| 824 assert(node.selector is Operator); | |
| 825 Operator op = node.selector; | |
| 826 if (const SourceString("[]") == op.source) { | |
| 827 HStatic target = new HStatic(interceptors.getIndexInterceptor()); | |
| 828 add(target); | |
| 829 visit(node.receiver); | |
| 830 HInstruction receiver = pop(); | |
| 831 visit(node.argumentsNode); | |
| 832 HInstruction index = pop(); | |
| 833 push(new HIndex(target, receiver, index)); | |
| 834 } else if (const SourceString("&&") == op.source || | |
| 835 const SourceString("||") == op.source) { | |
| 836 visitLogicalAndOr(node, op); | |
| 837 } else if (const SourceString("!") == op.source) { | |
| 838 visitLogicalNot(node); | |
| 839 } else if (node.argumentsNode is Prefix) { | |
| 840 visitUnary(node, op); | |
| 841 } else { | |
| 842 visit(node.receiver); | |
| 843 visit(node.argumentsNode); | |
| 844 var right = pop(); | |
| 845 var left = pop(); | |
| 846 visitBinary(left, op, right); | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 addVisitedSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | |
| 851 for (; !link.isEmpty(); link = link.tail) { | |
| 852 visit(link.head); | |
| 853 list.add(pop()); | |
| 854 } | |
| 855 } | |
| 856 | |
| 857 visitDynamicSend(Send node) { | |
| 858 var inputs = <HInstruction>[]; | |
| 859 | |
| 860 SourceString dartMethodName = node.selector.asIdentifier().source; | |
| 861 | |
| 862 Element interceptor = | |
| 863 interceptors.getStaticInterceptor(dartMethodName, node.argumentCount()); | |
| 864 if (interceptor != null) { | |
| 865 HStatic target = new HStatic(interceptor); | |
| 866 add(target); | |
| 867 inputs.add(target); | |
| 868 visit(node.receiver); | |
| 869 inputs.add(pop()); | |
| 870 addVisitedSendArgumentsToList(node.arguments, inputs); | |
| 871 push(new HInvokeInterceptor(dartMethodName.stringValue, false, inputs)); | |
| 872 return; | |
| 873 } | |
| 874 | |
| 875 if (node.receiver === null) { | |
| 876 HThis receiver = new HThis(); | |
| 877 add(receiver); | |
| 878 inputs.add(receiver); | |
| 879 } else { | |
| 880 visit(node.receiver); | |
| 881 inputs.add(pop()); | |
| 882 } | |
| 883 | |
| 884 addVisitedSendArgumentsToList(node.arguments, inputs); | |
| 885 | |
| 886 String jsMethodName = compiler.namer.instanceName(dartMethodName); | |
| 887 // The first entry in the inputs list is the receiver. | |
| 888 push(new HInvokeDynamicMethod(jsMethodName, inputs)); | |
| 889 } | |
| 890 | |
| 891 visitClosureSend(Send node) { | |
| 892 Element element = elements[node]; | |
| 893 HInstruction closureTarget; | |
| 894 if (element === null) { | |
|
ngeoffray
2012/01/05 14:05:46
Why not removing that check and just do visit(node
floitsch
2012/01/24 13:28:37
Because the selector doesn't (yet) have any elemen
| |
| 895 visit(node.selector); | |
| 896 closureTarget = pop(); | |
| 897 } else { | |
| 898 assert(element.kind === ElementKind.VARIABLE || | |
| 899 element.kind === ElementKind.PARAMETER); | |
| 900 closureTarget = definitions[element]; | |
| 901 assert(closureTarget !== null); | |
| 902 } | |
| 903 var inputs = <HInstruction>[]; | |
| 904 inputs.add(closureTarget); | |
| 905 addVisitedSendArgumentsToList(node.arguments, inputs); | |
| 906 String jsMethodName = compiler.namer.closureInvocationName(); | |
| 907 push(new HInvokeDynamicMethod(jsMethodName, inputs)); | |
| 908 } | |
| 909 | |
| 910 visitForeignSend(Send node) { | |
| 911 Link<Node> link = node.arguments; | |
| 912 // If the invoke is on foreign code, don't visit the first | |
| 913 // argument, which is the type, and the second argument, | |
| 914 // which is the foreign code. | |
| 915 link = link.tail.tail; | |
| 916 var inputs = <HInstruction>[]; | |
| 917 addVisitedSendArgumentsToList(link, inputs); | |
| 918 LiteralString type = node.arguments.head; | |
| 919 LiteralString literal = node.arguments.tail.head; | |
| 920 compiler.ensure(literal is LiteralString); | |
| 921 compiler.ensure(type is LiteralString); | |
| 922 compiler.ensure(literal.value.stringValue[0] == '@'); | |
| 923 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); | |
| 924 } | |
| 925 | |
| 926 visitStaticSend(Send node) { | |
| 927 Element element = elements[node]; | |
| 928 HStatic target = new HStatic(element); | |
| 929 add(target); | |
| 930 var inputs = <HInstruction>[]; | |
| 931 inputs.add(target); | |
| 932 addVisitedSendArgumentsToList(node.arguments, inputs); | |
| 933 push(new HInvokeStatic(inputs)); | |
| 934 } | |
| 935 | |
| 823 visitSend(Send node) { | 936 visitSend(Send node) { |
| 824 if (node.selector is Operator) { | 937 if (node.selector is Operator) { |
| 825 Operator op = node.selector; | 938 visitOperatorSend(node); |
| 826 if (const SourceString("[]") == op.source) { | |
| 827 HStatic target = new HStatic(interceptors.getIndexInterceptor()); | |
| 828 add(target); | |
| 829 visit(node.receiver); | |
| 830 HInstruction receiver = pop(); | |
| 831 visit(node.argumentsNode); | |
| 832 HInstruction index = pop(); | |
| 833 push(new HIndex(target, receiver, index)); | |
| 834 } else if (const SourceString("&&") == op.source || | |
| 835 const SourceString("||") == op.source) { | |
| 836 visitLogicalAndOr(node, op); | |
| 837 } else if (const SourceString("!") == op.source) { | |
| 838 visitLogicalNot(node); | |
| 839 } else if (node.argumentsNode is Prefix) { | |
| 840 visitUnary(node, op); | |
| 841 } else { | |
| 842 visit(node.receiver); | |
| 843 visit(node.argumentsNode); | |
| 844 var right = pop(); | |
| 845 var left = pop(); | |
| 846 visitBinary(left, op, right); | |
| 847 } | |
| 848 } else if (node.isPropertyAccess) { | 939 } else if (node.isPropertyAccess) { |
| 849 generateGetter(node, elements[node]); | 940 generateGetter(node, elements[node]); |
| 941 } else if (Elements.isClosureSend(node, elements)) { | |
| 942 assert(node.receiver === null); | |
|
ngeoffray
2012/01/05 14:05:46
I would not put that assert here. I you really wan
floitsch
2012/01/24 13:28:37
moved to visitClosureSend.
| |
| 943 visitClosureSend(node); | |
| 850 } else { | 944 } else { |
| 851 Element element = elements[node]; | 945 Element element = elements[node]; |
| 852 bool isInvokeDynamic = (element === null) || element.isInstanceMember(); | 946 if (element === null) { |
| 853 bool isForeign = | 947 // Example: f() with 'f' unbound. |
| 854 (element !== null) && (element.kind === ElementKind.FOREIGN); | 948 // This can only happen inside an instance method. |
| 855 bool isStatic = !isInvokeDynamic && !isForeign; | 949 visitDynamicSend(node); |
| 856 | 950 } else if (element.isInstanceMember()) { |
| 857 Link<Node> link = node.arguments; | 951 // Example: f() with 'f' bound to instance method. |
| 858 var inputs = <HInstruction>[]; | 952 visitDynamicSend(node); |
| 859 | 953 } else if (element.kind === ElementKind.FOREIGN) { |
| 860 SourceString dartMethodName; | 954 visitForeignSend(node); |
| 861 Element interceptor; | |
| 862 if (isInvokeDynamic) { | |
| 863 dartMethodName = node.selector.asIdentifier().source; | |
| 864 interceptor = interceptors.getStaticInterceptor( | |
| 865 dartMethodName, node.argumentCount()); | |
| 866 if (interceptor != null) { | |
| 867 HStatic target = new HStatic(interceptor); | |
| 868 add(target); | |
| 869 inputs.add(target); | |
| 870 visit(node.receiver); | |
| 871 inputs.add(pop()); | |
| 872 isInvokeDynamic = false; | |
| 873 } else if (node.receiver === null) { | |
| 874 HThis receiver = new HThis(); | |
| 875 add(receiver); | |
| 876 inputs.add(receiver); | |
| 877 } else { | |
| 878 visit(node.receiver); | |
| 879 inputs.add(pop()); | |
| 880 } | |
| 881 } else if (isForeign) { | |
| 882 // If the invoke is on foreign code, don't visit the first | |
| 883 // argument, which is the type, and the second argument, | |
| 884 // which is the foreign code. | |
| 885 link = link.tail.tail; | |
| 886 } else { | 955 } else { |
|
ngeoffray
2012/01/05 14:05:46
else if (!element.isInstanceMember()) {
...
} els
floitsch
2012/01/24 13:28:37
Done.
| |
| 887 HStatic target = new HStatic(element); | 956 // Example: A.f() or f() with 'f' bound to a static function. |
| 888 add(target); | 957 // Also includes new A() or new A.named() which is treated like a |
| 889 inputs.add(target); | 958 // static call to a factory. |
| 890 } | 959 assert(!element.isInstanceMember()); |
| 891 | 960 visitStaticSend(node); |
| 892 for (; !link.isEmpty(); link = link.tail) { | |
| 893 visit(link.head); | |
| 894 inputs.add(pop()); | |
| 895 } | |
| 896 | |
| 897 if (isInvokeDynamic) { | |
| 898 String jsMethodName = compiler.namer.instanceName(dartMethodName); | |
| 899 // The first entry in the inputs list is the receiver. | |
| 900 push(new HInvokeDynamicMethod(jsMethodName, inputs)); | |
| 901 } else if (isForeign) { | |
| 902 LiteralString type = node.arguments.head; | |
| 903 LiteralString literal = node.arguments.tail.head; | |
| 904 compiler.ensure(literal is LiteralString); | |
| 905 compiler.ensure(type is LiteralString); | |
| 906 compiler.ensure(literal.value.stringValue[0] == '@'); | |
| 907 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); | |
| 908 } else if (interceptor != null) { | |
| 909 push(new HInvokeInterceptor(dartMethodName.stringValue, false, inputs)); | |
| 910 } else { | |
| 911 assert(isStatic); | |
| 912 push(new HInvokeStatic(inputs)); | |
| 913 } | 961 } |
| 914 } | 962 } |
| 915 } | 963 } |
| 916 | 964 |
| 917 visitNewExpression(NewExpression node) => visitSend(node.send); | 965 visitNewExpression(NewExpression node) => visitSend(node.send); |
| 918 | 966 |
| 919 HInstruction updateDefinition(Node node, HInstruction value) { | 967 HInstruction updateDefinition(Node node, HInstruction value) { |
| 920 VariableElement element = elements[node]; | 968 VariableElement element = elements[node]; |
| 921 value = guard(element.type, value); | 969 value = guard(element.type, value); |
| 922 definitions[element] = value; | 970 definitions[element] = value; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1179 } | 1227 } |
| 1180 | 1228 |
| 1181 visitCatchBlock(CatchBlock node) { | 1229 visitCatchBlock(CatchBlock node) { |
| 1182 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); | 1230 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); |
| 1183 } | 1231 } |
| 1184 | 1232 |
| 1185 visitTypedef(Typedef node) { | 1233 visitTypedef(Typedef node) { |
| 1186 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 1234 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 1187 } | 1235 } |
| 1188 } | 1236 } |
| OLD | NEW |