From 76684949a29ae8e4bdc93e3858fffab86b73b4ba Mon Sep 17 00:00:00 2001 From: qiulaidongfeng <2645477756@qq.com> Date: Sat, 31 Aug 2024 09:49:52 +0800 Subject: [PATCH] new Change-Id: Ic392ffab19c02982c8676f274932ba0d61cc54da --- src/hash/maphash/maphash.go | 4 +- src/hash/maphash/maphash_purego.go | 13 ++-- src/hash/maphash/maphash_runtime.go | 6 +- src/hash/maphash/maphash_test.go | 99 +++++++++++++++++++---------- 4 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/hash/maphash/maphash.go b/src/hash/maphash/maphash.go index d39678c0fb..38d6c3de23 100644 --- a/src/hash/maphash/maphash.go +++ b/src/hash/maphash/maphash.go @@ -286,7 +286,7 @@ func (h *Hash) BlockSize() int { return len(h.buf) } // If v contains a floating-point NaN, then the hash is non-deterministically random. func Comparable[T comparable](seed Seed, v T) uint64 { abi.Escape(v) - t := abi.TypeOf(v) + t := abi.TypeFor[T]() len := t.Size() if len == 0 { return seed.s @@ -297,7 +297,7 @@ func Comparable[T comparable](seed Seed, v T) uint64 { // WriteComparable adds x to the data hashed by h. func WriteComparable[T comparable](h *Hash, x T) { v := Comparable(h.seed, x) - var buf []byte + var buf [8]byte byteorder.LePutUint64(buf[:], v) h.Write(buf[:]) } diff --git a/src/hash/maphash/maphash_purego.go b/src/hash/maphash/maphash_purego.go index 8d059835f2..83d7bd5d51 100644 --- a/src/hash/maphash/maphash_purego.go +++ b/src/hash/maphash/maphash_purego.go @@ -95,17 +95,12 @@ func mix(a, b uint64) uint64 { return hi ^ lo } -var byteSliceTyp = reflect.TypeFor[[]byte]() - -var strSliceTyp = reflect.TypeFor[string]() +var strTyp = reflect.TypeFor[string]() func comparableF[T comparable](seed uint64, v T, t *abi.Type) uint64 { vv := reflect.ValueOf(v) typ := vv.Type() - if typ == byteSliceTyp { - return wyhash(vv.Bytes(), seed, uint64(vv.Len())) - } - if typ == strSliceTyp { + if typ == strTyp { return rthashString(vv.String(), seed) } buf := make([]byte, 0, typ.Size()) @@ -119,7 +114,7 @@ func appendT(buf []byte, v reflect.Value) []byte { return byteorder.LeAppendUint64(buf, uint64(v.Int())) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr: return byteorder.LeAppendUint64(buf, v.Uint()) - case reflect.Array, reflect.Slice: + case reflect.Array: for i := range v.Len() { buf = appendT(buf, v.Index(i)) } @@ -142,6 +137,8 @@ func appendT(buf []byte, v reflect.Value) []byte { case reflect.UnsafePointer, reflect.Pointer: return byteorder.LeAppendUint64(buf, uint64(v.Pointer())) case reflect.Interface: + // There is no need to check comparability here, + // because !purego also treats it as a piece of memory. a := v.InterfaceData() buf = byteorder.LeAppendUint64(buf, uint64(a[0])) return byteorder.LeAppendUint64(buf, uint64(a[1])) diff --git a/src/hash/maphash/maphash_runtime.go b/src/hash/maphash/maphash_runtime.go index 1e519acdba..2f1b75f140 100644 --- a/src/hash/maphash/maphash_runtime.go +++ b/src/hash/maphash/maphash_runtime.go @@ -48,11 +48,7 @@ func comparableF[T comparable](seed uint64, v T, t *abi.Type) uint64 { k := t.Kind() len := t.Size() ptr := unsafe.Pointer(&v) - switch k { - case abi.Slice: - len = uintptr(((*unsafeheader.Slice)(unsafe.Pointer(&v))).Len) * t.Elem().Size() - ptr = ((*unsafeheader.Slice)(unsafe.Pointer(&v))).Data - case abi.String: + if k == abi.String { len = uintptr(((*unsafeheader.String)(unsafe.Pointer(&v))).Len) ptr = ((*unsafeheader.String)(unsafe.Pointer(&v))).Data } diff --git a/src/hash/maphash/maphash_test.go b/src/hash/maphash/maphash_test.go index 214f968650..8428f9a711 100644 --- a/src/hash/maphash/maphash_test.go +++ b/src/hash/maphash/maphash_test.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "hash" + "reflect" "testing" ) @@ -210,19 +211,36 @@ func TestSeedFromReset(t *testing.T) { } } -func TestCompare(t *testing.T) { - var a, b int = 2, 2 - var pa *int = &a - seed := MakeSeed() - if Comparable(seed, a) != Comparable(seed, b) { - t.Fatal("Comparable(seed, 2) != Comparable(seed, 2)") - } - old := Comparable(seed, pa) - stackGrow(8192) - new := Comparable(seed, pa) - if old != new { - t.Fatal("Comparable(seed, ptr) != Comparable(seed, ptr)") - } +func TestComparable(t *testing.T) { + testComparable(t, int64(2)) + testComparable(t, uint64(8)) + testComparable(t, uintptr(12)) + testComparable(t, any("s")) + testComparable(t, "s") + testComparable(t, new(float64)) + testComparable(t, float64(9)) + testComparable(t, complex128(9i+1)) + testComparable(t, struct { + i int + f float64 + }{i: 9, f: 9.9}) +} + +func testComparable[T comparable](t *testing.T, v T) { + t.Run(reflect.TypeFor[T]().Name(), func(t *testing.T) { + var a, b T = v, v + var pa *T = &a + seed := MakeSeed() + if Comparable(seed, a) != Comparable(seed, b) { + t.Fatalf("Comparable(seed, %v) != Comparable(seed, %v)", a, b) + } + old := Comparable(seed, pa) + stackGrow(8192) + new := Comparable(seed, pa) + if old != new { + t.Fatal("Comparable(seed, ptr) != Comparable(seed, ptr)") + } + }) } //go:noinline @@ -236,25 +254,42 @@ func stackGrow(dep int) { } func TestWriteComparable(t *testing.T) { - var a, b int = 2, 2 - var pa *int = &a - h1 := Hash{} - h2 := Hash{} - h1.seed = MakeSeed() - h2.seed = h1.seed - WriteComparable(&h1, a) - WriteComparable(&h2, b) - if h1.Sum64() != h1.Sum64() { - t.Fatal("WriteComparable(h, 2) != WriteComparable(h, 2)") - } - WriteComparable(&h1, pa) - old := h1.Sum64() - stackGrow(8192) - WriteComparable(&h2, pa) - new := h2.Sum64() - if old != new { - t.Fatal("WriteComparable(seed, ptr) != WriteComparable(seed, ptr)") - } + testWriteComparable(t, int64(2)) + testWriteComparable(t, uint64(8)) + testWriteComparable(t, uintptr(12)) + testWriteComparable(t, any("s")) + testWriteComparable(t, "s") + testWriteComparable(t, new(float64)) + testWriteComparable(t, float64(9)) + testWriteComparable(t, complex128(9i+1)) + testWriteComparable(t, struct { + i int + f float64 + }{i: 9, f: 9.9}) +} + +func testWriteComparable[T comparable](t *testing.T, v T) { + t.Run(reflect.TypeFor[T]().Name(), func(t *testing.T) { + var a, b T = v, v + var pa *T = &a + h1 := Hash{} + h2 := Hash{} + h1.seed = MakeSeed() + h2.seed = h1.seed + WriteComparable(&h1, a) + WriteComparable(&h2, b) + if h1.Sum64() != h1.Sum64() { + t.Fatalf("WriteComparable(h, %v) != WriteComparable(h, %v)", a, b) + } + WriteComparable(&h1, pa) + old := h1.Sum64() + stackGrow(8192) + WriteComparable(&h2, pa) + new := h2.Sum64() + if old != new { + t.Fatal("WriteComparable(seed, ptr) != WriteComparable(seed, ptr)") + } + }) } // Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces.