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 library dart2js.ir_nodes; | 4 library dart2js.ir_nodes; |
5 | 5 |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import '../constants/values.dart' as values; | 7 import '../constants/values.dart' as values; |
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
10 import '../io/source_information.dart' show SourceInformation; | 10 import '../io/source_information.dart' show SourceInformation; |
(...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 bool get isSafeForReordering => true; | 1177 bool get isSafeForReordering => true; |
1178 | 1178 |
1179 toString() => 'CreateInstance($classElement)'; | 1179 toString() => 'CreateInstance($classElement)'; |
1180 | 1180 |
1181 void setParentPointers() { | 1181 void setParentPointers() { |
1182 _setParentsOnList(arguments, this); | 1182 _setParentsOnList(arguments, this); |
1183 if (typeInformation != null) _setParentsOnList(typeInformation, this); | 1183 if (typeInformation != null) _setParentsOnList(typeInformation, this); |
1184 } | 1184 } |
1185 } | 1185 } |
1186 | 1186 |
| 1187 /// Obtains the interceptor for the given value. This is a method table |
| 1188 /// corresponding to the Dart class of the value. |
| 1189 /// |
| 1190 /// All values are either intercepted or self-intercepted. The interceptor for |
| 1191 /// an "intercepted value" is one of the subclasses of Interceptor. |
| 1192 /// The interceptor for a "self-intercepted value" is the value itself. |
| 1193 /// |
| 1194 /// If the input is an intercepted value, and any of its superclasses is in |
| 1195 /// [interceptedClasses], the method table for the input is returned. |
| 1196 /// Otherwise, the input itself is returned. |
| 1197 /// |
| 1198 /// There are thus three significant cases: |
| 1199 /// - the input is a self-interceptor |
| 1200 /// - the input is an intercepted value and is caught by [interceptedClasses] |
| 1201 /// - the input is an intercepted value but is bypassed by [interceptedClasses] |
| 1202 /// |
| 1203 /// The [flags] field indicates which of the above cases may happen, with |
| 1204 /// additional special cases for null (which can either by intercepted or |
| 1205 /// bypassed). |
1187 class Interceptor extends Primitive { | 1206 class Interceptor extends Primitive { |
1188 final Reference<Primitive> input; | 1207 final Reference<Primitive> input; |
1189 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); | 1208 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); |
1190 final SourceInformation sourceInformation; | 1209 final SourceInformation sourceInformation; |
1191 | 1210 |
1192 /// If non-null, all uses of this the interceptor call are guaranteed to | 1211 /// The input was a self-interceptor. |
1193 /// see this value. | 1212 static const int SELF_INTERCEPT = 1 << 0; |
1194 /// | 1213 |
1195 /// The interceptor call is not immediately replaced by the constant, because | 1214 /// A non-null value was mapped to an interceptor that was mentioned in |
1196 /// that might prevent the interceptor from being shared. | 1215 /// [interceptedClasses]. |
1197 /// | 1216 static const int NON_NULL_INTERCEPT_EXACT = 1 << 1; |
1198 /// The precise input type is not known when sharing interceptors, because | 1217 |
1199 /// refinement nodes have been removed by then. So this field carries the | 1218 /// A non-null value was mapped to an interceptor that is a subclass of |
1200 /// known constant until we know if it should be shared or replaced by | 1219 /// one mentioned in [interceptedClasses]. |
1201 /// the constant. | 1220 static const int NON_NULL_INTERCEPT_SUBCLASS = 1 << 2; |
1202 values.InterceptorConstantValue constantValue; | 1221 |
| 1222 /// A non-null intercepted value was bypassed because none of its supertypes |
| 1223 /// were mentioned in [interceptedClasses]. |
| 1224 static const int NON_NULL_BYPASS = 1 << 3; |
| 1225 |
| 1226 /// Null was returned as-is. |
| 1227 static const int NULL_BYPASS = 1 << 4; |
| 1228 |
| 1229 /// Null was mapped to JSNull, which was mentioned in [interceptedClasses]. |
| 1230 static const int NULL_INTERCEPT_EXACT = 1 << 5; |
| 1231 |
| 1232 /// Null was mapped to JSNull, because a superclass thereof (the interceptor |
| 1233 /// root class) was mentioned in [interceptedClasses]. |
| 1234 static const int NULL_INTERCEPT_SUBCLASS = 1 << 6; |
| 1235 |
| 1236 static const int NON_NULL_INTERCEPT = NON_NULL_INTERCEPT_EXACT | |
| 1237 NON_NULL_INTERCEPT_SUBCLASS; |
| 1238 static const int NULL_INTERCEPT = NULL_INTERCEPT_EXACT | |
| 1239 NULL_INTERCEPT_SUBCLASS; |
| 1240 static const int NULL = NULL_BYPASS | |
| 1241 NULL_INTERCEPT; |
| 1242 static const int INTERCEPT_EXACT = NON_NULL_INTERCEPT_EXACT | |
| 1243 NULL_INTERCEPT_EXACT; |
| 1244 static const int INTERCEPT_SUBCLASS = NON_NULL_INTERCEPT_SUBCLASS | |
| 1245 NULL_INTERCEPT_SUBCLASS; |
| 1246 static const int INTERCEPT = NULL_INTERCEPT | NON_NULL_INTERCEPT; |
| 1247 static const int BYPASS = NULL_BYPASS | NON_NULL_BYPASS; |
| 1248 |
| 1249 static const int ALL_FLAGS = SELF_INTERCEPT | BYPASS | INTERCEPT; |
| 1250 |
| 1251 /// Which of the above cases may happen at runtime. Set by type propagation. |
| 1252 int flags = ALL_FLAGS; |
| 1253 |
| 1254 void clearFlag(int flag) { |
| 1255 flags &= ~flag; |
| 1256 } |
| 1257 |
| 1258 bool get isAlwaysIntercepted => flags & ~INTERCEPT == 0; |
| 1259 bool get isAlwaysNullOrIntercepted => flags & ~(NULL | INTERCEPT) == 0; |
| 1260 |
| 1261 /// If the value is intercepted, it always matches exactly a class in |
| 1262 /// [interceptedClasses]. |
| 1263 bool get isInterceptedClassAlwaysExact { |
| 1264 return flags & (INTERCEPT & ~INTERCEPT_EXACT) == 0; |
| 1265 } |
1203 | 1266 |
1204 Interceptor(Primitive input, this.sourceInformation) | 1267 Interceptor(Primitive input, this.sourceInformation) |
1205 : this.input = new Reference<Primitive>(input); | 1268 : this.input = new Reference<Primitive>(input); |
1206 | 1269 |
1207 accept(Visitor visitor) => visitor.visitInterceptor(this); | 1270 accept(Visitor visitor) => visitor.visitInterceptor(this); |
1208 | 1271 |
1209 bool get isSafeForElimination => true; | 1272 bool get isSafeForElimination => true; |
1210 bool get isSafeForReordering => true; | 1273 bool get isSafeForReordering => true; |
1211 | 1274 |
1212 void setParentPointers() { | 1275 void setParentPointers() { |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2072 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 2135 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
2073 class RemovalVisitor extends TrampolineRecursiveVisitor { | 2136 class RemovalVisitor extends TrampolineRecursiveVisitor { |
2074 processReference(Reference reference) { | 2137 processReference(Reference reference) { |
2075 reference.unlink(); | 2138 reference.unlink(); |
2076 } | 2139 } |
2077 | 2140 |
2078 static void remove(Node node) { | 2141 static void remove(Node node) { |
2079 (new RemovalVisitor()).visit(node); | 2142 (new RemovalVisitor()).visit(node); |
2080 } | 2143 } |
2081 } | 2144 } |
OLD | NEW |