| ... | ... | @@ -773,11 +773,6 @@ pub fn HashMapUnmanaged( |
| 773 | 773 | self.used = 0; |
| 774 | 774 | self.fingerprint = tombstone; |
| 775 | 775 | } |
| 776 | | |
| 777 | | pub fn reset(self: *Metadata) void { |
| 778 | | self.used = 0; |
| 779 | | self.fingerprint = free; |
| 780 | | } |
| 781 | 776 | }; |
| 782 | 777 | |
| 783 | 778 | comptime { |
| ... | ... | @@ -1115,24 +1110,12 @@ pub fn HashMapUnmanaged( |
| 1115 | 1110 | } |
| 1116 | 1111 | const mask = self.capacity() - 1; |
| 1117 | 1112 | const fingerprint = Metadata.takeFingerprint(hash); |
| 1118 | | var start = @truncate(usize, hash & mask); |
| 1119 | | var idx = start; |
| 1113 | // Don't loop indefinitely when there are no empty slots. |
| 1114 | var limit = self.capacity(); |
| 1115 | var idx = @truncate(usize, hash & mask); |
| 1120 | 1116 | |
| 1121 | 1117 | var metadata = self.metadata.? + idx; |
| 1122 | | if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { |
| 1123 | | const test_key = &self.keys()[idx]; |
| 1124 | | const eql = ctx.eql(key, test_key.*); |
| 1125 | | if (eql) return idx; |
| 1126 | | } |
| 1127 | | // Temporarily mark the start position as "free" so that the probe loop |
| 1128 | | // doesn't infinitely loop when all other slots are filled or tombstones. |
| 1129 | | const saved = metadata[0]; |
| 1130 | | metadata[0].reset(); |
| 1131 | | defer self.metadata.?[start] = saved; |
| 1132 | | idx = (idx + 1) & mask; // initial idx was already checked |
| 1133 | | metadata = self.metadata.? + idx; |
| 1134 | | |
| 1135 | | while (metadata[0].isUsed() or metadata[0].isTombstone()) { |
| 1118 | while ((metadata[0].isUsed() or metadata[0].isTombstone()) and limit != 0) { |
| 1136 | 1119 | if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { |
| 1137 | 1120 | const test_key = &self.keys()[idx]; |
| 1138 | 1121 | // If you get a compile error on this line, it means that your generic eql |
| ... | ... | @@ -1148,6 +1131,7 @@ pub fn HashMapUnmanaged( |
| 1148 | 1131 | } |
| 1149 | 1132 | } |
| 1150 | 1133 | |
| 1134 | limit -= 1; |
| 1151 | 1135 | idx = (idx + 1) & mask; |
| 1152 | 1136 | metadata = self.metadata.? + idx; |
| 1153 | 1137 | } |
| ... | ... | @@ -1305,39 +1289,12 @@ pub fn HashMapUnmanaged( |
| 1305 | 1289 | } |
| 1306 | 1290 | const mask = self.capacity() - 1; |
| 1307 | 1291 | const fingerprint = Metadata.takeFingerprint(hash); |
| 1308 | | var start = @truncate(usize, hash & mask); |
| 1309 | | var idx = start; |
| 1292 | var limit = self.capacity(); |
| 1293 | var idx = @truncate(usize, hash & mask); |
| 1310 | 1294 | |
| 1311 | 1295 | var first_tombstone_idx: usize = self.capacity(); // invalid index |
| 1312 | 1296 | var metadata = self.metadata.? + idx; |
| 1313 | | if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { |
| 1314 | | const test_key = &self.keys()[idx]; |
| 1315 | | const eql = ctx.eql(key, test_key.*); |
| 1316 | | if (eql) { |
| 1317 | | return GetOrPutResult{ |
| 1318 | | .key_ptr = test_key, |
| 1319 | | .value_ptr = &self.values()[idx], |
| 1320 | | .found_existing = true, |
| 1321 | | }; |
| 1322 | | } |
| 1323 | | } else if (metadata[0].isTombstone()) { |
| 1324 | | first_tombstone_idx = idx; |
| 1325 | | } |
| 1326 | | // Temporarily mark the start position as "free" so that the probe loop |
| 1327 | | // doesn't infinitely loop when all other slots are filled or tombstones. |
| 1328 | | const saved = metadata[0]; |
| 1329 | | metadata[0].reset(); |
| 1330 | | defer { |
| 1331 | | // Don't restore when the 'home' slot was originally a tombstone |
| 1332 | | // and the probe missed, since it is now occupied by the new key. |
| 1333 | | const home = &self.metadata.?[start]; |
| 1334 | | assert(!home.isUsed() or home.fingerprint == fingerprint); |
| 1335 | | if (!home.isUsed()) home.* = saved; |
| 1336 | | } |
| 1337 | | idx = (idx + 1) & mask; // initial idx was already checked |
| 1338 | | metadata = self.metadata.? + idx; |
| 1339 | | |
| 1340 | | while (metadata[0].isUsed() or metadata[0].isTombstone()) { |
| 1297 | while ((metadata[0].isUsed() or metadata[0].isTombstone()) and limit != 0) { |
| 1341 | 1298 | if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { |
| 1342 | 1299 | const test_key = &self.keys()[idx]; |
| 1343 | 1300 | // If you get a compile error on this line, it means that your generic eql |
| ... | ... | @@ -1359,6 +1316,7 @@ pub fn HashMapUnmanaged( |
| 1359 | 1316 | first_tombstone_idx = idx; |
| 1360 | 1317 | } |
| 1361 | 1318 | |
| 1319 | limit -= 1; |
| 1362 | 1320 | idx = (idx + 1) & mask; |
| 1363 | 1321 | metadata = self.metadata.? + idx; |
| 1364 | 1322 | } |
| ... | ... | @@ -1944,7 +1902,6 @@ test "std.hash_map repeat putAssumeCapacity/remove" { |
| 1944 | 1902 | |
| 1945 | 1903 | try map.ensureTotalCapacity(20); |
| 1946 | 1904 | const limit = map.unmanaged.available; |
| 1947 | | const cycles = 100; |
| 1948 | 1905 | |
| 1949 | 1906 | var i: u32 = 0; |
| 1950 | 1907 | while (i < limit) : (i += 1) { |
| ... | ... | @@ -1954,7 +1911,7 @@ test "std.hash_map repeat putAssumeCapacity/remove" { |
| 1954 | 1911 | // Repeatedly delete/insert an entry without resizing the map. |
| 1955 | 1912 | // Put to different keys so entries don't land in the just-freed slot. |
| 1956 | 1913 | i = 0; |
| 1957 | | while (i < cycles * limit) : (i += 1) { |
| 1914 | while (i < 10 * limit) : (i += 1) { |
| 1958 | 1915 | try testing.expect(map.remove(i)); |
| 1959 | 1916 | if (i % 2 == 0) { |
| 1960 | 1917 | map.putAssumeCapacityNoClobber(limit + i, i); |
| ... | ... | @@ -1963,13 +1920,9 @@ test "std.hash_map repeat putAssumeCapacity/remove" { |
| 1963 | 1920 | } |
| 1964 | 1921 | } |
| 1965 | 1922 | |
| 1966 | | i = (cycles - 1) * limit; |
| 1967 | | while (i < cycles * limit) : (i += 1) { |
| 1968 | | try expectEqual(map.get(i), null); // (removed) key miss |
| 1969 | | try expectEqual(map.get(limit + i), i); // key hit |
| 1970 | | const gop = map.getOrPutAssumeCapacity(limit + i); |
| 1971 | | try testing.expect(gop.found_existing); |
| 1972 | | try testing.expectEqual(gop.value_ptr.*, i); |
| 1923 | i = 9 * limit; |
| 1924 | while (i < 10 * limit) : (i += 1) { |
| 1925 | try expectEqual(map.get(limit + i), i); |
| 1973 | 1926 | } |
| 1974 | 1927 | try expectEqual(map.unmanaged.available, 0); |
| 1975 | 1928 | try expectEqual(map.unmanaged.count(), limit); |