mirror of
https://github.com/golang/go.git
synced 2025-05-19 06:14:40 +00:00
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 <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
1a2ac46edd
commit
06a78b5737
@ -211,7 +211,7 @@ func runtimeTypes() []*types.Type {
|
|||||||
typs[58] = types.Types[TUNSAFEPTR]
|
typs[58] = types.Types[TUNSAFEPTR]
|
||||||
typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])})
|
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[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[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[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])})
|
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[60]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
|
||||||
|
@ -93,7 +93,7 @@ func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool)
|
|||||||
func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool)
|
func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool)
|
||||||
|
|
||||||
// *byte is really *runtime.Type
|
// *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(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_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||||
func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
|
func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||||
|
@ -1435,32 +1435,49 @@ opswitch:
|
|||||||
|
|
||||||
case OMAKEMAP:
|
case OMAKEMAP:
|
||||||
t := n.Type
|
t := n.Type
|
||||||
|
hmapType := hmap(t)
|
||||||
|
|
||||||
a := nodnil() // hmap buffer
|
// var h *hmap
|
||||||
r := nodnil() // bucket buffer
|
var h *Node
|
||||||
if n.Esc == EscNone {
|
if n.Esc == EscNone {
|
||||||
// Allocate hmap buffer on stack.
|
// Allocate hmap and one bucket on stack.
|
||||||
var_ := temp(hmap(t))
|
|
||||||
|
|
||||||
a = nod(OAS, var_, nil) // zero temp
|
// var hv hmap
|
||||||
a = typecheck(a, Etop)
|
hv := temp(hmapType)
|
||||||
init.Append(a)
|
zero := nod(OAS, hv, nil)
|
||||||
a = nod(OADDR, var_, 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
|
// Maximum key/value size is 128 bytes, larger objects
|
||||||
// are stored with an indirection. So max bucket size is 2048+eps.
|
// are stored with an indirection. So max bucket size is 2048+eps.
|
||||||
var_ = temp(mapbucket(t))
|
|
||||||
|
|
||||||
r = nod(OAS, var_, nil) // zero temp
|
// var bv bmap
|
||||||
r = typecheck(r, Etop)
|
bv := temp(mapbucket(t))
|
||||||
init.Append(r)
|
|
||||||
r = nod(OADDR, var_, nil)
|
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 := syslook("makemap")
|
||||||
fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Val())
|
fn = substArgTypes(fn, hmapType, t.Key(), t.Val())
|
||||||
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, types.Types[TINT64]), a, r)
|
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, types.Types[TINT64]), h)
|
||||||
|
|
||||||
case OMAKESLICE:
|
case OMAKESLICE:
|
||||||
l := n.Left
|
l := n.Left
|
||||||
|
@ -259,8 +259,8 @@ func (h *hmap) createOverflow() {
|
|||||||
// If the compiler has determined that the map or the first bucket
|
// 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.
|
// 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 h != nil, the map can be created directly in h.
|
||||||
// If bucket != nil, bucket can be used as the first bucket.
|
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
|
||||||
func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
|
func makemap(t *maptype, hint int64, h *hmap) *hmap {
|
||||||
if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != t.hmap.size {
|
if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != t.hmap.size {
|
||||||
println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size)
|
println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size)
|
||||||
throw("bad 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")
|
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
|
// initialize Hmap
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = (*hmap)(newobject(t.hmap))
|
h = (*hmap)(newobject(t.hmap))
|
||||||
}
|
}
|
||||||
h.B = B
|
|
||||||
h.extra = extra
|
|
||||||
h.hash0 = fastrand()
|
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
|
return h
|
||||||
}
|
}
|
||||||
@ -1171,7 +1168,7 @@ func ismapkey(t *_type) bool {
|
|||||||
|
|
||||||
//go:linkname reflect_makemap reflect.makemap
|
//go:linkname reflect_makemap reflect.makemap
|
||||||
func reflect_makemap(t *maptype, cap int) *hmap {
|
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
|
//go:linkname reflect_mapaccess reflect.mapaccess
|
||||||
|
Loading…
x
Reference in New Issue
Block a user