| 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 assert(node.receiver === null); |
| 893 Element element = elements[node]; |
| 894 HInstruction closureTarget; |
| 895 if (element === null) { |
| 896 visit(node.selector); |
| 897 closureTarget = pop(); |
| 898 } else { |
| 899 assert(element.kind === ElementKind.VARIABLE || |
| 900 element.kind === ElementKind.PARAMETER); |
| 901 closureTarget = definitions[element]; |
| 902 assert(closureTarget !== null); |
| 903 } |
| 904 var inputs = <HInstruction>[]; |
| 905 inputs.add(closureTarget); |
| 906 addVisitedSendArgumentsToList(node.arguments, inputs); |
| 907 String jsMethodName = compiler.namer.closureInvocationName(); |
| 908 push(new HInvokeDynamicMethod(jsMethodName, inputs)); |
| 909 } |
| 910 |
| 911 visitForeignSend(Send node) { |
| 912 Link<Node> link = node.arguments; |
| 913 // If the invoke is on foreign code, don't visit the first |
| 914 // argument, which is the type, and the second argument, |
| 915 // which is the foreign code. |
| 916 link = link.tail.tail; |
| 917 var inputs = <HInstruction>[]; |
| 918 addVisitedSendArgumentsToList(link, inputs); |
| 919 LiteralString type = node.arguments.head; |
| 920 LiteralString literal = node.arguments.tail.head; |
| 921 compiler.ensure(literal is LiteralString); |
| 922 compiler.ensure(type is LiteralString); |
| 923 compiler.ensure(literal.value.stringValue[0] == '@'); |
| 924 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); |
| 925 } |
| 926 |
| 927 visitStaticSend(Send node) { |
| 928 Element element = elements[node]; |
| 929 HStatic target = new HStatic(element); |
| 930 add(target); |
| 931 var inputs = <HInstruction>[]; |
| 932 inputs.add(target); |
| 933 addVisitedSendArgumentsToList(node.arguments, inputs); |
| 934 push(new HInvokeStatic(inputs)); |
| 935 } |
| 936 |
| 823 visitSend(Send node) { | 937 visitSend(Send node) { |
| 824 if (node.selector is Operator) { | 938 if (node.selector is Operator) { |
| 825 Operator op = node.selector; | 939 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) { | 940 } else if (node.isPropertyAccess) { |
| 849 generateGetter(node, elements[node]); | 941 generateGetter(node, elements[node]); |
| 942 } else if (Elements.isClosureSend(node, elements)) { |
| 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; | 955 } else if (!element.isInstanceMember()) { |
| 862 if (isInvokeDynamic) { | 956 // Example: A.f() or f() with 'f' bound to a static function. |
| 863 dartMethodName = node.selector.asIdentifier().source; | 957 // Also includes new A() or new A.named() which is treated like a |
| 864 interceptor = interceptors.getStaticInterceptor( | 958 // static call to a factory. |
| 865 dartMethodName, node.argumentCount()); | 959 visitStaticSend(node); |
| 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 { | 960 } else { |
| 887 HStatic target = new HStatic(element); | 961 compiler.internalError("Cannot generate code for send", node: node); |
| 888 add(target); | |
| 889 inputs.add(target); | |
| 890 } | |
| 891 | |
| 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 } | 962 } |
| 914 } | 963 } |
| 915 } | 964 } |
| 916 | 965 |
| 917 visitNewExpression(NewExpression node) => visitSend(node.send); | 966 visitNewExpression(NewExpression node) => visitSend(node.send); |
| 918 | 967 |
| 919 HInstruction updateDefinition(Node node, HInstruction value) { | 968 HInstruction updateDefinition(Node node, HInstruction value) { |
| 920 VariableElement element = elements[node]; | 969 VariableElement element = elements[node]; |
| 921 value = guard(element.type, value); | 970 value = guard(element.type, value); |
| 922 definitions[element] = value; | 971 definitions[element] = value; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 } | 1228 } |
| 1180 | 1229 |
| 1181 visitCatchBlock(CatchBlock node) { | 1230 visitCatchBlock(CatchBlock node) { |
| 1182 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); | 1231 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); |
| 1183 } | 1232 } |
| 1184 | 1233 |
| 1185 visitTypedef(Typedef node) { | 1234 visitTypedef(Typedef node) { |
| 1186 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 1235 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 1187 } | 1236 } |
| 1188 } | 1237 } |
| OLD | NEW |