diff --git a/src/runtime/memhash_fnv.go b/src/runtime/memhash_fnv.go index d3bf370e..585f99bc 100644 --- a/src/runtime/memhash_fnv.go +++ b/src/runtime/memhash_fnv.go @@ -1,5 +1,5 @@ -//go:build !runtime_memhash_tsip -// +build !runtime_memhash_tsip +//go:build !runtime_memhash_tsip && !runtime_memhash_leveldb +// +build !runtime_memhash_tsip,!runtime_memhash_leveldb package runtime diff --git a/src/runtime/memhash_leveldb.go b/src/runtime/memhash_leveldb.go new file mode 100644 index 00000000..1a32ae49 --- /dev/null +++ b/src/runtime/memhash_leveldb.go @@ -0,0 +1,74 @@ +//go:build runtime_memhash_leveldb +// +build runtime_memhash_leveldb + +package runtime + +import ( + "unsafe" +) + +func ptrToSlice(ptr unsafe.Pointer, n uintptr) []byte { + var p []byte + + type _bslice struct { + ptr *byte + len uintptr + cap uintptr + } + + pslice := (*_bslice)(unsafe.Pointer(&p)) + pslice.ptr = (*byte)(ptr) + pslice.cap = n + pslice.len = n + + return p +} + +// leveldb hash +func hash32(ptr unsafe.Pointer, n, seed uintptr) uint32 { + + const ( + lseed = 0xbc9f1d34 + m = 0xc6a4a793 + ) + + b := ptrToSlice(ptr, n) + + h := uint32(lseed^seed) ^ uint32(uint(len(b))*uint(m)) + + for ; len(b) >= 4; b = b[4:] { + h += uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + h *= m + h ^= h >> 16 + } + switch len(b) { + case 3: + h += uint32(b[2]) << 16 + fallthrough + case 2: + h += uint32(b[1]) << 8 + fallthrough + case 1: + h += uint32(b[0]) + h *= m + h ^= h >> 24 + } + + return h +} + +func hash64finalizer(key uint64) uint64 { + key = ^key + (key << 21) // key = (key << 21) - key - 1; + key = key ^ (key >> 24) + key = (key + (key << 3)) + (key << 8) // key * 265 + key = key ^ (key >> 14) + key = (key + (key << 2)) + (key << 4) // key * 21 + key = key ^ (key >> 28) + key = key + (key << 31) + return key +} + +func hash64(ptr unsafe.Pointer, n, seed uintptr) uint64 { + h32 := hash32(ptr, n, seed) + return hash64finalizer((uint64(h32^xorshift32(uint32(seed))) << 32) | uint64(h32)) +}