| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' show PrimitiveConstantValue; | 8 import '../constants/values.dart' show PrimitiveConstantValue; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../dart2jslib.dart'; | 10 import '../dart2jslib.dart'; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 /// Call [enterTry] before translating a try block and call this function | 154 /// Call [enterTry] before translating a try block and call this function |
| 155 /// after translating it. | 155 /// after translating it. |
| 156 void leaveTry() { | 156 void leaveTry() { |
| 157 _boxedTryVariables.removeLast(); | 157 _boxedTryVariables.removeLast(); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void _buildTryExit(IrBuilder builder) { | 160 void _buildTryExit(IrBuilder builder) { |
| 161 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) { | 161 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) { |
| 162 for (LocalVariableElement variable in boxedOnEntry) { | 162 for (LocalVariableElement variable in boxedOnEntry) { |
| 163 assert(builder.isInMutableVariable(variable)); | 163 assert(builder.isInMutableVariable(variable)); |
| 164 ir.Primitive value = builder.buildLocalGet(variable); | 164 ir.Primitive value = builder.buildLocalVariableGet(variable); |
| 165 builder.environment.update(variable, value); | 165 builder.environment.update(variable, value); |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 } | 168 } |
| 169 } | 169 } |
| 170 | 170 |
| 171 /// A class to collect 'forward' jumps. | 171 /// A class to collect 'forward' jumps. |
| 172 /// | 172 /// |
| 173 /// A forward jump to a continuation in the sense of the CPS translation is | 173 /// A forward jump to a continuation in the sense of the CPS translation is |
| 174 /// a jump where the jump is emitted before any code in the body of the | 174 /// a jump where the jump is emitted before any code in the body of the |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 List<ir.Primitive> arguments) { | 642 List<ir.Primitive> arguments) { |
| 643 assert(target.isInstanceMember); | 643 assert(target.isInstanceMember); |
| 644 assert(isOpen); | 644 assert(isOpen); |
| 645 return _continueWithExpression( | 645 return _continueWithExpression( |
| 646 (k) => new ir.InvokeMethodDirectly( | 646 (k) => new ir.InvokeMethodDirectly( |
| 647 buildThis(), target, selector, k, arguments)); | 647 buildThis(), target, selector, k, arguments)); |
| 648 } | 648 } |
| 649 | 649 |
| 650 ir.Primitive _buildInvokeDynamic(ir.Primitive receiver, | 650 ir.Primitive _buildInvokeDynamic(ir.Primitive receiver, |
| 651 Selector selector, | 651 Selector selector, |
| 652 List<ir.Primitive> arguments) { | 652 List<ir.Primitive> arguments, |
| 653 {SourceInformation sourceInformation}) { |
| 653 assert(isOpen); | 654 assert(isOpen); |
| 654 return _continueWithExpression( | 655 return _continueWithExpression( |
| 655 (k) => new ir.InvokeMethod(receiver, selector, k, arguments)); | 656 (k) => new ir.InvokeMethod(receiver, selector, k, arguments, |
| 657 sourceInformation: sourceInformation)); |
| 656 } | 658 } |
| 657 | 659 |
| 658 ir.Primitive _buildInvokeCall(ir.Primitive target, | 660 ir.Primitive _buildInvokeCall(ir.Primitive target, |
| 659 Selector selector, | 661 Selector selector, |
| 660 List<ir.Definition> arguments) { | 662 List<ir.Definition> arguments, |
| 663 {SourceInformation sourceInformation}) { |
| 661 Selector callSelector = new Selector.callClosureFrom(selector); | 664 Selector callSelector = new Selector.callClosureFrom(selector); |
| 662 return _buildInvokeDynamic(target, callSelector, arguments); | 665 return _buildInvokeDynamic(target, callSelector, arguments, |
| 666 sourceInformation: sourceInformation); |
| 663 } | 667 } |
| 664 | 668 |
| 665 | 669 |
| 666 /// Create a constant literal from [constant]. | 670 /// Create a constant literal from [constant]. |
| 667 ir.Constant buildConstantLiteral(ConstantExpression constant) { | 671 ir.Constant buildConstantLiteral(ConstantExpression constant) { |
| 668 assert(isOpen); | 672 assert(isOpen); |
| 669 return addPrimitive(new ir.Constant(constant)); | 673 return addPrimitive(new ir.Constant(constant)); |
| 670 } | 674 } |
| 671 | 675 |
| 672 // Helper for building primitive literals. | 676 // Helper for building primitive literals. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 | 871 |
| 868 ir.ConstructorDefinition makeConstructorDefinition( | 872 ir.ConstructorDefinition makeConstructorDefinition( |
| 869 List<ConstantExpression> defaults, List<ir.Initializer> initializers) { | 873 List<ConstantExpression> defaults, List<ir.Initializer> initializers) { |
| 870 FunctionElement element = state.currentElement; | 874 FunctionElement element = state.currentElement; |
| 871 ir.RunnableBody body = makeRunnableBody(); | 875 ir.RunnableBody body = makeRunnableBody(); |
| 872 return new ir.ConstructorDefinition( | 876 return new ir.ConstructorDefinition( |
| 873 element, state.thisParameter, state.functionParameters, body, initialize
rs, | 877 element, state.thisParameter, state.functionParameters, body, initialize
rs, |
| 874 state.localConstants, defaults); | 878 state.localConstants, defaults); |
| 875 } | 879 } |
| 876 | 880 |
| 877 /// Create a super invocation where the method name and the argument structure | 881 /// Create a invocation of the [method] on the super class where the call |
| 878 /// are defined by [selector] and the argument values are defined by | 882 /// structure is defined [selector] and the argument values are defined by |
| 879 /// [arguments]. | 883 /// [arguments]. |
| 880 ir.Primitive buildSuperInvocation(Element target, | 884 ir.Primitive buildSuperMethodInvocation(MethodElement method, |
| 881 Selector selector, | 885 Selector selector, |
| 882 List<ir.Primitive> arguments); | 886 List<ir.Primitive> arguments) { |
| 883 | 887 return _buildInvokeSuper(method, selector, arguments); |
| 884 /// Create a getter invocation of the [target] on the super class. | |
| 885 ir.Primitive buildSuperGet(Element target) { | |
| 886 Selector selector = new Selector.getter(target.name, target.library); | |
| 887 return buildSuperInvocation(target, selector, const <ir.Primitive>[]); | |
| 888 } | 888 } |
| 889 | 889 |
| 890 /// Create a setter invocation of the [target] on the super class of with | 890 /// Create a call invocation on the value of [field] on the super class where |
| 891 /// [value]. | 891 /// the call structure is defined [selector] and the argument values are |
| 892 ir.Primitive buildSuperSet(Element target, ir.Primitive value) { | 892 /// defined by [arguments]. |
| 893 Selector selector = new Selector.setter(target.name, target.library); | 893 ir.Primitive buildSuperFieldInvocation(FieldElement field, |
| 894 buildSuperInvocation(target, selector, [value]); | 894 Selector selector, |
| 895 List<ir.Primitive> arguments) { |
| 896 // TODO(johnniwinther): Maybe this should have its own ir node. |
| 897 return buildCallInvocation( |
| 898 buildSuperFieldGet(field), |
| 899 selector, |
| 900 arguments); |
| 901 } |
| 902 |
| 903 /// Create a call invocation on the value returned from the [getter] on the |
| 904 /// super class where the call structure is defined [selector] and the |
| 905 /// argument values are defined by [arguments]. |
| 906 ir.Primitive buildSuperGetterInvocation(MethodElement getter, |
| 907 Selector selector, |
| 908 List<ir.Primitive> arguments) { |
| 909 // TODO(johnniwinther): Maybe this should have its own ir node. |
| 910 return buildCallInvocation( |
| 911 buildSuperGetterGet(getter), |
| 912 selector, |
| 913 arguments); |
| 914 } |
| 915 |
| 916 /// Create a read access of the [field] on the super class. |
| 917 ir.Primitive buildSuperFieldGet(FieldElement field) { |
| 918 // TODO(johnniwinther): This should have its own ir node. |
| 919 return _buildInvokeSuper( |
| 920 field, |
| 921 new Selector.getter(field.name, field.library), |
| 922 const <ir.Primitive>[]); |
| 923 } |
| 924 |
| 925 /// Create a read access of the [method] on the super class, i.e. a |
| 926 /// closurization of [method]. |
| 927 ir.Primitive buildSuperMethodGet(MethodElement method) { |
| 928 // TODO(johnniwinther): This should have its own ir node. |
| 929 return _buildInvokeSuper( |
| 930 method, |
| 931 new Selector.getter(method.name, method.library), |
| 932 const <ir.Primitive>[]); |
| 933 } |
| 934 |
| 935 /// Create a getter invocation of the [getter] on the super class. |
| 936 ir.Primitive buildSuperGetterGet(MethodElement getter) { |
| 937 // TODO(johnniwinther): This should have its own ir node. |
| 938 return _buildInvokeSuper( |
| 939 getter, |
| 940 new Selector.getter(getter.name, getter.library), |
| 941 const <ir.Primitive>[]); |
| 942 } |
| 943 |
| 944 /// Create a write access to the [field] on the super class of with [value]. |
| 945 ir.Primitive buildSuperFieldSet(Element field, ir.Primitive value) { |
| 946 // TODO(johnniwinther): This should have its own ir node. |
| 947 _buildInvokeSuper( |
| 948 field, |
| 949 new Selector.setter(field.name, field.library), |
| 950 <ir.Primitive>[value]); |
| 895 return value; | 951 return value; |
| 896 } | 952 } |
| 897 | 953 |
| 898 /// Create an index set invocation on the super class with the provided | 954 /// Create an setter invocation of the [setter] on the super class with |
| 899 /// [index] and [value]. | 955 /// [value]. |
| 900 ir.Primitive buildSuperIndexSet(Element target, | 956 ir.Primitive buildSuperSetterSet(MethodElement setter, |
| 957 ir.Primitive value) { |
| 958 // TODO(johnniwinther): This should have its own ir node. |
| 959 _buildInvokeSuper( |
| 960 setter, |
| 961 new Selector.setter(setter.name, setter.library), |
| 962 <ir.Primitive>[value]); |
| 963 return value; |
| 964 } |
| 965 |
| 966 /// Create an invocation of the index set [method] on the super class with |
| 967 /// the provided [index] and [value]. |
| 968 ir.Primitive buildSuperIndexSet(MethodElement method, |
| 901 ir.Primitive index, | 969 ir.Primitive index, |
| 902 ir.Primitive value) { | 970 ir.Primitive value) { |
| 903 _buildInvokeSuper(target, new Selector.indexSet(), | 971 _buildInvokeSuper(method, new Selector.indexSet(), |
| 904 <ir.Primitive>[index, value]); | 972 <ir.Primitive>[index, value]); |
| 905 return value; | 973 return value; |
| 906 } | 974 } |
| 907 | 975 |
| 908 /// Create a dynamic invocation on [receiver] where the method name and | 976 /// Create a dynamic invocation on [receiver] where the method name and |
| 909 /// argument structure are defined by [selector] and the argument values are | 977 /// argument structure are defined by [selector] and the argument values are |
| 910 /// defined by [arguments]. | 978 /// defined by [arguments]. |
| 911 ir.Primitive buildDynamicInvocation(ir.Primitive receiver, | 979 ir.Primitive buildDynamicInvocation(ir.Primitive receiver, |
| 912 Selector selector, | 980 Selector selector, |
| 913 List<ir.Primitive> arguments) { | 981 List<ir.Primitive> arguments) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 934 /// Create a dynamic index set invocation on [receiver] with the provided | 1002 /// Create a dynamic index set invocation on [receiver] with the provided |
| 935 /// [index] and [value]. | 1003 /// [index] and [value]. |
| 936 ir.Primitive buildDynamicIndexSet(ir.Primitive receiver, | 1004 ir.Primitive buildDynamicIndexSet(ir.Primitive receiver, |
| 937 ir.Primitive index, | 1005 ir.Primitive index, |
| 938 ir.Primitive value) { | 1006 ir.Primitive value) { |
| 939 _buildInvokeDynamic( | 1007 _buildInvokeDynamic( |
| 940 receiver, new Selector.indexSet(), <ir.Primitive>[index, value]); | 1008 receiver, new Selector.indexSet(), <ir.Primitive>[index, value]); |
| 941 return value; | 1009 return value; |
| 942 } | 1010 } |
| 943 | 1011 |
| 944 /// Create a read access of [local]. | 1012 ir.Primitive _buildLocalGet(LocalElement element); |
| 945 ir.Primitive buildLocalGet(LocalElement element); | |
| 946 | 1013 |
| 947 /// Create a write access to [local] with the provided [value]. | 1014 /// Create a read access of the [local] variable or parameter. |
| 948 ir.Primitive buildLocalSet(LocalElement element, ir.Primitive value); | 1015 ir.Primitive buildLocalVariableGet(LocalElement local) { |
| 949 | 1016 // TODO(johnniwinther): Separate function access from variable access. |
| 950 /// Create an invocation of the local [element] where argument structure is | 1017 return _buildLocalGet(local); |
| 951 /// defined by [selector] and the argument values are defined by [arguments]. | |
| 952 ir.Primitive buildLocalInvocation(LocalElement element, | |
| 953 Selector selector, | |
| 954 List<ir.Primitive> arguments) { | |
| 955 return buildCallInvocation(buildLocalGet(element), selector, arguments); | |
| 956 } | 1018 } |
| 957 | 1019 |
| 958 /// Create a static invocation of [element] where argument structure is | 1020 /// Create a read access of the local [function], i.e. closurization of |
| 959 /// defined by [selector] and the argument values are defined by [arguments]. | 1021 /// [function]. |
| 960 ir.Primitive buildStaticInvocation(Element element, | 1022 ir.Primitive buildLocalFunctionGet(LocalFunctionElement function) { |
| 961 Selector selector, | 1023 // TODO(johnniwinther): Separate function access from variable access. |
| 962 List<ir.Primitive> arguments, | 1024 return _buildLocalGet(function); |
| 963 {SourceInformation sourceInformation}) { | |
| 964 return _buildInvokeStatic(element, selector, arguments, sourceInformation); | |
| 965 } | 1025 } |
| 966 | 1026 |
| 967 /// Create a static getter invocation of [element] where the getter name is | 1027 /// Create a write access to the [local] variable or parameter with the |
| 968 /// defined by [selector]. | 1028 /// provided [value]. |
| 969 ir.Primitive buildStaticGet(Element element, | 1029 ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value); |
| 970 {SourceInformation sourceInformation}) { | 1030 |
| 971 Selector selector = new Selector.getter(element.name, element.library); | 1031 /// Create an invocation of the the [local] variable or parameter where |
| 1032 /// argument structure is defined by [selector] and the argument values are |
| 1033 /// defined by [arguments]. |
| 1034 ir.Primitive buildLocalVariableInvocation(LocalVariableElement local, |
| 1035 Selector selector, |
| 1036 List<ir.Primitive> arguments) { |
| 1037 return buildCallInvocation( |
| 1038 buildLocalVariableGet(local), selector, arguments); |
| 1039 } |
| 1040 |
| 1041 /// Create an invocation of the local [function] where argument structure is |
| 1042 /// defined by [selector] and the argument values are defined by [arguments]. |
| 1043 ir.Primitive buildLocalFunctionInvocation( |
| 1044 LocalFunctionElement function, |
| 1045 Selector selector, |
| 1046 List<ir.Primitive> arguments) { |
| 1047 // TODO(johnniwinther): Maybe this should have its own ir node. |
| 1048 return buildCallInvocation( |
| 1049 buildLocalFunctionGet(function), selector, arguments); |
| 1050 } |
| 1051 |
| 1052 /// Create a static invocation of [function] where argument structure is |
| 1053 /// defined by [selector] and the argument values are defined by [arguments]. |
| 1054 ir.Primitive buildStaticFunctionInvocation( |
| 1055 MethodElement function, |
| 1056 Selector selector, |
| 1057 List<ir.Primitive> arguments, |
| 1058 {SourceInformation sourceInformation}) { |
| 1059 return _buildInvokeStatic(function, selector, arguments, sourceInformation); |
| 1060 } |
| 1061 |
| 1062 /// Create a call invocation of the value of the static [field] where argument |
| 1063 /// structure is defined by [selector] and the argument values are defined by |
| 1064 /// [arguments]. |
| 1065 ir.Primitive buildStaticFieldInvocation( |
| 1066 FieldElement field, |
| 1067 Selector selector, |
| 1068 List<ir.Primitive> arguments, |
| 1069 {SourceInformation sourceInformation}) { |
| 1070 // TODO(johnniwinther): Maybe this should have its own node. |
| 1071 return buildCallInvocation( |
| 1072 buildStaticFieldGet(field), |
| 1073 selector, |
| 1074 arguments, |
| 1075 sourceInformation: sourceInformation); |
| 1076 } |
| 1077 |
| 1078 /// Create a call invocation of the result of calling the static [getter] |
| 1079 /// where argument structure is defined by [selector] and the argument values |
| 1080 /// are defined by [arguments]. |
| 1081 ir.Primitive buildStaticGetterInvocation( |
| 1082 MethodElement getter, |
| 1083 Selector selector, |
| 1084 List<ir.Primitive> arguments, |
| 1085 {SourceInformation sourceInformation}) { |
| 1086 // TODO(johnniwinther): Maybe this should have its own node. |
| 1087 return buildCallInvocation( |
| 1088 buildStaticGetterGet(getter), |
| 1089 selector, |
| 1090 arguments, |
| 1091 sourceInformation: sourceInformation); |
| 1092 } |
| 1093 |
| 1094 /// Create a read access of the static [field]. |
| 1095 ir.Primitive buildStaticFieldGet(FieldElement field, |
| 1096 {SourceInformation sourceInformation}) { |
| 1097 Selector selector = new Selector.getter(field.name, field.library); |
| 972 // TODO(karlklose,sigurdm): build different nodes for getters. | 1098 // TODO(karlklose,sigurdm): build different nodes for getters. |
| 973 return _buildInvokeStatic( | 1099 return _buildInvokeStatic( |
| 974 element, selector, const <ir.Primitive>[], sourceInformation); | 1100 field, selector, const <ir.Primitive>[], sourceInformation); |
| 975 } | 1101 } |
| 976 | 1102 |
| 977 /// Create a static setter invocation of [element] where the setter name and | 1103 /// Create a getter invocation of the static [getter]. |
| 978 /// argument are defined by [selector] and [value], respectively. | 1104 ir.Primitive buildStaticGetterGet(MethodElement getter, |
| 979 ir.Primitive buildStaticSet(Element element, | 1105 {SourceInformation sourceInformation}) { |
| 980 ir.Primitive value, | 1106 Selector selector = new Selector.getter(getter.name, getter.library); |
| 981 {SourceInformation sourceInformation}) { | 1107 // TODO(karlklose,sigurdm): build different nodes for getters. |
| 982 Selector selector = new Selector.setter(element.name, element.library); | 1108 return _buildInvokeStatic( |
| 1109 getter, selector, const <ir.Primitive>[], sourceInformation); |
| 1110 } |
| 1111 |
| 1112 /// Create a read access of the static [function], i.e. a closurization of |
| 1113 /// [function]. |
| 1114 ir.Primitive buildStaticFunctionGet(MethodElement function, |
| 1115 {SourceInformation sourceInformation}) { |
| 1116 Selector selector = |
| 1117 new Selector.getter(function.name, function.library); |
| 1118 // TODO(karlklose,sigurdm): build different nodes for getters. |
| 1119 return _buildInvokeStatic( |
| 1120 function, selector, const <ir.Primitive>[], sourceInformation); |
| 1121 } |
| 1122 |
| 1123 /// Create a write access to the static [field] with the [value]. |
| 1124 ir.Primitive buildStaticFieldSet(FieldElement field, |
| 1125 ir.Primitive value, |
| 1126 {SourceInformation sourceInformation}) { |
| 1127 Selector selector = new Selector.setter(field.name, field.library); |
| 983 // TODO(karlklose,sigurdm): build different nodes for setters. | 1128 // TODO(karlklose,sigurdm): build different nodes for setters. |
| 984 _buildInvokeStatic( | 1129 _buildInvokeStatic( |
| 985 element, selector, <ir.Primitive>[value], sourceInformation); | 1130 field, selector, <ir.Primitive>[value], sourceInformation); |
| 986 return value; | 1131 return value; |
| 987 } | 1132 } |
| 988 | 1133 |
| 1134 /// Create a setter invocation of the static [setter] with the [value]. |
| 1135 ir.Primitive buildStaticSetterSet(MethodElement setter, |
| 1136 ir.Primitive value, |
| 1137 {SourceInformation sourceInformation}) { |
| 1138 Selector selector = new Selector.setter(setter.name, setter.library); |
| 1139 // TODO(karlklose,sigurdm): build different nodes for setters. |
| 1140 _buildInvokeStatic( |
| 1141 setter, selector, <ir.Primitive>[value], sourceInformation); |
| 1142 return value; |
| 1143 } |
| 1144 |
| 1145 /// Create an erroneous invocation where argument structure is defined by |
| 1146 /// [selector] and the argument values are defined by [arguments]. |
| 1147 // TODO(johnniwinther): Make this more fine-grained. |
| 1148 ir.Primitive buildErroneousInvocation( |
| 1149 Element element, |
| 1150 Selector selector, |
| 1151 List<ir.Primitive> arguments) { |
| 1152 // TODO(johnniwinther): This should have its own ir node. |
| 1153 return _buildInvokeStatic( element, selector, arguments, null); |
| 1154 } |
| 1155 |
| 989 /// Create a constructor invocation of [element] on [type] where the | 1156 /// Create a constructor invocation of [element] on [type] where the |
| 990 /// constructor name and argument structure are defined by [selector] and the | 1157 /// constructor name and argument structure are defined by [selector] and the |
| 991 /// argument values are defined by [arguments]. | 1158 /// argument values are defined by [arguments]. |
| 992 ir.Primitive buildConstructorInvocation(FunctionElement element, | 1159 ir.Primitive buildConstructorInvocation(FunctionElement element, |
| 993 Selector selector, | 1160 Selector selector, |
| 994 DartType type, | 1161 DartType type, |
| 995 List<ir.Primitive> arguments); | 1162 List<ir.Primitive> arguments); |
| 996 | 1163 |
| 997 /// Create a string concatenation of the [arguments]. | 1164 /// Create a string concatenation of the [arguments]. |
| 998 ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) { | 1165 ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) { |
| 999 assert(isOpen); | 1166 assert(isOpen); |
| 1000 return _continueWithExpression( | 1167 return _continueWithExpression( |
| 1001 (k) => new ir.ConcatenateStrings(k, arguments)); | 1168 (k) => new ir.ConcatenateStrings(k, arguments)); |
| 1002 } | 1169 } |
| 1003 | 1170 |
| 1004 /// Create an invocation of the `call` method of [functionExpression], where | 1171 /// Create an invocation of the `call` method of [functionExpression], where |
| 1005 /// the named arguments are given by [selector]. | 1172 /// the named arguments are given by [selector]. |
| 1006 ir.Primitive buildCallInvocation( | 1173 ir.Primitive buildCallInvocation( |
| 1007 ir.Primitive functionExpression, | 1174 ir.Primitive functionExpression, |
| 1008 Selector selector, | 1175 Selector selector, |
| 1009 List<ir.Definition> arguments) { | 1176 List<ir.Definition> arguments, |
| 1010 return _buildInvokeCall(functionExpression, selector, arguments); | 1177 {SourceInformation sourceInformation}) { |
| 1178 return _buildInvokeCall(functionExpression, selector, arguments, |
| 1179 sourceInformation: sourceInformation); |
| 1011 } | 1180 } |
| 1012 | 1181 |
| 1013 /// Creates an if-then-else statement with the provided [condition] where the | 1182 /// Creates an if-then-else statement with the provided [condition] where the |
| 1014 /// then and else branches are created through the [buildThenPart] and | 1183 /// then and else branches are created through the [buildThenPart] and |
| 1015 /// [buildElsePart] functions, respectively. | 1184 /// [buildElsePart] functions, respectively. |
| 1016 /// | 1185 /// |
| 1017 /// An if-then statement is created if [buildElsePart] is a no-op. | 1186 /// An if-then statement is created if [buildElsePart] is a no-op. |
| 1018 // TODO(johnniwinther): Unify implementation with [buildConditional] and | 1187 // TODO(johnniwinther): Unify implementation with [buildConditional] and |
| 1019 // [_buildLogicalOperator]. | 1188 // [_buildLogicalOperator]. |
| 1020 void buildIf(ir.Primitive condition, | 1189 void buildIf(ir.Primitive condition, |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 if (buildVariableDeclaration != null) { | 1485 if (buildVariableDeclaration != null) { |
| 1317 buildVariableDeclaration(bodyBuilder); | 1486 buildVariableDeclaration(bodyBuilder); |
| 1318 } | 1487 } |
| 1319 ir.Parameter currentValue = new ir.Parameter(null); | 1488 ir.Parameter currentValue = new ir.Parameter(null); |
| 1320 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); | 1489 ir.Continuation currentInvoked = new ir.Continuation([currentValue]); |
| 1321 bodyBuilder.add(new ir.LetCont(currentInvoked, | 1490 bodyBuilder.add(new ir.LetCont(currentInvoked, |
| 1322 new ir.InvokeMethod(iterator, new Selector.getter("current", null), | 1491 new ir.InvokeMethod(iterator, new Selector.getter("current", null), |
| 1323 currentInvoked, emptyArguments))); | 1492 currentInvoked, emptyArguments))); |
| 1324 // TODO(sra): Does this cover all cases? The general setter case include | 1493 // TODO(sra): Does this cover all cases? The general setter case include |
| 1325 // super. | 1494 // super. |
| 1495 // TODO(johnniwinther): Extract this as a provided strategy. |
| 1326 if (Elements.isLocal(variableElement)) { | 1496 if (Elements.isLocal(variableElement)) { |
| 1327 bodyBuilder.buildLocalSet(variableElement, currentValue); | 1497 bodyBuilder.buildLocalVariableSet(variableElement, currentValue); |
| 1328 } else if (Elements.isStaticOrTopLevel(variableElement) || | 1498 } else if (Elements.isErroneous(variableElement)) { |
| 1329 Elements.isErroneous(variableElement)) { | 1499 bodyBuilder.buildErroneousInvocation(variableElement, |
| 1330 bodyBuilder.buildStaticSet(variableElement, currentValue); | 1500 new Selector.setter(variableElement.name, variableElement.library), |
| 1501 <ir.Primitive>[currentValue]); |
| 1502 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 1503 if (variableElement.isField) { |
| 1504 bodyBuilder.buildStaticFieldSet(variableElement, currentValue); |
| 1505 } else { |
| 1506 bodyBuilder.buildStaticSetterSet(variableElement, currentValue); |
| 1507 } |
| 1331 } else { | 1508 } else { |
| 1332 ir.Primitive receiver = bodyBuilder.buildThis(); | 1509 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 1333 assert(receiver != null); | 1510 assert(receiver != null); |
| 1334 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); | 1511 bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue); |
| 1335 } | 1512 } |
| 1336 | 1513 |
| 1337 // Translate the body in the hole in the delimited term above, and add | 1514 // Translate the body in the hole in the delimited term above, and add |
| 1338 // a jump to the loop if control flow is live after the body. | 1515 // a jump to the loop if control flow is live after the body. |
| 1339 JumpCollector breakCollector = | 1516 JumpCollector breakCollector = |
| 1340 new ForwardJumpCollector(environment, target: target); | 1517 new ForwardJumpCollector(environment, target: target); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 // entry to any try block. They are not filtered out before this because | 1769 // entry to any try block. They are not filtered out before this because |
| 1593 // we can not identify all of them in the same pass where we identify the | 1770 // we can not identify all of them in the same pass where we identify the |
| 1594 // variables assigned in the try (they may be captured by a closure after | 1771 // variables assigned in the try (they may be captured by a closure after |
| 1595 // the try statement). | 1772 // the try statement). |
| 1596 Iterable<LocalVariableElement> boxedOnEntry = | 1773 Iterable<LocalVariableElement> boxedOnEntry = |
| 1597 tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) { | 1774 tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) { |
| 1598 return !tryCatchBuilder.mutableCapturedVariables.contains(variable); | 1775 return !tryCatchBuilder.mutableCapturedVariables.contains(variable); |
| 1599 }); | 1776 }); |
| 1600 for (LocalVariableElement variable in boxedOnEntry) { | 1777 for (LocalVariableElement variable in boxedOnEntry) { |
| 1601 assert(!tryCatchBuilder.isInMutableVariable(variable)); | 1778 assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| 1602 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); | 1779 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); |
| 1603 tryCatchBuilder.makeMutableVariable(variable); | 1780 tryCatchBuilder.makeMutableVariable(variable); |
| 1604 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); | 1781 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| 1605 } | 1782 } |
| 1606 | 1783 |
| 1607 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1784 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1608 | 1785 |
| 1609 void interceptJumps(JumpCollector collector) { | 1786 void interceptJumps(JumpCollector collector) { |
| 1610 collector.enterTry(boxedOnEntry); | 1787 collector.enterTry(boxedOnEntry); |
| 1611 } | 1788 } |
| 1612 void restoreJumps(JumpCollector collector) { | 1789 void restoreJumps(JumpCollector collector) { |
| 1613 collector.leaveTry(); | 1790 collector.leaveTry(); |
| 1614 } | 1791 } |
| 1615 tryBuilder.state.breakCollectors.forEach(interceptJumps); | 1792 tryBuilder.state.breakCollectors.forEach(interceptJumps); |
| 1616 tryBuilder.state.continueCollectors.forEach(interceptJumps); | 1793 tryBuilder.state.continueCollectors.forEach(interceptJumps); |
| 1617 buildTryBlock(tryBuilder); | 1794 buildTryBlock(tryBuilder); |
| 1618 if (tryBuilder.isOpen) { | 1795 if (tryBuilder.isOpen) { |
| 1619 interceptJumps(join); | 1796 interceptJumps(join); |
| 1620 tryBuilder.jumpTo(join); | 1797 tryBuilder.jumpTo(join); |
| 1621 restoreJumps(join); | 1798 restoreJumps(join); |
| 1622 } | 1799 } |
| 1623 tryBuilder.state.breakCollectors.forEach(restoreJumps); | 1800 tryBuilder.state.breakCollectors.forEach(restoreJumps); |
| 1624 tryBuilder.state.continueCollectors.forEach(restoreJumps); | 1801 tryBuilder.state.continueCollectors.forEach(restoreJumps); |
| 1625 | 1802 |
| 1626 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1803 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1627 for (LocalVariableElement variable in boxedOnEntry) { | 1804 for (LocalVariableElement variable in boxedOnEntry) { |
| 1628 assert(catchBuilder.isInMutableVariable(variable)); | 1805 assert(catchBuilder.isInMutableVariable(variable)); |
| 1629 ir.Primitive value = catchBuilder.buildLocalGet(variable); | 1806 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable); |
| 1630 // Note that we remove the variable from the set of mutable variables | 1807 // Note that we remove the variable from the set of mutable variables |
| 1631 // here (and not above for the try body). This is because the set of | 1808 // here (and not above for the try body). This is because the set of |
| 1632 // mutable variables is global for the whole function and not local to | 1809 // mutable variables is global for the whole function and not local to |
| 1633 // a delimited builder. | 1810 // a delimited builder. |
| 1634 catchBuilder.removeMutableVariable(variable); | 1811 catchBuilder.removeMutableVariable(variable); |
| 1635 catchBuilder.environment.update(variable, value); | 1812 catchBuilder.environment.update(variable, value); |
| 1636 } | 1813 } |
| 1637 | 1814 |
| 1638 // TODO(kmillikin): Handle multiple catch clauses. | 1815 // TODO(kmillikin): Handle multiple catch clauses. |
| 1639 assert(catchClauseInfos.length == 1); | 1816 assert(catchClauseInfos.length == 1); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2077 prim.useElementAsHint(functionElement); | 2254 prim.useElementAsHint(functionElement); |
| 2078 } | 2255 } |
| 2079 } | 2256 } |
| 2080 | 2257 |
| 2081 /// Create a function expression from [definition]. | 2258 /// Create a function expression from [definition]. |
| 2082 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { | 2259 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { |
| 2083 return addPrimitive(new ir.CreateFunction(definition)); | 2260 return addPrimitive(new ir.CreateFunction(definition)); |
| 2084 } | 2261 } |
| 2085 | 2262 |
| 2086 /// Create a read access of [local]. | 2263 /// Create a read access of [local]. |
| 2087 ir.Primitive buildLocalGet(LocalElement local) { | 2264 @override |
| 2265 ir.Primitive _buildLocalGet(LocalElement local) { |
| 2088 assert(isOpen); | 2266 assert(isOpen); |
| 2089 if (isInMutableVariable(local)) { | 2267 if (isInMutableVariable(local)) { |
| 2090 // Do not use [local] as a hint on [result]. The variable should always | 2268 // Do not use [local] as a hint on [result]. The variable should always |
| 2091 // be inlined, but the hint prevents it. | 2269 // be inlined, but the hint prevents it. |
| 2092 return addPrimitive(new ir.GetMutableVariable(getMutableVariable(local))); | 2270 return addPrimitive(new ir.GetMutableVariable(getMutableVariable(local))); |
| 2093 } else { | 2271 } else { |
| 2094 return environment.lookup(local); | 2272 return environment.lookup(local); |
| 2095 } | 2273 } |
| 2096 } | 2274 } |
| 2097 | 2275 |
| 2098 /// Create a write access to [local] with the provided [value]. | 2276 /// Create a write access to [local] with the provided [value]. |
| 2099 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2277 @override |
| 2278 ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value) { |
| 2100 assert(isOpen); | 2279 assert(isOpen); |
| 2101 if (isInMutableVariable(local)) { | 2280 if (isInMutableVariable(local)) { |
| 2102 add(new ir.SetMutableVariable(getMutableVariable(local), value)); | 2281 add(new ir.SetMutableVariable(getMutableVariable(local), value)); |
| 2103 } else { | 2282 } else { |
| 2104 value.useElementAsHint(local); | 2283 value.useElementAsHint(local); |
| 2105 environment.update(local, value); | 2284 environment.update(local, value); |
| 2106 } | 2285 } |
| 2107 return value; | 2286 return value; |
| 2108 } | 2287 } |
| 2109 | 2288 |
| 2110 ir.Primitive buildThis() { | 2289 ir.Primitive buildThis() { |
| 2111 return state.enclosingMethodThisParameter; | 2290 return state.enclosingMethodThisParameter; |
| 2112 } | 2291 } |
| 2113 | 2292 |
| 2114 ir.Primitive buildSuperInvocation(Element target, | |
| 2115 Selector selector, | |
| 2116 List<ir.Primitive> arguments) { | |
| 2117 return _buildInvokeSuper(target, selector, arguments); | |
| 2118 } | |
| 2119 | |
| 2120 @override | 2293 @override |
| 2121 ir.Primitive buildConstructorInvocation(FunctionElement element, | 2294 ir.Primitive buildConstructorInvocation(FunctionElement element, |
| 2122 Selector selector, | 2295 Selector selector, |
| 2123 DartType type, | 2296 DartType type, |
| 2124 List<ir.Primitive> arguments) { | 2297 List<ir.Primitive> arguments) { |
| 2125 assert(isOpen); | 2298 assert(isOpen); |
| 2126 return _continueWithExpression( | 2299 return _continueWithExpression( |
| 2127 (k) => new ir.InvokeConstructor(type, element, selector, k, | 2300 (k) => new ir.InvokeConstructor(type, element, selector, k, |
| 2128 arguments)); | 2301 arguments)); |
| 2129 } | 2302 } |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2281 // so treat that specially. | 2454 // so treat that specially. |
| 2282 ir.Primitive value = field.local is ThisLocal | 2455 ir.Primitive value = field.local is ThisLocal |
| 2283 ? buildThis() | 2456 ? buildThis() |
| 2284 : environment.lookup(field.local); | 2457 : environment.lookup(field.local); |
| 2285 arguments.add(value); | 2458 arguments.add(value); |
| 2286 } | 2459 } |
| 2287 return addPrimitive( | 2460 return addPrimitive( |
| 2288 new ir.CreateInstance(classElement, arguments, const <ir.Primitive>[])); | 2461 new ir.CreateInstance(classElement, arguments, const <ir.Primitive>[])); |
| 2289 } | 2462 } |
| 2290 | 2463 |
| 2291 /// Create a read access of [local]. | 2464 /// Create a read access of [local] variable or parameter. |
| 2292 ir.Primitive buildLocalGet(LocalElement local) { | 2465 @override |
| 2466 ir.Primitive _buildLocalGet(LocalElement local) { |
| 2293 assert(isOpen); | 2467 assert(isOpen); |
| 2294 ClosureLocation location = jsState.boxedVariables[local]; | 2468 ClosureLocation location = jsState.boxedVariables[local]; |
| 2295 if (location != null) { | 2469 if (location != null) { |
| 2296 ir.Primitive result = new ir.GetField(environment.lookup(location.box), | 2470 ir.Primitive result = new ir.GetField(environment.lookup(location.box), |
| 2297 location.field); | 2471 location.field); |
| 2298 result.useElementAsHint(local); | 2472 result.useElementAsHint(local); |
| 2299 return addPrimitive(result); | 2473 return addPrimitive(result); |
| 2300 } else { | 2474 } else { |
| 2301 return environment.lookup(local); | 2475 return environment.lookup(local); |
| 2302 } | 2476 } |
| 2303 } | 2477 } |
| 2304 | 2478 |
| 2305 /// Create a write access to [local] with the provided [value]. | 2479 /// Create a write access to [local] variable or parameter with the provided |
| 2306 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2480 /// [value]. |
| 2481 @override |
| 2482 ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value) { |
| 2307 assert(isOpen); | 2483 assert(isOpen); |
| 2308 ClosureLocation location = jsState.boxedVariables[local]; | 2484 ClosureLocation location = jsState.boxedVariables[local]; |
| 2309 if (location != null) { | 2485 if (location != null) { |
| 2310 add(new ir.SetField(environment.lookup(location.box), | 2486 add(new ir.SetField(environment.lookup(location.box), |
| 2311 location.field, | 2487 location.field, |
| 2312 value)); | 2488 value)); |
| 2313 } else { | 2489 } else { |
| 2314 value.useElementAsHint(local); | 2490 value.useElementAsHint(local); |
| 2315 environment.update(local, value); | 2491 environment.update(local, value); |
| 2316 } | 2492 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 add(new ir.SetField(newBox, location.field, value)); | 2526 add(new ir.SetField(newBox, location.field, value)); |
| 2351 } | 2527 } |
| 2352 environment.update(scope.box, newBox); | 2528 environment.update(scope.box, newBox); |
| 2353 } | 2529 } |
| 2354 | 2530 |
| 2355 ir.Primitive buildThis() { | 2531 ir.Primitive buildThis() { |
| 2356 if (jsState.receiver != null) return jsState.receiver; | 2532 if (jsState.receiver != null) return jsState.receiver; |
| 2357 return state.thisParameter; | 2533 return state.thisParameter; |
| 2358 } | 2534 } |
| 2359 | 2535 |
| 2360 ir.Primitive buildSuperInvocation(Element target, | 2536 @override |
| 2361 Selector selector, | 2537 ir.Primitive buildSuperFieldGet(FieldElement target) { |
| 2362 List<ir.Primitive> arguments) { | 2538 return addPrimitive(new ir.GetField(buildThis(), target)); |
| 2363 // Direct calls to FieldElements are currently problematic because the | 2539 } |
| 2364 // backend will not issue a getter for the field unless it finds a dynamic | 2540 |
| 2365 // access that matches its getter. | 2541 @override |
| 2366 // As a workaround, we generate GetField for this case, although ideally | 2542 ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value) { |
| 2367 // this should be the result of inlining the field's getter. | 2543 add(new ir.SetField(buildThis(), target, value)); |
| 2368 if (target is FieldElement) { | 2544 return value; |
| 2369 if (selector.isGetter) { | |
| 2370 return addPrimitive(new ir.GetField(buildThis(), target)); | |
| 2371 } else { | |
| 2372 assert(selector.isSetter); | |
| 2373 add(new ir.SetField(buildThis(), target, arguments.single)); | |
| 2374 return arguments.single; | |
| 2375 } | |
| 2376 } else { | |
| 2377 return _buildInvokeSuper(target, selector, arguments); | |
| 2378 } | |
| 2379 } | 2545 } |
| 2380 | 2546 |
| 2381 ir.Primitive buildInvokeDirectly(FunctionElement target, | 2547 ir.Primitive buildInvokeDirectly(FunctionElement target, |
| 2382 ir.Primitive receiver, | 2548 ir.Primitive receiver, |
| 2383 List<ir.Primitive> arguments) { | 2549 List<ir.Primitive> arguments) { |
| 2384 assert(isOpen); | 2550 assert(isOpen); |
| 2385 Selector selector = | 2551 Selector selector = |
| 2386 new Selector.call(target.name, target.library, arguments.length); | 2552 new Selector.call(target.name, target.library, arguments.length); |
| 2387 return _continueWithExpression( | 2553 return _continueWithExpression( |
| 2388 (k) => new ir.InvokeMethodDirectly( | 2554 (k) => new ir.InvokeMethodDirectly( |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2536 } | 2702 } |
| 2537 | 2703 |
| 2538 /// Synthetic parameter to a JavaScript factory method that takes the type | 2704 /// Synthetic parameter to a JavaScript factory method that takes the type |
| 2539 /// argument given for the type variable [variable]. | 2705 /// argument given for the type variable [variable]. |
| 2540 class TypeInformationParameter implements Local { | 2706 class TypeInformationParameter implements Local { |
| 2541 final TypeVariableElement variable; | 2707 final TypeVariableElement variable; |
| 2542 final ExecutableElement executableContext; | 2708 final ExecutableElement executableContext; |
| 2543 TypeInformationParameter(this.variable, this.executableContext); | 2709 TypeInformationParameter(this.variable, this.executableContext); |
| 2544 String get name => variable.name; | 2710 String get name => variable.name; |
| 2545 } | 2711 } |
| OLD | NEW |