1
0
mirror of https://github.com/golang/go synced 2024-11-26 14:08:37 -07:00

cmd/compile: generate makemap calls with int arguments

Where possible generate calls to runtime makemap with int hint argument
during compile time instead of makemap with int64 hint argument.

This eliminates converting the hint argument for calls to makemap with
int64 hint argument for platforms where int64 values do not fit into
an argument of type int.

A similar optimization for makeslice was introduced in CL
golang.org/cl/27851.

386:
name         old time/op    new time/op    delta
NewEmptyMap    53.5ns ± 5%    41.9ns ± 5%  -21.56%  (p=0.000 n=10+10)
NewSmallMap     182ns ± 1%     165ns ± 1%   -8.92%  (p=0.000 n=10+10)

Change-Id: Ibd2b4c57b36f171b173bf7a0602b3a59771e6e44
Reviewed-on: https://go-review.googlesource.com/55142
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Martin Möhrmann 2017-08-14 10:16:21 +02:00
parent 0fb0f575bc
commit cbc4e5d9c4
6 changed files with 191 additions and 132 deletions

View File

@ -72,83 +72,84 @@ var runtimeDecls = [...]struct {
{"panicnildottype", funcTag, 55}, {"panicnildottype", funcTag, 55},
{"ifaceeq", funcTag, 58}, {"ifaceeq", funcTag, 58},
{"efaceeq", funcTag, 58}, {"efaceeq", funcTag, 58},
{"makemap", funcTag, 60}, {"makemap64", funcTag, 60},
{"mapaccess1", funcTag, 61}, {"makemap", funcTag, 61},
{"mapaccess1_fast32", funcTag, 62}, {"mapaccess1", funcTag, 62},
{"mapaccess1_fast64", funcTag, 62}, {"mapaccess1_fast32", funcTag, 63},
{"mapaccess1_faststr", funcTag, 62}, {"mapaccess1_fast64", funcTag, 63},
{"mapaccess1_fat", funcTag, 63}, {"mapaccess1_faststr", funcTag, 63},
{"mapaccess2", funcTag, 64}, {"mapaccess1_fat", funcTag, 64},
{"mapaccess2_fast32", funcTag, 65}, {"mapaccess2", funcTag, 65},
{"mapaccess2_fast64", funcTag, 65}, {"mapaccess2_fast32", funcTag, 66},
{"mapaccess2_faststr", funcTag, 65}, {"mapaccess2_fast64", funcTag, 66},
{"mapaccess2_fat", funcTag, 66}, {"mapaccess2_faststr", funcTag, 66},
{"mapassign", funcTag, 61}, {"mapaccess2_fat", funcTag, 67},
{"mapassign_fast32", funcTag, 62}, {"mapassign", funcTag, 62},
{"mapassign_fast64", funcTag, 62}, {"mapassign_fast32", funcTag, 63},
{"mapassign_faststr", funcTag, 62}, {"mapassign_fast64", funcTag, 63},
{"mapiterinit", funcTag, 67}, {"mapassign_faststr", funcTag, 63},
{"mapdelete", funcTag, 67}, {"mapiterinit", funcTag, 68},
{"mapdelete_fast32", funcTag, 68}, {"mapdelete", funcTag, 68},
{"mapdelete_fast64", funcTag, 68}, {"mapdelete_fast32", funcTag, 69},
{"mapdelete_faststr", funcTag, 68}, {"mapdelete_fast64", funcTag, 69},
{"mapiternext", funcTag, 69}, {"mapdelete_faststr", funcTag, 69},
{"makechan64", funcTag, 71}, {"mapiternext", funcTag, 70},
{"makechan", funcTag, 72}, {"makechan64", funcTag, 72},
{"chanrecv1", funcTag, 74}, {"makechan", funcTag, 73},
{"chanrecv2", funcTag, 75}, {"chanrecv1", funcTag, 75},
{"chansend1", funcTag, 77}, {"chanrecv2", funcTag, 76},
{"chansend1", funcTag, 78},
{"closechan", funcTag, 23}, {"closechan", funcTag, 23},
{"writeBarrier", varTag, 79}, {"writeBarrier", varTag, 80},
{"writebarrierptr", funcTag, 80}, {"writebarrierptr", funcTag, 81},
{"typedmemmove", funcTag, 81}, {"typedmemmove", funcTag, 82},
{"typedmemclr", funcTag, 82}, {"typedmemclr", funcTag, 83},
{"typedslicecopy", funcTag, 83}, {"typedslicecopy", funcTag, 84},
{"selectnbsend", funcTag, 84}, {"selectnbsend", funcTag, 85},
{"selectnbrecv", funcTag, 85}, {"selectnbrecv", funcTag, 86},
{"selectnbrecv2", funcTag, 87}, {"selectnbrecv2", funcTag, 88},
{"newselect", funcTag, 88}, {"newselect", funcTag, 89},
{"selectsend", funcTag, 89}, {"selectsend", funcTag, 90},
{"selectrecv", funcTag, 90}, {"selectrecv", funcTag, 91},
{"selectdefault", funcTag, 55}, {"selectdefault", funcTag, 55},
{"selectgo", funcTag, 91}, {"selectgo", funcTag, 92},
{"block", funcTag, 5}, {"block", funcTag, 5},
{"makeslice", funcTag, 93}, {"makeslice", funcTag, 94},
{"makeslice64", funcTag, 94}, {"makeslice64", funcTag, 95},
{"growslice", funcTag, 95}, {"growslice", funcTag, 96},
{"memmove", funcTag, 96}, {"memmove", funcTag, 97},
{"memclrNoHeapPointers", funcTag, 97}, {"memclrNoHeapPointers", funcTag, 98},
{"memclrHasPointers", funcTag, 97}, {"memclrHasPointers", funcTag, 98},
{"memequal", funcTag, 98}, {"memequal", funcTag, 99},
{"memequal8", funcTag, 99}, {"memequal8", funcTag, 100},
{"memequal16", funcTag, 99}, {"memequal16", funcTag, 100},
{"memequal32", funcTag, 99}, {"memequal32", funcTag, 100},
{"memequal64", funcTag, 99}, {"memequal64", funcTag, 100},
{"memequal128", funcTag, 99}, {"memequal128", funcTag, 100},
{"int64div", funcTag, 100}, {"int64div", funcTag, 101},
{"uint64div", funcTag, 101}, {"uint64div", funcTag, 102},
{"int64mod", funcTag, 100}, {"int64mod", funcTag, 101},
{"uint64mod", funcTag, 101}, {"uint64mod", funcTag, 102},
{"float64toint64", funcTag, 102}, {"float64toint64", funcTag, 103},
{"float64touint64", funcTag, 103}, {"float64touint64", funcTag, 104},
{"float64touint32", funcTag, 105}, {"float64touint32", funcTag, 106},
{"int64tofloat64", funcTag, 106}, {"int64tofloat64", funcTag, 107},
{"uint64tofloat64", funcTag, 107}, {"uint64tofloat64", funcTag, 108},
{"uint32tofloat64", funcTag, 108}, {"uint32tofloat64", funcTag, 109},
{"complex128div", funcTag, 109}, {"complex128div", funcTag, 110},
{"racefuncenter", funcTag, 110}, {"racefuncenter", funcTag, 111},
{"racefuncexit", funcTag, 5}, {"racefuncexit", funcTag, 5},
{"raceread", funcTag, 110}, {"raceread", funcTag, 111},
{"racewrite", funcTag, 110}, {"racewrite", funcTag, 111},
{"racereadrange", funcTag, 111}, {"racereadrange", funcTag, 112},
{"racewriterange", funcTag, 111}, {"racewriterange", funcTag, 112},
{"msanread", funcTag, 111}, {"msanread", funcTag, 112},
{"msanwrite", funcTag, 111}, {"msanwrite", funcTag, 112},
{"support_popcnt", varTag, 11}, {"support_popcnt", varTag, 11},
} }
func runtimeTypes() []*types.Type { func runtimeTypes() []*types.Type {
var typs [112]*types.Type var typs [113]*types.Type
typs[0] = types.Bytetype typs[0] = types.Bytetype
typs[1] = types.NewPtr(typs[0]) typs[1] = types.NewPtr(typs[0])
typs[2] = types.Types[TANY] typs[2] = types.Types[TANY]
@ -210,56 +211,57 @@ func runtimeTypes() []*types.Type {
typs[58] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[57]), anonfield(typs[57])}, []*Node{anonfield(typs[11])}) typs[58] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[57]), anonfield(typs[57])}, []*Node{anonfield(typs[11])})
typs[59] = types.NewMap(typs[2], typs[2]) typs[59] = types.NewMap(typs[2], typs[2])
typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[59])}) typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[59])})
typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[59])})
typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, nil) typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])})
typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, nil) typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, nil)
typs[69] = functype(nil, []*Node{anonfield(typs[3])}, nil) typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, nil)
typs[70] = types.NewChan(typs[2], types.Cboth) typs[70] = functype(nil, []*Node{anonfield(typs[3])}, nil)
typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[70])}) typs[71] = types.NewChan(typs[2], types.Cboth)
typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[70])}) typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[71])})
typs[73] = types.NewChan(typs[2], types.Crecv) typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[71])})
typs[74] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, nil) typs[74] = types.NewChan(typs[2], types.Crecv)
typs[75] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) typs[75] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, nil)
typs[76] = types.NewChan(typs[2], types.Csend) typs[76] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
typs[77] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, nil) typs[77] = types.NewChan(typs[2], types.Csend)
typs[78] = types.NewArray(typs[0], 3) typs[78] = functype(nil, []*Node{anonfield(typs[77]), anonfield(typs[3])}, nil)
typs[79] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[78]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])}) typs[79] = types.NewArray(typs[0], 3)
typs[80] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil) typs[80] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[79]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])})
typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) typs[81] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil)
typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])}) typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
typs[84] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) typs[84] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])})
typs[85] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[73])}, []*Node{anonfield(typs[11])}) typs[85] = functype(nil, []*Node{anonfield(typs[77]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
typs[86] = types.NewPtr(typs[11]) typs[86] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[74])}, []*Node{anonfield(typs[11])})
typs[87] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[86]), anonfield(typs[73])}, []*Node{anonfield(typs[11])}) typs[87] = types.NewPtr(typs[11])
typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil) typs[88] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[87]), anonfield(typs[74])}, []*Node{anonfield(typs[11])})
typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[76]), anonfield(typs[3])}, nil) typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil)
typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[73]), anonfield(typs[3]), anonfield(typs[86])}, nil) typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[77]), anonfield(typs[3])}, nil)
typs[91] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])}) typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3]), anonfield(typs[87])}, nil)
typs[92] = types.NewSlice(typs[2]) typs[92] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])})
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[92])}) typs[93] = types.NewSlice(typs[2])
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[92])}) typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[93])})
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[92]), anonfield(typs[32])}, []*Node{anonfield(typs[92])}) typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[93])})
typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, nil) typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[93]), anonfield(typs[32])}, []*Node{anonfield(typs[93])})
typs[97] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[48])}, nil) typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, nil)
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, []*Node{anonfield(typs[11])}) typs[98] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[48])}, nil)
typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, []*Node{anonfield(typs[11])})
typs[100] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])})
typs[101] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])}) typs[101] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
typs[102] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])}) typs[102] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])})
typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])}) typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])})
typs[104] = types.Types[TUINT32] typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])})
typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[104])}) typs[105] = types.Types[TUINT32]
typs[106] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])}) typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[105])})
typs[107] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])}) typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])})
typs[108] = functype(nil, []*Node{anonfield(typs[104])}, []*Node{anonfield(typs[13])}) typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])})
typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) typs[109] = functype(nil, []*Node{anonfield(typs[105])}, []*Node{anonfield(typs[13])})
typs[110] = functype(nil, []*Node{anonfield(typs[48])}, nil) typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
typs[111] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[48])}, nil) typs[111] = functype(nil, []*Node{anonfield(typs[48])}, nil)
typs[112] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[48])}, nil)
return typs[:] return typs[:]
} }

View File

@ -92,7 +92,8 @@ 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) (hmap map[any]any) func makemap64(mapType *byte, hint int64, mapbuf *any) (hmap map[any]any)
func makemap(mapType *byte, hint int, 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)

View File

@ -1484,9 +1484,24 @@ opswitch:
h = nodnil() h = nodnil()
} }
fn := syslook("makemap") // 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]
// Type checking guarantees that TIDEAL hint is positive and fits in an int.
// See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function.
// The case of hint overflow when converting TUINT or TUINTPTR to TINT
// will be handled by the negative range checks in makemap during runtime.
if hint.Type.IsKind(TIDEAL) || maxintval[hint.Type.Etype].Cmp(maxintval[TUINT]) <= 0 {
fnname = "makemap"
argtype = types.Types[TINT]
}
fn := syslook(fnname)
fn = substArgTypes(fn, hmapType, 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]), h) n = mkcall1(fn, n.Type, init, typename(n.Type), conv(hint, argtype), h)
case OMAKESLICE: case OMAKESLICE:
l := n.Left l := n.Left

View File

@ -255,18 +255,25 @@ func (h *hmap) createOverflow() {
} }
} }
func makemap64(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
if int64(int(hint)) != hint {
hint = 0
}
return makemap(t, int(hint), h)
}
// makemap implements a Go map creation make(map[k]v, hint) // makemap implements a Go map creation make(map[k]v, hint)
// 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 h.buckets != nil, bucket pointed to 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) *hmap { func makemap(t *maptype, hint int, 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")
} }
if hint < 0 || hint > int64(maxSliceCap(t.bucket.size)) { if hint < 0 || hint > int(maxSliceCap(t.bucket.size)) {
hint = 0 hint = 0
} }
@ -589,7 +596,7 @@ again:
// If we hit the max load factor or we have too many overflow buckets, // If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing. // and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) { if !h.growing() && (overLoadFactor(h.count, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h) hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again goto again // Growing the table invalidates everything, so try again
} }
@ -920,7 +927,7 @@ func hashGrow(t *maptype, h *hmap) {
// Otherwise, there are too many overflow buckets, // Otherwise, there are too many overflow buckets,
// so keep the same number of buckets and "grow" laterally. // so keep the same number of buckets and "grow" laterally.
bigger := uint8(1) bigger := uint8(1)
if !overLoadFactor(int64(h.count), h.B) { if !overLoadFactor(h.count, h.B) {
bigger = 0 bigger = 0
h.flags |= sameSizeGrow h.flags |= sameSizeGrow
} }
@ -959,7 +966,7 @@ func hashGrow(t *maptype, h *hmap) {
} }
// overLoadFactor reports whether count items placed in 1<<B buckets is over loadFactor. // overLoadFactor reports whether count items placed in 1<<B buckets is over loadFactor.
func overLoadFactor(count int64, B uint8) bool { func overLoadFactor(count int, B uint8) bool {
return count >= bucketCnt && uint64(count) >= loadFactorNum*((uint64(1)<<B)/loadFactorDen) return count >= bucketCnt && uint64(count) >= loadFactorNum*((uint64(1)<<B)/loadFactorDen)
} }
@ -1168,7 +1175,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) return makemap(t, cap, nil)
} }
//go:linkname reflect_mapaccess reflect.mapaccess //go:linkname reflect_mapaccess reflect.mapaccess

View File

@ -462,7 +462,7 @@ again:
// If we hit the max load factor or we have too many overflow buckets, // If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing. // and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) { if !h.growing() && (overLoadFactor(h.count, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h) hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again goto again // Growing the table invalidates everything, so try again
} }
@ -547,7 +547,7 @@ again:
// If we hit the max load factor or we have too many overflow buckets, // If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing. // and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) { if !h.growing() && (overLoadFactor(h.count, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h) hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again goto again // Growing the table invalidates everything, so try again
} }
@ -637,7 +637,7 @@ again:
// If we hit the max load factor or we have too many overflow buckets, // If we hit the max load factor or we have too many overflow buckets,
// and we're not already in the middle of growing, start growing. // and we're not already in the middle of growing, start growing.
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) { if !h.growing() && (overLoadFactor(h.count, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h) hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again goto again // Growing the table invalidates everything, so try again
} }

34
test/makemap.go Normal file
View File

@ -0,0 +1,34 @@
// errorcheck
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Ensure that typed non-integer, negative and too large
// values are not accepted as size argument in make for
// maps.
package main
type T map[int]int
var sink T
func main() {
sink = make(T, -1) // ERROR "negative size argument in make.*"
sink = make(T, uint64(1<<63)) // ERROR "size argument too large in make.*"
sink = make(T, 0.5) // ERROR "constant 0.5 truncated to integer"
sink = make(T, 1.0)
sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*"
sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*"
sink = make(T, 1.0)
sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*"
sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*"
sink = make(T, 1+0i)
sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*"
sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*"
sink = make(T, 1+0i)
sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*"
sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*"
}