case OMAKEMAP:
t := n.Type
hmapType := hmap(t)
+ hint := n.Left
// var h *hmap
var h *Node
if n.Esc == EscNone {
- // Allocate hmap and one bucket on stack.
+ // Allocate hmap on stack.
// var hv hmap
hv := temp(hmapType)
// h = &hv
h = nod(OADDR, hv, nil)
- // Allocate one bucket pointed to by hmap.buckets on stack.
- // Maximum key/value size is 128 bytes, larger objects
+ // Allocate one bucket pointed to by hmap.buckets on stack if hint
+ // is not larger than BUCKETSIZE. In case hint is larger than
+ // BUCKETSIZE runtime.makemap will allocate the buckets on the heap.
+ // Maximum key and value size is 128 bytes, larger objects
// are stored with an indirection. So max bucket size is 2048+eps.
+ if !Isconst(hint, CTINT) ||
+ !(hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) > 0) {
+ // var bv bmap
+ bv := temp(bmap(t))
- // var bv bmap
- bv := temp(bmap(t))
-
- zero = nod(OAS, bv, nil)
- zero = typecheck(zero, Etop)
- init.Append(zero)
+ 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)
+ // 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()
// When hint fits into int, use makemap instead of
// makemap64, which is faster and shorter on 32 bit platforms.
- hint := n.Left
fnname := "makemap64"
argtype := types.Types[TINT64]
func BenchmarkMapPop1000(b *testing.B) { benchmarkMapPop(b, 1000) }
func BenchmarkMapPop10000(b *testing.B) { benchmarkMapPop(b, 10000) }
+var testNonEscapingMapVariable int = 8
+
func TestNonEscapingMap(t *testing.T) {
n := testing.AllocsPerRun(1000, func() {
m := make(map[int]int)
m[0] = 0
})
if n != 0 {
- t.Fatalf("want 0 allocs, got %v", n)
+ t.Fatalf("no hint: want 0 allocs, got %v", n)
+ }
+ n = testing.AllocsPerRun(1000, func() {
+ m := make(map[int]int, 8)
+ m[0] = 0
+ })
+ if n != 0 {
+ t.Fatalf("with small hint: want 0 allocs, got %v", n)
}
+ n = testing.AllocsPerRun(1000, func() {
+ m := make(map[int]int, testNonEscapingMapVariable)
+ m[0] = 0
+ })
+ if n != 0 {
+ t.Fatalf("with variable hint: want 0 allocs, got %v", n)
+ }
+
}
func benchmarkMapAssignInt32(b *testing.B, n int) {