annotate libgo/go/runtime/map_fast64.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 // Copyright 2018 The Go Authors. All rights reserved.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3 // license that can be found in the LICENSE file.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5 package runtime
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 import (
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 "runtime/internal/sys"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 "unsafe"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10 )
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
12 // For gccgo, use go:linkname to export compiler-called functions.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
13 //
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
14 //go:linkname mapaccess1_fast64
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
15 //go:linkname mapaccess2_fast64
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
16 //go:linkname mapassign_fast64
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
17 //go:linkname mapassign_fast64ptr
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
18 //go:linkname mapdelete_fast64
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
19
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20 func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 if raceenabled && h != nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 callerpc := getcallerpc()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast64))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 if h == nil || h.count == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 return unsafe.Pointer(&zeroVal[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 if h.flags&hashWriting != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 throw("concurrent map read and map write")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 var b *bmap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 if h.B == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 // One-bucket table. No need to hash.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 b = (*bmap)(h.buckets)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 } else {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
36 hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 m := bucketMask(h.B)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 if c := h.oldbuckets; c != nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 if !h.sameSizeGrow() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 // There used to be half as many buckets; mask down one more power of two.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 m >>= 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 if !evacuated(oldb) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46 b = oldb
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 for ; b != nil; b = b.overflow(t) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 for i, k := uintptr(0), b.keys(); i < bucketCnt; i, k = i+1, add(k, 8) {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
52 if *(*uint64)(k) == key && !isEmpty(b.tophash[i]) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
53 return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.elemsize))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 return unsafe.Pointer(&zeroVal[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60 func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 if raceenabled && h != nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 callerpc := getcallerpc()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast64))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 if h == nil || h.count == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 return unsafe.Pointer(&zeroVal[0]), false
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 if h.flags&hashWriting != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 throw("concurrent map read and map write")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 var b *bmap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 if h.B == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 // One-bucket table. No need to hash.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 b = (*bmap)(h.buckets)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 } else {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
76 hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 m := bucketMask(h.B)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79 if c := h.oldbuckets; c != nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 if !h.sameSizeGrow() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81 // There used to be half as many buckets; mask down one more power of two.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 m >>= 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 if !evacuated(oldb) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 b = oldb
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 for ; b != nil; b = b.overflow(t) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 for i, k := uintptr(0), b.keys(); i < bucketCnt; i, k = i+1, add(k, 8) {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
92 if *(*uint64)(k) == key && !isEmpty(b.tophash[i]) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
93 return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.elemsize)), true
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 return unsafe.Pointer(&zeroVal[0]), false
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 if h == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 panic(plainError("assignment to entry in nil map"))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 if raceenabled {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 callerpc := getcallerpc()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106 racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 if h.flags&hashWriting != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
111 hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
113 // Set hashWriting after calling t.hasher for consistency with mapassign.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
114 h.flags ^= hashWriting
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 if h.buckets == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 h.buckets = newobject(t.bucket) // newarray(t.bucket, 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 again:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 bucket := hash & bucketMask(h.B)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 if h.growing() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 growWork_fast64(t, h, bucket)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 var insertb *bmap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 var inserti uintptr
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 var insertk unsafe.Pointer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
131 bucketloop:
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 for {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 for i := uintptr(0); i < bucketCnt; i++ {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
134 if isEmpty(b.tophash[i]) {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 if insertb == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 insertb = b
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 inserti = i
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
139 if b.tophash[i] == emptyRest {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
140 break bucketloop
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
141 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 k := *((*uint64)(add(unsafe.Pointer(b), dataOffset+i*8)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 if k != key {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 insertb = b
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 inserti = i
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 goto done
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 ovf := b.overflow(t)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 if ovf == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 break
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156 b = ovf
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 // Did not find mapping for key. Allocate new cell & add entry.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 // If we hit the max load factor or we have too many overflow buckets,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 // and we're not already in the middle of growing, start growing.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 if !h.growing() && (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 hashGrow(t, h)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 goto again // Growing the table invalidates everything, so try again
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 if insertb == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169 // all current buckets are full, allocate a new one.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 insertb = h.newoverflow(t, b)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 inserti = 0 // not necessary, but avoids needlessly spilling inserti
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 insertb.tophash[inserti&(bucketCnt-1)] = tophash(hash) // mask inserti to avoid bounds checks
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 insertk = add(unsafe.Pointer(insertb), dataOffset+inserti*8)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 // store new key at insert position
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 *(*uint64)(insertk) = key
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 h.count++
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 done:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
182 elem := add(unsafe.Pointer(insertb), dataOffset+bucketCnt*8+inserti*uintptr(t.elemsize))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 if h.flags&hashWriting == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186 h.flags &^= hashWriting
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
187 return elem
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 func mapassign_fast64ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 if h == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 panic(plainError("assignment to entry in nil map"))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 if raceenabled {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 callerpc := getcallerpc()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 if h.flags&hashWriting != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
201 hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
203 // Set hashWriting after calling t.hasher for consistency with mapassign.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
204 h.flags ^= hashWriting
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206 if h.buckets == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 h.buckets = newobject(t.bucket) // newarray(t.bucket, 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 again:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 bucket := hash & bucketMask(h.B)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 if h.growing() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213 growWork_fast64(t, h, bucket)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 var insertb *bmap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 var inserti uintptr
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219 var insertk unsafe.Pointer
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
221 bucketloop:
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 for {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223 for i := uintptr(0); i < bucketCnt; i++ {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
224 if isEmpty(b.tophash[i]) {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 if insertb == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 insertb = b
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 inserti = i
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
229 if b.tophash[i] == emptyRest {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
230 break bucketloop
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
231 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 k := *((*unsafe.Pointer)(add(unsafe.Pointer(b), dataOffset+i*8)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 if k != key {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 insertb = b
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 inserti = i
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 goto done
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 ovf := b.overflow(t)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243 if ovf == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 break
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 b = ovf
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 // Did not find mapping for key. Allocate new cell & add entry.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 // If we hit the max load factor or we have too many overflow buckets,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 // and we're not already in the middle of growing, start growing.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 if !h.growing() && (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 hashGrow(t, h)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 goto again // Growing the table invalidates everything, so try again
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 if insertb == nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259 // all current buckets are full, allocate a new one.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 insertb = h.newoverflow(t, b)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 inserti = 0 // not necessary, but avoids needlessly spilling inserti
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 insertb.tophash[inserti&(bucketCnt-1)] = tophash(hash) // mask inserti to avoid bounds checks
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 insertk = add(unsafe.Pointer(insertb), dataOffset+inserti*8)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 // store new key at insert position
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 *(*unsafe.Pointer)(insertk) = key
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 h.count++
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 done:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
272 elem := add(unsafe.Pointer(insertb), dataOffset+bucketCnt*8+inserti*uintptr(t.elemsize))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 if h.flags&hashWriting == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 h.flags &^= hashWriting
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
277 return elem
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 func mapdelete_fast64(t *maptype, h *hmap, key uint64) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 if raceenabled && h != nil {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 callerpc := getcallerpc()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapdelete_fast64))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 if h == nil || h.count == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 return
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 if h.flags&hashWriting != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
292 hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
294 // Set hashWriting after calling t.hasher for consistency with mapdelete
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
295 h.flags ^= hashWriting
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 bucket := hash & bucketMask(h.B)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298 if h.growing() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 growWork_fast64(t, h, bucket)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301 b := (*bmap)(add(h.buckets, bucket*uintptr(t.bucketsize)))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
302 bOrig := b
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 search:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 for ; b != nil; b = b.overflow(t) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 for i, k := uintptr(0), b.keys(); i < bucketCnt; i, k = i+1, add(k, 8) {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
306 if key != *(*uint64)(k) || isEmpty(b.tophash[i]) {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 // Only clear key if there are pointers in it.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
310 if t.key.ptrdata != 0 {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311 memclrHasPointers(k, t.key.size)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
313 e := add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.elemsize))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
314 if t.elem.ptrdata != 0 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
315 memclrHasPointers(e, t.elem.size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
316 } else {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
317 memclrNoHeapPointers(e, t.elem.size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
318 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
319 b.tophash[i] = emptyOne
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
320 // If the bucket now ends in a bunch of emptyOne states,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
321 // change those to emptyRest states.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
322 if i == bucketCnt-1 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
323 if b.overflow(t) != nil && b.overflow(t).tophash[0] != emptyRest {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
324 goto notLast
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
325 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 } else {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
327 if b.tophash[i+1] != emptyRest {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
328 goto notLast
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
329 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
331 for {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
332 b.tophash[i] = emptyRest
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
333 if i == 0 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
334 if b == bOrig {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
335 break // beginning of initial bucket, we're done.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
336 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
337 // Find previous bucket, continue at its last entry.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
338 c := b
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
339 for b = bOrig; b.overflow(t) != c; b = b.overflow(t) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
340 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
341 i = bucketCnt - 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
342 } else {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
343 i--
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
344 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
345 if b.tophash[i] != emptyOne {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
346 break
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
349 notLast:
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350 h.count--
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351 break search
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
355 if h.flags&hashWriting == 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 throw("concurrent map writes")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 h.flags &^= hashWriting
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361 func growWork_fast64(t *maptype, h *hmap, bucket uintptr) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 // make sure we evacuate the oldbucket corresponding
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363 // to the bucket we're about to use
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
364 evacuate_fast64(t, h, bucket&h.oldbucketmask())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
366 // evacuate one more oldbucket to make progress on growing
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
367 if h.growing() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
368 evacuate_fast64(t, h, h.nevacuate)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
369 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
370 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
371
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
372 func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 b := (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
374 newbit := h.noldbuckets()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
375 if !evacuated(b) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 // TODO: reuse overflow buckets instead of using new ones, if there
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377 // is no iterator using the old buckets. (If !oldIterator.)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 // xy contains the x and y (low and high) evacuation destinations.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 var xy [2]evacDst
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381 x := &xy[0]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382 x.b = (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 x.k = add(unsafe.Pointer(x.b), dataOffset)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
384 x.e = add(x.k, bucketCnt*8)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386 if !h.sameSizeGrow() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 // Only calculate y pointers if we're growing bigger.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
388 // Otherwise GC can see bad pointers.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 y := &xy[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 y.b = (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391 y.k = add(unsafe.Pointer(y.b), dataOffset)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
392 y.e = add(y.k, bucketCnt*8)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 for ; b != nil; b = b.overflow(t) {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396 k := add(unsafe.Pointer(b), dataOffset)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
397 e := add(k, bucketCnt*8)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
398 for i := 0; i < bucketCnt; i, k, e = i+1, add(k, 8), add(e, uintptr(t.elemsize)) {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 top := b.tophash[i]
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
400 if isEmpty(top) {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 b.tophash[i] = evacuatedEmpty
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 continue
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 if top < minTopHash {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 throw("bad map state")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407 var useY uint8
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 if !h.sameSizeGrow() {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 // Compute hash to make our evacuation decision (whether we need
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
410 // to send this key/elem to bucket x or bucket y).
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
411 hash := t.hasher(k, uintptr(h.hash0))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 if hash&newbit != 0 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 useY = 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 b.tophash[i] = evacuatedX + useY // evacuatedX + 1 == evacuatedY, enforced in makemap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 dst := &xy[useY] // evacuation destination
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420 if dst.i == bucketCnt {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 dst.b = h.newoverflow(t, dst.b)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 dst.i = 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423 dst.k = add(unsafe.Pointer(dst.b), dataOffset)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
424 dst.e = add(dst.k, bucketCnt*8)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
427
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 // Copy key.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
429 if t.key.ptrdata != 0 && writeBarrier.enabled {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 if sys.PtrSize == 8 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431 // Write with a write barrier.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432 *(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 } else {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434 // There are three ways to squeeze at least one 32 bit pointer into 64 bits.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 // Give up and call typedmemmove.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436 typedmemmove(t.key, dst.k, k)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
437 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
438 } else {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
439 *(*uint64)(dst.k) = *(*uint64)(k)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
440 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
441
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
442 typedmemmove(t.elem, dst.e, e)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443 dst.i++
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444 // These updates might push these pointers past the end of the
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
445 // key or elem arrays. That's ok, as we have the overflow pointer
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446 // at the end of the bucket to protect against pointing past the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447 // end of the bucket.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448 dst.k = add(dst.k, 8)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
449 dst.e = add(dst.e, uintptr(t.elemsize))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
452 // Unlink the overflow buckets & clear key/elem to help GC.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
453 if h.flags&oldIterator == 0 && t.bucket.ptrdata != 0 {
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455 // Preserve b.tophash because the evacuation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 // state is maintained there.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 ptr := add(b, dataOffset)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458 n := uintptr(t.bucketsize) - dataOffset
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459 memclrHasPointers(ptr, n)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 if oldbucket == h.nevacuate {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 advanceEvacuationMark(h, t, newbit)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 }