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

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

Issue 983703003: Replace Linked{Identity,Custom}Hash{Map,Set} with compact implementation; remove old code and flag. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 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 | « no previous file | runtime/lib/compact_hash.dart » ('j') | runtime/lib/compact_hash.dart » ('J')
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) {
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 var _previousEntry; 911 var _previousEntry;
912 912
913 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2), 913 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
914 int hashCode(K key), 914 int hashCode(K key),
915 bool isValidKey(potentialKey) }) { 915 bool isValidKey(potentialKey) }) {
916 if (isValidKey == null) { 916 if (isValidKey == null) {
917 if (hashCode == null) { 917 if (hashCode == null) {
918 if (equals == null) { 918 if (equals == null) {
919 if (_useInternalCached) { 919 if (_useInternalCached) {
920 return new _InternalLinkedHashMap<K, V>(); 920 return new _InternalLinkedHashMap<K, V>();
921 } else if (_useCompactCached) { 921 } else {
922 return new _CompactLinkedHashMap<K, V>(); 922 return new _CompactLinkedHashMap<K, V>();
923 } else {
924 return new _LinkedHashMap<K, V>();
925 } 923 }
926 } 924 }
927 hashCode = _defaultHashCode; 925 hashCode = _defaultHashCode;
928 } else { 926 } else {
929 if (identical(identityHashCode, hashCode) && 927 if (identical(identityHashCode, hashCode) &&
930 identical(identical, equals)) { 928 identical(identical, equals)) {
931 return new _LinkedIdentityHashMap<K, V>(); 929 return new _CompactLinkedIdentityHashMap<K, V>();
932 } 930 }
933 if (equals == null) { 931 if (equals == null) {
934 equals = _defaultEquals; 932 equals = _defaultEquals;
935 } 933 }
936 } 934 }
937 } else { 935 } else {
938 if (hashCode == null) { 936 if (hashCode == null) {
939 hashCode = _defaultHashCode; 937 hashCode = _defaultHashCode;
940 } 938 }
941 if (equals == null) { 939 if (equals == null) {
942 equals = _defaultEquals; 940 equals = _defaultEquals;
943 } 941 }
944 } 942 }
945 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); 943 return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
946 } 944 }
947 945
948 /* patch */ factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>; 946 /* patch */ factory LinkedHashMap.identity() =
947 _CompactLinkedIdentityHashMap<K, V>;
949 948
950 static final bool _useInternalCached = _useInternal; 949 static final bool _useInternalCached = _useInternal;
951 static bool get _useInternal native "LinkedHashMap_useInternal"; 950 static bool get _useInternal native "LinkedHashMap_useInternal";
952 static final bool _useCompactCached = _useCompact;
953 static bool get _useCompact native "LinkedHashMap_useCompact";
954 } 951 }
955 952
956 // Methods that are exactly the same in all three linked hash map variants.
957 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> {
958 var _nextEntry;
959 var _previousEntry;
960
961
962 bool containsValue(Object value) {
963 int modificationCount = _modificationCount;
964 var cursor = _nextEntry;
965 while (!identical(cursor, this)) {
966 _HashMapEntry entry = cursor;
967 if (entry.value == value) return true;
968 if (modificationCount != _modificationCount) {
969 throw new ConcurrentModificationError(this);
970 }
971 cursor = cursor._nextEntry;
972 }
973 return false;
974 }
975
976 void forEach(void action(K key, V value)) {
977 int modificationCount = _modificationCount;
978 var cursor = _nextEntry;
979 while (!identical(cursor, this)) {
980 _HashMapEntry entry = cursor;
981 action(entry.key, entry.value);
982 if (modificationCount != _modificationCount) {
983 throw new ConcurrentModificationError(this);
984 }
985 cursor = cursor._nextEntry;
986 }
987 }
988
989 void clear() {
990 _nextEntry = _previousEntry = this;
991 _buckets = new List(_HashMap._INITIAL_CAPACITY);
992 if (_elementCount > 0) {
993 _elementCount = 0;
994 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
995 }
996 }
997
998 void _addEntry(List buckets, int index, int length,
999 K key, V value, int hashCode) {
1000 _HashMapEntry entry =
1001 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
1002 _previousEntry, this);
1003 buckets[index] = entry;
1004 int newElements = _elementCount + 1;
1005 _elementCount = newElements;
1006
1007 // If we end up with more than 75% non-empty entries, we
1008 // resize the backing store.
1009 if ((newElements << 2) > ((length << 1) + length)) _resize();
1010 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
1011 }
1012
1013 void _removeEntry(_LinkedHashMapEntry entry,
1014 _HashMapEntry previousInBucket,
1015 int bucketIndex) {
1016 var previousInChain = entry._previousEntry;
1017 var nextInChain = entry._nextEntry;
1018 previousInChain._nextEntry = nextInChain;
1019 nextInChain._previousEntry = previousInChain;
1020 if (previousInBucket == null) {
1021 _buckets[bucketIndex] = entry.next;
1022 } else {
1023 previousInBucket.next = entry.next;
1024 }
1025 }
1026
1027
1028 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
1029 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
1030 }
1031
1032 class _LinkedHashMap<K, V> extends _HashMap<K, V>
1033 with _LinkedHashMapMixin<K, V> {
1034 _LinkedHashMap() {
1035 _nextEntry = _previousEntry = this;
1036 }
1037
1038 Set<K> _newKeySet() => new _LinkedHashSet<K>();
1039 }
1040
1041 class _LinkedIdentityHashMap<K, V> extends _IdentityHashMap<K, V>
1042 with _LinkedHashMapMixin<K, V> {
1043 _LinkedIdentityHashMap() {
1044 _nextEntry = _previousEntry = this;
1045 }
1046
1047 Set<K> _newKeySet() => new _LinkedIdentityHashSet<K>();
1048 }
1049
1050 class _LinkedCustomHashMap<K, V> extends _CustomHashMap<K, V>
1051 with _LinkedHashMapMixin<K, V> {
1052 _LinkedCustomHashMap(bool equals(K key1, K key2),
1053 int hashCode(K key),
1054 bool isValidKey(potentialKey))
1055 : super(equals, hashCode, isValidKey) {
1056 _nextEntry = _previousEntry = this;
1057 }
1058 Set<K> _newKeySet() =>
1059 new _LinkedCustomHashSet<K>(_equals, _hashCode, _validKey);
1060 }
1061
1062
1063 patch class LinkedHashSet<E> { 953 patch class LinkedHashSet<E> {
1064 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2), 954 /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
1065 int hashCode(E e), 955 int hashCode(E e),
1066 bool isValidKey(potentialKey) }) { 956 bool isValidKey(potentialKey) }) {
1067 if (isValidKey == null) { 957 if (isValidKey == null) {
1068 if (hashCode == null) { 958 if (hashCode == null) {
1069 if (equals == null) { 959 if (equals == null) {
1070 if (LinkedHashMap._useCompactCached) { 960 return new _CompactLinkedHashSet<E>();
1071 return new _CompactLinkedHashSet<E>();
1072 } else {
1073 return new _LinkedHashSet<E>();
1074 }
1075 } 961 }
1076 hashCode = _defaultHashCode; 962 hashCode = _defaultHashCode;
1077 } else { 963 } else {
1078 if (identical(identityHashCode, hashCode) && 964 if (identical(identityHashCode, hashCode) &&
1079 identical(identical, equals)) { 965 identical(identical, equals)) {
1080 return new _LinkedIdentityHashSet<E>(); 966 return new _CompactLinkedIdentityHashSet<E>();
1081 } 967 }
1082 if (equals == null) { 968 if (equals == null) {
1083 equals = _defaultEquals; 969 equals = _defaultEquals;
1084 } 970 }
1085 } 971 }
1086 } else { 972 } else {
1087 if (hashCode == null) { 973 if (hashCode == null) {
1088 hashCode = _defaultHashCode; 974 hashCode = _defaultHashCode;
1089 } 975 }
1090 if (equals == null) { 976 if (equals == null) {
1091 equals = _defaultEquals; 977 equals = _defaultEquals;
1092 } 978 }
1093 } 979 }
1094 return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey); 980 return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey);
1095 } 981 }
1096 982
1097 /* patch */ factory LinkedHashSet.identity() = _LinkedIdentityHashSet<E>; 983 /* patch */ factory LinkedHashSet.identity() =
984 _CompactLinkedIdentityHashSet<E>;
1098 } 985 }
1099
1100 class _LinkedHashSetEntry extends _HashSetEntry {
1101 /// Links this element into a double-linked list of elements of a hash set.
1102 /// The hash set object itself is used as the head entry of the list, so
1103 /// the field is typed as "var".
1104 /// Both links are initialized to `this` when the object is created.
1105 var _nextEntry;
1106 var _previousEntry;
1107 _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next,
1108 this._previousEntry, this._nextEntry)
1109 : super(key, hashCode, next) {
1110 _previousEntry._nextEntry = _nextEntry._previousEntry = this;
1111 }
1112
1113 _LinkedHashSetEntry remove() {
1114 _previousEntry._nextEntry = _nextEntry;
1115 _nextEntry._previousEntry = _previousEntry;
1116 _nextEntry = _previousEntry = this;
1117 return super.remove();
1118 }
1119 }
1120
1121 class _LinkedHashSet<E> extends _HashSet<E>
1122 implements LinkedHashSet<E> {
1123 /// Holds a double linked list of the element entries of the set in
1124 /// insertion order.
1125 /// The fields have the same names as the ones in [_LinkedHashSetEntry],
1126 /// allowing this object to be used as the head entry of the list.
1127 /// The fields are initialized to `this` when created, representing the
1128 /// empty list that only contains the head entry.
1129 var _nextEntry;
1130 var _previousEntry;
1131
1132 _LinkedHashSet() {
1133 _nextEntry = _previousEntry = this;
1134 }
1135
1136 // Iterable.
1137
1138 Iterator<E> get iterator => new _LinkedHashSetIterator<E>(this);
1139
1140 void forEach(void action(E element)) {
1141 var cursor = _nextEntry;
1142 int modificationCount = _modificationCount;
1143 while (!identical(cursor, this)) {
1144 _LinkedHashSetEntry entry = cursor;
1145 action(entry.key);
1146 if (_modificationCount != modificationCount) {
1147 throw new ConcurrentModificationError(this);
1148 }
1149 cursor = entry._nextEntry;
1150 }
1151 }
1152
1153 E get first {
1154 if (identical(_nextEntry, this)) {
1155 throw new StateError("No elements");
1156 }
1157 _LinkedHashSetEntry entry = _nextEntry;
1158 return entry.key;
1159 }
1160
1161 E get last {
1162 if (identical(_previousEntry, this)) {
1163 throw new StateError("No elements");
1164 }
1165 _LinkedHashSetEntry entry = _previousEntry;
1166 return entry.key;
1167 }
1168
1169 // Set.
1170
1171 void _filterWhere(bool test(E element), bool removeMatching) {
1172 var cursor = _nextEntry;
1173 while (!identical(cursor, this)) {
1174 _LinkedHashSetEntry entry = cursor;
1175 int modificationCount = _modificationCount;
1176 bool testResult = test(entry.key);
1177 if (modificationCount != _modificationCount) {
1178 throw new ConcurrentModificationError(this);
1179 }
1180 cursor = entry._nextEntry;
1181 if (testResult == removeMatching) {
1182 _remove(entry.key, entry.hashCode);
1183 }
1184 }
1185 }
1186
1187 void _addEntry(E key, int hashCode, int index) {
1188 _buckets[index] =
1189 new _LinkedHashSetEntry(key, hashCode, _buckets[index],
1190 _previousEntry, this);
1191 int newElements = _elementCount + 1;
1192 _elementCount = newElements;
1193 int length = _buckets.length;
1194 // If we end up with more than 75% non-empty entries, we
1195 // resize the backing store.
1196 if ((newElements << 2) > ((length << 1) + length)) _resize();
1197 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
1198 }
1199
1200 void clear() {
1201 _nextEntry = _previousEntry = this;
1202 super.clear();
1203 }
1204
1205 HashSet<E> _newSet() => new _LinkedHashSet<E>();
1206 }
1207
1208 class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> {
1209 int _hashCode(e) => identityHashCode(e);
1210 bool _equals(e1, e2) => identical(e1, e2);
1211 HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>();
1212 }
1213
1214 class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> {
1215 final _Equality<E> _equality;
1216 final _Hasher<E> _hasher;
1217 final _Predicate _validKey;
1218
1219 _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(Object o))
1220 : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
1221
1222 bool _equals(e1, e2) => _equality(e1, e2);
1223
1224 int _hashCode(e) => _hasher(e);
1225
1226 bool contains(Object o) {
1227 if (!_validKey(o)) return false;
1228 return super.contains(o);
1229 }
1230
1231 E lookup(Object o) {
1232 if (!_validKey(o)) return null;
1233 return super.lookup(o);
1234 }
1235
1236 bool remove(Object o) {
1237 if (!_validKey(o)) return false;
1238 return super.remove(o);
1239 }
1240
1241 bool containsAll(Iterable<Object> elements) {
1242 for (Object element in elements) {
1243 if (!_validKey(element) || !this.contains(element)) return false;
1244 }
1245 return true;
1246 }
1247
1248 void removeAll(Iterable<Object> elements) {
1249 for (Object element in elements) {
1250 if (_validKey(element)) {
1251 super._remove(element, _hasher(element));
1252 }
1253 }
1254 }
1255
1256 HashSet<E> _newSet() =>
1257 new _LinkedCustomHashSet<E>(_equality, _hasher, _validKey);
1258 }
1259
1260 class _LinkedHashSetIterator<E> implements Iterator<E> {
1261 final _LinkedHashSet _set;
1262 final int _modificationCount;
1263 var _next;
1264 E _current;
1265
1266 _LinkedHashSetIterator(_LinkedHashSet hashSet)
1267 : _set = hashSet,
1268 _modificationCount = hashSet._modificationCount,
1269 _next = hashSet._nextEntry;
1270
1271 bool moveNext() {
1272 if (_modificationCount != _set._modificationCount) {
1273 throw new ConcurrentModificationError(_set);
1274 }
1275 if (identical(_set, _next)) {
1276 _current = null;
1277 return false;
1278 }
1279 _LinkedHashSetEntry entry = _next;
1280 _current = entry.key;
1281 _next = entry._nextEntry;
1282 return true;
1283 }
1284
1285 E get current => _current;
1286 }
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/compact_hash.dart » ('j') | runtime/lib/compact_hash.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698