all: use unsafe.Add instead of unsafe.Pointer(uintptr(...) + ...)

We have an optimization for this specific pattern, but it's really just
a hack. With the addition of unsafe.Add in Go 1.17 we can directly
specify the intent instead and eventually remove this special case.

The code is also easier to read.
This commit is contained in:
Ayke van Laethem
2022-12-21 16:14:36 +01:00
committed by Ron Evans
parent d98c0afbab
commit 4ec1e58aa6
29 changed files with 84 additions and 95 deletions
+15 -20
View File
@@ -169,8 +169,7 @@ func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
numBuckets := uintptr(1) << m.bucketBits
bucketNumber := (uintptr(hash) & (numBuckets - 1))
bucketSize := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*8
bucketAddr := uintptr(m.buckets) + bucketSize*bucketNumber
bucket := (*hashmapBucket)(unsafe.Pointer(bucketAddr))
bucket := (*hashmapBucket)(unsafe.Add(m.buckets, bucketSize*bucketNumber))
var lastBucket *hashmapBucket
// See whether the key already exists somewhere.
@@ -180,9 +179,9 @@ func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
for bucket != nil {
for i := uintptr(0); i < 8; i++ {
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*uintptr(i)
slotKey := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotKeyOffset)
slotKey := unsafe.Add(unsafe.Pointer(bucket), slotKeyOffset)
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*uintptr(i)
slotValue := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotValueOffset)
slotValue := unsafe.Add(unsafe.Pointer(bucket), slotValueOffset)
if bucket.tophash[i] == 0 && emptySlotKey == nil {
// Found an empty slot, store it for if we couldn't find an
// existing slot.
@@ -225,9 +224,9 @@ func hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash u
bucketBuf := alloc(bucketBufSize, nil)
// Insert into the first slot, which is empty as it has just been allocated.
slotKeyOffset := unsafe.Sizeof(hashmapBucket{})
slotKey := unsafe.Pointer(uintptr(bucketBuf) + slotKeyOffset)
slotKey := unsafe.Add(bucketBuf, slotKeyOffset)
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8
slotValue := unsafe.Pointer(uintptr(bucketBuf) + slotValueOffset)
slotValue := unsafe.Add(bucketBuf, slotValueOffset)
m.count++
memcpy(slotKey, key, m.keySize)
memcpy(slotValue, value, m.valueSize)
@@ -276,8 +275,7 @@ func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash u
numBuckets := uintptr(1) << m.bucketBits
bucketNumber := (uintptr(hash) & (numBuckets - 1))
bucketSize := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*8
bucketAddr := uintptr(m.buckets) + bucketSize*bucketNumber
bucket := (*hashmapBucket)(unsafe.Pointer(bucketAddr))
bucket := (*hashmapBucket)(unsafe.Add(m.buckets, bucketSize*bucketNumber))
tophash := uint8(hash >> 24)
if tophash < 1 {
@@ -289,9 +287,9 @@ func hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash u
for bucket != nil {
for i := uintptr(0); i < 8; i++ {
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*uintptr(i)
slotKey := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotKeyOffset)
slotKey := unsafe.Add(unsafe.Pointer(bucket), slotKeyOffset)
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*uintptr(i)
slotValue := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotValueOffset)
slotValue := unsafe.Add(unsafe.Pointer(bucket), slotValueOffset)
if bucket.tophash[i] == tophash {
// This could be the key we're looking for.
if m.keyEqual(key, slotKey, m.keySize) {
@@ -327,8 +325,7 @@ func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32) {
numBuckets := uintptr(1) << m.bucketBits
bucketNumber := (uintptr(hash) & (numBuckets - 1))
bucketSize := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*8
bucketAddr := uintptr(m.buckets) + bucketSize*bucketNumber
bucket := (*hashmapBucket)(unsafe.Pointer(bucketAddr))
bucket := (*hashmapBucket)(unsafe.Add(m.buckets, bucketSize*bucketNumber))
tophash := uint8(hash >> 24)
if tophash < 1 {
@@ -340,7 +337,7 @@ func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32) {
for bucket != nil {
for i := uintptr(0); i < 8; i++ {
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*uintptr(i)
slotKey := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotKeyOffset)
slotKey := unsafe.Add(unsafe.Pointer(bucket), slotKeyOffset)
if bucket.tophash[i] == tophash {
// This could be the key we're looking for.
if m.keyEqual(key, slotKey, m.keySize) {
@@ -382,8 +379,7 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
return false
}
bucketSize := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*8
bucketAddr := uintptr(it.buckets) + bucketSize*it.bucketNumber
it.bucket = (*hashmapBucket)(unsafe.Pointer(bucketAddr))
it.bucket = (*hashmapBucket)(unsafe.Add(it.buckets, bucketSize*it.bucketNumber))
it.bucketNumber++ // next bucket
}
if it.bucket.tophash[it.bucketIndex] == 0 {
@@ -392,16 +388,15 @@ func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) boo
continue
}
bucketAddr := uintptr(unsafe.Pointer(it.bucket))
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*uintptr(it.bucketIndex)
slotKey := unsafe.Pointer(bucketAddr + slotKeyOffset)
slotKey := unsafe.Add(unsafe.Pointer(it.bucket), slotKeyOffset)
memcpy(key, slotKey, m.keySize)
if it.buckets == m.buckets {
// Our view of the buckets is the same as the parent map.
// Just copy the value we have
slotValueOffset := unsafe.Sizeof(hashmapBucket{}) + m.keySize*8 + m.valueSize*uintptr(it.bucketIndex)
slotValue := unsafe.Pointer(bucketAddr + slotValueOffset)
slotValue := unsafe.Add(unsafe.Pointer(it.bucket), slotValueOffset)
memcpy(value, slotValue, m.valueSize)
it.bucketIndex++
} else {
@@ -574,10 +569,10 @@ func hashmapInterfaceHash(itf interface{}, seed uintptr) uint32 {
case reflect.Float64:
return hashmapFloat64Hash(ptr, seed)
case reflect.Complex64:
rptr, iptr := ptr, unsafe.Pointer(uintptr(ptr)+4)
rptr, iptr := ptr, unsafe.Add(ptr, 4)
return hashmapFloat32Hash(rptr, seed) ^ hashmapFloat32Hash(iptr, seed)
case reflect.Complex128:
rptr, iptr := ptr, unsafe.Pointer(uintptr(ptr)+8)
rptr, iptr := ptr, unsafe.Add(ptr, 8)
return hashmapFloat64Hash(rptr, seed) ^ hashmapFloat64Hash(iptr, seed)
case reflect.String:
return hashmapStringHash(x.String(), seed)