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.resetGrowthLeft()
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 func (t *table) resetGrowthLeft() {
116 var growthLeft 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 growthLeft = t.capacity - 1
129 } else {
130 if t.capacity*maxAvgGroupLoad < t.capacity {
131
132 panic("overflow")
133 }
134 growthLeft = (t.capacity * maxAvgGroupLoad) / abi.SwissMapGroupSlots
135 }
136 t.growthLeft = growthLeft
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 slotKey := g.key(typ, i)
332 if typ.IndirectKey() {
333 kmem := newobject(typ.Key)
334 *(*unsafe.Pointer)(slotKey) = kmem
335 slotKey = kmem
336 }
337 typedmemmove(typ.Key, slotKey, key)
338
339 slotElem := g.elem(typ, i)
340 if typ.IndirectElem() {
341 emem := newobject(typ.Elem)
342 *(*unsafe.Pointer)(slotElem) = emem
343 slotElem = emem
344 }
345
346 g.ctrls().set(i, ctrl(h2(hash)))
347 t.growthLeft--
348 t.used++
349 m.used++
350
351 t.checkInvariants(typ, m)
352 return slotElem, true
353 }
354
355 t.rehash(typ, m)
356 return nil, false
357 }
358 }
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 func (t *table) uncheckedPutSlot(typ *abi.SwissMapType, hash uintptr, key unsafe.Pointer) unsafe.Pointer {
374 if t.growthLeft == 0 {
375 panic("invariant failed: growthLeft is unexpectedly 0")
376 }
377
378
379
380
381
382 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
383 for ; ; seq = seq.next() {
384 g := t.groups.group(typ, seq.offset)
385
386 match := g.ctrls().matchEmptyOrDeleted()
387 if match != 0 {
388 i := match.first()
389
390 slotKey := g.key(typ, i)
391 if typ.IndirectKey() {
392 kmem := newobject(typ.Key)
393 *(*unsafe.Pointer)(slotKey) = kmem
394 slotKey = kmem
395 }
396 typedmemmove(typ.Key, slotKey, key)
397
398 slotElem := g.elem(typ, i)
399 if typ.IndirectElem() {
400 emem := newobject(typ.Elem)
401 *(*unsafe.Pointer)(slotElem) = emem
402 slotElem = emem
403 }
404
405 t.growthLeft--
406 g.ctrls().set(i, ctrl(h2(hash)))
407 return slotElem
408 }
409 }
410 }
411
412 func (t *table) Delete(typ *abi.SwissMapType, m *Map, hash uintptr, key unsafe.Pointer) {
413 seq := makeProbeSeq(h1(hash), t.groups.lengthMask)
414 for ; ; seq = seq.next() {
415 g := t.groups.group(typ, seq.offset)
416 match := g.ctrls().matchH2(h2(hash))
417
418 for match != 0 {
419 i := match.first()
420
421 slotKey := g.key(typ, i)
422 origSlotKey := slotKey
423 if typ.IndirectKey() {
424 slotKey = *((*unsafe.Pointer)(slotKey))
425 }
426
427 if typ.Key.Equal(key, slotKey) {
428 t.used--
429 m.used--
430
431 if typ.IndirectKey() {
432
433 *(*unsafe.Pointer)(origSlotKey) = nil
434 } else if typ.Key.Pointers() {
435
436
437 typedmemclr(typ.Key, slotKey)
438 }
439
440 slotElem := g.elem(typ, i)
441 if typ.IndirectElem() {
442
443 *(*unsafe.Pointer)(slotElem) = nil
444 } else {
445
446
447
448
449
450 typedmemclr(typ.Elem, slotElem)
451 }
452
453
454
455
456
457
458
459
460
461 if g.ctrls().matchEmpty() != 0 {
462 g.ctrls().set(i, ctrlEmpty)
463 t.growthLeft++
464 } else {
465 g.ctrls().set(i, ctrlDeleted)
466 }
467
468 t.checkInvariants(typ, m)
469 return
470 }
471 match = match.removeFirst()
472 }
473
474 match = g.ctrls().matchEmpty()
475 if match != 0 {
476
477
478 return
479 }
480 }
481 }
482
483
484
485
486 func (t *table) tombstones() uint16 {
487 return (t.capacity*maxAvgGroupLoad)/abi.SwissMapGroupSlots - t.used - t.growthLeft
488 }
489
490
491 func (t *table) Clear(typ *abi.SwissMapType) {
492 for i := uint64(0); i <= t.groups.lengthMask; i++ {
493 g := t.groups.group(typ, i)
494 typedmemclr(typ.Group, g.data)
495 g.ctrls().setEmpty()
496 }
497
498 t.used = 0
499 t.resetGrowthLeft()
500 }
501
502 type Iter struct {
503 key unsafe.Pointer
504 elem unsafe.Pointer
505 typ *abi.SwissMapType
506 m *Map
507
508
509
510
511 entryOffset uint64
512 dirOffset uint64
513
514
515
516 clearSeq uint64
517
518
519
520 globalDepth uint8
521
522
523
524 dirIdx int
525
526
527 tab *table
528
529
530 group groupReference
531
532
533
534
535 entryIdx uint64
536 }
537
538
539 func (it *Iter) Init(typ *abi.SwissMapType, m *Map) {
540 it.typ = typ
541
542 if m == nil || m.used == 0 {
543 return
544 }
545
546 dirIdx := 0
547 var groupSmall groupReference
548 if m.dirLen <= 0 {
549
550 dirIdx = -1
551 groupSmall.data = m.dirPtr
552 }
553
554 it.m = m
555 it.entryOffset = rand()
556 it.dirOffset = rand()
557 it.globalDepth = m.globalDepth
558 it.dirIdx = dirIdx
559 it.group = groupSmall
560 it.clearSeq = m.clearSeq
561 }
562
563 func (it *Iter) Initialized() bool {
564 return it.typ != nil
565 }
566
567
568 func (it *Iter) Map() *Map {
569 return it.m
570 }
571
572
573
574
575 func (it *Iter) Key() unsafe.Pointer {
576 return it.key
577 }
578
579
580
581
582
583 func (it *Iter) Elem() unsafe.Pointer {
584 return it.elem
585 }
586
587 func (it *Iter) nextDirIdx() {
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 entries := 1 << (it.m.globalDepth - it.tab.localDepth)
615 it.dirIdx += entries
616 it.tab = nil
617 it.group = groupReference{}
618 it.entryIdx = 0
619 }
620
621
622
623 func (it *Iter) grownKeyElem(key unsafe.Pointer, slotIdx uintptr) (unsafe.Pointer, unsafe.Pointer, bool) {
624 newKey, newElem, ok := it.m.getWithKey(it.typ, key)
625 if !ok {
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649 if it.clearSeq == it.m.clearSeq && !it.typ.Key.Equal(key, key) {
650 elem := it.group.elem(it.typ, slotIdx)
651 if it.typ.IndirectElem() {
652 elem = *((*unsafe.Pointer)(elem))
653 }
654 return key, elem, true
655 }
656
657
658 return nil, nil, false
659 }
660
661 return newKey, newElem, true
662 }
663
664
665
666
667
668
669
670
671 func (it *Iter) Next() {
672 if it.m == nil {
673
674 it.key = nil
675 it.elem = nil
676 return
677 }
678
679 if it.m.writing != 0 {
680 fatal("concurrent map iteration and map write")
681 return
682 }
683
684 if it.dirIdx < 0 {
685
686 for ; it.entryIdx < abi.SwissMapGroupSlots; it.entryIdx++ {
687 k := uintptr(it.entryIdx+it.entryOffset) % abi.SwissMapGroupSlots
688
689 if (it.group.ctrls().get(k) & ctrlEmpty) == ctrlEmpty {
690
691 continue
692 }
693
694 key := it.group.key(it.typ, k)
695 if it.typ.IndirectKey() {
696 key = *((*unsafe.Pointer)(key))
697 }
698
699
700
701
702
703 grown := it.m.dirLen > 0
704 var elem unsafe.Pointer
705 if grown {
706 var ok bool
707 newKey, newElem, ok := it.m.getWithKey(it.typ, key)
708 if !ok {
709
710 if it.clearSeq == it.m.clearSeq && !it.typ.Key.Equal(key, key) {
711 elem = it.group.elem(it.typ, k)
712 if it.typ.IndirectElem() {
713 elem = *((*unsafe.Pointer)(elem))
714 }
715 } else {
716 continue
717 }
718 } else {
719 key = newKey
720 elem = newElem
721 }
722 } else {
723 elem = it.group.elem(it.typ, k)
724 if it.typ.IndirectElem() {
725 elem = *((*unsafe.Pointer)(elem))
726 }
727 }
728
729 it.entryIdx++
730 it.key = key
731 it.elem = elem
732 return
733 }
734 it.key = nil
735 it.elem = nil
736 return
737 }
738
739 if it.globalDepth != it.m.globalDepth {
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769 orders := it.m.globalDepth - it.globalDepth
770 it.dirIdx <<= orders
771 it.dirOffset <<= orders
772
773
774 it.globalDepth = it.m.globalDepth
775 }
776
777
778 for ; it.dirIdx < it.m.dirLen; it.nextDirIdx() {
779
780 if it.tab == nil {
781 dirIdx := int((uint64(it.dirIdx) + it.dirOffset) & uint64(it.m.dirLen-1))
782 newTab := it.m.directoryAt(uintptr(dirIdx))
783 if newTab.index != dirIdx {
784
785
786
787
788
789
790
791
792
793
794
795 diff := dirIdx - newTab.index
796 it.dirOffset -= uint64(diff)
797 dirIdx = newTab.index
798 }
799 it.tab = newTab
800 }
801
802
803
804
805
806 if it.entryIdx > it.tab.groups.entryMask {
807
808 continue
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822 entryIdx := (it.entryIdx + it.entryOffset) & it.tab.groups.entryMask
823 slotIdx := uintptr(entryIdx & (abi.SwissMapGroupSlots - 1))
824 if slotIdx == 0 || it.group.data == nil {
825
826
827
828
829 groupIdx := entryIdx >> abi.SwissMapGroupSlotsBits
830 it.group = it.tab.groups.group(it.typ, groupIdx)
831 }
832
833 if (it.group.ctrls().get(slotIdx) & ctrlEmpty) == 0 {
834
835
836 key := it.group.key(it.typ, slotIdx)
837 if it.typ.IndirectKey() {
838 key = *((*unsafe.Pointer)(key))
839 }
840
841 grown := it.tab.index == -1
842 var elem unsafe.Pointer
843 if grown {
844 newKey, newElem, ok := it.grownKeyElem(key, slotIdx)
845 if !ok {
846
847
848
849 goto next
850 } else {
851 key = newKey
852 elem = newElem
853 }
854 } else {
855 elem = it.group.elem(it.typ, slotIdx)
856 if it.typ.IndirectElem() {
857 elem = *((*unsafe.Pointer)(elem))
858 }
859 }
860
861 it.entryIdx++
862 it.key = key
863 it.elem = elem
864 return
865 }
866
867 next:
868 it.entryIdx++
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 var groupMatch bitset
888 for it.entryIdx <= it.tab.groups.entryMask {
889 entryIdx := (it.entryIdx + it.entryOffset) & it.tab.groups.entryMask
890 slotIdx := uintptr(entryIdx & (abi.SwissMapGroupSlots - 1))
891
892 if slotIdx == 0 || it.group.data == nil {
893
894
895
896
897 groupIdx := entryIdx >> abi.SwissMapGroupSlotsBits
898 it.group = it.tab.groups.group(it.typ, groupIdx)
899 }
900
901 if groupMatch == 0 {
902 groupMatch = it.group.ctrls().matchFull()
903
904 if slotIdx != 0 {
905
906
907 groupMatch = groupMatch.removeBelow(slotIdx)
908 }
909
910
911
912 if groupMatch == 0 {
913
914
915 it.entryIdx += abi.SwissMapGroupSlots - uint64(slotIdx)
916 continue
917 }
918
919 i := groupMatch.first()
920 it.entryIdx += uint64(i - slotIdx)
921 if it.entryIdx > it.tab.groups.entryMask {
922
923 continue
924 }
925 entryIdx += uint64(i - slotIdx)
926 slotIdx = i
927 }
928
929 key := it.group.key(it.typ, slotIdx)
930 if it.typ.IndirectKey() {
931 key = *((*unsafe.Pointer)(key))
932 }
933
934
935
936
937
938
939
940
941
942
943
944
945 grown := it.tab.index == -1
946 var elem unsafe.Pointer
947 if grown {
948 newKey, newElem, ok := it.grownKeyElem(key, slotIdx)
949 if !ok {
950
951
952 groupMatch = groupMatch.removeFirst()
953 if groupMatch == 0 {
954
955
956
957 it.entryIdx += abi.SwissMapGroupSlots - uint64(slotIdx)
958 continue
959 }
960
961
962 i := groupMatch.first()
963 it.entryIdx += uint64(i - slotIdx)
964 continue
965 } else {
966 key = newKey
967 elem = newElem
968 }
969 } else {
970 elem = it.group.elem(it.typ, slotIdx)
971 if it.typ.IndirectElem() {
972 elem = *((*unsafe.Pointer)(elem))
973 }
974 }
975
976
977 groupMatch = groupMatch.removeFirst()
978 if groupMatch == 0 {
979
980
981
982 it.entryIdx += abi.SwissMapGroupSlots - uint64(slotIdx)
983 } else {
984
985 i := groupMatch.first()
986 it.entryIdx += uint64(i - slotIdx)
987 }
988
989 it.key = key
990 it.elem = elem
991 return
992 }
993
994
995 }
996
997 it.key = nil
998 it.elem = nil
999 return
1000 }
1001
1002
1003
1004
1005 func (t *table) rehash(typ *abi.SwissMapType, m *Map) {
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 newCapacity := 2 * t.capacity
1022 if newCapacity <= maxTableCapacity {
1023 t.grow(typ, m, newCapacity)
1024 return
1025 }
1026
1027 t.split(typ, m)
1028 }
1029
1030
1031 func localDepthMask(localDepth uint8) uintptr {
1032 if goarch.PtrSize == 4 {
1033 return uintptr(1) << (32 - localDepth)
1034 }
1035 return uintptr(1) << (64 - localDepth)
1036 }
1037
1038
1039 func (t *table) split(typ *abi.SwissMapType, m *Map) {
1040 localDepth := t.localDepth
1041 localDepth++
1042
1043
1044 left := newTable(typ, maxTableCapacity, -1, localDepth)
1045 right := newTable(typ, maxTableCapacity, -1, localDepth)
1046
1047
1048 mask := localDepthMask(localDepth)
1049
1050 for i := uint64(0); i <= t.groups.lengthMask; i++ {
1051 g := t.groups.group(typ, i)
1052 for j := uintptr(0); j < abi.SwissMapGroupSlots; j++ {
1053 if (g.ctrls().get(j) & ctrlEmpty) == ctrlEmpty {
1054
1055 continue
1056 }
1057
1058 key := g.key(typ, j)
1059 if typ.IndirectKey() {
1060 key = *((*unsafe.Pointer)(key))
1061 }
1062
1063 elem := g.elem(typ, j)
1064 if typ.IndirectElem() {
1065 elem = *((*unsafe.Pointer)(elem))
1066 }
1067
1068 hash := typ.Hasher(key, m.seed)
1069 var newTable *table
1070 if hash&mask == 0 {
1071 newTable = left
1072 } else {
1073 newTable = right
1074 }
1075
1076
1077
1078
1079 slotElem := newTable.uncheckedPutSlot(typ, hash, key)
1080 typedmemmove(typ.Elem, slotElem, elem)
1081 newTable.used++
1082 }
1083 }
1084
1085 m.installTableSplit(t, left, right)
1086 t.index = -1
1087 }
1088
1089
1090
1091
1092
1093 func (t *table) grow(typ *abi.SwissMapType, m *Map, newCapacity uint16) {
1094 newTable := newTable(typ, uint64(newCapacity), t.index, t.localDepth)
1095
1096 if t.capacity > 0 {
1097 for i := uint64(0); i <= t.groups.lengthMask; i++ {
1098 g := t.groups.group(typ, i)
1099 for j := uintptr(0); j < abi.SwissMapGroupSlots; j++ {
1100 if (g.ctrls().get(j) & ctrlEmpty) == ctrlEmpty {
1101
1102 continue
1103 }
1104
1105 key := g.key(typ, j)
1106 if typ.IndirectKey() {
1107 key = *((*unsafe.Pointer)(key))
1108 }
1109
1110 elem := g.elem(typ, j)
1111 if typ.IndirectElem() {
1112 elem = *((*unsafe.Pointer)(elem))
1113 }
1114
1115 hash := typ.Hasher(key, m.seed)
1116
1117
1118
1119
1120
1121 slotElem := newTable.uncheckedPutSlot(typ, hash, key)
1122 typedmemmove(typ.Elem, slotElem, elem)
1123 newTable.used++
1124 }
1125 }
1126 }
1127
1128 newTable.checkInvariants(typ, m)
1129 m.replaceTable(newTable)
1130 t.index = -1
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 type probeSeq struct {
1145 mask uint64
1146 offset uint64
1147 index uint64
1148 }
1149
1150 func makeProbeSeq(hash uintptr, mask uint64) probeSeq {
1151 return probeSeq{
1152 mask: mask,
1153 offset: uint64(hash) & mask,
1154 index: 0,
1155 }
1156 }
1157
1158 func (s probeSeq) next() probeSeq {
1159 s.index++
1160 s.offset = (s.offset + s.index) & s.mask
1161 return s
1162 }
1163
View as plain text