Skip to content

Commit b07fb48

Browse files
committed
maphash: copy source from v0.1.0
1 parent 8c626d4 commit b07fb48

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

contrab/maphash/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# maphash
2+
3+
kanged from github.com/dolthub/[email protected]

contrab/maphash/hasher.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2022 Dolthub, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package maphash
16+
17+
import "unsafe"
18+
19+
// Hasher hashes values of type K.
20+
// Uses runtime AES-based hashing.
21+
type Hasher[K comparable] struct {
22+
hash hashfn
23+
seed uintptr
24+
}
25+
26+
// NewHasher creates a new Hasher[K] with a random seed.
27+
func NewHasher[K comparable]() Hasher[K] {
28+
return Hasher[K]{
29+
hash: getRuntimeHasher[K](),
30+
seed: newHashSeed(),
31+
}
32+
}
33+
34+
// NewSeed returns a copy of |h| with a new hash seed.
35+
func NewSeed[K comparable](h Hasher[K]) Hasher[K] {
36+
return Hasher[K]{
37+
hash: h.hash,
38+
seed: newHashSeed(),
39+
}
40+
}
41+
42+
// Hash hashes |key|.
43+
func (h Hasher[K]) Hash(key K) uint64 {
44+
// promise to the compiler that pointer
45+
// |p| does not escape the stack.
46+
p := noescape(unsafe.Pointer(&key))
47+
return uint64(h.hash(p, h.seed))
48+
}

contrab/maphash/runtime.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2022 Dolthub, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// This file incorporates work covered by the following copyright and
16+
// permission notice:
17+
//
18+
// Copyright 2022 The Go Authors. All rights reserved.
19+
// Use of this source code is governed by a BSD-style
20+
// license that can be found in the LICENSE file.
21+
22+
//go:build go1.18 || go1.19
23+
// +build go1.18 go1.19
24+
25+
package maphash
26+
27+
import (
28+
"math/rand"
29+
"unsafe"
30+
)
31+
32+
type hashfn func(unsafe.Pointer, uintptr) uintptr
33+
34+
func getRuntimeHasher[K comparable]() (h hashfn) {
35+
a := any(make(map[K]struct{}))
36+
i := (*mapiface)(unsafe.Pointer(&a))
37+
h = i.typ.hasher
38+
return
39+
}
40+
41+
func newHashSeed() uintptr {
42+
return uintptr(rand.Int())
43+
}
44+
45+
// noescape hides a pointer from escape analysis. It is the identity function
46+
// but escape analysis doesn't think the output depends on the input.
47+
// noescape is inlined and currently compiles down to zero instructions.
48+
// USE CAREFULLY!
49+
// This was copied from the runtime (via pkg "strings"); see issues 23382 and 7921.
50+
//
51+
//go:nosplit
52+
//go:nocheckptr
53+
func noescape(p unsafe.Pointer) unsafe.Pointer {
54+
x := uintptr(p)
55+
return unsafe.Pointer(x ^ 0)
56+
}
57+
58+
type mapiface struct {
59+
typ *maptype
60+
val *hmap
61+
}
62+
63+
// go/src/runtime/type.go
64+
type maptype struct {
65+
typ _type
66+
key *_type
67+
elem *_type
68+
bucket *_type
69+
// function for hashing keys (ptr to key, seed) -> hash
70+
hasher func(unsafe.Pointer, uintptr) uintptr
71+
keysize uint8
72+
elemsize uint8
73+
bucketsize uint16
74+
flags uint32
75+
}
76+
77+
// go/src/runtime/map.go
78+
type hmap struct {
79+
count int
80+
flags uint8
81+
B uint8
82+
noverflow uint16
83+
// hash seed
84+
hash0 uint32
85+
buckets unsafe.Pointer
86+
oldbuckets unsafe.Pointer
87+
nevacuate uintptr
88+
// true type is *mapextra
89+
// but we don't need this data
90+
extra unsafe.Pointer
91+
}
92+
93+
// go/src/runtime/type.go
94+
type tflag uint8
95+
type nameOff int32
96+
type typeOff int32
97+
98+
// go/src/runtime/type.go
99+
type _type struct {
100+
size uintptr
101+
ptrdata uintptr
102+
hash uint32
103+
tflag tflag
104+
align uint8
105+
fieldAlign uint8
106+
kind uint8
107+
equal func(unsafe.Pointer, unsafe.Pointer) bool
108+
gcdata *byte
109+
str nameOff
110+
ptrToThis typeOff
111+
}

0 commit comments

Comments
 (0)