]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimize make+copy pattern to avoid memclr
authorMartin Möhrmann <moehrmann@google.com>
Tue, 23 Oct 2018 11:50:07 +0000 (13:50 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Thu, 7 May 2020 17:50:24 +0000 (17:50 +0000)
match:
 m = make([]T, x); copy(m, s)
for pointer free T and x==len(s) rewrite to:
 m = mallocgc(x*elemsize(T), nil, false); memmove(&m, &s, x*elemsize(T))
otherwise rewrite to:
 m = makeslicecopy([]T, x, s)

This avoids memclear and shading of pointers in the newly created slice
before the copy.

With this CL "s" is only be allowed to bev a variable and not a more
complex expression. This restriction could be lifted in future versions
of this optimization when it can be proven that "s" is not referencing "m".

Triggers 450 times during make.bash..
Reduces go binary size by ~8 kbyte.

name                           old time/op  new time/op  delta
MakeSliceCopy/mallocmove/Byte  71.1ns ± 1%  65.8ns ± 0%  -7.49%  (p=0.000 n=10+9)
MakeSliceCopy/mallocmove/Int   71.2ns ± 1%  66.0ns ± 0%  -7.27%  (p=0.000 n=10+8)
MakeSliceCopy/mallocmove/Ptr    104ns ± 4%    99ns ± 1%  -5.13%  (p=0.000 n=10+10)
MakeSliceCopy/makecopy/Byte    70.3ns ± 0%  68.0ns ± 0%  -3.22%  (p=0.000 n=10+9)
MakeSliceCopy/makecopy/Int     70.3ns ± 0%  68.5ns ± 1%  -2.59%  (p=0.000 n=9+10)
MakeSliceCopy/makecopy/Ptr      102ns ± 0%    99ns ± 1%  -2.97%  (p=0.000 n=9+9)
MakeSliceCopy/nilappend/Byte   75.4ns ± 0%  74.9ns ± 2%  -0.63%  (p=0.015 n=9+9)
MakeSliceCopy/nilappend/Int    75.6ns ± 0%  76.4ns ± 3%    ~     (p=0.245 n=9+10)
MakeSliceCopy/nilappend/Ptr     107ns ± 0%   108ns ± 1%  +0.93%  (p=0.005 n=9+10)

Fixes #26252

Change-Id: Iec553dd1fef6ded16197216a472351c8799a8e71
Reviewed-on: https://go-review.googlesource.com/c/go/+/146719
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

12 files changed:
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/op_string.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go
src/runtime/slice.go
src/runtime/slice_test.go
test/codegen/slices.go
test/makeslice.go [new file with mode: 0644]

index c2525395b064f980c781914cc0b9fd88027be683..2cf2f4687eb5f192e7448ddc283c31d4c973f17c 100644 (file)
@@ -10,325 +10,329 @@ var runtimeDecls = [...]struct {
        typ  int
 }{
        {"newobject", funcTag, 4},
-       {"panicdivide", funcTag, 5},
-       {"panicshift", funcTag, 5},
-       {"panicmakeslicelen", funcTag, 5},
-       {"panicmakeslicecap", funcTag, 5},
-       {"throwinit", funcTag, 5},
-       {"panicwrap", funcTag, 5},
-       {"gopanic", funcTag, 7},
-       {"gorecover", funcTag, 10},
-       {"goschedguarded", funcTag, 5},
-       {"goPanicIndex", funcTag, 12},
-       {"goPanicIndexU", funcTag, 14},
-       {"goPanicSliceAlen", funcTag, 12},
-       {"goPanicSliceAlenU", funcTag, 14},
-       {"goPanicSliceAcap", funcTag, 12},
-       {"goPanicSliceAcapU", funcTag, 14},
-       {"goPanicSliceB", funcTag, 12},
-       {"goPanicSliceBU", funcTag, 14},
-       {"goPanicSlice3Alen", funcTag, 12},
-       {"goPanicSlice3AlenU", funcTag, 14},
-       {"goPanicSlice3Acap", funcTag, 12},
-       {"goPanicSlice3AcapU", funcTag, 14},
-       {"goPanicSlice3B", funcTag, 12},
-       {"goPanicSlice3BU", funcTag, 14},
-       {"goPanicSlice3C", funcTag, 12},
-       {"goPanicSlice3CU", funcTag, 14},
-       {"printbool", funcTag, 16},
-       {"printfloat", funcTag, 18},
-       {"printint", funcTag, 20},
-       {"printhex", funcTag, 22},
-       {"printuint", funcTag, 22},
-       {"printcomplex", funcTag, 24},
-       {"printstring", funcTag, 26},
-       {"printpointer", funcTag, 27},
-       {"printiface", funcTag, 27},
-       {"printeface", funcTag, 27},
-       {"printslice", funcTag, 27},
-       {"printnl", funcTag, 5},
-       {"printsp", funcTag, 5},
-       {"printlock", funcTag, 5},
-       {"printunlock", funcTag, 5},
-       {"concatstring2", funcTag, 30},
-       {"concatstring3", funcTag, 31},
-       {"concatstring4", funcTag, 32},
-       {"concatstring5", funcTag, 33},
-       {"concatstrings", funcTag, 35},
-       {"cmpstring", funcTag, 36},
-       {"intstring", funcTag, 39},
-       {"slicebytetostring", funcTag, 40},
-       {"slicebytetostringtmp", funcTag, 41},
-       {"slicerunetostring", funcTag, 44},
-       {"stringtoslicebyte", funcTag, 46},
-       {"stringtoslicerune", funcTag, 49},
-       {"slicecopy", funcTag, 51},
-       {"slicestringcopy", funcTag, 52},
-       {"decoderune", funcTag, 53},
-       {"countrunes", funcTag, 54},
-       {"convI2I", funcTag, 55},
-       {"convT16", funcTag, 57},
-       {"convT32", funcTag, 57},
-       {"convT64", funcTag, 57},
-       {"convTstring", funcTag, 57},
-       {"convTslice", funcTag, 57},
-       {"convT2E", funcTag, 58},
-       {"convT2Enoptr", funcTag, 58},
-       {"convT2I", funcTag, 58},
-       {"convT2Inoptr", funcTag, 58},
-       {"assertE2I", funcTag, 55},
-       {"assertE2I2", funcTag, 59},
-       {"assertI2I", funcTag, 55},
-       {"assertI2I2", funcTag, 59},
-       {"panicdottypeE", funcTag, 60},
-       {"panicdottypeI", funcTag, 60},
-       {"panicnildottype", funcTag, 61},
-       {"ifaceeq", funcTag, 63},
-       {"efaceeq", funcTag, 63},
-       {"fastrand", funcTag, 65},
-       {"makemap64", funcTag, 67},
-       {"makemap", funcTag, 68},
-       {"makemap_small", funcTag, 69},
-       {"mapaccess1", funcTag, 70},
-       {"mapaccess1_fast32", funcTag, 71},
-       {"mapaccess1_fast64", funcTag, 71},
-       {"mapaccess1_faststr", funcTag, 71},
-       {"mapaccess1_fat", funcTag, 72},
-       {"mapaccess2", funcTag, 73},
-       {"mapaccess2_fast32", funcTag, 74},
-       {"mapaccess2_fast64", funcTag, 74},
-       {"mapaccess2_faststr", funcTag, 74},
-       {"mapaccess2_fat", funcTag, 75},
-       {"mapassign", funcTag, 70},
-       {"mapassign_fast32", funcTag, 71},
-       {"mapassign_fast32ptr", funcTag, 71},
-       {"mapassign_fast64", funcTag, 71},
-       {"mapassign_fast64ptr", funcTag, 71},
-       {"mapassign_faststr", funcTag, 71},
-       {"mapiterinit", funcTag, 76},
-       {"mapdelete", funcTag, 76},
-       {"mapdelete_fast32", funcTag, 77},
-       {"mapdelete_fast64", funcTag, 77},
-       {"mapdelete_faststr", funcTag, 77},
-       {"mapiternext", funcTag, 78},
-       {"mapclear", funcTag, 79},
-       {"makechan64", funcTag, 81},
-       {"makechan", funcTag, 82},
-       {"chanrecv1", funcTag, 84},
-       {"chanrecv2", funcTag, 85},
-       {"chansend1", funcTag, 87},
-       {"closechan", funcTag, 27},
-       {"writeBarrier", varTag, 89},
-       {"typedmemmove", funcTag, 90},
-       {"typedmemclr", funcTag, 91},
-       {"typedslicecopy", funcTag, 92},
-       {"selectnbsend", funcTag, 93},
-       {"selectnbrecv", funcTag, 94},
-       {"selectnbrecv2", funcTag, 96},
-       {"selectsetpc", funcTag, 61},
-       {"selectgo", funcTag, 97},
-       {"block", funcTag, 5},
-       {"makeslice", funcTag, 98},
-       {"makeslice64", funcTag, 99},
-       {"growslice", funcTag, 101},
-       {"memmove", funcTag, 102},
-       {"memclrNoHeapPointers", funcTag, 103},
-       {"memclrHasPointers", funcTag, 103},
-       {"memequal", funcTag, 104},
-       {"memequal0", funcTag, 105},
-       {"memequal8", funcTag, 105},
-       {"memequal16", funcTag, 105},
-       {"memequal32", funcTag, 105},
-       {"memequal64", funcTag, 105},
-       {"memequal128", funcTag, 105},
-       {"f32equal", funcTag, 106},
-       {"f64equal", funcTag, 106},
-       {"c64equal", funcTag, 106},
-       {"c128equal", funcTag, 106},
-       {"strequal", funcTag, 106},
-       {"interequal", funcTag, 106},
-       {"nilinterequal", funcTag, 106},
-       {"memhash", funcTag, 107},
-       {"memhash0", funcTag, 108},
-       {"memhash8", funcTag, 108},
-       {"memhash16", funcTag, 108},
-       {"memhash32", funcTag, 108},
-       {"memhash64", funcTag, 108},
-       {"memhash128", funcTag, 108},
-       {"f32hash", funcTag, 108},
-       {"f64hash", funcTag, 108},
-       {"c64hash", funcTag, 108},
-       {"c128hash", funcTag, 108},
-       {"strhash", funcTag, 108},
-       {"interhash", funcTag, 108},
-       {"nilinterhash", funcTag, 108},
-       {"int64div", funcTag, 109},
-       {"uint64div", funcTag, 110},
-       {"int64mod", funcTag, 109},
-       {"uint64mod", funcTag, 110},
-       {"float64toint64", funcTag, 111},
-       {"float64touint64", funcTag, 112},
-       {"float64touint32", funcTag, 113},
-       {"int64tofloat64", funcTag, 114},
-       {"uint64tofloat64", funcTag, 115},
-       {"uint32tofloat64", funcTag, 116},
-       {"complex128div", funcTag, 117},
-       {"racefuncenter", funcTag, 118},
-       {"racefuncenterfp", funcTag, 5},
-       {"racefuncexit", funcTag, 5},
-       {"raceread", funcTag, 118},
-       {"racewrite", funcTag, 118},
-       {"racereadrange", funcTag, 119},
-       {"racewriterange", funcTag, 119},
-       {"msanread", funcTag, 119},
-       {"msanwrite", funcTag, 119},
-       {"checkptrAlignment", funcTag, 120},
-       {"checkptrArithmetic", funcTag, 122},
-       {"libfuzzerTraceCmp1", funcTag, 124},
-       {"libfuzzerTraceCmp2", funcTag, 126},
-       {"libfuzzerTraceCmp4", funcTag, 127},
-       {"libfuzzerTraceCmp8", funcTag, 128},
-       {"libfuzzerTraceConstCmp1", funcTag, 124},
-       {"libfuzzerTraceConstCmp2", funcTag, 126},
-       {"libfuzzerTraceConstCmp4", funcTag, 127},
-       {"libfuzzerTraceConstCmp8", funcTag, 128},
-       {"x86HasPOPCNT", varTag, 15},
-       {"x86HasSSE41", varTag, 15},
-       {"x86HasFMA", varTag, 15},
-       {"armHasVFPv4", varTag, 15},
-       {"arm64HasATOMICS", varTag, 15},
+       {"mallocgc", funcTag, 8},
+       {"panicdivide", funcTag, 9},
+       {"panicshift", funcTag, 9},
+       {"panicmakeslicelen", funcTag, 9},
+       {"panicmakeslicecap", funcTag, 9},
+       {"throwinit", funcTag, 9},
+       {"panicwrap", funcTag, 9},
+       {"gopanic", funcTag, 11},
+       {"gorecover", funcTag, 14},
+       {"goschedguarded", funcTag, 9},
+       {"goPanicIndex", funcTag, 16},
+       {"goPanicIndexU", funcTag, 18},
+       {"goPanicSliceAlen", funcTag, 16},
+       {"goPanicSliceAlenU", funcTag, 18},
+       {"goPanicSliceAcap", funcTag, 16},
+       {"goPanicSliceAcapU", funcTag, 18},
+       {"goPanicSliceB", funcTag, 16},
+       {"goPanicSliceBU", funcTag, 18},
+       {"goPanicSlice3Alen", funcTag, 16},
+       {"goPanicSlice3AlenU", funcTag, 18},
+       {"goPanicSlice3Acap", funcTag, 16},
+       {"goPanicSlice3AcapU", funcTag, 18},
+       {"goPanicSlice3B", funcTag, 16},
+       {"goPanicSlice3BU", funcTag, 18},
+       {"goPanicSlice3C", funcTag, 16},
+       {"goPanicSlice3CU", funcTag, 18},
+       {"printbool", funcTag, 19},
+       {"printfloat", funcTag, 21},
+       {"printint", funcTag, 23},
+       {"printhex", funcTag, 25},
+       {"printuint", funcTag, 25},
+       {"printcomplex", funcTag, 27},
+       {"printstring", funcTag, 29},
+       {"printpointer", funcTag, 30},
+       {"printiface", funcTag, 30},
+       {"printeface", funcTag, 30},
+       {"printslice", funcTag, 30},
+       {"printnl", funcTag, 9},
+       {"printsp", funcTag, 9},
+       {"printlock", funcTag, 9},
+       {"printunlock", funcTag, 9},
+       {"concatstring2", funcTag, 33},
+       {"concatstring3", funcTag, 34},
+       {"concatstring4", funcTag, 35},
+       {"concatstring5", funcTag, 36},
+       {"concatstrings", funcTag, 38},
+       {"cmpstring", funcTag, 39},
+       {"intstring", funcTag, 42},
+       {"slicebytetostring", funcTag, 43},
+       {"slicebytetostringtmp", funcTag, 44},
+       {"slicerunetostring", funcTag, 47},
+       {"stringtoslicebyte", funcTag, 49},
+       {"stringtoslicerune", funcTag, 52},
+       {"slicecopy", funcTag, 53},
+       {"slicestringcopy", funcTag, 54},
+       {"decoderune", funcTag, 55},
+       {"countrunes", funcTag, 56},
+       {"convI2I", funcTag, 57},
+       {"convT16", funcTag, 58},
+       {"convT32", funcTag, 58},
+       {"convT64", funcTag, 58},
+       {"convTstring", funcTag, 58},
+       {"convTslice", funcTag, 58},
+       {"convT2E", funcTag, 59},
+       {"convT2Enoptr", funcTag, 59},
+       {"convT2I", funcTag, 59},
+       {"convT2Inoptr", funcTag, 59},
+       {"assertE2I", funcTag, 57},
+       {"assertE2I2", funcTag, 60},
+       {"assertI2I", funcTag, 57},
+       {"assertI2I2", funcTag, 60},
+       {"panicdottypeE", funcTag, 61},
+       {"panicdottypeI", funcTag, 61},
+       {"panicnildottype", funcTag, 62},
+       {"ifaceeq", funcTag, 64},
+       {"efaceeq", funcTag, 64},
+       {"fastrand", funcTag, 66},
+       {"makemap64", funcTag, 68},
+       {"makemap", funcTag, 69},
+       {"makemap_small", funcTag, 70},
+       {"mapaccess1", funcTag, 71},
+       {"mapaccess1_fast32", funcTag, 72},
+       {"mapaccess1_fast64", funcTag, 72},
+       {"mapaccess1_faststr", funcTag, 72},
+       {"mapaccess1_fat", funcTag, 73},
+       {"mapaccess2", funcTag, 74},
+       {"mapaccess2_fast32", funcTag, 75},
+       {"mapaccess2_fast64", funcTag, 75},
+       {"mapaccess2_faststr", funcTag, 75},
+       {"mapaccess2_fat", funcTag, 76},
+       {"mapassign", funcTag, 71},
+       {"mapassign_fast32", funcTag, 72},
+       {"mapassign_fast32ptr", funcTag, 72},
+       {"mapassign_fast64", funcTag, 72},
+       {"mapassign_fast64ptr", funcTag, 72},
+       {"mapassign_faststr", funcTag, 72},
+       {"mapiterinit", funcTag, 77},
+       {"mapdelete", funcTag, 77},
+       {"mapdelete_fast32", funcTag, 78},
+       {"mapdelete_fast64", funcTag, 78},
+       {"mapdelete_faststr", funcTag, 78},
+       {"mapiternext", funcTag, 79},
+       {"mapclear", funcTag, 80},
+       {"makechan64", funcTag, 82},
+       {"makechan", funcTag, 83},
+       {"chanrecv1", funcTag, 85},
+       {"chanrecv2", funcTag, 86},
+       {"chansend1", funcTag, 88},
+       {"closechan", funcTag, 30},
+       {"writeBarrier", varTag, 90},
+       {"typedmemmove", funcTag, 91},
+       {"typedmemclr", funcTag, 92},
+       {"typedslicecopy", funcTag, 93},
+       {"selectnbsend", funcTag, 94},
+       {"selectnbrecv", funcTag, 95},
+       {"selectnbrecv2", funcTag, 97},
+       {"selectsetpc", funcTag, 62},
+       {"selectgo", funcTag, 98},
+       {"block", funcTag, 9},
+       {"makeslice", funcTag, 99},
+       {"makeslice64", funcTag, 100},
+       {"makeslicecopy", funcTag, 101},
+       {"growslice", funcTag, 103},
+       {"memmove", funcTag, 104},
+       {"memclrNoHeapPointers", funcTag, 105},
+       {"memclrHasPointers", funcTag, 105},
+       {"memequal", funcTag, 106},
+       {"memequal0", funcTag, 107},
+       {"memequal8", funcTag, 107},
+       {"memequal16", funcTag, 107},
+       {"memequal32", funcTag, 107},
+       {"memequal64", funcTag, 107},
+       {"memequal128", funcTag, 107},
+       {"f32equal", funcTag, 108},
+       {"f64equal", funcTag, 108},
+       {"c64equal", funcTag, 108},
+       {"c128equal", funcTag, 108},
+       {"strequal", funcTag, 108},
+       {"interequal", funcTag, 108},
+       {"nilinterequal", funcTag, 108},
+       {"memhash", funcTag, 109},
+       {"memhash0", funcTag, 110},
+       {"memhash8", funcTag, 110},
+       {"memhash16", funcTag, 110},
+       {"memhash32", funcTag, 110},
+       {"memhash64", funcTag, 110},
+       {"memhash128", funcTag, 110},
+       {"f32hash", funcTag, 110},
+       {"f64hash", funcTag, 110},
+       {"c64hash", funcTag, 110},
+       {"c128hash", funcTag, 110},
+       {"strhash", funcTag, 110},
+       {"interhash", funcTag, 110},
+       {"nilinterhash", funcTag, 110},
+       {"int64div", funcTag, 111},
+       {"uint64div", funcTag, 112},
+       {"int64mod", funcTag, 111},
+       {"uint64mod", funcTag, 112},
+       {"float64toint64", funcTag, 113},
+       {"float64touint64", funcTag, 114},
+       {"float64touint32", funcTag, 115},
+       {"int64tofloat64", funcTag, 116},
+       {"uint64tofloat64", funcTag, 117},
+       {"uint32tofloat64", funcTag, 118},
+       {"complex128div", funcTag, 119},
+       {"racefuncenter", funcTag, 120},
+       {"racefuncenterfp", funcTag, 9},
+       {"racefuncexit", funcTag, 9},
+       {"raceread", funcTag, 120},
+       {"racewrite", funcTag, 120},
+       {"racereadrange", funcTag, 121},
+       {"racewriterange", funcTag, 121},
+       {"msanread", funcTag, 121},
+       {"msanwrite", funcTag, 121},
+       {"checkptrAlignment", funcTag, 122},
+       {"checkptrArithmetic", funcTag, 124},
+       {"libfuzzerTraceCmp1", funcTag, 126},
+       {"libfuzzerTraceCmp2", funcTag, 128},
+       {"libfuzzerTraceCmp4", funcTag, 129},
+       {"libfuzzerTraceCmp8", funcTag, 130},
+       {"libfuzzerTraceConstCmp1", funcTag, 126},
+       {"libfuzzerTraceConstCmp2", funcTag, 128},
+       {"libfuzzerTraceConstCmp4", funcTag, 129},
+       {"libfuzzerTraceConstCmp8", funcTag, 130},
+       {"x86HasPOPCNT", varTag, 6},
+       {"x86HasSSE41", varTag, 6},
+       {"x86HasFMA", varTag, 6},
+       {"armHasVFPv4", varTag, 6},
+       {"arm64HasATOMICS", varTag, 6},
 }
 
 func runtimeTypes() []*types.Type {
-       var typs [129]*types.Type
+       var typs [131]*types.Type
        typs[0] = types.Bytetype
        typs[1] = types.NewPtr(typs[0])
        typs[2] = types.Types[TANY]
        typs[3] = types.NewPtr(typs[2])
        typs[4] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[3])})
-       typs[5] = functype(nil, nil, nil)
-       typs[6] = types.Types[TINTER]
-       typs[7] = functype(nil, []*Node{anonfield(typs[6])}, nil)
-       typs[8] = types.Types[TINT32]
-       typs[9] = types.NewPtr(typs[8])
-       typs[10] = functype(nil, []*Node{anonfield(typs[9])}, []*Node{anonfield(typs[6])})
-       typs[11] = types.Types[TINT]
-       typs[12] = functype(nil, []*Node{anonfield(typs[11]), anonfield(typs[11])}, nil)
-       typs[13] = types.Types[TUINT]
-       typs[14] = functype(nil, []*Node{anonfield(typs[13]), anonfield(typs[11])}, nil)
-       typs[15] = types.Types[TBOOL]
-       typs[16] = functype(nil, []*Node{anonfield(typs[15])}, nil)
-       typs[17] = types.Types[TFLOAT64]
-       typs[18] = functype(nil, []*Node{anonfield(typs[17])}, nil)
-       typs[19] = types.Types[TINT64]
-       typs[20] = functype(nil, []*Node{anonfield(typs[19])}, nil)
-       typs[21] = types.Types[TUINT64]
-       typs[22] = functype(nil, []*Node{anonfield(typs[21])}, nil)
-       typs[23] = types.Types[TCOMPLEX128]
-       typs[24] = functype(nil, []*Node{anonfield(typs[23])}, nil)
-       typs[25] = types.Types[TSTRING]
-       typs[26] = functype(nil, []*Node{anonfield(typs[25])}, nil)
-       typs[27] = functype(nil, []*Node{anonfield(typs[2])}, nil)
-       typs[28] = types.NewArray(typs[0], 32)
-       typs[29] = types.NewPtr(typs[28])
-       typs[30] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
-       typs[31] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
-       typs[32] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
-       typs[33] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
-       typs[34] = types.NewSlice(typs[25])
-       typs[35] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[34])}, []*Node{anonfield(typs[25])})
-       typs[36] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[11])})
-       typs[37] = types.NewArray(typs[0], 4)
-       typs[38] = types.NewPtr(typs[37])
-       typs[39] = functype(nil, []*Node{anonfield(typs[38]), anonfield(typs[19])}, []*Node{anonfield(typs[25])})
-       typs[40] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[25])})
-       typs[41] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[25])})
-       typs[42] = types.Runetype
-       typs[43] = types.NewSlice(typs[42])
-       typs[44] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[43])}, []*Node{anonfield(typs[25])})
-       typs[45] = types.NewSlice(typs[0])
-       typs[46] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25])}, []*Node{anonfield(typs[45])})
-       typs[47] = types.NewArray(typs[42], 32)
-       typs[48] = types.NewPtr(typs[47])
-       typs[49] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[25])}, []*Node{anonfield(typs[43])})
-       typs[50] = types.Types[TUINTPTR]
-       typs[51] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[50])}, []*Node{anonfield(typs[11])})
-       typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[25])}, []*Node{anonfield(typs[11])})
-       typs[53] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[11])}, []*Node{anonfield(typs[42]), anonfield(typs[11])})
-       typs[54] = functype(nil, []*Node{anonfield(typs[25])}, []*Node{anonfield(typs[11])})
-       typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
-       typs[56] = types.Types[TUNSAFEPTR]
-       typs[57] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[56])})
-       typs[58] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
-       typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[15])})
-       typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
-       typs[61] = functype(nil, []*Node{anonfield(typs[1])}, nil)
-       typs[62] = types.NewPtr(typs[50])
-       typs[63] = functype(nil, []*Node{anonfield(typs[62]), anonfield(typs[56]), anonfield(typs[56])}, []*Node{anonfield(typs[15])})
-       typs[64] = types.Types[TUINT32]
-       typs[65] = functype(nil, nil, []*Node{anonfield(typs[64])})
-       typs[66] = types.NewMap(typs[2], typs[2])
-       typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
-       typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
-       typs[69] = functype(nil, nil, []*Node{anonfield(typs[66])})
-       typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
-       typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
-       typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
-       typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
-       typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
-       typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
-       typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, nil)
-       typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, nil)
-       typs[78] = functype(nil, []*Node{anonfield(typs[3])}, nil)
-       typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66])}, nil)
-       typs[80] = types.NewChan(typs[2], types.Cboth)
-       typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19])}, []*Node{anonfield(typs[80])})
-       typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[80])})
-       typs[83] = types.NewChan(typs[2], types.Crecv)
-       typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil)
-       typs[85] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
-       typs[86] = types.NewChan(typs[2], types.Csend)
-       typs[87] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, nil)
-       typs[88] = types.NewArray(typs[0], 3)
-       typs[89] = tostruct([]*Node{namedfield("enabled", typs[15]), namedfield("pad", typs[88]), namedfield("needed", typs[15]), namedfield("cgo", typs[15]), namedfield("alignme", typs[21])})
-       typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
-       typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
-       typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[3]), anonfield(typs[11])}, []*Node{anonfield(typs[11])})
-       typs[93] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
-       typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[83])}, []*Node{anonfield(typs[15])})
-       typs[95] = types.NewPtr(typs[15])
-       typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[95]), anonfield(typs[83])}, []*Node{anonfield(typs[15])})
-       typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[11]), anonfield(typs[15])})
-       typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[11])}, []*Node{anonfield(typs[56])})
-       typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[56])})
-       typs[100] = types.NewSlice(typs[2])
-       typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[100]), anonfield(typs[11])}, []*Node{anonfield(typs[100])})
-       typs[102] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, nil)
-       typs[103] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50])}, nil)
-       typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, []*Node{anonfield(typs[15])})
-       typs[105] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
-       typs[106] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[56])}, []*Node{anonfield(typs[15])})
-       typs[107] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50]), anonfield(typs[50])}, []*Node{anonfield(typs[50])})
-       typs[108] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50])}, []*Node{anonfield(typs[50])})
-       typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
-       typs[110] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[21])})
-       typs[111] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[19])})
-       typs[112] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[21])})
-       typs[113] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[64])})
-       typs[114] = functype(nil, []*Node{anonfield(typs[19])}, []*Node{anonfield(typs[17])})
-       typs[115] = functype(nil, []*Node{anonfield(typs[21])}, []*Node{anonfield(typs[17])})
-       typs[116] = functype(nil, []*Node{anonfield(typs[64])}, []*Node{anonfield(typs[17])})
-       typs[117] = functype(nil, []*Node{anonfield(typs[23]), anonfield(typs[23])}, []*Node{anonfield(typs[23])})
-       typs[118] = functype(nil, []*Node{anonfield(typs[50])}, nil)
-       typs[119] = functype(nil, []*Node{anonfield(typs[50]), anonfield(typs[50])}, nil)
-       typs[120] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[1]), anonfield(typs[50])}, nil)
-       typs[121] = types.NewSlice(typs[56])
-       typs[122] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[121])}, nil)
-       typs[123] = types.Types[TUINT8]
-       typs[124] = functype(nil, []*Node{anonfield(typs[123]), anonfield(typs[123])}, nil)
-       typs[125] = types.Types[TUINT16]
+       typs[5] = types.Types[TUINTPTR]
+       typs[6] = types.Types[TBOOL]
+       typs[7] = types.Types[TUNSAFEPTR]
+       typs[8] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*Node{anonfield(typs[7])})
+       typs[9] = functype(nil, nil, nil)
+       typs[10] = types.Types[TINTER]
+       typs[11] = functype(nil, []*Node{anonfield(typs[10])}, nil)
+       typs[12] = types.Types[TINT32]
+       typs[13] = types.NewPtr(typs[12])
+       typs[14] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[10])})
+       typs[15] = types.Types[TINT]
+       typs[16] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, nil)
+       typs[17] = types.Types[TUINT]
+       typs[18] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[15])}, nil)
+       typs[19] = functype(nil, []*Node{anonfield(typs[6])}, nil)
+       typs[20] = types.Types[TFLOAT64]
+       typs[21] = functype(nil, []*Node{anonfield(typs[20])}, nil)
+       typs[22] = types.Types[TINT64]
+       typs[23] = functype(nil, []*Node{anonfield(typs[22])}, nil)
+       typs[24] = types.Types[TUINT64]
+       typs[25] = functype(nil, []*Node{anonfield(typs[24])}, nil)
+       typs[26] = types.Types[TCOMPLEX128]
+       typs[27] = functype(nil, []*Node{anonfield(typs[26])}, nil)
+       typs[28] = types.Types[TSTRING]
+       typs[29] = functype(nil, []*Node{anonfield(typs[28])}, nil)
+       typs[30] = functype(nil, []*Node{anonfield(typs[2])}, nil)
+       typs[31] = types.NewArray(typs[0], 32)
+       typs[32] = types.NewPtr(typs[31])
+       typs[33] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+       typs[34] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+       typs[35] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+       typs[36] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+       typs[37] = types.NewSlice(typs[28])
+       typs[38] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[37])}, []*Node{anonfield(typs[28])})
+       typs[39] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+       typs[40] = types.NewArray(typs[0], 4)
+       typs[41] = types.NewPtr(typs[40])
+       typs[42] = functype(nil, []*Node{anonfield(typs[41]), anonfield(typs[22])}, []*Node{anonfield(typs[28])})
+       typs[43] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])})
+       typs[44] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])})
+       typs[45] = types.Runetype
+       typs[46] = types.NewSlice(typs[45])
+       typs[47] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[46])}, []*Node{anonfield(typs[28])})
+       typs[48] = types.NewSlice(typs[0])
+       typs[49] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28])}, []*Node{anonfield(typs[48])})
+       typs[50] = types.NewArray(typs[45], 32)
+       typs[51] = types.NewPtr(typs[50])
+       typs[52] = functype(nil, []*Node{anonfield(typs[51]), anonfield(typs[28])}, []*Node{anonfield(typs[46])})
+       typs[53] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*Node{anonfield(typs[15])})
+       typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+       typs[55] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])})
+       typs[56] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+       typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
+       typs[58] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])})
+       typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
+       typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])})
+       typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
+       typs[62] = functype(nil, []*Node{anonfield(typs[1])}, nil)
+       typs[63] = types.NewPtr(typs[5])
+       typs[64] = functype(nil, []*Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+       typs[65] = types.Types[TUINT32]
+       typs[66] = functype(nil, nil, []*Node{anonfield(typs[65])})
+       typs[67] = types.NewMap(typs[2], typs[2])
+       typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
+       typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
+       typs[70] = functype(nil, nil, []*Node{anonfield(typs[67])})
+       typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
+       typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
+       typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
+       typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+       typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+       typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+       typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil)
+       typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil)
+       typs[79] = functype(nil, []*Node{anonfield(typs[3])}, nil)
+       typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67])}, nil)
+       typs[81] = types.NewChan(typs[2], types.Cboth)
+       typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[81])})
+       typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[81])})
+       typs[84] = types.NewChan(typs[2], types.Crecv)
+       typs[85] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, nil)
+       typs[86] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+       typs[87] = types.NewChan(typs[2], types.Csend)
+       typs[88] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, nil)
+       typs[89] = types.NewArray(typs[0], 3)
+       typs[90] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
+       typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+       typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
+       typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
+       typs[94] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+       typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
+       typs[96] = types.NewPtr(typs[6])
+       typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
+       typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[15]), anonfield(typs[6])})
+       typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])})
+       typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])})
+       typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])})
+       typs[102] = types.NewSlice(typs[2])
+       typs[103] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[102]), anonfield(typs[15])}, []*Node{anonfield(typs[102])})
+       typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
+       typs[105] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil)
+       typs[106] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])})
+       typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+       typs[108] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+       typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+       typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+       typs[111] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])})
+       typs[112] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])})
+       typs[113] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])})
+       typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])})
+       typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[65])})
+       typs[116] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])})
+       typs[117] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])})
+       typs[118] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])})
+       typs[119] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])})
+       typs[120] = functype(nil, []*Node{anonfield(typs[5])}, nil)
+       typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil)
+       typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
+       typs[123] = types.NewSlice(typs[7])
+       typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil)
+       typs[125] = types.Types[TUINT8]
        typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil)
-       typs[127] = functype(nil, []*Node{anonfield(typs[64]), anonfield(typs[64])}, nil)
-       typs[128] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, nil)
+       typs[127] = types.Types[TUINT16]
+       typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil)
+       typs[129] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil)
+       typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil)
        return typs[:]
 }
index 3475d4c375babb153168fb08076ecb14a9c27ff4..00448272c5b502d6b8cbf35957bb653376b62f40 100644 (file)
@@ -15,6 +15,7 @@ package runtime
 import "unsafe"
 
 func newobject(typ *byte) *any
+func mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer
 func panicdivide()
 func panicshift()
 func panicmakeslicelen()
@@ -174,6 +175,7 @@ func block()
 
 func makeslice(typ *byte, len int, cap int) unsafe.Pointer
 func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
+func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
 func growslice(typ *byte, old []any, cap int) (ary []any)
 func memmove(to *any, frm *any, length uintptr)
 func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
index 63a58d0a066f6790142ee22648f9b7bfb804c4ae..d6cc9fa4cf3a3897d297c86c64ff17c88ba1dd52 100644 (file)
@@ -1165,92 +1165,93 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
 }
 
 var opprec = []int{
-       OALIGNOF:     8,
-       OAPPEND:      8,
-       OBYTES2STR:   8,
-       OARRAYLIT:    8,
-       OSLICELIT:    8,
-       ORUNES2STR:   8,
-       OCALLFUNC:    8,
-       OCALLINTER:   8,
-       OCALLMETH:    8,
-       OCALL:        8,
-       OCAP:         8,
-       OCLOSE:       8,
-       OCONVIFACE:   8,
-       OCONVNOP:     8,
-       OCONV:        8,
-       OCOPY:        8,
-       ODELETE:      8,
-       OGETG:        8,
-       OLEN:         8,
-       OLITERAL:     8,
-       OMAKESLICE:   8,
-       OMAKE:        8,
-       OMAPLIT:      8,
-       ONAME:        8,
-       ONEW:         8,
-       ONONAME:      8,
-       OOFFSETOF:    8,
-       OPACK:        8,
-       OPANIC:       8,
-       OPAREN:       8,
-       OPRINTN:      8,
-       OPRINT:       8,
-       ORUNESTR:     8,
-       OSIZEOF:      8,
-       OSTR2BYTES:   8,
-       OSTR2RUNES:   8,
-       OSTRUCTLIT:   8,
-       OTARRAY:      8,
-       OTCHAN:       8,
-       OTFUNC:       8,
-       OTINTER:      8,
-       OTMAP:        8,
-       OTSTRUCT:     8,
-       OINDEXMAP:    8,
-       OINDEX:       8,
-       OSLICE:       8,
-       OSLICESTR:    8,
-       OSLICEARR:    8,
-       OSLICE3:      8,
-       OSLICE3ARR:   8,
-       OSLICEHEADER: 8,
-       ODOTINTER:    8,
-       ODOTMETH:     8,
-       ODOTPTR:      8,
-       ODOTTYPE2:    8,
-       ODOTTYPE:     8,
-       ODOT:         8,
-       OXDOT:        8,
-       OCALLPART:    8,
-       OPLUS:        7,
-       ONOT:         7,
-       OBITNOT:      7,
-       ONEG:         7,
-       OADDR:        7,
-       ODEREF:       7,
-       ORECV:        7,
-       OMUL:         6,
-       ODIV:         6,
-       OMOD:         6,
-       OLSH:         6,
-       ORSH:         6,
-       OAND:         6,
-       OANDNOT:      6,
-       OADD:         5,
-       OSUB:         5,
-       OOR:          5,
-       OXOR:         5,
-       OEQ:          4,
-       OLT:          4,
-       OLE:          4,
-       OGE:          4,
-       OGT:          4,
-       ONE:          4,
-       OSEND:        3,
-       OANDAND:      2,
-       OOROR:        1,
+       OALIGNOF:       8,
+       OAPPEND:        8,
+       OBYTES2STR:     8,
+       OARRAYLIT:      8,
+       OSLICELIT:      8,
+       ORUNES2STR:     8,
+       OCALLFUNC:      8,
+       OCALLINTER:     8,
+       OCALLMETH:      8,
+       OCALL:          8,
+       OCAP:           8,
+       OCLOSE:         8,
+       OCONVIFACE:     8,
+       OCONVNOP:       8,
+       OCONV:          8,
+       OCOPY:          8,
+       ODELETE:        8,
+       OGETG:          8,
+       OLEN:           8,
+       OLITERAL:       8,
+       OMAKESLICE:     8,
+       OMAKESLICECOPY: 8,
+       OMAKE:          8,
+       OMAPLIT:        8,
+       ONAME:          8,
+       ONEW:           8,
+       ONONAME:        8,
+       OOFFSETOF:      8,
+       OPACK:          8,
+       OPANIC:         8,
+       OPAREN:         8,
+       OPRINTN:        8,
+       OPRINT:         8,
+       ORUNESTR:       8,
+       OSIZEOF:        8,
+       OSTR2BYTES:     8,
+       OSTR2RUNES:     8,
+       OSTRUCTLIT:     8,
+       OTARRAY:        8,
+       OTCHAN:         8,
+       OTFUNC:         8,
+       OTINTER:        8,
+       OTMAP:          8,
+       OTSTRUCT:       8,
+       OINDEXMAP:      8,
+       OINDEX:         8,
+       OSLICE:         8,
+       OSLICESTR:      8,
+       OSLICEARR:      8,
+       OSLICE3:        8,
+       OSLICE3ARR:     8,
+       OSLICEHEADER:   8,
+       ODOTINTER:      8,
+       ODOTMETH:       8,
+       ODOTPTR:        8,
+       ODOTTYPE2:      8,
+       ODOTTYPE:       8,
+       ODOT:           8,
+       OXDOT:          8,
+       OCALLPART:      8,
+       OPLUS:          7,
+       ONOT:           7,
+       OBITNOT:        7,
+       ONEG:           7,
+       OADDR:          7,
+       ODEREF:         7,
+       ORECV:          7,
+       OMUL:           6,
+       ODIV:           6,
+       OMOD:           6,
+       OLSH:           6,
+       ORSH:           6,
+       OAND:           6,
+       OANDNOT:        6,
+       OADD:           5,
+       OSUB:           5,
+       OOR:            5,
+       OXOR:           5,
+       OEQ:            4,
+       OLT:            4,
+       OLE:            4,
+       OGE:            4,
+       OGT:            4,
+       ONE:            4,
+       OSEND:          3,
+       OANDAND:        2,
+       OOROR:          1,
 
        // Statements handled by stmtfmt
        OAS:         -1,
@@ -1572,6 +1573,9 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
                }
                mode.Fprintf(s, "make(%v)", n.Type)
 
+       case OMAKESLICECOPY:
+               mode.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type, n.Left, n.Right)
+
        case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
                // Unary
                mode.Fprintf(s, "%#v", n.Op)
index 3622884527ab03e076a5b1f8535152ac6aab9b90..41d588309c01eedea9e2f744ffdd5b96f8990683 100644 (file)
@@ -82,89 +82,90 @@ func _() {
        _ = x[OMAKECHAN-71]
        _ = x[OMAKEMAP-72]
        _ = x[OMAKESLICE-73]
-       _ = x[OMUL-74]
-       _ = x[ODIV-75]
-       _ = x[OMOD-76]
-       _ = x[OLSH-77]
-       _ = x[ORSH-78]
-       _ = x[OAND-79]
-       _ = x[OANDNOT-80]
-       _ = x[ONEW-81]
-       _ = x[ONEWOBJ-82]
-       _ = x[ONOT-83]
-       _ = x[OBITNOT-84]
-       _ = x[OPLUS-85]
-       _ = x[ONEG-86]
-       _ = x[OOROR-87]
-       _ = x[OPANIC-88]
-       _ = x[OPRINT-89]
-       _ = x[OPRINTN-90]
-       _ = x[OPAREN-91]
-       _ = x[OSEND-92]
-       _ = x[OSLICE-93]
-       _ = x[OSLICEARR-94]
-       _ = x[OSLICESTR-95]
-       _ = x[OSLICE3-96]
-       _ = x[OSLICE3ARR-97]
-       _ = x[OSLICEHEADER-98]
-       _ = x[ORECOVER-99]
-       _ = x[ORECV-100]
-       _ = x[ORUNESTR-101]
-       _ = x[OSELRECV-102]
-       _ = x[OSELRECV2-103]
-       _ = x[OIOTA-104]
-       _ = x[OREAL-105]
-       _ = x[OIMAG-106]
-       _ = x[OCOMPLEX-107]
-       _ = x[OALIGNOF-108]
-       _ = x[OOFFSETOF-109]
-       _ = x[OSIZEOF-110]
-       _ = x[OBLOCK-111]
-       _ = x[OBREAK-112]
-       _ = x[OCASE-113]
-       _ = x[OCONTINUE-114]
-       _ = x[ODEFER-115]
-       _ = x[OEMPTY-116]
-       _ = x[OFALL-117]
-       _ = x[OFOR-118]
-       _ = x[OFORUNTIL-119]
-       _ = x[OGOTO-120]
-       _ = x[OIF-121]
-       _ = x[OLABEL-122]
-       _ = x[OGO-123]
-       _ = x[ORANGE-124]
-       _ = x[ORETURN-125]
-       _ = x[OSELECT-126]
-       _ = x[OSWITCH-127]
-       _ = x[OTYPESW-128]
-       _ = x[OTCHAN-129]
-       _ = x[OTMAP-130]
-       _ = x[OTSTRUCT-131]
-       _ = x[OTINTER-132]
-       _ = x[OTFUNC-133]
-       _ = x[OTARRAY-134]
-       _ = x[ODDD-135]
-       _ = x[OINLCALL-136]
-       _ = x[OEFACE-137]
-       _ = x[OITAB-138]
-       _ = x[OIDATA-139]
-       _ = x[OSPTR-140]
-       _ = x[OCLOSUREVAR-141]
-       _ = x[OCFUNC-142]
-       _ = x[OCHECKNIL-143]
-       _ = x[OVARDEF-144]
-       _ = x[OVARKILL-145]
-       _ = x[OVARLIVE-146]
-       _ = x[ORESULT-147]
-       _ = x[OINLMARK-148]
-       _ = x[ORETJMP-149]
-       _ = x[OGETG-150]
-       _ = x[OEND-151]
+       _ = x[OMAKESLICECOPY-74]
+       _ = x[OMUL-75]
+       _ = x[ODIV-76]
+       _ = x[OMOD-77]
+       _ = x[OLSH-78]
+       _ = x[ORSH-79]
+       _ = x[OAND-80]
+       _ = x[OANDNOT-81]
+       _ = x[ONEW-82]
+       _ = x[ONEWOBJ-83]
+       _ = x[ONOT-84]
+       _ = x[OBITNOT-85]
+       _ = x[OPLUS-86]
+       _ = x[ONEG-87]
+       _ = x[OOROR-88]
+       _ = x[OPANIC-89]
+       _ = x[OPRINT-90]
+       _ = x[OPRINTN-91]
+       _ = x[OPAREN-92]
+       _ = x[OSEND-93]
+       _ = x[OSLICE-94]
+       _ = x[OSLICEARR-95]
+       _ = x[OSLICESTR-96]
+       _ = x[OSLICE3-97]
+       _ = x[OSLICE3ARR-98]
+       _ = x[OSLICEHEADER-99]
+       _ = x[ORECOVER-100]
+       _ = x[ORECV-101]
+       _ = x[ORUNESTR-102]
+       _ = x[OSELRECV-103]
+       _ = x[OSELRECV2-104]
+       _ = x[OIOTA-105]
+       _ = x[OREAL-106]
+       _ = x[OIMAG-107]
+       _ = x[OCOMPLEX-108]
+       _ = x[OALIGNOF-109]
+       _ = x[OOFFSETOF-110]
+       _ = x[OSIZEOF-111]
+       _ = x[OBLOCK-112]
+       _ = x[OBREAK-113]
+       _ = x[OCASE-114]
+       _ = x[OCONTINUE-115]
+       _ = x[ODEFER-116]
+       _ = x[OEMPTY-117]
+       _ = x[OFALL-118]
+       _ = x[OFOR-119]
+       _ = x[OFORUNTIL-120]
+       _ = x[OGOTO-121]
+       _ = x[OIF-122]
+       _ = x[OLABEL-123]
+       _ = x[OGO-124]
+       _ = x[ORANGE-125]
+       _ = x[ORETURN-126]
+       _ = x[OSELECT-127]
+       _ = x[OSWITCH-128]
+       _ = x[OTYPESW-129]
+       _ = x[OTCHAN-130]
+       _ = x[OTMAP-131]
+       _ = x[OTSTRUCT-132]
+       _ = x[OTINTER-133]
+       _ = x[OTFUNC-134]
+       _ = x[OTARRAY-135]
+       _ = x[ODDD-136]
+       _ = x[OINLCALL-137]
+       _ = x[OEFACE-138]
+       _ = x[OITAB-139]
+       _ = x[OIDATA-140]
+       _ = x[OSPTR-141]
+       _ = x[OCLOSUREVAR-142]
+       _ = x[OCFUNC-143]
+       _ = x[OCHECKNIL-144]
+       _ = x[OVARDEF-145]
+       _ = x[OVARKILL-146]
+       _ = x[OVARLIVE-147]
+       _ = x[ORESULT-148]
+       _ = x[OINLMARK-149]
+       _ = x[ORETJMP-150]
+       _ = x[OGETG-151]
+       _ = x[OEND-152]
 }
 
-const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
+const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
 
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 70, 82, 91, 100, 112, 121, 123, 126, 136, 143, 150, 157, 161, 165, 173, 181, 190, 198, 201, 206, 213, 220, 226, 235, 243, 251, 257, 261, 270, 277, 281, 284, 291, 299, 307, 314, 320, 323, 329, 336, 344, 348, 355, 363, 365, 367, 369, 371, 373, 375, 380, 385, 393, 396, 405, 408, 412, 420, 427, 436, 439, 442, 445, 448, 451, 454, 460, 463, 469, 472, 478, 482, 485, 489, 494, 499, 505, 510, 514, 519, 527, 535, 541, 550, 561, 568, 572, 579, 586, 594, 598, 602, 606, 613, 620, 628, 634, 639, 644, 648, 656, 661, 666, 670, 673, 681, 685, 687, 692, 694, 699, 705, 711, 717, 723, 728, 732, 739, 745, 750, 756, 759, 766, 771, 775, 780, 784, 794, 799, 807, 813, 820, 827, 833, 840, 846, 850, 853}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 70, 82, 91, 100, 112, 121, 123, 126, 136, 143, 150, 157, 161, 165, 173, 181, 190, 198, 201, 206, 213, 220, 226, 235, 243, 251, 257, 261, 270, 277, 281, 284, 291, 299, 307, 314, 320, 323, 329, 336, 344, 348, 355, 363, 365, 367, 369, 371, 373, 375, 380, 385, 393, 396, 405, 408, 412, 420, 427, 436, 449, 452, 455, 458, 461, 464, 467, 473, 476, 482, 485, 491, 495, 498, 502, 507, 512, 518, 523, 527, 532, 540, 548, 554, 563, 574, 581, 585, 592, 599, 607, 611, 615, 619, 626, 633, 641, 647, 652, 657, 661, 669, 674, 679, 683, 686, 694, 698, 700, 705, 707, 712, 718, 724, 730, 736, 741, 745, 752, 758, 763, 769, 772, 779, 784, 788, 793, 797, 807, 812, 820, 826, 833, 840, 846, 853, 859, 863, 866}
 
 func (i Op) String() string {
        if i >= Op(len(_Op_index)-1) {
index 8bce71b883d82531fc27b192d42063fafcc7f46e..6b6107290ada62022ca2f0870826699c5a1ab8c0 100644 (file)
@@ -319,9 +319,80 @@ func (o *Order) cleanTemp(top ordermarker) {
 
 // stmtList orders each of the statements in the list.
 func (o *Order) stmtList(l Nodes) {
-       for _, n := range l.Slice() {
-               o.stmt(n)
+       s := l.Slice()
+       for i := range s {
+               orderMakeSliceCopy(s[i:])
+               o.stmt(s[i])
+       }
+}
+
+// orderMakeSliceCopy matches the pattern:
+//  m = OMAKESLICE([]T, x); OCOPY(m, s)
+// and rewrites it to:
+//  m = OMAKESLICECOPY([]T, x, s); nil
+func orderMakeSliceCopy(s []*Node) {
+       const go115makeslicecopy = true
+       if !go115makeslicecopy {
+               return
        }
+
+       if Debug['N'] != 0 || instrumenting {
+               return
+       }
+
+       if len(s) < 2 {
+               return
+       }
+
+       asn := s[0]
+       copyn := s[1]
+
+       if asn == nil || asn.Op != OAS {
+               return
+       }
+       if asn.Left.Op != ONAME {
+               return
+       }
+       if asn.Left.isBlank() {
+               return
+       }
+       maken := asn.Right
+       if maken == nil || maken.Op != OMAKESLICE {
+               return
+       }
+       if maken.Esc == EscNone {
+               return
+       }
+       if maken.Left == nil || maken.Right != nil {
+               return
+       }
+       if copyn.Op != OCOPY {
+               return
+       }
+       if copyn.Left.Op != ONAME {
+               return
+       }
+       if asn.Left.Sym != copyn.Left.Sym {
+               return
+       }
+       if copyn.Right.Op != ONAME {
+               return
+       }
+
+       if copyn.Left.Sym == copyn.Right.Sym {
+               return
+       }
+
+       maken.Op = OMAKESLICECOPY
+       maken.Right = copyn.Right
+       // Set bounded when m = OMAKESLICE([]T, len(s)); OCOPY(m, s)
+       maken.SetBounded(maken.Left.Op == OLEN && samesafeexpr(maken.Left.Left, copyn.Right))
+
+       maken = typecheck(maken, ctxExpr)
+
+       s[1] = nil // remove separate copy call
+
+       return
 }
 
 // edge inserts coverage instrumentation for libfuzzer.
@@ -1150,6 +1221,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
                OMAKECHAN,
                OMAKEMAP,
                OMAKESLICE,
+               OMAKESLICECOPY,
                ONEW,
                OREAL,
                ORECOVER,
index a9bd723351b966891b7c2180067c211fef0589b6..b658410c53cd513e3772c7925ca155cf2bc7075a 100644 (file)
@@ -208,12 +208,16 @@ func (n *Node) MarkNonNil() {
 // SetBounded indicates whether operation n does not need safety checks.
 // When n is an index or slice operation, n does not need bounds checks.
 // When n is a dereferencing operation, n does not need nil checks.
+// When n is a makeslice+copy operation, n does not need length and cap checks.
 func (n *Node) SetBounded(b bool) {
        switch n.Op {
        case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
                // No bounds checks needed.
        case ODOTPTR, ODEREF:
                // No nil check needed.
+       case OMAKESLICECOPY:
+               // No length and cap checks needed
+               // since new slice and copied over slice data have same length.
        default:
                Fatalf("SetBounded(%v)", n)
        }
@@ -714,30 +718,38 @@ const (
        ODCLCONST // const pi = 3.14
        ODCLTYPE  // type Int int or type Int = int
 
-       ODELETE      // delete(Left, Right)
-       ODOT         // Left.Sym (Left is of struct type)
-       ODOTPTR      // Left.Sym (Left is of pointer to struct type)
-       ODOTMETH     // Left.Sym (Left is non-interface, Right is method name)
-       ODOTINTER    // Left.Sym (Left is interface, Right is method name)
-       OXDOT        // Left.Sym (before rewrite to one of the preceding)
-       ODOTTYPE     // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
-       ODOTTYPE2    // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
-       OEQ          // Left == Right
-       ONE          // Left != Right
-       OLT          // Left < Right
-       OLE          // Left <= Right
-       OGE          // Left >= Right
-       OGT          // Left > Right
-       ODEREF       // *Left
-       OINDEX       // Left[Right] (index of array or slice)
-       OINDEXMAP    // Left[Right] (index of map)
-       OKEY         // Left:Right (key:value in struct/array/map literal)
-       OSTRUCTKEY   // Sym:Left (key:value in struct literal, after type checking)
-       OLEN         // len(Left)
-       OMAKE        // make(List) (before type checking converts to one of the following)
-       OMAKECHAN    // make(Type, Left) (type is chan)
-       OMAKEMAP     // make(Type, Left) (type is map)
-       OMAKESLICE   // make(Type, Left, Right) (type is slice)
+       ODELETE        // delete(Left, Right)
+       ODOT           // Left.Sym (Left is of struct type)
+       ODOTPTR        // Left.Sym (Left is of pointer to struct type)
+       ODOTMETH       // Left.Sym (Left is non-interface, Right is method name)
+       ODOTINTER      // Left.Sym (Left is interface, Right is method name)
+       OXDOT          // Left.Sym (before rewrite to one of the preceding)
+       ODOTTYPE       // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
+       ODOTTYPE2      // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
+       OEQ            // Left == Right
+       ONE            // Left != Right
+       OLT            // Left < Right
+       OLE            // Left <= Right
+       OGE            // Left >= Right
+       OGT            // Left > Right
+       ODEREF         // *Left
+       OINDEX         // Left[Right] (index of array or slice)
+       OINDEXMAP      // Left[Right] (index of map)
+       OKEY           // Left:Right (key:value in struct/array/map literal)
+       OSTRUCTKEY     // Sym:Left (key:value in struct literal, after type checking)
+       OLEN           // len(Left)
+       OMAKE          // make(List) (before type checking converts to one of the following)
+       OMAKECHAN      // make(Type, Left) (type is chan)
+       OMAKEMAP       // make(Type, Left) (type is map)
+       OMAKESLICE     // make(Type, Left, Right) (type is slice)
+       OMAKESLICECOPY // makeslicecopy(Type, Left, Right) (type is slice; Left is length and Right is the copied from slice)
+       // OMAKESLICECOPY is created by the order pass and corresponds to:
+       //  s = make(Type, Left); copy(s, Right)
+       //
+       // Bounded can be set on the node when Left == len(Right) is known at compile time.
+       //
+       // This node is created so the walk pass can optimize this pattern which would
+       // otherwise be hard to detect after the order pass.
        OMUL         // Left * Right
        ODIV         // Left / Right
        OMOD         // Left % Right
index 6e04908b46471b4d4fad5c88942bdd13c63913e0..8132aee863969fbd71765d82cfb4b8165bc87256 100644 (file)
@@ -1149,6 +1149,49 @@ func typecheck1(n *Node, top int) (res *Node) {
                n.List.SetFirst(l)
                n.List.SetSecond(c)
 
+       case OMAKESLICECOPY:
+               // Errors here are Fatalf instead of yyerror because only the compiler
+               // can construct an OMAKESLICECOPY node.
+               // Components used in OMAKESCLICECOPY that are supplied by parsed source code
+               // have already been typechecked in OMAKE and OCOPY earlier.
+               ok |= ctxExpr
+
+               t := n.Type
+
+               if t == nil {
+                       Fatalf("no type specified for OMAKESLICECOPY")
+               }
+
+               if !t.IsSlice() {
+                       Fatalf("invalid type %v for OMAKESLICECOPY", n.Type)
+               }
+
+               if n.Left == nil {
+                       Fatalf("missing len argument for OMAKESLICECOPY")
+               }
+
+               if n.Right == nil {
+                       Fatalf("missing slice argument to copy for OMAKESLICECOPY")
+               }
+
+               n.Left = typecheck(n.Left, ctxExpr)
+               n.Right = typecheck(n.Right, ctxExpr)
+
+               n.Left = defaultlit(n.Left, types.Types[TINT])
+
+               if !n.Left.Type.IsInteger() && n.Type.Etype != TIDEAL {
+                       yyerror("non-integer len argument in OMAKESLICECOPY")
+               }
+
+               if Isconst(n.Left, CTINT) {
+                       if n.Left.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
+                               Fatalf("len for OMAKESLICECOPY too large")
+                       }
+                       if n.Left.Int64() < 0 {
+                               Fatalf("len for OMAKESLICECOPY must be non-negative")
+                       }
+               }
+
        case OSLICE, OSLICE3:
                ok |= ctxExpr
                n.Left = typecheck(n.Left, ctxExpr)
index 84ba528bc9674ade36a2583949b58790ecdc48bf..1e6d913ae644324ec56269d89380a962e4871c07 100644 (file)
@@ -1390,6 +1390,63 @@ opswitch:
                        n = m
                }
 
+       case OMAKESLICECOPY:
+               if n.Esc == EscNone {
+                       Fatalf("OMAKESLICECOPY with EscNone: %v", n)
+               }
+
+               t := n.Type
+               if t.Elem().NotInHeap() {
+                       Fatalf("%v is go:notinheap; heap allocation disallowed", t.Elem())
+               }
+
+               length := conv(n.Left, types.Types[TINT])
+               copylen := nod(OLEN, n.Right, nil)
+               copyptr := nod(OSPTR, n.Right, nil)
+
+               if !types.Haspointers(t.Elem()) && n.Bounded() {
+                       // When len(to)==len(from) and elements have no pointers:
+                       // replace make+copy with runtime.mallocgc+runtime.memmove.
+
+                       // We do not check for overflow of len(to)*elem.Width here
+                       // since len(from) is an existing checked slice capacity
+                       // with same elem.Width for the from slice.
+                       size := nod(OMUL, conv(length, types.Types[TUINTPTR]), conv(nodintconst(t.Elem().Width), types.Types[TUINTPTR]))
+
+                       // instantiate mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer
+                       fn := syslook("mallocgc")
+                       sh := nod(OSLICEHEADER, nil, nil)
+                       sh.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, size, nodnil(), nodbool(false))
+                       sh.Left.MarkNonNil()
+                       sh.List.Set2(length, length)
+                       sh.Type = t
+
+                       s := temp(t)
+                       r := typecheck(nod(OAS, s, sh), ctxStmt)
+                       r = walkexpr(r, init)
+                       init.Append(r)
+
+                       // instantiate memmove(to *any, frm *any, size uintptr)
+                       fn = syslook("memmove")
+                       fn = substArgTypes(fn, t.Elem(), t.Elem())
+                       ncopy := mkcall1(fn, nil, init, nod(OSPTR, s, nil), copyptr, size)
+                       ncopy = typecheck(ncopy, ctxStmt)
+                       ncopy = walkexpr(ncopy, init)
+                       init.Append(ncopy)
+
+                       n = s
+               } else { // Replace make+copy with runtime.makeslicecopy.
+                       // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
+                       fn := syslook("makeslicecopy")
+                       s := nod(OSLICEHEADER, nil, nil)
+                       s.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[TUNSAFEPTR]))
+                       s.Left.MarkNonNil()
+                       s.List.Set2(length, length)
+                       s.Type = t
+                       n = typecheck(s, ctxExpr)
+                       n = walkexpr(n, init)
+               }
+
        case ORUNESTR:
                a := nodnil()
                if n.Esc == EscNone {
@@ -3772,6 +3829,9 @@ func candiscard(n *Node) bool {
                // Difficult to tell what sizes are okay.
        case OMAKESLICE:
                return false
+
+       case OMAKESLICECOPY:
+               return false
        }
 
        if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
index 4ea4478601b7232d51e1089c28783f1d8dd6b21b..d9949e793924b341bb4a8d8652f65eb305712170 100644 (file)
@@ -31,6 +31,55 @@ func panicmakeslicecap() {
        panic(errorString("makeslice: cap out of range"))
 }
 
+// makeslicecopy allocates a slice of "tolen" elements of type "et",
+// then copies "fromlen" elements of type "et" into that new allocation from "from".
+func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer {
+       var tomem, copymem uintptr
+       if uintptr(tolen) > uintptr(fromlen) {
+               var overflow bool
+               tomem, overflow = math.MulUintptr(et.size, uintptr(tolen))
+               if overflow || tomem > maxAlloc || tolen < 0 {
+                       panicmakeslicelen()
+               }
+               copymem = et.size * uintptr(fromlen)
+       } else {
+               // fromlen is a known good length providing and equal or greater than tolen,
+               // thereby making tolen a good slice length too as from and to slices have the
+               // same element width.
+               tomem = et.size * uintptr(tolen)
+               copymem = tomem
+       }
+
+       var to unsafe.Pointer
+       if et.ptrdata == 0 {
+               to = mallocgc(tomem, nil, false)
+               if copymem < tomem {
+                       memclrNoHeapPointers(add(to, copymem), tomem-copymem)
+               }
+       } else {
+               // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
+               to = mallocgc(tomem, et, true)
+               if writeBarrier.enabled {
+                       // Only shade the pointers in old.array since we know the destination slice to
+                       // only contains nil pointers because it has been cleared during alloc.
+                       bulkBarrierPreWriteSrcOnly(uintptr(to), uintptr(from), copymem)
+               }
+       }
+
+       if raceenabled {
+               callerpc := getcallerpc()
+               pc := funcPC(makeslicecopy)
+               racereadrangepc(from, copymem, callerpc, pc)
+       }
+       if msanenabled {
+               msanread(from, copymem)
+       }
+
+       memmove(to, from, copymem)
+
+       return to
+}
+
 func makeslice(et *_type, len, cap int) unsafe.Pointer {
        mem, overflow := math.MulUintptr(et.size, uintptr(cap))
        if overflow || mem > maxAlloc || len < 0 || len > cap {
index 0463fc70a764bb8cc8a1de44e5efa6dac046db34..e963a43dd31cb88525a9248ba1115c8fc2990e43 100644 (file)
@@ -10,6 +10,84 @@ import (
 
 const N = 20
 
+func BenchmarkMakeSliceCopy(b *testing.B) {
+       const length = 32
+       var bytes = make([]byte, 8*length)
+       var ints = make([]int, length)
+       var ptrs = make([]*byte, length)
+       b.Run("mallocmove", func(b *testing.B) {
+               b.Run("Byte", func(b *testing.B) {
+                       var x []byte
+                       for i := 0; i < b.N; i++ {
+                               x = make([]byte, len(bytes))
+                               copy(x, bytes)
+                       }
+               })
+               b.Run("Int", func(b *testing.B) {
+                       var x []int
+                       for i := 0; i < b.N; i++ {
+                               x = make([]int, len(ints))
+                               copy(x, ints)
+                       }
+               })
+               b.Run("Ptr", func(b *testing.B) {
+                       var x []*byte
+                       for i := 0; i < b.N; i++ {
+                               x = make([]*byte, len(ptrs))
+                               copy(x, ptrs)
+                       }
+
+               })
+       })
+       b.Run("makecopy", func(b *testing.B) {
+               b.Run("Byte", func(b *testing.B) {
+                       var x []byte
+                       for i := 0; i < b.N; i++ {
+                               x = make([]byte, 8*length)
+                               copy(x, bytes)
+                       }
+               })
+               b.Run("Int", func(b *testing.B) {
+                       var x []int
+                       for i := 0; i < b.N; i++ {
+                               x = make([]int, length)
+                               copy(x, ints)
+                       }
+               })
+               b.Run("Ptr", func(b *testing.B) {
+                       var x []*byte
+                       for i := 0; i < b.N; i++ {
+                               x = make([]*byte, length)
+                               copy(x, ptrs)
+                       }
+
+               })
+       })
+       b.Run("nilappend", func(b *testing.B) {
+               b.Run("Byte", func(b *testing.B) {
+                       var x []byte
+                       for i := 0; i < b.N; i++ {
+                               x = append([]byte(nil), bytes...)
+                               _ = x
+                       }
+               })
+               b.Run("Int", func(b *testing.B) {
+                       var x []int
+                       for i := 0; i < b.N; i++ {
+                               x = append([]int(nil), ints...)
+                               _ = x
+                       }
+               })
+               b.Run("Ptr", func(b *testing.B) {
+                       var x []*byte
+                       for i := 0; i < b.N; i++ {
+                               x = append([]*byte(nil), ptrs...)
+                               _ = x
+                       }
+               })
+       })
+}
+
 type (
        struct24 struct{ a, b, c int64 }
        struct32 struct{ a, b, c, d int64 }
index cf569e27fbde136ba75327705460d4a4144f48df..40e857f9f69d7f83cb263fffe717d7d6be5dfff4 100644 (file)
@@ -104,6 +104,189 @@ func SliceExtensionInt64(s []int, l64 int64) []int {
        return append(s, make([]int, l64)...)
 }
 
+// ------------------ //
+//      Make+Copy     //
+// ------------------ //
+
+// Issue #26252 - avoid memclr for make+copy
+
+func SliceMakeCopyLen(s []int) []int {
+       // amd64:`.*runtime\.mallocgc`
+       // amd64:`.*runtime\.memmove`
+       // amd64:-`.*runtime\.makeslice`
+       a := make([]int, len(s))
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyLenPtr(s []*int) []*int {
+       // amd64:`.*runtime\.makeslicecopy`
+       // amd64:-`.*runtime\.makeslice\(`
+       // amd64:-`.*runtime\.typedslicecopy
+       a := make([]*int, len(s))
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyConst(s []int) []int {
+       // amd64:`.*runtime\.makeslicecopy`
+       // amd64:-`.*runtime\.makeslice\(`
+       // amd64:-`.*runtime\.memmove`
+       a := make([]int, 4)
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyConstPtr(s []*int) []*int {
+       // amd64:`.*runtime\.makeslicecopy`
+       // amd64:-`.*runtime\.makeslice\(`
+       // amd64:-`.*runtime\.typedslicecopy
+       a := make([]*int, 4)
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoOptNoDeref(s []*int) []*int {
+       a := new([]*int)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       *a = make([]*int, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(*a, s)
+       return *a
+}
+
+func SliceMakeCopyNoOptNoVar(s []*int) []*int {
+       a := make([][]*int, 1)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a[0] = make([]*int, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(a[0], s)
+       return a[0]
+}
+
+func SliceMakeCopyNoOptBlank(s []*int) []*int {
+       var a []*int
+       // amd64:-`.*runtime\.makeslicecopy`
+       _ = make([]*int, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoOptNoMake(s []*int) []*int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:-`.*runtime\.objectnew`
+       a := *new([]*int)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoOptNoHeapAlloc(s []*int) int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       a := make([]*int, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(a, s)
+       return cap(a)
+}
+
+func SliceMakeCopyNoOptNoCap(s []*int) []*int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 0, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.typedslicecopy`
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoOptNoCopy(s []*int) []*int {
+       copy := func(x, y []*int) {}
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 4)
+       // amd64:-`.*runtime\.makeslicecopy`
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoOptWrongOrder(s []*int) []*int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 4)
+       // amd64:`.*runtime\.typedslicecopy`
+       // amd64:-`.*runtime\.makeslicecopy`
+       copy(s, a)
+       return a
+}
+
+func SliceMakeCopyNoOptWrongAssign(s []*int) []*int {
+       var a []*int
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       s = make([]*int, 4)
+       // amd64:`.*runtime\.typedslicecopy`
+       // amd64:-`.*runtime\.makeslicecopy`
+       copy(a, s)
+       return s
+}
+
+func SliceMakeCopyNoOptCopyLength(s []*int) (int, []*int) {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 4)
+       // amd64:`.*runtime\.typedslicecopy`
+       // amd64:-`.*runtime\.makeslicecopy`
+       n := copy(a, s)
+       return n, a
+}
+
+func SliceMakeCopyNoOptSelfCopy(s []*int) []*int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 4)
+       // amd64:`.*runtime\.typedslicecopy`
+       // amd64:-`.*runtime\.makeslicecopy`
+       copy(a, a)
+       return a
+}
+
+func SliceMakeCopyNoOptTargetReference(s []*int) []*int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]*int, 4)
+       // amd64:`.*runtime\.typedslicecopy`
+       // amd64:-`.*runtime\.makeslicecopy`
+       copy(a, s[:len(a)])
+       return a
+}
+
+func SliceMakeCopyNoOptCap(s []int) []int {
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.makeslice\(`
+       a := make([]int, len(s), 9)
+       // amd64:-`.*runtime\.makeslicecopy`
+       // amd64:`.*runtime\.memmove`
+       copy(a, s)
+       return a
+}
+
+func SliceMakeCopyNoMemmoveDifferentLen(s []int) []int {
+       // amd64:`.*runtime\.makeslicecopy`
+       // amd64:-`.*runtime\.memmove`
+       a := make([]int, len(s)-1)
+       // amd64:-`.*runtime\.memmove`
+       copy(a, s)
+       return a
+}
+
 // ---------------------- //
 //   Nil check of &s[0]   //
 // ---------------------- //
diff --git a/test/makeslice.go b/test/makeslice.go
new file mode 100644 (file)
index 0000000..0ffecd7
--- /dev/null
@@ -0,0 +1,149 @@
+// run
+
+// Copyright 2013 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.
+
+package main
+
+import (
+       "strings"
+       "unsafe"
+)
+
+func main() {
+       n := -1
+       testInts(uint64(n))
+       testBytes(uint64(n))
+
+       var t *byte
+       if unsafe.Sizeof(t) == 8 {
+               // Test mem > maxAlloc
+               testInts(1 << 59)
+
+               // Test elem.size*cap overflow
+               testInts(1<<63 - 1)
+
+               testInts(1<<64 - 1)
+               testBytes(1<<64 - 1)
+       } else {
+               testInts(1<<31 - 1)
+
+               // Test elem.size*cap overflow
+               testInts(1<<32 - 1)
+               testBytes(1<<32 - 1)
+       }
+}
+
+func shouldPanic(str string, f func()) {
+       defer func() {
+               err := recover()
+               if err == nil {
+                       panic("did not panic")
+               }
+               s := err.(error).Error()
+               if !strings.Contains(s, str) {
+                       panic("got panic " + s + ", want " + str)
+               }
+       }()
+
+       f()
+}
+
+func testInts(n uint64) {
+       testMakeInts(n)
+       testMakeCopyInts(n)
+       testMakeInAppendInts(n)
+}
+
+func testBytes(n uint64) {
+       testMakeBytes(n)
+       testMakeCopyBytes(n)
+       testMakeInAppendBytes(n)
+}
+
+// Test make panics for given length or capacity n.
+func testMakeInts(n uint64) {
+       type T []int
+       shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+func testMakeBytes(n uint64) {
+       type T []byte
+       shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+       shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+// Test make+copy panics since the gc compiler optimizes these
+// to runtime.makeslicecopy calls.
+func testMakeCopyInts(n uint64) {
+       type T []int
+       var c = make(T, 8)
+       shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+func testMakeCopyBytes(n uint64) {
+       type T []byte
+       var c = make(T, 8)
+       shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+       shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+       shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+// Test make in append panics for int slices since the gc compiler optimizes makes in appends.
+func testMakeInAppendInts(n uint64) {
+       type T []int
+       for _, length := range []int{0, 1} {
+               t := make(T, length)
+               shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+       }
+}
+
+func testMakeInAppendBytes(n uint64) {
+       type T []byte
+       for _, length := range []int{0, 1} {
+               t := make(T, length)
+               shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+               shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+               shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+       }
+}