]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: pass stack allocated bucket to makemap inside hmap
authorMartin Möhrmann <moehrmann@google.com>
Wed, 16 Aug 2017 21:36:58 +0000 (23:36 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Tue, 22 Aug 2017 06:01:59 +0000 (06:01 +0000)
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 <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/walk.go
src/runtime/hashmap.go

index 269f054f0a4381c9d119ad6f309da0cffb3e912f..05836cc951fde485415c4b9f31b2cb4004396893 100644 (file)
@@ -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])})
index bb7a8a9c9e7deeaf29fec90b1c17e14d75443da0..f69459c5490a5026de4a65c5d92898a937363d84 100644 (file)
@@ -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)
index ac9edca80130ecd6697e63d96a62af8b70a267ef..dea5893beae8f639bdfe2fc3f2474527c1ba42d7 100644 (file)
@@ -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
index efb8a780243b48d245af9d65d52174890ce9c969..852b65d1db8147bc7cbbc94ac73cdf72c81d45bf 100644 (file)
@@ -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