From cbc4e5d9c4f2444c5d40ae6333b4e1f4c9cfbd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 14 Aug 2017 10:16:21 +0200 Subject: [PATCH] cmd/compile: generate makemap calls with int arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/cmd/compile/internal/gc/builtin.go | 242 +++++++++--------- .../compile/internal/gc/builtin/runtime.go | 3 +- src/cmd/compile/internal/gc/walk.go | 19 +- src/runtime/hashmap.go | 19 +- src/runtime/hashmap_fast.go | 6 +- test/makemap.go | 34 +++ 6 files changed, 191 insertions(+), 132 deletions(-) create mode 100644 test/makemap.go diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index fb3fdf90df9..79e1a51a4be 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -72,83 +72,84 @@ var runtimeDecls = [...]struct { {"panicnildottype", funcTag, 55}, {"ifaceeq", funcTag, 58}, {"efaceeq", funcTag, 58}, - {"makemap", funcTag, 60}, - {"mapaccess1", funcTag, 61}, - {"mapaccess1_fast32", funcTag, 62}, - {"mapaccess1_fast64", funcTag, 62}, - {"mapaccess1_faststr", funcTag, 62}, - {"mapaccess1_fat", funcTag, 63}, - {"mapaccess2", funcTag, 64}, - {"mapaccess2_fast32", funcTag, 65}, - {"mapaccess2_fast64", funcTag, 65}, - {"mapaccess2_faststr", funcTag, 65}, - {"mapaccess2_fat", funcTag, 66}, - {"mapassign", funcTag, 61}, - {"mapassign_fast32", funcTag, 62}, - {"mapassign_fast64", funcTag, 62}, - {"mapassign_faststr", funcTag, 62}, - {"mapiterinit", funcTag, 67}, - {"mapdelete", funcTag, 67}, - {"mapdelete_fast32", funcTag, 68}, - {"mapdelete_fast64", funcTag, 68}, - {"mapdelete_faststr", funcTag, 68}, - {"mapiternext", funcTag, 69}, - {"makechan64", funcTag, 71}, - {"makechan", funcTag, 72}, - {"chanrecv1", funcTag, 74}, - {"chanrecv2", funcTag, 75}, - {"chansend1", funcTag, 77}, + {"makemap64", funcTag, 60}, + {"makemap", funcTag, 61}, + {"mapaccess1", funcTag, 62}, + {"mapaccess1_fast32", funcTag, 63}, + {"mapaccess1_fast64", funcTag, 63}, + {"mapaccess1_faststr", funcTag, 63}, + {"mapaccess1_fat", funcTag, 64}, + {"mapaccess2", funcTag, 65}, + {"mapaccess2_fast32", funcTag, 66}, + {"mapaccess2_fast64", funcTag, 66}, + {"mapaccess2_faststr", funcTag, 66}, + {"mapaccess2_fat", funcTag, 67}, + {"mapassign", funcTag, 62}, + {"mapassign_fast32", funcTag, 63}, + {"mapassign_fast64", funcTag, 63}, + {"mapassign_faststr", funcTag, 63}, + {"mapiterinit", funcTag, 68}, + {"mapdelete", funcTag, 68}, + {"mapdelete_fast32", funcTag, 69}, + {"mapdelete_fast64", funcTag, 69}, + {"mapdelete_faststr", funcTag, 69}, + {"mapiternext", funcTag, 70}, + {"makechan64", funcTag, 72}, + {"makechan", funcTag, 73}, + {"chanrecv1", funcTag, 75}, + {"chanrecv2", funcTag, 76}, + {"chansend1", funcTag, 78}, {"closechan", funcTag, 23}, - {"writeBarrier", varTag, 79}, - {"writebarrierptr", funcTag, 80}, - {"typedmemmove", funcTag, 81}, - {"typedmemclr", funcTag, 82}, - {"typedslicecopy", funcTag, 83}, - {"selectnbsend", funcTag, 84}, - {"selectnbrecv", funcTag, 85}, - {"selectnbrecv2", funcTag, 87}, - {"newselect", funcTag, 88}, - {"selectsend", funcTag, 89}, - {"selectrecv", funcTag, 90}, + {"writeBarrier", varTag, 80}, + {"writebarrierptr", funcTag, 81}, + {"typedmemmove", funcTag, 82}, + {"typedmemclr", funcTag, 83}, + {"typedslicecopy", funcTag, 84}, + {"selectnbsend", funcTag, 85}, + {"selectnbrecv", funcTag, 86}, + {"selectnbrecv2", funcTag, 88}, + {"newselect", funcTag, 89}, + {"selectsend", funcTag, 90}, + {"selectrecv", funcTag, 91}, {"selectdefault", funcTag, 55}, - {"selectgo", funcTag, 91}, + {"selectgo", funcTag, 92}, {"block", funcTag, 5}, - {"makeslice", funcTag, 93}, - {"makeslice64", funcTag, 94}, - {"growslice", funcTag, 95}, - {"memmove", funcTag, 96}, - {"memclrNoHeapPointers", funcTag, 97}, - {"memclrHasPointers", funcTag, 97}, - {"memequal", funcTag, 98}, - {"memequal8", funcTag, 99}, - {"memequal16", funcTag, 99}, - {"memequal32", funcTag, 99}, - {"memequal64", funcTag, 99}, - {"memequal128", funcTag, 99}, - {"int64div", funcTag, 100}, - {"uint64div", funcTag, 101}, - {"int64mod", funcTag, 100}, - {"uint64mod", funcTag, 101}, - {"float64toint64", funcTag, 102}, - {"float64touint64", funcTag, 103}, - {"float64touint32", funcTag, 105}, - {"int64tofloat64", funcTag, 106}, - {"uint64tofloat64", funcTag, 107}, - {"uint32tofloat64", funcTag, 108}, - {"complex128div", funcTag, 109}, - {"racefuncenter", funcTag, 110}, + {"makeslice", funcTag, 94}, + {"makeslice64", funcTag, 95}, + {"growslice", funcTag, 96}, + {"memmove", funcTag, 97}, + {"memclrNoHeapPointers", funcTag, 98}, + {"memclrHasPointers", funcTag, 98}, + {"memequal", funcTag, 99}, + {"memequal8", funcTag, 100}, + {"memequal16", funcTag, 100}, + {"memequal32", funcTag, 100}, + {"memequal64", funcTag, 100}, + {"memequal128", funcTag, 100}, + {"int64div", funcTag, 101}, + {"uint64div", funcTag, 102}, + {"int64mod", funcTag, 101}, + {"uint64mod", funcTag, 102}, + {"float64toint64", funcTag, 103}, + {"float64touint64", funcTag, 104}, + {"float64touint32", funcTag, 106}, + {"int64tofloat64", funcTag, 107}, + {"uint64tofloat64", funcTag, 108}, + {"uint32tofloat64", funcTag, 109}, + {"complex128div", funcTag, 110}, + {"racefuncenter", funcTag, 111}, {"racefuncexit", funcTag, 5}, - {"raceread", funcTag, 110}, - {"racewrite", funcTag, 110}, - {"racereadrange", funcTag, 111}, - {"racewriterange", funcTag, 111}, - {"msanread", funcTag, 111}, - {"msanwrite", funcTag, 111}, + {"raceread", funcTag, 111}, + {"racewrite", funcTag, 111}, + {"racereadrange", funcTag, 112}, + {"racewriterange", funcTag, 112}, + {"msanread", funcTag, 112}, + {"msanwrite", funcTag, 112}, {"support_popcnt", varTag, 11}, } func runtimeTypes() []*types.Type { - var typs [112]*types.Type + var typs [113]*types.Type typs[0] = types.Bytetype typs[1] = types.NewPtr(typs[0]) 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[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[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) - typs[62] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*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[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) - typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, []*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[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[3])}, nil) - typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, nil) - typs[69] = functype(nil, []*Node{anonfield(typs[3])}, nil) - typs[70] = types.NewChan(typs[2], types.Cboth) - typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[70])}) - typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[70])}) - typs[73] = types.NewChan(typs[2], types.Crecv) - typs[74] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, nil) - typs[75] = functype(nil, []*Node{anonfield(typs[73]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[76] = types.NewChan(typs[2], types.Csend) - typs[77] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, nil) - typs[78] = types.NewArray(typs[0], 3) - 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[80] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[2])}, nil) - typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) - typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) - typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])}) - typs[84] = functype(nil, []*Node{anonfield(typs[76]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[85] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[73])}, []*Node{anonfield(typs[11])}) - typs[86] = types.NewPtr(typs[11]) - typs[87] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[86]), anonfield(typs[73])}, []*Node{anonfield(typs[11])}) - typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[8])}, nil) - typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[76]), anonfield(typs[3])}, nil) - typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[73]), anonfield(typs[3]), anonfield(typs[86])}, nil) - typs[91] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])}) - typs[92] = types.NewSlice(typs[2]) - typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[92])}) - typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[92])}) - typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[92]), anonfield(typs[32])}, []*Node{anonfield(typs[92])}) - typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, nil) - typs[97] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[48])}, nil) - typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[48])}, []*Node{anonfield(typs[11])}) - typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[100] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) - typs[101] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])}) - typs[102] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])}) - typs[103] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])}) - typs[104] = types.Types[TUINT32] - typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[104])}) - typs[106] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])}) - typs[107] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])}) - typs[108] = functype(nil, []*Node{anonfield(typs[104])}, []*Node{anonfield(typs[13])}) - typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) - typs[110] = functype(nil, []*Node{anonfield(typs[48])}, nil) - typs[111] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[48])}, nil) + 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[3])}, []*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]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) + 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[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) + 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[3])}, nil) + typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[59]), anonfield(typs[2])}, nil) + typs[70] = functype(nil, []*Node{anonfield(typs[3])}, nil) + typs[71] = types.NewChan(typs[2], types.Cboth) + typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[71])}) + typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[71])}) + typs[74] = types.NewChan(typs[2], types.Crecv) + typs[75] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, nil) + typs[76] = functype(nil, []*Node{anonfield(typs[74]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[77] = types.NewChan(typs[2], types.Csend) + typs[78] = functype(nil, []*Node{anonfield(typs[77]), anonfield(typs[3])}, nil) + typs[79] = types.NewArray(typs[0], 3) + 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[3]), anonfield(typs[2])}, 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[3])}, nil) + 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[77]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[86] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[74])}, []*Node{anonfield(typs[11])}) + typs[87] = types.NewPtr(typs[11]) + 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[15]), anonfield(typs[8])}, nil) + typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[77]), anonfield(typs[3])}, nil) + typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[74]), anonfield(typs[3]), anonfield(typs[87])}, nil) + typs[92] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[32])}) + typs[93] = types.NewSlice(typs[2]) + 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[15]), anonfield(typs[15])}, []*Node{anonfield(typs[93])}) + 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[3]), anonfield(typs[3]), anonfield(typs[48])}, nil) + typs[98] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[48])}, nil) + 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[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[101] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*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[15])}) + typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])}) + typs[105] = types.Types[TUINT32] + typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[105])}) + typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])}) + typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])}) + typs[109] = functype(nil, []*Node{anonfield(typs[105])}, []*Node{anonfield(typs[13])}) + typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) + typs[111] = functype(nil, []*Node{anonfield(typs[48])}, nil) + typs[112] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[48])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index 6313b1a44c0..1fb42e72231 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -92,7 +92,8 @@ 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) (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_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 3ed4bc3edd3..83c82a6a843 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1484,9 +1484,24 @@ opswitch: 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()) - 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: l := n.Left diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index 852b65d1db8..d4d02388dbc 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -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) // 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 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 { println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.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 } @@ -589,7 +596,7 @@ again: // 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. - 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) 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, // so keep the same number of buckets and "grow" laterally. bigger := uint8(1) - if !overLoadFactor(int64(h.count), h.B) { + if !overLoadFactor(h.count, h.B) { bigger = 0 h.flags |= sameSizeGrow } @@ -959,7 +966,7 @@ func hashGrow(t *maptype, h *hmap) { } // overLoadFactor reports whether count items placed in 1<= bucketCnt && uint64(count) >= loadFactorNum*((uint64(1)<