Chromium Code Reviews| 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 library dart2js.js_emitter.constant_ordering; | 5 library dart2js.js_emitter.constant_ordering; |
| 6 | 6 |
| 7 import '../constants/values.dart'; | 7 import '../constants/values.dart'; |
| 8 import '../elements/elements.dart' show Elements; | 8 import '../elements/elements.dart' show Elements; |
| 9 import '../elements/entities.dart' show Entity, FieldEntity; | 9 import '../elements/entities.dart' |
| 10 import '../elements/resolution_types.dart'; | 10 show Entity, ClassEntity, FieldEntity, MemberEntity, TypedefEntity; |
| 11 import '../elements/resolution_types.dart' | |
| 12 show GenericType, ResolutionDartType, ResolutionTypeKind; | |
| 13 import '../elements/types.dart'; | |
| 11 import '../js_backend/js_backend.dart' show SyntheticConstantKind; | 14 import '../js_backend/js_backend.dart' show SyntheticConstantKind; |
| 15 import 'sorter.dart' show Sorter; | |
| 12 | 16 |
| 13 /// A canonical but arbitrary ordering of constants. The ordering is 'stable' | 17 /// A canonical but arbitrary ordering of constants. The ordering is 'stable' |
| 14 /// under perturbation of the source. | 18 /// under perturbation of the source. |
| 15 int deepCompareConstants(ConstantValue a, ConstantValue b) { | 19 abstract class ConstantOrdering { |
| 16 return _CompareVisitor.compareValues(a, b); | 20 factory ConstantOrdering(Sorter sorter) = _ConstantOrdering; |
| 21 | |
| 22 int compare(ConstantValue a, ConstantValue b); | |
| 17 } | 23 } |
| 18 | 24 |
| 19 class _CompareVisitor implements ConstantValueVisitor<int, ConstantValue> { | 25 class _ConstantOrdering |
| 20 const _CompareVisitor(); | 26 implements ConstantOrdering, ConstantValueVisitor<int, ConstantValue> { |
| 27 final Sorter _sorter; | |
| 28 _DartTypeOrdering _dartTypeOrdering; | |
| 29 _ConstantOrdering(this._sorter) { | |
| 30 _dartTypeOrdering = new _DartTypeOrdering(this); | |
| 31 } | |
| 21 | 32 |
| 22 static int compareValues(ConstantValue a, ConstantValue b) { | 33 int compare(ConstantValue a, ConstantValue b) => compareValues(a, b); |
| 34 | |
| 35 int compareValues(ConstantValue a, ConstantValue b) { | |
| 23 if (identical(a, b)) return 0; | 36 if (identical(a, b)) return 0; |
| 24 int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b)); | 37 int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b)); |
| 25 if (r != 0) return r; | 38 if (r != 0) return r; |
| 26 r = a.accept(const _CompareVisitor(), b); | 39 return a.accept(this, b); |
| 27 return r; | |
| 28 } | 40 } |
| 29 | 41 |
| 30 static int compareNullable(int compare(a, b), a, b) { | 42 static int compareNullable(int compare(a, b), a, b) { |
| 31 if (a == null && b == null) return 0; | 43 if (a == null && b == null) return 0; |
| 32 if (a == null) return -1; | 44 if (a == null) return -1; |
| 33 if (b == null) return 1; | 45 if (b == null) return 1; |
| 34 return compare(a, b); | 46 return compare(a, b); |
| 35 } | 47 } |
| 36 | 48 |
| 37 static int compareLists(int compare(a, b), List a, List b) { | 49 static int compareLists(int compare(a, b), List a, List b) { |
| 38 int r = a.length.compareTo(b.length); | 50 int r = a.length.compareTo(b.length); |
| 39 if (r != 0) return r; | 51 if (r != 0) return r; |
| 40 for (int i = 0; i < a.length; i++) { | 52 for (int i = 0; i < a.length; i++) { |
| 41 r = compare(a[i], b[i]); | 53 r = compare(a[i], b[i]); |
| 42 if (r != 0) return r; | 54 if (r != 0) return r; |
| 43 } | 55 } |
| 44 return 0; | 56 return 0; |
| 45 } | 57 } |
| 46 | 58 |
| 47 static int compareElements(Entity a, Entity b) { | 59 static int compareElements(Entity a, Entity b) { |
| 48 int r = a.name.compareTo(b.name); | 60 int r = a.name.compareTo(b.name); |
| 49 if (r != 0) return r; | 61 if (r != 0) return r; |
| 50 return Elements.compareByPosition(a, b); | 62 return Elements.compareByPosition(a, b); |
| 51 } | 63 } |
| 52 | 64 |
| 53 static int compareDartTypes(ResolutionDartType a, ResolutionDartType b) { | 65 int compareClasses(ClassEntity a, ClassEntity b) { |
| 66 int r = a.name.compareTo(b.name); | |
| 67 if (r != 0) return r; | |
| 68 return _sorter.compareClassesByLocation(a, b); | |
| 69 } | |
| 70 | |
| 71 int compareMembers(MemberEntity a, MemberEntity b) { | |
| 72 int r = a.name.compareTo(b.name); | |
| 73 if (r != 0) return r; | |
| 74 return _sorter.compareMembersByLocation(a, b); | |
| 75 } | |
| 76 | |
| 77 int compareTypedefs(TypedefEntity a, TypedefEntity b) { | |
| 78 int r = a.name.compareTo(b.name); | |
| 79 if (r != 0) return r; | |
| 80 return _sorter.compareTypedefsByLocation(a, b); | |
| 81 } | |
| 82 | |
| 83 static int _compareResolutionDartTypes( | |
| 84 ResolutionDartType a, ResolutionDartType b) { | |
| 54 if (a == b) return 0; | 85 if (a == b) return 0; |
| 55 int r = a.kind.index.compareTo(b.kind.index); | 86 int r = a.kind.index.compareTo(b.kind.index); |
| 56 if (r != 0) return r; | 87 if (r != 0) return r; |
| 57 r = compareNullable(compareElements, a.element, b.element); | 88 r = compareNullable(compareElements, a.element, b.element); |
| 58 if (r != 0) return r; | 89 if (r != 0) return r; |
| 59 | 90 |
| 60 if (a is GenericType) { | 91 if (a is GenericType) { |
| 61 GenericType aGeneric = a; | 92 GenericType aGeneric = a; |
| 62 GenericType bGeneric = b; | 93 GenericType bGeneric = b; |
| 63 r = compareLists( | 94 r = compareLists(_compareResolutionDartTypes, aGeneric.typeArguments, |
| 64 compareDartTypes, aGeneric.typeArguments, bGeneric.typeArguments); | 95 bGeneric.typeArguments); |
| 65 if (r != 0) return r; | 96 if (r != 0) return r; |
| 66 } | 97 } |
| 67 throw 'unexpected compareDartTypes $a $b'; | 98 throw 'unexpected compareDartTypes $a $b'; |
| 68 } | 99 } |
| 69 | 100 |
| 101 int compareDartTypes(DartType a, DartType b) { | |
| 102 if (a is ResolutionDartType && b is ResolutionDartType) { | |
| 103 // TODO(redemption): Remove this path. | |
| 104 return _compareResolutionDartTypes(a, b); | |
|
Johnni Winther
2017/09/05 07:19:56
Can't we use _dartTypeOrdering for ResolutionDartT
sra1
2017/09/05 18:30:21
print(const Foo<String>());
print(const Foo<Unreso
Johnni Winther
2017/09/06 07:16:48
Acknowledged.
| |
| 105 } | |
| 106 return _dartTypeOrdering.compare(a, b); | |
| 107 } | |
| 108 | |
| 70 int visitFunction(FunctionConstantValue a, FunctionConstantValue b) { | 109 int visitFunction(FunctionConstantValue a, FunctionConstantValue b) { |
| 71 return compareElements(a.element, b.element); | 110 return compareMembers(a.element, b.element); |
| 72 } | 111 } |
| 73 | 112 |
| 74 int visitNull(NullConstantValue a, NullConstantValue b) { | 113 int visitNull(NullConstantValue a, NullConstantValue b) { |
| 75 return 0; | 114 return 0; |
| 76 } | 115 } |
| 77 | 116 |
| 78 int visitNonConstant(NonConstantValue a, NonConstantValue b) { | 117 int visitNonConstant(NonConstantValue a, NonConstantValue b) { |
| 79 return 0; | 118 return 0; |
| 80 } | 119 } |
| 81 | 120 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 95 | 134 |
| 96 int visitString(StringConstantValue a, StringConstantValue b) { | 135 int visitString(StringConstantValue a, StringConstantValue b) { |
| 97 String aString = a.primitiveValue; | 136 String aString = a.primitiveValue; |
| 98 String bString = b.primitiveValue; | 137 String bString = b.primitiveValue; |
| 99 return aString.compareTo(bString); | 138 return aString.compareTo(bString); |
| 100 } | 139 } |
| 101 | 140 |
| 102 int visitList(ListConstantValue a, ListConstantValue b) { | 141 int visitList(ListConstantValue a, ListConstantValue b) { |
| 103 int r = compareLists(compareValues, a.entries, b.entries); | 142 int r = compareLists(compareValues, a.entries, b.entries); |
| 104 if (r != 0) return r; | 143 if (r != 0) return r; |
| 105 ResolutionInterfaceType type1 = a.type; | 144 return compareDartTypes(a.type, b.type); |
| 106 ResolutionInterfaceType type2 = b.type; | |
| 107 return compareDartTypes(type1, type2); | |
| 108 } | 145 } |
| 109 | 146 |
| 110 int visitMap(MapConstantValue a, MapConstantValue b) { | 147 int visitMap(MapConstantValue a, MapConstantValue b) { |
| 111 int r = compareLists(compareValues, a.keys, b.keys); | 148 int r = compareLists(compareValues, a.keys, b.keys); |
| 112 if (r != 0) return r; | 149 if (r != 0) return r; |
| 113 r = compareLists(compareValues, a.values, b.values); | 150 r = compareLists(compareValues, a.values, b.values); |
| 114 if (r != 0) return r; | 151 if (r != 0) return r; |
| 115 ResolutionInterfaceType type1 = a.type; | 152 return compareDartTypes(a.type, b.type); |
| 116 ResolutionInterfaceType type2 = b.type; | |
| 117 return compareDartTypes(type1, type2); | |
| 118 } | 153 } |
| 119 | 154 |
| 120 int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) { | 155 int visitConstructed(ConstructedConstantValue a, ConstructedConstantValue b) { |
| 121 ResolutionInterfaceType type1 = a.type; | 156 int r = compareDartTypes(a.type, b.type); |
| 122 ResolutionInterfaceType type2 = b.type; | |
| 123 int r = compareDartTypes(type1, type2); | |
| 124 if (r != 0) return r; | 157 if (r != 0) return r; |
| 125 | 158 |
| 126 List<FieldEntity> aFields = a.fields.keys.toList()..sort(compareElements); | 159 // TODO(sra): Avoid all these tear-offs. |
| 127 List<FieldEntity> bFields = b.fields.keys.toList()..sort(compareElements); | 160 List<FieldEntity> aFields = a.fields.keys.toList()..sort(compareMembers); |
| 161 List<FieldEntity> bFields = b.fields.keys.toList()..sort(compareMembers); | |
| 128 | 162 |
| 129 r = compareLists(compareElements, aFields, bFields); | 163 r = compareLists(compareMembers, aFields, bFields); |
| 130 if (r != 0) return r; | 164 if (r != 0) return r; |
| 131 | 165 |
| 132 return compareLists( | 166 return compareLists( |
| 133 compareValues, | 167 compareValues, |
| 134 aFields.map((field) => a.fields[field]).toList(), | 168 aFields.map((field) => a.fields[field]).toList(), |
| 135 aFields.map((field) => b.fields[field]).toList()); | 169 aFields.map((field) => b.fields[field]).toList()); |
| 136 } | 170 } |
| 137 | 171 |
| 138 int visitType(TypeConstantValue a, TypeConstantValue b) { | 172 int visitType(TypeConstantValue a, TypeConstantValue b) { |
| 139 int r = compareDartTypes(a.representedType, b.representedType); | 173 int r = compareDartTypes(a.representedType, b.representedType); |
| 140 if (r != 0) return r; | 174 if (r != 0) return r; |
| 141 ResolutionInterfaceType type1 = a.type; | 175 return compareDartTypes(a.type, b.type); |
| 142 ResolutionInterfaceType type2 = b.type; | |
| 143 return compareDartTypes(type1, type2); | |
| 144 } | 176 } |
| 145 | 177 |
| 146 int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) { | 178 int visitInterceptor(InterceptorConstantValue a, InterceptorConstantValue b) { |
| 147 return compareElements(a.cls, b.cls); | 179 return compareClasses(a.cls, b.cls); |
| 148 } | 180 } |
| 149 | 181 |
| 150 int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) { | 182 int visitSynthetic(SyntheticConstantValue a, SyntheticConstantValue b) { |
| 151 // [SyntheticConstantValue]s have abstract fields that are set only by | 183 // [SyntheticConstantValue]s have abstract fields that are set only by |
| 152 // convention. Lucky for us, they do not occur as top level constant, only | 184 // convention. Lucky for us, they do not occur as top level constant, only |
| 153 // as elements of a few constants. If this becomes a source of instability, | 185 // as elements of a few constants. If this becomes a source of instability, |
| 154 // we will need to add a total ordering on JavaScript ASTs including | 186 // we will need to add a total ordering on JavaScript ASTs including |
| 155 // deferred elements. | 187 // deferred elements. |
| 156 SyntheticConstantKind aKind = a.valueKind; | 188 SyntheticConstantKind aKind = a.valueKind; |
| 157 SyntheticConstantKind bKind = b.valueKind; | 189 SyntheticConstantKind bKind = b.valueKind; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 171 return 0; | 203 return 0; |
| 172 default: | 204 default: |
| 173 // Should not happen. | 205 // Should not happen. |
| 174 throw 'unexpected SyntheticConstantKind $aKind'; | 206 throw 'unexpected SyntheticConstantKind $aKind'; |
| 175 } | 207 } |
| 176 } | 208 } |
| 177 | 209 |
| 178 int visitDeferred(DeferredConstantValue a, DeferredConstantValue b) { | 210 int visitDeferred(DeferredConstantValue a, DeferredConstantValue b) { |
| 179 int r = compareValues(a.referenced, b.referenced); | 211 int r = compareValues(a.referenced, b.referenced); |
| 180 if (r != 0) return r; | 212 if (r != 0) return r; |
| 213 // TODO(sra): Implement deferred imports for Kernel. | |
| 214 // TODO(sra): What kind of Entity is `prefix`? | |
| 181 return compareElements(a.prefix, b.prefix); | 215 return compareElements(a.prefix, b.prefix); |
| 182 } | 216 } |
| 183 } | 217 } |
| 184 | 218 |
| 185 class _KindVisitor implements ConstantValueVisitor<int, Null> { | 219 class _KindVisitor implements ConstantValueVisitor<int, Null> { |
| 186 const _KindVisitor(); | 220 const _KindVisitor(); |
| 187 | 221 |
| 188 static const int FUNCTION = 1; | 222 static const int FUNCTION = 1; |
| 189 static const int NULL = 2; | 223 static const int NULL = 2; |
| 190 static const int INT = 3; | 224 static const int INT = 3; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 211 int visitBool(BoolConstantValue a, _) => BOOL; | 245 int visitBool(BoolConstantValue a, _) => BOOL; |
| 212 int visitString(StringConstantValue a, _) => STRING; | 246 int visitString(StringConstantValue a, _) => STRING; |
| 213 int visitList(ListConstantValue a, _) => LIST; | 247 int visitList(ListConstantValue a, _) => LIST; |
| 214 int visitMap(MapConstantValue a, _) => MAP; | 248 int visitMap(MapConstantValue a, _) => MAP; |
| 215 int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED; | 249 int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED; |
| 216 int visitType(TypeConstantValue a, _) => TYPE; | 250 int visitType(TypeConstantValue a, _) => TYPE; |
| 217 int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR; | 251 int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR; |
| 218 int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC; | 252 int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC; |
| 219 int visitDeferred(DeferredConstantValue a, _) => DEFERRED; | 253 int visitDeferred(DeferredConstantValue a, _) => DEFERRED; |
| 220 } | 254 } |
| 255 | |
| 256 /// Visitor for distinguishing types by kind. | |
| 257 class _DartTypeKindVisitor extends DartTypeVisitor<int, Null> { | |
| 258 const _DartTypeKindVisitor(); | |
| 259 | |
| 260 static int kind(DartType type) { | |
| 261 assert(_usesLegacyOrder); | |
| 262 return type.accept(const _DartTypeKindVisitor(), null); | |
| 263 } | |
| 264 | |
| 265 int visitVoidType(covariant VoidType type, _) => 6; | |
| 266 int visitTypeVariableType(covariant TypeVariableType type, _) => 3; | |
| 267 int visitFunctionType(covariant FunctionType type, _) => 0; | |
| 268 int visitInterfaceType(covariant InterfaceType type, _) => 1; | |
| 269 int visitTypedefType(covariant TypedefType type, _) => 2; | |
| 270 int visitDynamicType(covariant DynamicType type, _) => 5; | |
| 271 | |
| 272 // Check that the ordering of different kinds of type is consistent with | |
| 273 // ResolutionDartTypes. | |
| 274 // TODO(redemption): Remove this check. | |
| 275 static bool _usesLegacyOrder = () { | |
| 276 var v = const _DartTypeKindVisitor(); | |
| 277 assert( | |
| 278 v.visitFunctionType(null, null) == ResolutionTypeKind.FUNCTION.index); | |
| 279 assert( | |
| 280 v.visitInterfaceType(null, null) == ResolutionTypeKind.INTERFACE.index); | |
| 281 assert(v.visitTypedefType(null, null) == ResolutionTypeKind.TYPEDEF.index); | |
| 282 assert(v.visitTypeVariableType(null, null) == | |
| 283 ResolutionTypeKind.TYPE_VARIABLE.index); | |
| 284 // There is no analogue of ResolutionTypeKind.MALFORMED_TYPE. | |
| 285 assert(v.visitDynamicType(null, null) == ResolutionTypeKind.DYNAMIC.index); | |
| 286 assert(v.visitVoidType(null, null) == ResolutionTypeKind.VOID.index); | |
| 287 }(); | |
| 288 } | |
| 289 | |
| 290 class _DartTypeOrdering extends DartTypeVisitor<int, DartType> { | |
| 291 final _ConstantOrdering _constantOrdering; | |
| 292 DartType _root; | |
| 293 _DartTypeOrdering(this._constantOrdering); | |
| 294 | |
| 295 int compare(DartType a, DartType b) { | |
| 296 if (a == b) return 0; | |
| 297 int r = | |
| 298 _DartTypeKindVisitor.kind(a).compareTo(_DartTypeKindVisitor.kind(b)); | |
| 299 if (r != 0) return r; | |
| 300 _root = a; | |
| 301 r = a.accept(this, b); | |
| 302 _root = null; | |
| 303 return r; | |
| 304 } | |
| 305 | |
| 306 int visitVoidType(covariant VoidType type, covariant VoidType other) { | |
| 307 throw new UnsupportedError('Unreachable'); | |
| 308 } | |
| 309 | |
| 310 int visitTypeVariableType( | |
| 311 covariant TypeVariableType type, covariant TypeVariableType other) { | |
| 312 throw new UnimplementedError( | |
| 313 "Type variables are not expected in constants: '$type' in '$_root'"); | |
| 314 } | |
| 315 | |
| 316 int visitFunctionType(covariant FunctionType type, DartType _other) { | |
| 317 throw new UnimplementedError( | |
| 318 "Unimplemented FuntionType '$type' in '$_root'"); | |
| 319 } | |
| 320 | |
| 321 int visitInterfaceType( | |
| 322 covariant InterfaceType type, covariant InterfaceType other) { | |
| 323 int r = _constantOrdering.compareClasses(type.element, other.element); | |
| 324 if (r != 0) return r; | |
| 325 return _compareTypeArguments(type.typeArguments, other.typeArguments); | |
| 326 } | |
| 327 | |
| 328 int visitTypedefType( | |
| 329 covariant TypedefType type, covariant TypedefType other) { | |
| 330 int r = _constantOrdering.compareTypedefs(type.element, other.element); | |
| 331 if (r != 0) return r; | |
| 332 return _compareTypeArguments(type.typeArguments, other.typeArguments); | |
| 333 } | |
| 334 | |
| 335 int visitDynamicType( | |
| 336 covariant DynamicType type, covariant DynamicType other) { | |
| 337 throw new UnsupportedError('Unreachable'); | |
| 338 } | |
| 339 | |
| 340 int _compareTypeArguments( | |
| 341 List<DartType> aArguments, List<DartType> bArguments) { | |
| 342 return _ConstantOrdering.compareLists(compare, aArguments, bArguments); | |
| 343 } | |
| 344 } | |
| OLD | NEW |