From: Martin Möhrmann Date: Wed, 16 Aug 2017 21:36:58 +0000 (+0200) Subject: cmd/compile: pass stack allocated bucket to makemap inside hmap X-Git-Tag: go1.10beta1~1427 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=06a78b57377ce63c7fca968af5056a3dec0a06bb;p=gostls13.git cmd/compile: pass stack allocated bucket to makemap inside hmap name old time/op new time/op delta NewEmptyMap 53.2ns ± 7% 48.0ns ± 5% -9.77% (p=0.000 n=20+20) NewSmallMap 111ns ± 1% 106ns ± 2% -3.78% (p=0.000 n=20+19) Change-Id: I979d21ab16eae9f6893873becca517db57e054b5 Reviewed-on: https://go-review.googlesource.com/56290 Run-TryBot: Martin Möhrmann TryBot-Result: Gobot Gobot Reviewed-by: Josh Bleecher Snyder --- 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,34 +312,31 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap { throw("bad evacuatedN") } + // initialize Hmap + if h == nil { + h = (*hmap)(newobject(t.hmap)) + } + h.hash0 = fastrand() + // find size parameter which will hold the requested # of elements B := uint8(0) - for ; overLoadFactor(hint, B); B++ { + 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. - buckets := bucket - var extra *mapextra - if B != 0 { + if h.B != 0 { var nextOverflow *bmap - buckets, nextOverflow = makeBucketArray(t, B) + h.buckets, nextOverflow = makeBucketArray(t, h.B) if nextOverflow != nil { - extra = new(mapextra) - extra.nextOverflow = nextOverflow + h.extra = new(mapextra) + h.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 - 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