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