mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: on map update, don't overwrite key if we don't need to.
Keep track of which types of keys need an update and which don't. Strings need an update because the new key might pin a smaller backing store. Floats need an update because it might be +0/-0. Interfaces need an update because they may contain strings or floats. Fixes #11088 Change-Id: I9ade53c1dfb3c1a2870d68d07201bc8128e9f217 Reviewed-on: https://go-review.googlesource.com/10843 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
af7c9a42c1
commit
00c638d243
4 changed files with 86 additions and 6 deletions
|
|
@ -347,6 +347,7 @@ type mapType struct {
|
|||
indirectvalue uint8 // store ptr to value instead of value itself
|
||||
bucketsize uint16 // size of bucket
|
||||
reflexivekey bool // true if k==k for all keys
|
||||
needkeyupdate bool // true if we need to update key on an overwrite
|
||||
}
|
||||
|
||||
// ptrType represents a pointer type.
|
||||
|
|
@ -1525,6 +1526,7 @@ func MapOf(key, elem Type) Type {
|
|||
}
|
||||
mt.bucketsize = uint16(mt.bucket.size)
|
||||
mt.reflexivekey = isReflexive(ktyp)
|
||||
mt.needkeyupdate = needKeyUpdate(ktyp)
|
||||
mt.uncommonType = nil
|
||||
mt.ptrToThis = nil
|
||||
|
||||
|
|
@ -1669,6 +1671,33 @@ func isReflexive(t *rtype) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// needKeyUpdate reports whether map overwrites require the key to be copied.
|
||||
func needKeyUpdate(t *rtype) bool {
|
||||
switch t.Kind() {
|
||||
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer:
|
||||
return false
|
||||
case Float32, Float64, Complex64, Complex128, Interface, String:
|
||||
// Float keys can be updated from +0 to -0.
|
||||
// String keys can be updated to use a smaller backing store.
|
||||
// Interfaces might have floats of strings in them.
|
||||
return true
|
||||
case Array:
|
||||
tt := (*arrayType)(unsafe.Pointer(t))
|
||||
return needKeyUpdate(tt.elem)
|
||||
case Struct:
|
||||
tt := (*structType)(unsafe.Pointer(t))
|
||||
for _, f := range tt.fields {
|
||||
if needKeyUpdate(f.typ) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
// Func, Map, Slice, Invalid
|
||||
panic("needKeyUpdate called on non-key type " + t.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure these routines stay in sync with ../../runtime/hashmap.go!
|
||||
// These types exist only for GC, so we only fill out GC relevant info.
|
||||
// Currently, that's just size and the GC program. We also fill in string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue