Merge pull request #915 from visualfc/runtime.hash

[WIP] internal/runtime: type hash
This commit is contained in:
xushiwei
2024-12-26 08:30:34 +08:00
committed by GitHub
2 changed files with 122 additions and 10 deletions

View File

@@ -116,6 +116,7 @@ func NewNamed(pkgPath string, name string, kind abi.Kind, size uintptr, methods,
}
ret := allocUncommonType(kind, size, methods, abi.TFlagUninited|abi.TFlagNamed|abi.TFlagUncommon, pkgPath)
ret.Str_ = name
ret.Hash = 9157 + hashString(pkgPath) + hashString(name)
if ptrMethods == 0 {
ret.PtrToThis_ = newPointer(ret)
} else {
@@ -210,7 +211,6 @@ func Func(in, out []*Type, variadic bool) *FuncType {
Type: Type{
Size_: 2 * unsafe.Sizeof(uintptr(0)),
PtrBytes: 2 * pointerSize,
Hash: uint32(abi.Func), // TODO(xsw): hash
Align_: uint8(pointerAlign),
FieldAlign_: uint8(pointerAlign),
Kind_: uint8(abi.Func),
@@ -218,9 +218,13 @@ func Func(in, out []*Type, variadic bool) *FuncType {
In: in,
Out: out,
}
var hash uint32 = 9091
if variadic {
hash *= 8863
ret.TFlag |= abi.TFlagVariadic
}
hash += 3*hashTuple(in) + 5*hashTuple(out)
ret.Hash = hash
ret.Str_ = funcStr(ret)
rtypeList.addType(&ret.Type)
return ret
@@ -243,7 +247,7 @@ func NewNamedInterface(pkgPath, name string) *InterfaceType {
Type: Type{
Size_: unsafe.Sizeof(eface{}),
PtrBytes: 2 * pointerSize,
Hash: uint32(abi.Interface), // TODO(xsw): hash
Hash: 9157 + hashString(pkgPath) + hashString(name),
Align_: uint8(pointerAlign),
FieldAlign_: uint8(pointerAlign),
Kind_: uint8(abi.Interface),
@@ -277,7 +281,6 @@ func Interface(pkgPath string, methods []Imethod) *InterfaceType {
Type: Type{
Size_: unsafe.Sizeof(eface{}),
PtrBytes: 2 * pointerSize,
Hash: uint32(abi.Interface), // TODO(xsw): hash
Align_: uint8(pointerAlign),
FieldAlign_: uint8(pointerAlign),
Kind_: uint8(abi.Interface),
@@ -291,6 +294,14 @@ func Interface(pkgPath string, methods []Imethod) *InterfaceType {
ret.Equal = interequal
}
ret.Str_ = interfaceStr(ret)
var hash uint32 = 9103
// Hash methods.
for _, m := range methods {
// Use shallow hash on method signature to
// avoid anonymous interface cycles.
hash += 3*hashString(m.Name()) + 5*shallowHash(&m.Typ_.Type)
}
ret.Hash = hash
rtypeList.addType(&ret.Type)
return ret
}
@@ -537,4 +548,88 @@ func funcStr(ft *abi.FuncType) string {
return string(repr)
}
func hashTuple(tuple []*Type) uint32 {
// See go/types.identicalTypes for rationale.
n := len(tuple)
hash := 9137 + 2*uint32(n)
for i := 0; i < n; i++ {
hash += 3 * tuple[i].Hash
}
return hash
}
// shallowHash computes a hash of t without looking at any of its
// element Types, to avoid potential anonymous cycles in the types of
// interface methods.
//
// When an unnamed non-empty interface type appears anywhere among the
// arguments or results of an interface method, there is a potential
// for endless recursion. Consider:
//
// type X interface { m() []*interface { X } }
//
// The problem is that the Methods of the interface in m's result type
// include m itself; there is no mention of the named type X that
// might help us break the cycle.
// (See comment in go/types.identical, case *Interface, for more.)
func shallowHash(t *abi.Type) uint32 {
// t is the type of an interface method (Signature),
// its params or results (Tuples), or their immediate
// elements (mostly Slice, Pointer, Basic, Named),
// so there's no need to optimize anything else.
if t.HasName() {
return 9157 + hashString(t.Uncommon().PkgPath_) + hashString(t.Str_)
}
switch t.Kind() {
case abi.Bool, abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Int64,
abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uint64, abi.Uintptr,
abi.Float32, abi.Float64, abi.Complex64, abi.Complex128, abi.String, abi.UnsafePointer:
return 45212177 * uint32(t.Kind())
case abi.Func:
t := t.FuncType()
var hash uint32 = 604171
if t.Variadic() {
hash *= 971767
}
// The Signature/Tuple recursion is always finite
// and invariably shallow.
return hash + 1062599*shallowHashTuple(t.In) + 1282529*shallowHashTuple(t.Out)
case abi.Array:
return 1524181 + 2*uint32(t.ArrayType().Len)
case abi.Slice:
return 2690201
case abi.Struct:
return 3326489
case abi.Pointer:
return 4393139
case abi.Interface:
return 2124679 // no recursion here
case abi.Map:
return 9109
case abi.Chan:
return 9127
}
panic("shallowHash:" + t.String())
}
func shallowHashTuple(tuple []*Type) uint32 {
n := len(tuple)
hash := 9137 + 2*uint32(n)
for i := 0; i < n; i++ {
hash += 53471161 * shallowHash(tuple[i])
}
return hash
}
// -----------------------------------------------------------------------------