runtime: if key type is reflexive, don't call equal(k, k)

Most types are reflexive (k == k for all k of type t), so don't
bother calling equal(k, k) when the key type is reflexive.

Change-Id: Ia716b4198b8b298687843b94b878dbc5e8fc2c65
Reviewed-on: https://go-review.googlesource.com/1480
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Keith Randall 2014-12-12 13:45:19 -08:00
parent 324f38a222
commit df1739c77d
4 changed files with 81 additions and 3 deletions

View file

@ -345,6 +345,7 @@ type mapType struct {
valuesize uint8 // size of value slot
indirectvalue uint8 // store ptr to value instead of value itself
bucketsize uint16 // size of bucket
reflexivekey bool // true if k==k for all keys
}
// ptrType represents a pointer type.
@ -1489,6 +1490,7 @@ func MapOf(key, elem Type) Type {
mt.indirectvalue = 0
}
mt.bucketsize = uint16(mt.bucket.size)
mt.reflexivekey = isReflexive(ktyp)
mt.uncommonType = nil
mt.ptrToThis = nil
mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0])
@ -1496,6 +1498,31 @@ func MapOf(key, elem Type) Type {
return cachePut(ckey, &mt.rtype)
}
// isReflexive reports whether the == operation on the type is reflexive.
// That is, x == x for all values x of type t.
func isReflexive(t *rtype) bool {
switch t.Kind() {
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer:
return true
case Float32, Float64, Complex64, Complex128, Interface:
return false
case Array:
tt := (*arrayType)(unsafe.Pointer(t))
return isReflexive(tt.elem)
case Struct:
tt := (*structType)(unsafe.Pointer(t))
for _, f := range tt.fields {
if !isReflexive(f.typ) {
return false
}
}
return true
default:
// Func, Map, Slice, Invalid
panic("isReflexive called on non-key type " + t.String())
}
}
// gcProg is a helper type for generatation of GC pointer info.
type gcProg struct {
gc []byte