compiler, runtime: implement delete builtin

This commit is contained in:
Ayke van Laethem
2018-10-20 16:18:55 +02:00
parent 7f60dd79ee
commit c0c1ccb381
6 changed files with 179 additions and 73 deletions
+45
View File
@@ -158,6 +158,41 @@ func hashmapGet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint3
memzero(value, uintptr(m.valueSize))
}
// Delete a given key from the map. No-op when the key does not exist in the
// map.
//go:nobounds
func hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
numBuckets := uintptr(1) << m.bucketBits
bucketNumber := (uintptr(hash) & (numBuckets - 1))
bucketSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8
bucketAddr := uintptr(m.buckets) + bucketSize*bucketNumber
bucket := (*hashmapBucket)(unsafe.Pointer(bucketAddr))
tophash := uint8(hash >> 24)
if tophash < 1 {
// 0 means empty slot, so make it bigger.
tophash += 1
}
// Try to find the key.
for bucket != nil {
for i := uintptr(0); i < 8; i++ {
slotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*uintptr(i)
slotKey := unsafe.Pointer(uintptr(unsafe.Pointer(bucket)) + slotKeyOffset)
if bucket.tophash[i] == tophash {
// This could be the key we're looking for.
if keyEqual(key, slotKey, uintptr(m.keySize)) {
// Found the key, delete it.
bucket.tophash[i] = 0
m.count--
return
}
}
}
bucket = bucket.next
}
}
// Iterate over a hashmap.
//go:nobounds
func hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) bool {
@@ -209,6 +244,11 @@ func hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer) {
hashmapGet(m, key, value, hash, memequal)
}
func hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {
hash := hashmapHash(key, uintptr(m.keySize))
hashmapDelete(m, key, hash, memequal)
}
// Hashmap with string keys (a common case).
func hashmapStringEqual(x, y unsafe.Pointer, n uintptr) bool {
@@ -229,3 +269,8 @@ func hashmapStringGet(m *hashmap, key string, value unsafe.Pointer) {
hash := hashmapStringHash(key)
hashmapGet(m, unsafe.Pointer(&key), value, hash, hashmapStringEqual)
}
func hashmapStringDelete(m *hashmap, key string) {
hash := hashmapStringHash(key)
hashmapDelete(m, unsafe.Pointer(&key), hash, hashmapStringEqual)
}