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

Side by Side Diff: runtime/lib/collection_patch.dart

Issue 24267023: Update implementations to use Object.identityHashCode for identity map/set (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Add tests. Fix few bugs now that it can run. Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « pkg/http_server/test/http_body_test.dart ('k') | sdk/lib/_internal/lib/collection_patch.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) 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 patch class HashMap<K, V> { 5 patch class HashMap<K, V> {
6 /* patch */ factory HashMap({ bool equals(K key1, K key2), 6 /* patch */ factory HashMap({ bool equals(K key1, K key2),
7 int hashCode(K key), 7 int hashCode(K key),
8 bool isValidKey(potentialKey) }) { 8 bool isValidKey(potentialKey) }) {
9 if (isValidKey == null) { 9 if (isValidKey == null) {
10 if (hashCode == null) { 10 if (hashCode == null) {
11 if (equals == null) { 11 if (equals == null) {
12 return new _HashMap<K, V>(); 12 return new _HashMap<K, V>();
13 } 13 }
14 if (identical(identical, equals)) { 14 hashCode = _defaultHashCode;
15 } else {
16 if (identical(identityHashCode, hashCode) &&
17 identical(identical, equals)) {
15 return new _IdentityHashMap<K, V>(); 18 return new _IdentityHashMap<K, V>();
16 } 19 }
17 hashCode = _defaultHashCode; 20 if (equals == null) {
18 } else if (equals == null) { 21 equals = _defaultEquals;
19 equals = _defaultEquals; 22 }
20 } 23 }
21 } else { 24 } else {
22 if (hashCode == null) { 25 if (hashCode == null) {
23 hashCode = _defaultHashCode; 26 hashCode = _defaultHashCode;
24 } 27 }
25 if (equals == null) { 28 if (equals == null) {
26 equals = _defaultEquals; 29 equals = _defaultEquals;
27 } 30 }
28 } 31 }
29 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); 32 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey);
30 } 33 }
34
35 /* patch */ factory HashMap.identity() = _IdentityHashMap<K, V>;
31 } 36 }
32 37
38
33 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; 39 const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
34 40
35 class _HashMap<K, V> implements HashMap<K, V> { 41 class _HashMap<K, V> implements HashMap<K, V> {
36 static const int _INITIAL_CAPACITY = 8; 42 static const int _INITIAL_CAPACITY = 8;
37 43
38 44
39 int _elementCount = 0; 45 int _elementCount = 0;
40 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 46 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
41 int _modificationCount = 0; 47 int _modificationCount = 0;
42 48
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 319 }
314 return null; 320 return null;
315 } 321 }
316 322
317 String toString() => Maps.mapToString(this); 323 String toString() => Maps.mapToString(this);
318 } 324 }
319 325
320 class _IdentityHashMap<K, V> extends _HashMap<K, V> { 326 class _IdentityHashMap<K, V> extends _HashMap<K, V> {
321 327
322 bool containsKey(Object key) { 328 bool containsKey(Object key) {
323 int hashCode = key.hashCode; 329 int hashCode = identityHashCode(key);
324 List buckets = _buckets; 330 List buckets = _buckets;
325 int index = hashCode & (buckets.length - 1); 331 int index = hashCode & (buckets.length - 1);
326 _HashMapEntry entry = buckets[index]; 332 _HashMapEntry entry = buckets[index];
327 while (entry != null) { 333 while (entry != null) {
328 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; 334 if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
329 entry = entry.next; 335 entry = entry.next;
330 } 336 }
331 return false; 337 return false;
332 } 338 }
333 339
334 V operator[](Object key) { 340 V operator[](Object key) {
335 int hashCode = key.hashCode; 341 int hashCode = identityHashCode(key);
336 List buckets = _buckets; 342 List buckets = _buckets;
337 int index = hashCode & (buckets.length - 1); 343 int index = hashCode & (buckets.length - 1);
338 _HashMapEntry entry = buckets[index]; 344 _HashMapEntry entry = buckets[index];
339 while (entry != null) { 345 while (entry != null) {
340 if (hashCode == entry.hashCode && identical(entry.key, key)) { 346 if (hashCode == entry.hashCode && identical(entry.key, key)) {
341 return entry.value; 347 return entry.value;
342 } 348 }
343 entry = entry.next; 349 entry = entry.next;
344 } 350 }
345 return null; 351 return null;
346 } 352 }
347 353
348 void operator []=(K key, V value) { 354 void operator []=(K key, V value) {
349 int hashCode = key.hashCode; 355 int hashCode = identityHashCode(key);
350 List buckets = _buckets; 356 List buckets = _buckets;
351 int length = buckets.length; 357 int length = buckets.length;
352 int index = hashCode & (length - 1); 358 int index = hashCode & (length - 1);
353 _HashMapEntry entry = buckets[index]; 359 _HashMapEntry entry = buckets[index];
354 while (entry != null) { 360 while (entry != null) {
355 if (hashCode == entry.hashCode && identical(entry.key, key)) { 361 if (hashCode == entry.hashCode && identical(entry.key, key)) {
356 entry.value = value; 362 entry.value = value;
357 return; 363 return;
358 } 364 }
359 entry = entry.next; 365 entry = entry.next;
360 } 366 }
361 _addEntry(buckets, index, length, key, value, hashCode); 367 _addEntry(buckets, index, length, key, value, hashCode);
362 } 368 }
363 369
364 V putIfAbsent(K key, V ifAbsent()) { 370 V putIfAbsent(K key, V ifAbsent()) {
365 int hashCode = key.hashCode; 371 int hashCode = identityHashCode(key);
366 List buckets = _buckets; 372 List buckets = _buckets;
367 int length = buckets.length; 373 int length = buckets.length;
368 int index = hashCode & (length - 1); 374 int index = hashCode & (length - 1);
369 _HashMapEntry entry = buckets[index]; 375 _HashMapEntry entry = buckets[index];
370 while (entry != null) { 376 while (entry != null) {
371 if (hashCode == entry.hashCode && identical(entry.key, key)) { 377 if (hashCode == entry.hashCode && identical(entry.key, key)) {
372 return entry.value; 378 return entry.value;
373 } 379 }
374 entry = entry.next; 380 entry = entry.next;
375 } 381 }
376 int stamp = _modificationCount; 382 int stamp = _modificationCount;
377 V value = ifAbsent(); 383 V value = ifAbsent();
378 if (stamp == _modificationCount) { 384 if (stamp == _modificationCount) {
379 _addEntry(buckets, index, length, key, value, hashCode); 385 _addEntry(buckets, index, length, key, value, hashCode);
380 } else { 386 } else {
381 this[key] = value; 387 this[key] = value;
382 } 388 }
383 return value; 389 return value;
384 } 390 }
385 391
386 V remove(Object key) { 392 V remove(Object key) {
387 int hashCode = key.hashCode; 393 int hashCode = identityHashCode(key);
388 List buckets = _buckets; 394 List buckets = _buckets;
389 int index = hashCode & (buckets.length - 1); 395 int index = hashCode & (buckets.length - 1);
390 _HashMapEntry entry = buckets[index]; 396 _HashMapEntry entry = buckets[index];
391 _HashMapEntry previous = null; 397 _HashMapEntry previous = null;
392 while (entry != null) { 398 while (entry != null) {
393 _HashMapEntry next = entry.next; 399 _HashMapEntry next = entry.next;
394 if (hashCode == entry.hashCode && identical(entry.key, key)) { 400 if (hashCode == entry.hashCode && identical(entry.key, key)) {
395 _removeEntry(entry, previous, index); 401 _removeEntry(entry, previous, index);
396 _elementCount--; 402 _elementCount--;
397 _modificationCount = 403 _modificationCount =
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 508
503 patch class HashSet<E> { 509 patch class HashSet<E> {
504 /* patch */ factory HashSet({ bool equals(E e1, E e2), 510 /* patch */ factory HashSet({ bool equals(E e1, E e2),
505 int hashCode(E e), 511 int hashCode(E e),
506 bool isValidKey(potentialKey) }) { 512 bool isValidKey(potentialKey) }) {
507 if (isValidKey == null) { 513 if (isValidKey == null) {
508 if (hashCode == null) { 514 if (hashCode == null) {
509 if (equals == null) { 515 if (equals == null) {
510 return new _HashSet<E>(); 516 return new _HashSet<E>();
511 } 517 }
512 if (identical(identical, equals)) { 518 hashCode = _defaultHashCode;
519 } else {
520 if (identical(identityHashCode, hashCode) &&
521 identical(identical, equals)) {
513 return new _IdentityHashSet<E>(); 522 return new _IdentityHashSet<E>();
514 } 523 }
515 _hashCode = _defaultHashCode; 524 if (equals == null) {
516 } else if (equals == null) { 525 equals = _defaultEquals;
517 _equals = _defaultEquals; 526 }
518 } 527 }
519 isValidKey = new _TypeTest<E>().test;
520 } else { 528 } else {
521 if (hashCode == null) hashCode = _defaultHashCode; 529 if (hashCode == null) {
522 if (equals == null) equals = _defaultEquals; 530 hashCode = _defaultHashCode;
531 }
532 if (equals == null) {
533 equals = _defaultEquals;
534 }
523 } 535 }
524 return new _CustomHashSet<E>(equals, hashCode, isValidKey); 536 return new _CustomHashSet<E>(equals, hashCode, isValidKey);
525 } 537 }
538
539 /* patch */ factory HashSet.identity() = _IdentityHashSet<E>;
526 } 540 }
527 541
528 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { 542 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> {
529 static const int _INITIAL_CAPACITY = 8; 543 static const int _INITIAL_CAPACITY = 8;
530 544
531 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); 545 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY);
532 int _elementCount = 0; 546 int _elementCount = 0;
533 int _modificationCount = 0; 547 int _modificationCount = 0;
534 548
535 bool _equals(e1, e2) => e1 == e2; 549 bool _equals(e1, e2) => e1 == e2;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 entry = next; 695 entry = next;
682 } 696 }
683 } 697 }
684 _buckets = newBuckets; 698 _buckets = newBuckets;
685 } 699 }
686 700
687 HashSet<E> _newSet() => new _HashSet<E>(); 701 HashSet<E> _newSet() => new _HashSet<E>();
688 } 702 }
689 703
690 class _IdentityHashSet<E> extends _HashSet<E> { 704 class _IdentityHashSet<E> extends _HashSet<E> {
705 int _hashCode(e) => identityHashCode(e);
691 bool _equals(e1, e2) => identical(e1, e2); 706 bool _equals(e1, e2) => identical(e1, e2);
692 HashSet<E> _newSet() => new _IdentityHashSet<E>(); 707 HashSet<E> _newSet() => new _IdentityHashSet<E>();
693 } 708 }
694 709
695 class _CustomHashSet<E> extends _HashSet<E> { 710 class _CustomHashSet<E> extends _HashSet<E> {
696 final _Equality<E> _equality; 711 final _Equality<E> _equality;
697 final _Hasher<E> _hasher; 712 final _Hasher<E> _hasher;
698 final _Predicate _validKey; 713 final _Predicate _validKey;
699 _CustomHashSet(this._equality, this._hasher, this._validKey); 714 _CustomHashSet(this._equality, this._hasher, bool validKey(Object o))
715 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
700 716
701 bool remove(Object element) { 717 bool remove(Object element) {
702 if (!_validKey(element)) return false; 718 if (!_validKey(element)) return false;
703 return super.remove(element); 719 return super.remove(element);
704 } 720 }
705 721
706 bool contains(Object element) { 722 bool contains(Object element) {
707 if (!_validKey(element)) return false; 723 if (!_validKey(element)) return false;
708 return super.contains(element); 724 return super.contains(element);
709 } 725 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 var _previousEntry; 886 var _previousEntry;
871 887
872 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2), 888 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
873 int hashCode(K key), 889 int hashCode(K key),
874 bool isValidKey(potentialKey) }) { 890 bool isValidKey(potentialKey) }) {
875 if (isValidKey == null) { 891 if (isValidKey == null) {
876 if (hashCode == null) { 892 if (hashCode == null) {
877 if (equals == null) { 893 if (equals == null) {
878 return new _LinkedHashMap<K, V>(); 894 return new _LinkedHashMap<K, V>();
879 } 895 }
880 if (identical(identical, equals)) { 896 hashCode = _defaultHashCode;
897 } else {
898 if (identical(identityHashCode, hashCode) &&
899 identical(identical, equals)) {
881 return new _LinkedIdentityHashMap<K, V>(); 900 return new _LinkedIdentityHashMap<K, V>();
882 } 901 }
883 hashCode = _defaultHashCode; 902 if (equals == null) {
884 } else if (equals == null) { 903 equals = _defaultEquals;
885 equals = _defaultEquals; 904 }
886 } 905 }
887 } else { 906 } else {
888 if (hashCode == null) { 907 if (hashCode == null) {
889 hashCode = _defaultHashCode; 908 hashCode = _defaultHashCode;
890 } 909 }
891 if (equals == null) { 910 if (equals == null) {
892 equals = _defaultEquals; 911 equals = _defaultEquals;
893 } 912 }
894 } 913 }
895 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); 914 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
896 } 915 }
916
917 /* patch */ factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>;
897 } 918 }
898 919
899 // Methods that are exactly the same in all three linked hash map variants. 920 // Methods that are exactly the same in all three linked hash map variants.
900 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> { 921 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> {
901 var _nextEntry; 922 var _nextEntry;
902 var _previousEntry; 923 var _previousEntry;
903 924
904 925
905 bool containsValue(Object value) { 926 bool containsValue(Object value) {
906 int modificationCount = _modificationCount; 927 int modificationCount = _modificationCount;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 1018
998 patch class LinkedHashSet<E> { 1019 patch class LinkedHashSet<E> {
999 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2), 1020 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
1000 int hashCode(E e), 1021 int hashCode(E e),
1001 bool isValidKey(potentialKey) }) { 1022 bool isValidKey(potentialKey) }) {
1002 if (isValidKey == null) { 1023 if (isValidKey == null) {
1003 if (hashCode == null) { 1024 if (hashCode == null) {
1004 if (equals == null) { 1025 if (equals == null) {
1005 return new _LinkedHashSet<E>(); 1026 return new _LinkedHashSet<E>();
1006 } 1027 }
1007 if (identical(identical, equals)) { 1028 hashCode = _defaultHashCode;
1029 } else {
1030 if (identical(identityHashCode, hashCode) &&
1031 identical(identical, equals)) {
1008 return new _LinkedIdentityHashSet<E>(); 1032 return new _LinkedIdentityHashSet<E>();
1009 } 1033 }
1010 _hashCode = _defaultHashCode; 1034 if (equals == null) {
1011 } else if (equals == null) { 1035 equals = _defaultEquals;
1012 _equals = _defaultEquals; 1036 }
1013 } 1037 }
1014 isValidKey = new _TypeTest<E>().test;
1015 } else { 1038 } else {
1016 if (hashCode == null) hashCode = _defaultHashCode; 1039 if (hashCode == null) {
1017 if (equals == null) equals = _defaultEquals; 1040 hashCode = _defaultHashCode;
1041 }
1042 if (equals == null) {
1043 equals = _defaultEquals;
1044 }
1018 } 1045 }
1019 return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey); 1046 return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey);
1020 } 1047 }
1048
1049 /* patch */ factory LinkedHashSet.identity() = _LinkedIdentityHashSet<E>;
1021 } 1050 }
1022 1051
1023 class _LinkedHashSetEntry extends _HashSetEntry { 1052 class _LinkedHashSetEntry extends _HashSetEntry {
1024 /// Links this element into a double-linked list of elements of a hash set. 1053 /// Links this element into a double-linked list of elements of a hash set.
1025 /// The hash set object itself is used as the head entry of the list, so 1054 /// The hash set object itself is used as the head entry of the list, so
1026 /// the field is typed as "var". 1055 /// the field is typed as "var".
1027 /// Both links are initialized to `this` when the object is created. 1056 /// Both links are initialized to `this` when the object is created.
1028 var _nextEntry; 1057 var _nextEntry;
1029 var _previousEntry; 1058 var _previousEntry;
1030 _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next, 1059 _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next,
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1122 1151
1123 void clear() { 1152 void clear() {
1124 _nextEntry = _previousEntry = this; 1153 _nextEntry = _previousEntry = this;
1125 super.clear(); 1154 super.clear();
1126 } 1155 }
1127 1156
1128 HashSet<E> _newSet() => new _LinkedHashSet<E>(); 1157 HashSet<E> _newSet() => new _LinkedHashSet<E>();
1129 } 1158 }
1130 1159
1131 class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> { 1160 class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> {
1161 int _hashCode(e) => identityHashCode(e);
1132 bool _equals(e1, e2) => identical(e1, e2); 1162 bool _equals(e1, e2) => identical(e1, e2);
1133 HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>(); 1163 HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>();
1134 } 1164 }
1135 1165
1136 class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> { 1166 class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> {
1137 final _Equality<E> _equality; 1167 final _Equality<E> _equality;
1138 final _Hasher<E> _hasher; 1168 final _Hasher<E> _hasher;
1139 final _Predicate _validKey; 1169 final _Predicate _validKey;
1140 1170
1141 _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(object)) 1171 _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(Object o))
1142 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test; 1172 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
1143 1173
1144 bool _equals(e1, e2) => _equality(e1, e2); 1174 bool _equals(e1, e2) => _equality(e1, e2);
1145 1175
1146 int _hashCode(e) => _hasher(e); 1176 int _hashCode(e) => _hasher(e);
1147 1177
1148 bool contains(Object o) { 1178 bool contains(Object o) {
1149 if (!_validKey(o)) return false; 1179 if (!_validKey(o)) return false;
1150 return super.contains(o); 1180 return super.contains(o);
1151 } 1181 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 return false; 1228 return false;
1199 } 1229 }
1200 _LinkedHashSetEntry entry = _next; 1230 _LinkedHashSetEntry entry = _next;
1201 _current = entry.key; 1231 _current = entry.key;
1202 _next = entry._nextEntry; 1232 _next = entry._nextEntry;
1203 return true; 1233 return true;
1204 } 1234 }
1205 1235
1206 E get current => _current; 1236 E get current => _current;
1207 } 1237 }
OLDNEW
« no previous file with comments | « pkg/http_server/test/http_body_test.dart ('k') | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698