mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: load map length with the right type
len(map) is lowered to loading the first field of the map structure, which is the length. Currently it is a load of an int. With the old map, the first field is indeed an int. With Swiss map, however, it is a uint64. On big-endian 32-bit machine, loading an (32-bit) int from a uint64 would load just the high bits, which are (probably) all 0. Change to a load with the proper type. Fixes #70248. Change-Id: I39cf2d1e6658dac5a8de25c858e1580e2a14b894 Reviewed-on: https://go-review.googlesource.com/c/go/+/638375 Run-TryBot: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
06b191e11f
commit
500675a7c8
2 changed files with 10 additions and 4 deletions
|
|
@ -5452,12 +5452,15 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
|
||||||
if n.X.Type().IsChan() && n.Op() == ir.OCAP {
|
if n.X.Type().IsChan() && n.Op() == ir.OCAP {
|
||||||
s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now
|
s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now
|
||||||
}
|
}
|
||||||
|
if n.X.Type().IsMap() && n.Op() == ir.OCAP {
|
||||||
|
s.Fatalf("cannot inline cap(map)") // cap(map) does not exist
|
||||||
|
}
|
||||||
// if n == nil {
|
// if n == nil {
|
||||||
// return 0
|
// return 0
|
||||||
// } else {
|
// } else {
|
||||||
// // len
|
// // len, the actual loadType depends
|
||||||
// return *((*int)n)
|
// return int(*((*loadType)n))
|
||||||
// // cap
|
// // cap (chan only, not used for now)
|
||||||
// return *(((*int)n)+1)
|
// return *(((*int)n)+1)
|
||||||
// }
|
// }
|
||||||
lenType := n.Type()
|
lenType := n.Type()
|
||||||
|
|
@ -5485,7 +5488,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
|
||||||
case ir.OLEN:
|
case ir.OLEN:
|
||||||
if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() {
|
if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() {
|
||||||
// length is stored in the first word.
|
// length is stored in the first word.
|
||||||
s.vars[n] = s.load(lenType, x)
|
loadType := reflectdata.SwissMapType().Field(0).Type // uint64
|
||||||
|
load := s.load(loadType, x)
|
||||||
|
s.vars[n] = s.conv(nil, load, loadType, lenType) // integer conversion doesn't need Node
|
||||||
} else {
|
} else {
|
||||||
// length is stored in the first word for map/chan
|
// length is stored in the first word for map/chan
|
||||||
s.vars[n] = s.load(lenType, x)
|
s.vars[n] = s.load(lenType, x)
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ func h2(h uintptr) uintptr {
|
||||||
type Map struct {
|
type Map struct {
|
||||||
// The number of filled slots (i.e. the number of elements in all
|
// The number of filled slots (i.e. the number of elements in all
|
||||||
// tables). Excludes deleted slots.
|
// tables). Excludes deleted slots.
|
||||||
|
// Must be first (known by the compiler, for len() builtin).
|
||||||
used uint64
|
used uint64
|
||||||
|
|
||||||
// seed is the hash seed, computed as a unique random number per map.
|
// seed is the hash seed, computed as a unique random number per map.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue