Skip to content

Commit

Permalink
cmd/compile: load map length with the right type
Browse files Browse the repository at this point in the history
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 <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
cherrymui committed Dec 22, 2024
1 parent 06b191e commit 500675a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 4 deletions.
13 changes: 9 additions & 4 deletions src/cmd/compile/internal/ssagen/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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 {
// return 0
// } else {
// // len
// return *((*int)n)
// // cap
// // len, the actual loadType depends
// return int(*((*loadType)n))
// // cap (chan only, not used for now)
// return *(((*int)n)+1)
// }
lenType := n.Type()
Expand Down Expand Up @@ -5485,7 +5488,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
case ir.OLEN:
if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() {
// 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 {
// length is stored in the first word for map/chan
s.vars[n] = s.load(lenType, x)
Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/maps/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ func h2(h uintptr) uintptr {
type Map struct {
// The number of filled slots (i.e. the number of elements in all
// tables). Excludes deleted slots.
// Must be first (known by the compiler, for len() builtin).
used uint64

// seed is the hash seed, computed as a unique random number per map.
Expand Down

0 comments on commit 500675a

Please sign in to comment.