1
2
3
4
5 package maps
6
7 import (
8 "internal/abi"
9 "internal/goexperiment"
10 "internal/runtime/math"
11 "unsafe"
12 )
13
14
15
16
17
18
19
20 const maxTableCapacity = 1024
21
22
23
24 var _ = uint16(maxTableCapacity)
25
26
27
28
29
30
31
32
33
34 type table struct {
35
36 used uint16
37
38
39
40 capacity uint16
41
42
43
44
45
46
47 growthLeft uint16
48
49
50
51
52 localDepth uint8
53
54
55
56
57
58
59
60 index int
61
62
63
64
65
66
67
68
69
70
71 groups groupsReference
72 }
73
74 func newTable(typ *abi.MapType, capacity uint64, index int, localDepth uint8) *table {
75 if capacity < abi.MapGroupSlots {
76 capacity = abi.MapGroupSlots
77 }
78
79 t := &table{
80 index: index,
81 localDepth: localDepth,
82 }
83
84 if capacity > maxTableCapacity {
85 panic("initial table capacity too large")
86 }
87
88
89
90 capacity, overflow := alignUpPow2(capacity)
91 if overflow {
92 panic("rounded-up capacity overflows uint64")
93 }
94
95 t.reset(typ, uint16(capacity))
96
97 return t
98 }
99
100
101
102 func (t *table) reset(typ *abi.MapType, capacity uint16) {
103 groupCount := uint64(capacity) / abi.MapGroupSlots
104 t.groups = newGroups(typ, groupCount)
105 t.capacity = capacity
106 t.growthLeft = t.maxGrowthLeft()
107
108 for i := uint64(0); i <= t.groups.lengthMask; i++ {
109 g := t.groups.group(typ, i)
110 g.ctrls().setEmpty()
111 }
112 }
113
114
115
116 func (t *table) maxGrowthLeft() uint16 {
117 if t.capacity == 0 {
118
119
120 panic("table must have positive capacity")
121 } else if t.capacity <= abi.MapGroupSlots {
122
123
124
125
126
127
128 return t.capacity - 1
129 } else {
130 if t.capacity > math.MaxUint16/maxAvgGroupLoad {
131 panic("overflow")
132 }
133 return (t.capacity * maxAvgGroupLoad) / abi.MapGroupSlots
134 }
135
136 }
137
138 func (t *table) Used() uint64 {
139 return uint64(t.used)
140 }
141
142
143
144 func (t *table) Get(typ *abi.MapType, m *Map, key unsafe.Pointer) (unsafe.Pointer, bool) {
145
146
147
148
149
150
151 hash := typ.Hasher(key, m.seed)
152 _, elem, ok := t.getWithKey(typ, hash, key)
153 return elem, ok
154 }
155
156
157
158
159
160
161
162
163
164
165 func (t *table) getWithKey(typ *abi.MapType, hash uintptr, key unsafe.Pointer) (unsafe.Pointer, unsafe.Pointer, bool) {
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
194 h2Hash := h2(hash)
195 for ; ; seq = seq.next() {
196 g := t.groups.group(typ, seq.offset)
197
198 match := g.ctrls().matchH2(h2Hash)
199
200 for match != 0 {
201 i := match.first()
202
203 slotKey := g.key(typ, i)
204 if typ.IndirectKey() {
205 slotKey = *((*unsafe.Pointer)(slotKey))
206 }
207 if typ.Key.Equal(key, slotKey) {
208 slotElem := g.elem(typ, i)
209 if typ.IndirectElem() {
210 slotElem = *((*unsafe.Pointer)(slotElem))
211 }
212 return slotKey, slotElem, true
213 }
214 match = match.removeFirst()
215 }
216
217 match = g.ctrls().matchEmpty()
218 if match != 0 {
219
220
221 return nil, nil, false
222 }
223 }
224 }
225
226 func (t *table) getWithoutKey(typ *abi.MapType, hash uintptr, key unsafe.Pointer) (unsafe.Pointer, bool) {
227 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
228 h2Hash := h2(hash)
229 for ; ; seq = seq.next() {
230 g := t.groups.group(typ, seq.offset)
231
232 match := g.ctrls().matchH2(h2Hash)
233
234 for match != 0 {
235 i := match.first()
236
237 slotKey := g.key(typ, i)
238 if typ.IndirectKey() {
239 slotKey = *((*unsafe.Pointer)(slotKey))
240 }
241 if typ.Key.Equal(key, slotKey) {
242 slotElem := g.elem(typ, i)
243 if typ.IndirectElem() {
244 slotElem = *((*unsafe.Pointer)(slotElem))
245 }
246 return slotElem, true
247 }
248 match = match.removeFirst()
249 }
250
251 match = g.ctrls().matchEmpty()
252 if match != 0 {
253
254
255 return nil, false
256 }
257 }
258 }
259
260
261
262
263
264
265
266
267 func (t *table) PutSlot(typ *abi.MapType, m *Map, hash uintptr, key unsafe.Pointer) (unsafe.Pointer, bool) {
268 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
269
270
271
272 var firstDeletedGroup groupReference
273 var firstDeletedSlot uintptr
274
275 h2Hash := h2(hash)
276 for ; ; seq = seq.next() {
277 g := t.groups.group(typ, seq.offset)
278 match := g.ctrls().matchH2(h2Hash)
279
280
281 for match != 0 {
282 i := match.first()
283
284 slotKey := g.key(typ, i)
285 if typ.IndirectKey() {
286 slotKey = *((*unsafe.Pointer)(slotKey))
287 }
288 if typ.Key.Equal(key, slotKey) {
289 if typ.NeedKeyUpdate() {
290 typedmemmove(typ.Key, slotKey, key)
291 }
292
293 slotElem := g.elem(typ, i)
294 if typ.IndirectElem() {
295 slotElem = *((*unsafe.Pointer)(slotElem))
296 }
297
298 t.checkInvariants(typ, m)
299 return slotElem, true
300 }
301 match = match.removeFirst()
302 }
303
304
305
306 match = g.ctrls().matchEmptyOrDeleted()
307 if match == 0 {
308 continue
309 }
310 i := match.first()
311 if g.ctrls().get(i) == ctrlDeleted {
312
313
314 if firstDeletedGroup.data == nil {
315 firstDeletedGroup = g
316 firstDeletedSlot = i
317 }
318 continue
319 }
320
321
322
323
324
325 if firstDeletedGroup.data != nil {
326 g = firstDeletedGroup
327 i = firstDeletedSlot
328 t.growthLeft++
329 }
330
331
332 if t.growthLeft == 0 {
333 t.pruneTombstones(typ, m)
334 }
335
336
337 if t.growthLeft > 0 {
338 slotKey := g.key(typ, i)
339 if typ.IndirectKey() {
340 kmem := newobject(typ.Key)
341 *(*unsafe.Pointer)(slotKey) = kmem
342 slotKey = kmem
343 }
344 typedmemmove(typ.Key, slotKey, key)
345
346 slotElem := g.elem(typ, i)
347 if typ.IndirectElem() {
348 emem := newobject(typ.Elem)
349 *(*unsafe.Pointer)(slotElem) = emem
350 slotElem = emem
351 }
352
353 g.ctrls().set(i, ctrl(h2Hash))
354 t.growthLeft--
355 t.used++
356 m.used++
357
358 t.checkInvariants(typ, m)
359 return slotElem, true
360 }
361
362 t.rehash(typ, m)
363 return nil, false
364 }
365 }
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383 func (t *table) uncheckedPutSlot(typ *abi.MapType, hash uintptr, key, elem unsafe.Pointer) {
384 if t.growthLeft == 0 {
385 panic("invariant failed: growthLeft is unexpectedly 0")
386 }
387
388
389
390
391
392 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
393 for ; ; seq = seq.next() {
394 g := t.groups.group(typ, seq.offset)
395
396 match := g.ctrls().matchEmptyOrDeleted()
397 if match != 0 {
398 i := match.first()
399
400 slotKey := g.key(typ, i)
401 if typ.IndirectKey() {
402 *(*unsafe.Pointer)(slotKey) = key
403 } else {
404 typedmemmove(typ.Key, slotKey, key)
405 }
406
407 slotElem := g.elem(typ, i)
408 if typ.IndirectElem() {
409 *(*unsafe.Pointer)(slotElem) = elem
410 } else {
411 typedmemmove(typ.Elem, slotElem, elem)
412 }
413
414 t.growthLeft--
415 t.used++
416 g.ctrls().set(i, ctrl(h2(hash)))
417 return
418 }
419 }
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436 func (t *table) uncheckedPutSlotForAssign(typ *abi.MapType, hash uintptr, key unsafe.Pointer) unsafe.Pointer {
437 if t.growthLeft == 0 {
438 panic("invariant failed: growthLeft is unexpectedly 0")
439 }
440
441
442
443
444
445
446 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
447 for ; ; seq = seq.next() {
448 g := t.groups.group(typ, seq.offset)
449
450 match := g.ctrls().matchEmptyOrDeleted()
451 if match != 0 {
452 i := match.first()
453
454 slotKey := g.key(typ, i)
455 if typ.IndirectKey() {
456 kmem := newobject(typ.Key)
457 *(*unsafe.Pointer)(slotKey) = kmem
458 slotKey = kmem
459 }
460 typedmemmove(typ.Key, slotKey, key)
461
462 slotElem := g.elem(typ, i)
463 if typ.IndirectElem() {
464 emem := newobject(typ.Elem)
465 *(*unsafe.Pointer)(slotElem) = emem
466 slotElem = emem
467 }
468
469 t.growthLeft--
470 t.used++
471 g.ctrls().set(i, ctrl(h2(hash)))
472 return slotElem
473 }
474 }
475 }
476
477
478 func (t *table) Delete(typ *abi.MapType, m *Map, hash uintptr, key unsafe.Pointer) bool {
479 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
480 h2Hash := h2(hash)
481 for ; ; seq = seq.next() {
482 g := t.groups.group(typ, seq.offset)
483 match := g.ctrls().matchH2(h2Hash)
484
485 for match != 0 {
486 i := match.first()
487
488 slotKey := g.key(typ, i)
489 origSlotKey := slotKey
490 if typ.IndirectKey() {
491 slotKey = *((*unsafe.Pointer)(slotKey))
492 }
493
494 if typ.Key.Equal(key, slotKey) {
495 t.used--
496 m.used--
497
498 if typ.IndirectKey() {
499
500 *(*unsafe.Pointer)(origSlotKey) = nil
501 } else if typ.Key.Pointers() {
502
503
504 typedmemclr(typ.Key, slotKey)
505 }
506
507 slotElem := g.elem(typ, i)
508 if typ.IndirectElem() {
509
510 *(*unsafe.Pointer)(slotElem) = nil
511 } else {
512
513
514
515
516
517 typedmemclr(typ.Elem, slotElem)
518 }
519
520
521
522
523
524
525
526
527
528 var tombstone bool
529 if g.ctrls().matchEmpty() != 0 {
530 g.ctrls().set(i, ctrlEmpty)
531 t.growthLeft++
532 } else {
533 g.ctrls().set(i, ctrlDeleted)
534 tombstone = true
535 }
536
537 t.checkInvariants(typ, m)
538 return tombstone
539 }
540 match = match.removeFirst()
541 }
542
543 match = g.ctrls().matchEmpty()
544 if match != 0 {
545
546
547 return false
548 }
549 }
550 }
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566 func (t *table) pruneTombstones(typ *abi.MapType, m *Map) {
567 if t.tombstones()*10 < t.capacity {
568
569 return
570 }
571
572
573 var needed [(maxTableCapacity/abi.MapGroupSlots + 31) / 32]uint32
574
575
576 for i := uint64(0); i <= t.groups.lengthMask; i++ {
577 g := t.groups.group(typ, i)
578 match := g.ctrls().matchFull()
579 for match != 0 {
580 j := match.first()
581 match = match.removeFirst()
582 key := g.key(typ, j)
583 if typ.IndirectKey() {
584 key = *((*unsafe.Pointer)(key))
585 }
586 if !typ.Key.Equal(key, key) {
587
588
589
590 continue
591 }
592
593
594 hash := typ.Hasher(key, m.seed)
595 for seq := makeProbeSeq(h1(hash), t.groups.lengthMask); ; seq = seq.next() {
596 if seq.offset == i {
597 break
598 }
599 g := t.groups.group(typ, seq.offset)
600 m := g.ctrls().matchEmptyOrDeleted()
601 if m != 0 {
602
603 needed[seq.offset/32] |= 1 << (seq.offset % 32)
604 }
605 }
606 }
607 if g.ctrls().matchEmpty() != 0 {
608
609
610 needed[i/32] |= 1 << (i % 32)
611 }
612 }
613
614
615
616
617 cnt := 0
618 for i := uint64(0); i <= t.groups.lengthMask; i++ {
619 if needed[i/32]>>(i%32)&1 != 0 {
620 continue
621 }
622 g := t.groups.group(typ, i)
623 m := g.ctrls().matchEmptyOrDeleted()
624 cnt += m.count()
625 }
626 if cnt*10 < int(t.capacity) {
627 return
628 }
629
630
631 for i := uint64(0); i <= t.groups.lengthMask; i++ {
632 if needed[i/32]>>(i%32)&1 != 0 {
633 continue
634 }
635 g := t.groups.group(typ, i)
636 m := g.ctrls().matchEmptyOrDeleted()
637 for m != 0 {
638 k := m.first()
639 m = m.removeFirst()
640 g.ctrls().set(k, ctrlEmpty)
641 t.growthLeft++
642 }
643
644
645 }
646 }
647
648
649
650
651 func (t *table) tombstones() uint16 {
652 return (t.capacity*maxAvgGroupLoad)/abi.MapGroupSlots - t.used - t.growthLeft
653 }
654
655
656 func (t *table) Clear(typ *abi.MapType) {
657 mgl := t.maxGrowthLeft()
658 if t.used == 0 && t.growthLeft == mgl {
659 return
660 }
661
662
663
664
665
666
667
668
669
670
671
672
673 fullTest := uint64(t.used)*4 <= t.groups.lengthMask
674 if goexperiment.MapSplitGroup {
675 if (typ.KeyStride + typ.ElemStride) > 32 {
676
677 fullTest = true
678 }
679 } else {
680 if typ.KeyStride > 32 {
681
682 fullTest = true
683 }
684 }
685 if fullTest {
686 for i := uint64(0); i <= t.groups.lengthMask; i++ {
687 g := t.groups.group(typ, i)
688 if g.ctrls().anyFull() {
689 typedmemclr(typ.Group, g.data)
690 }
691 g.ctrls().setEmpty()
692 }
693 } else {
694 for i := uint64(0); i <= t.groups.lengthMask; i++ {
695 g := t.groups.group(typ, i)
696 typedmemclr(typ.Group, g.data)
697 g.ctrls().setEmpty()
698 }
699 }
700 t.used = 0
701 t.growthLeft = mgl
702 }
703
704 type Iter struct {
705 key unsafe.Pointer
706 elem unsafe.Pointer
707 typ *abi.MapType
708 m *Map
709
710
711
712
713 entryOffset uint64
714 dirOffset uint64
715
716
717
718 clearSeq uint64
719
720
721
722 globalDepth uint8
723
724
725
726 dirIdx int
727
728
729 tab *table
730
731
732 group groupReference
733
734
735
736
737 entryIdx uint64
738 }
739
740
741 func (it *Iter) Init(typ *abi.MapType, m *Map) {
742 it.typ = typ
743
744 if m == nil || m.used == 0 {
745 return
746 }
747
748 dirIdx := 0
749 var groupSmall groupReference
750 if m.dirLen <= 0 {
751
752 dirIdx = -1
753 groupSmall.data = m.dirPtr
754 }
755
756 it.m = m
757 it.entryOffset = rand()
758 it.dirOffset = rand()
759 it.globalDepth = m.globalDepth
760 it.dirIdx = dirIdx
761 it.group = groupSmall
762 it.clearSeq = m.clearSeq
763 }
764
765 func (it *Iter) Initialized() bool {
766 return it.typ != nil
767 }
768
769
770 func (it *Iter) Map() *Map {
771 return it.m
772 }
773
774
775
776
777 func (it *Iter) Key() unsafe.Pointer {
778 return it.key
779 }
780
781
782
783
784
785 func (it *Iter) Elem() unsafe.Pointer {
786 return it.elem
787 }
788
789 func (it *Iter) nextDirIdx() {
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816 entries := 1 << (it.m.globalDepth - it.tab.localDepth)
817 it.dirIdx += entries
818 it.tab = nil
819 it.group = groupReference{}
820 it.entryIdx = 0
821 }
822
823
824
825 func (it *Iter) grownKeyElem(key unsafe.Pointer, slotIdx uintptr) (unsafe.Pointer, unsafe.Pointer, bool) {
826 newKey, newElem, ok := it.m.getWithKey(it.typ, key)
827 if !ok {
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851 if it.clearSeq == it.m.clearSeq && !it.typ.Key.Equal(key, key) {
852 elem := it.group.elem(it.typ, slotIdx)
853 if it.typ.IndirectElem() {
854 elem = *((*unsafe.Pointer)(elem))
855 }
856 return key, elem, true
857 }
858
859
860 return nil, nil, false
861 }
862
863 return newKey, newElem, true
864 }
865
866
867
868
869
870
871
872
873 func (it *Iter) Next() {
874 if it.m == nil {
875
876 it.key = nil
877 it.elem = nil
878 return
879 }
880
881 if it.m.writing != 0 {
882 fatal("concurrent map iteration and map write")
883 return
884 }
885
886 if it.dirIdx < 0 {
887
888 for ; it.entryIdx < abi.MapGroupSlots; it.entryIdx++ {
889 k := uintptr(it.entryIdx+it.entryOffset) % abi.MapGroupSlots
890
891 if (it.group.ctrls().get(k) & ctrlEmpty) == ctrlEmpty {
892
893 continue
894 }
895
896 key := it.group.key(it.typ, k)
897 if it.typ.IndirectKey() {
898 key = *((*unsafe.Pointer)(key))
899 }
900
901
902
903
904
905 grown := it.m.dirLen > 0
906 var elem unsafe.Pointer
907 if grown {
908 var ok bool
909 newKey, newElem, ok := it.m.getWithKey(it.typ, key)
910 if !ok {
911
912 if it.clearSeq == it.m.clearSeq && !it.typ.Key.Equal(key, key) {
913 elem = it.group.elem(it.typ, k)
914 if it.typ.IndirectElem() {
915 elem = *((*unsafe.Pointer)(elem))
916 }
917 } else {
918 continue
919 }
920 } else {
921 key = newKey
922 elem = newElem
923 }
924 } else {
925 elem = it.group.elem(it.typ, k)
926 if it.typ.IndirectElem() {
927 elem = *((*unsafe.Pointer)(elem))
928 }
929 }
930
931 it.entryIdx++
932 it.key = key
933 it.elem = elem
934 return
935 }
936 it.key = nil
937 it.elem = nil
938 return
939 }
940
941 if it.globalDepth != it.m.globalDepth {
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971 orders := it.m.globalDepth - it.globalDepth
972 it.dirIdx <<= orders
973 it.dirOffset <<= orders
974
975
976 it.globalDepth = it.m.globalDepth
977 }
978
979
980 for ; it.dirIdx < it.m.dirLen; it.nextDirIdx() {
981
982 if it.tab == nil {
983 dirIdx := int((uint64(it.dirIdx) + it.dirOffset) & uint64(it.m.dirLen-1))
984 newTab := it.m.directoryAt(uintptr(dirIdx))
985 if newTab.index != dirIdx {
986
987
988
989
990
991
992
993
994
995
996
997 diff := dirIdx - newTab.index
998 it.dirOffset -= uint64(diff)
999 dirIdx = newTab.index
1000 }
1001 it.tab = newTab
1002 }
1003
1004
1005
1006
1007
1008 entryMask := uint64(it.tab.capacity) - 1
1009 if it.entryIdx > entryMask {
1010
1011 continue
1012 }
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025 entryIdx := (it.entryIdx + it.entryOffset) & entryMask
1026 slotIdx := uintptr(entryIdx & (abi.MapGroupSlots - 1))
1027 if slotIdx == 0 || it.group.data == nil {
1028
1029
1030
1031
1032 groupIdx := entryIdx >> abi.MapGroupSlotsBits
1033 it.group = it.tab.groups.group(it.typ, groupIdx)
1034 }
1035
1036 if (it.group.ctrls().get(slotIdx) & ctrlEmpty) == 0 {
1037
1038
1039 key := it.group.key(it.typ, slotIdx)
1040 if it.typ.IndirectKey() {
1041 key = *((*unsafe.Pointer)(key))
1042 }
1043
1044 grown := it.tab.index == -1
1045 var elem unsafe.Pointer
1046 if grown {
1047 newKey, newElem, ok := it.grownKeyElem(key, slotIdx)
1048 if !ok {
1049
1050
1051
1052 goto next
1053 } else {
1054 key = newKey
1055 elem = newElem
1056 }
1057 } else {
1058 elem = it.group.elem(it.typ, slotIdx)
1059 if it.typ.IndirectElem() {
1060 elem = *((*unsafe.Pointer)(elem))
1061 }
1062 }
1063
1064 it.entryIdx++
1065 it.key = key
1066 it.elem = elem
1067 return
1068 }
1069
1070 next:
1071 it.entryIdx++
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 var groupMatch bitset
1091 for it.entryIdx <= entryMask {
1092 entryIdx := (it.entryIdx + it.entryOffset) & entryMask
1093 slotIdx := uintptr(entryIdx & (abi.MapGroupSlots - 1))
1094
1095 if slotIdx == 0 || it.group.data == nil {
1096
1097
1098
1099
1100 groupIdx := entryIdx >> abi.MapGroupSlotsBits
1101 it.group = it.tab.groups.group(it.typ, groupIdx)
1102 }
1103
1104 if groupMatch == 0 {
1105 groupMatch = it.group.ctrls().matchFull()
1106
1107 if slotIdx != 0 {
1108
1109
1110 groupMatch = groupMatch.removeBelow(slotIdx)
1111 }
1112
1113
1114
1115 if groupMatch == 0 {
1116
1117
1118 it.entryIdx += abi.MapGroupSlots - uint64(slotIdx)
1119 continue
1120 }
1121
1122 i := groupMatch.first()
1123 it.entryIdx += uint64(i - slotIdx)
1124 if it.entryIdx > entryMask {
1125
1126 continue
1127 }
1128 entryIdx += uint64(i - slotIdx)
1129 slotIdx = i
1130 }
1131
1132 key := it.group.key(it.typ, slotIdx)
1133 if it.typ.IndirectKey() {
1134 key = *((*unsafe.Pointer)(key))
1135 }
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148 grown := it.tab.index == -1
1149 var elem unsafe.Pointer
1150 if grown {
1151 newKey, newElem, ok := it.grownKeyElem(key, slotIdx)
1152 if !ok {
1153
1154
1155 groupMatch = groupMatch.removeFirst()
1156 if groupMatch == 0 {
1157
1158
1159
1160 it.entryIdx += abi.MapGroupSlots - uint64(slotIdx)
1161 continue
1162 }
1163
1164
1165 i := groupMatch.first()
1166 it.entryIdx += uint64(i - slotIdx)
1167 continue
1168 } else {
1169 key = newKey
1170 elem = newElem
1171 }
1172 } else {
1173 elem = it.group.elem(it.typ, slotIdx)
1174 if it.typ.IndirectElem() {
1175 elem = *((*unsafe.Pointer)(elem))
1176 }
1177 }
1178
1179
1180 groupMatch = groupMatch.removeFirst()
1181 if groupMatch == 0 {
1182
1183
1184
1185 it.entryIdx += abi.MapGroupSlots - uint64(slotIdx)
1186 } else {
1187
1188 i := groupMatch.first()
1189 it.entryIdx += uint64(i - slotIdx)
1190 }
1191
1192 it.key = key
1193 it.elem = elem
1194 return
1195 }
1196
1197
1198 }
1199
1200 it.key = nil
1201 it.elem = nil
1202 return
1203 }
1204
1205
1206
1207
1208 func (t *table) rehash(typ *abi.MapType, m *Map) {
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224 newCapacity := 2 * t.capacity
1225 if newCapacity <= maxTableCapacity {
1226 t.grow(typ, m, newCapacity)
1227 return
1228 }
1229
1230 t.split(typ, m)
1231 }
1232
1233
1234 func localDepthMask(localDepth uint8) uintptr {
1235 if !Use64BitHash {
1236 return uintptr(1) << (32 - localDepth)
1237 }
1238 return uintptr(1) << (64 - localDepth)
1239 }
1240
1241
1242 func (t *table) split(typ *abi.MapType, m *Map) {
1243 localDepth := t.localDepth
1244 localDepth++
1245
1246
1247 left := newTable(typ, maxTableCapacity, -1, localDepth)
1248 right := newTable(typ, maxTableCapacity, -1, localDepth)
1249
1250
1251 mask := localDepthMask(localDepth)
1252
1253 for i := uint64(0); i <= t.groups.lengthMask; i++ {
1254 g := t.groups.group(typ, i)
1255 for j := uintptr(0); j < abi.MapGroupSlots; j++ {
1256 if (g.ctrls().get(j) & ctrlEmpty) == ctrlEmpty {
1257
1258 continue
1259 }
1260
1261 key := g.key(typ, j)
1262 if typ.IndirectKey() {
1263 key = *((*unsafe.Pointer)(key))
1264 }
1265
1266 elem := g.elem(typ, j)
1267 if typ.IndirectElem() {
1268 elem = *((*unsafe.Pointer)(elem))
1269 }
1270
1271 hash := typ.Hasher(key, m.seed)
1272 var newTable *table
1273 if hash&mask == 0 {
1274 newTable = left
1275 } else {
1276 newTable = right
1277 }
1278 newTable.uncheckedPutSlot(typ, hash, key, elem)
1279 }
1280 }
1281
1282 m.installTableSplit(t, left, right)
1283 t.index = -1
1284 }
1285
1286
1287
1288
1289
1290 func (t *table) grow(typ *abi.MapType, m *Map, newCapacity uint16) {
1291 newTable := newTable(typ, uint64(newCapacity), t.index, t.localDepth)
1292
1293 if t.capacity > 0 {
1294 for i := uint64(0); i <= t.groups.lengthMask; i++ {
1295 g := t.groups.group(typ, i)
1296 for j := uintptr(0); j < abi.MapGroupSlots; j++ {
1297 if (g.ctrls().get(j) & ctrlEmpty) == ctrlEmpty {
1298
1299 continue
1300 }
1301
1302 key := g.key(typ, j)
1303 if typ.IndirectKey() {
1304 key = *((*unsafe.Pointer)(key))
1305 }
1306
1307 elem := g.elem(typ, j)
1308 if typ.IndirectElem() {
1309 elem = *((*unsafe.Pointer)(elem))
1310 }
1311
1312 hash := typ.Hasher(key, m.seed)
1313
1314 newTable.uncheckedPutSlot(typ, hash, key, elem)
1315 }
1316 }
1317 }
1318
1319 newTable.checkInvariants(typ, m)
1320 m.replaceTable(newTable)
1321 t.index = -1
1322 }
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337 type probeSeq struct {
1338 mask uint64
1339 offset uint64
1340 index uint64
1341 }
1342
1343 func makeProbeSeq(hash uintptr, mask uint64) probeSeq {
1344 return probeSeq{
1345 mask: mask,
1346 offset: uint64(hash) & mask,
1347 index: 0,
1348 }
1349 }
1350
1351 func (s probeSeq) next() probeSeq {
1352 s.index++
1353 s.offset = (s.offset + s.index) & s.mask
1354 return s
1355 }
1356
1357 func (t *table) clone(typ *abi.MapType) *table {
1358
1359 t2 := new(table)
1360 *t2 = *t
1361 t = t2
1362
1363
1364 oldGroups := t.groups
1365 newGroups := newGroups(typ, oldGroups.lengthMask+1)
1366 for i := uint64(0); i <= oldGroups.lengthMask; i++ {
1367 oldGroup := oldGroups.group(typ, i)
1368 newGroup := newGroups.group(typ, i)
1369 cloneGroup(typ, newGroup, oldGroup)
1370 }
1371 t.groups = newGroups
1372
1373 return t
1374 }
1375
View as plain text