Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(308)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/constant_ordering.dart

Issue 3011803002: dart2js kernel: Sort constants
Patch Set: implement DartType ordering Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698