diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index 269f054f0a..05836cc951 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -211,7 +211,7 @@ func runtimeTypes() []*types.Type { typs[58] = types.Types[TUNSAFEPTR] typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])}) typs[60] = types.NewMap(typs[2], typs[2]) - typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[60])}) + typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[60])}) typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index bb7a8a9c9e..f69459c549 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -93,7 +93,7 @@ func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool) func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool) // *byte is really *runtime.Type -func makemap(mapType *byte, hint int64, mapbuf *any, bucketbuf *any) (hmap map[any]any) +func makemap(mapType *byte, hint int64, mapbuf *any) (hmap map[any]any) func mapaccess1(mapType *byte, hmap map[any]any, key *any) (val *any) func mapaccess1_fast32(mapType *byte, hmap map[any]any, key any) (val *any) func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index ac9edca801..dea5893bea 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1435,32 +1435,49 @@ opswitch: case OMAKEMAP: t := n.Type + hmapType := hmap(t) - a := nodnil() // hmap buffer - r := nodnil() // bucket buffer + // var h *hmap + var h *Node if n.Esc == EscNone { - // Allocate hmap buffer on stack. - var_ := temp(hmap(t)) + // Allocate hmap and one bucket on stack. - a = nod(OAS, var_, nil) // zero temp - a = typecheck(a, Etop) - init.Append(a) - a = nod(OADDR, var_, nil) + // var hv hmap + hv := temp(hmapType) + zero := nod(OAS, hv, nil) + zero = typecheck(zero, Etop) + init.Append(zero) + // h = &hv + h = nod(OADDR, hv, nil) - // Allocate one bucket on stack. + // Allocate one bucket pointed to by hmap.buckets on stack. // Maximum key/value size is 128 bytes, larger objects // are stored with an indirection. So max bucket size is 2048+eps. - var_ = temp(mapbucket(t)) - r = nod(OAS, var_, nil) // zero temp - r = typecheck(r, Etop) - init.Append(r) - r = nod(OADDR, var_, nil) + // var bv bmap + bv := temp(mapbucket(t)) + + zero = nod(OAS, bv, nil) + zero = typecheck(zero, Etop) + init.Append(zero) + + // b = &bv + b := nod(OADDR, bv, nil) + + // h.buckets = b + bsym := hmapType.Field(5).Sym // hmap.buckets see reflect.go:hmap + na := nod(OAS, nodSym(ODOT, h, bsym), b) + na = typecheck(na, Etop) + init.Append(na) + + } else { + // h = nil + h = nodnil() } fn := syslook("makemap") - fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Val()) - n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, types.Types[TINT64]), a, r) + fn = substArgTypes(fn, hmapType, t.Key(), t.Val()) + n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, types.Types[TINT64]), h) case OMAKESLICE: l := n.Left diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index efb8a78024..852b65d1db 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -259,8 +259,8 @@ func (h *hmap) createOverflow() { // If the compiler has determined that the map or the first bucket // can be created on the stack, h and/or bucket may be non-nil. // If h != nil, the map can be created directly in h. -// If bucket != nil, bucket can be used as the first bucket. -func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap { +// If h.buckets != nil, bucket pointed to can be used as the first bucket. +func makemap(t *maptype, hint int64, h *hmap) *hmap { if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != t.hmap.size { println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size) throw("bad hmap size") @@ -312,33 +312,30 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap { throw("bad evacuatedN") } - // find size parameter which will hold the requested # of elements - B := uint8(0) - for ; overLoadFactor(hint, B); B++ { - } - - // allocate initial hash table - // if B == 0, the buckets field is allocated lazily later (in mapassign) - // If hint is large zeroing this memory could take a while. - buckets := bucket - var extra *mapextra - if B != 0 { - var nextOverflow *bmap - buckets, nextOverflow = makeBucketArray(t, B) - if nextOverflow != nil { - extra = new(mapextra) - extra.nextOverflow = nextOverflow - } - } - // initialize Hmap if h == nil { h = (*hmap)(newobject(t.hmap)) } - h.B = B - h.extra = extra h.hash0 = fastrand() - h.buckets = buckets + + // find size parameter which will hold the requested # of elements + B := uint8(0) + for overLoadFactor(hint, B) { + B++ + } + h.B = B + + // allocate initial hash table + // if B == 0, the buckets field is allocated lazily later (in mapassign) + // If hint is large zeroing this memory could take a while. + if h.B != 0 { + var nextOverflow *bmap + h.buckets, nextOverflow = makeBucketArray(t, h.B) + if nextOverflow != nil { + h.extra = new(mapextra) + h.extra.nextOverflow = nextOverflow + } + } return h } @@ -1171,7 +1168,7 @@ func ismapkey(t *_type) bool { //go:linkname reflect_makemap reflect.makemap func reflect_makemap(t *maptype, cap int) *hmap { - return makemap(t, int64(cap), nil, nil) + return makemap(t, int64(cap), nil) } //go:linkname reflect_mapaccess reflect.mapaccess