1
0
mirror of https://github.com/golang/go synced 2024-11-26 14:56:47 -07:00

internal/runtime/maps: hash copy of key instead of key itself

Hashing the key means we have to take the address of it. That inhibits
subsequent optimizations on the key variable.

By hashing a copy, we incur an extra store at the hash callsite, but
we no longer need a load of the key in the inner loop. It can live
in a register throughout. (Technically, it gets spilled around
the call to the hasher, but it gets restored outside the loop.)

Maybe one day we can have special hash functions that take
int64/int32/string instead of *int64/*int32/*string.

Change-Id: Iba3133f6e82328f53c0abcb5eec13ee47c4969d1
Reviewed-on: https://go-review.googlesource.com/c/go/+/629419
Reviewed-by: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Keith Randall 2024-11-18 16:37:59 -08:00
parent c14fc500c7
commit d13e6d0b08
3 changed files with 22 additions and 11 deletions

View File

@ -48,7 +48,8 @@ func runtime_mapaccess1_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe
return unsafe.Pointer(&zeroVal[0])
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -116,7 +117,8 @@ func runtime_mapaccess2_fast32(typ *abi.SwissMapType, m *Map, key uint32) (unsaf
return unsafe.Pointer(&zeroVal[0]), false
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -203,7 +205,8 @@ func runtime_mapassign_fast32(typ *abi.SwissMapType, m *Map, key uint32) unsafe.
fatal("concurrent map writes")
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Set writing after calling Hasher, since Hasher may panic, in which
// case we have not actually done a write.
@ -336,7 +339,8 @@ func runtime_mapassign_fast32ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point
fatal("concurrent map writes")
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Set writing after calling Hasher, since Hasher may panic, in which
// case we have not actually done a write.

View File

@ -48,7 +48,8 @@ func runtime_mapaccess1_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe
return unsafe.Pointer(&zeroVal[0])
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -116,7 +117,8 @@ func runtime_mapaccess2_fast64(typ *abi.SwissMapType, m *Map, key uint64) (unsaf
return unsafe.Pointer(&zeroVal[0]), false
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -203,7 +205,8 @@ func runtime_mapassign_fast64(typ *abi.SwissMapType, m *Map, key uint64) unsafe.
fatal("concurrent map writes")
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Set writing after calling Hasher, since Hasher may panic, in which
// case we have not actually done a write.
@ -374,7 +377,8 @@ func runtime_mapassign_fast64ptr(typ *abi.SwissMapType, m *Map, key unsafe.Point
fatal("concurrent map writes")
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Set writing after calling Hasher, since Hasher may panic, in which
// case we have not actually done a write.

View File

@ -124,7 +124,8 @@ func runtime_mapaccess1_faststr(typ *abi.SwissMapType, m *Map, key string) unsaf
return elem
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -182,7 +183,8 @@ func runtime_mapaccess2_faststr(typ *abi.SwissMapType, m *Map, key string) (unsa
return elem, true
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Select table.
idx := m.directoryIndex(hash)
@ -271,7 +273,8 @@ func runtime_mapassign_faststr(typ *abi.SwissMapType, m *Map, key string) unsafe
fatal("concurrent map writes")
}
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&key)), m.seed)
k := key
hash := typ.Hasher(abi.NoEscape(unsafe.Pointer(&k)), m.seed)
// Set writing after calling Hasher, since Hasher may panic, in which
// case we have not actually done a write.