Commit 020a18c5 authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Martin Möhrmann

cmd/compile: move slice construction to callers of makeslice

Only return a pointer p to the new slices backing array from makeslice.
Makeslice callers then construct sliceheader{p, len, cap} explictly
instead of makeslice returning the slice.

Reduces go binary size by ~0.2%.
Removes 92 (~3.5%) panicindex calls from go binary.

Change-Id: I29b7c3b5fe8b9dcec96e2c43730575071cfe8a94
Reviewed-on: https://go-review.googlesource.com/c/141822
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
parent c86d4647
...@@ -117,8 +117,8 @@ var runtimeDecls = [...]struct { ...@@ -117,8 +117,8 @@ var runtimeDecls = [...]struct {
{"selectsetpc", funcTag, 56}, {"selectsetpc", funcTag, 56},
{"selectgo", funcTag, 93}, {"selectgo", funcTag, 93},
{"block", funcTag, 5}, {"block", funcTag, 5},
{"makeslice", funcTag, 95}, {"makeslice", funcTag, 94},
{"makeslice64", funcTag, 96}, {"makeslice64", funcTag, 95},
{"growslice", funcTag, 97}, {"growslice", funcTag, 97},
{"memmove", funcTag, 98}, {"memmove", funcTag, 98},
{"memclrNoHeapPointers", funcTag, 99}, {"memclrNoHeapPointers", funcTag, 99},
...@@ -249,10 +249,10 @@ func runtimeTypes() []*types.Type { ...@@ -249,10 +249,10 @@ func runtimeTypes() []*types.Type {
typs[91] = types.NewPtr(typs[11]) typs[91] = types.NewPtr(typs[11])
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])}) typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])}) typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
typs[94] = types.NewSlice(typs[2]) typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[94])}) typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[94])}) typs[96] = types.NewSlice(typs[2])
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[94]), anonfield(typs[32])}, []*Node{anonfield(typs[94])}) typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil) typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil) typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])}) typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
......
...@@ -153,8 +153,8 @@ func selectsetpc(cas *byte) ...@@ -153,8 +153,8 @@ func selectsetpc(cas *byte)
func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool) func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool)
func block() func block()
func makeslice(typ *byte, len int, cap int) (ary []any) func makeslice(typ *byte, len int, cap int) unsafe.Pointer
func makeslice64(typ *byte, len int64, cap int64) (ary []any) func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
func growslice(typ *byte, old []any, cap int) (ary []any) func growslice(typ *byte, old []any, cap int) (ary []any)
func memmove(to *any, frm *any, length uintptr) func memmove(to *any, frm *any, length uintptr)
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
......
...@@ -4,9 +4,9 @@ package gc ...@@ -4,9 +4,9 @@ package gc
import "strconv" import "strconv"
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND" const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICEHEADERSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 550, 559, 566, 570, 577, 584, 592, 596, 600, 604, 611, 618, 626, 632, 637, 642, 646, 651, 659, 664, 669, 673, 676, 684, 688, 690, 695, 699, 704, 710, 716, 722, 728, 733, 737, 744, 750, 755, 761, 764, 770, 777, 782, 786, 791, 795, 805, 810, 818, 824, 831, 838, 846, 852, 856, 859} var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 555, 561, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
func (i Op) String() string { func (i Op) String() string {
if i >= Op(len(_Op_index)-1) { if i >= Op(len(_Op_index)-1) {
......
...@@ -2321,6 +2321,12 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -2321,6 +2321,12 @@ func (s *state) expr(n *Node) *ssa.Value {
data := s.expr(n.Right) data := s.expr(n.Right)
return s.newValue2(ssa.OpIMake, n.Type, tab, data) return s.newValue2(ssa.OpIMake, n.Type, tab, data)
case OSLICEHEADER:
p := s.expr(n.Left)
l := s.expr(n.List.First())
c := s.expr(n.List.Second())
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR: case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
v := s.expr(n.Left) v := s.expr(n.Left)
var i, j, k *ssa.Value var i, j, k *ssa.Value
......
...@@ -683,6 +683,7 @@ const ( ...@@ -683,6 +683,7 @@ const (
OSLICESTR // Left[List[0] : List[1]] (Left is string) OSLICESTR // Left[List[0] : List[1]] (Left is string)
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice) OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array) OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
OSLICEHEADER // sliceheader{Left, List[0], List[1]} (Left is unsafe.Pointer, List[0] is length, List[1] is capacity)
ORECOVER // recover() ORECOVER // recover()
ORECV // <-Left ORECV // <-Left
ORUNESTR // Type(Left) (Type is string, Left is rune) ORUNESTR // Type(Left) (Type is string, Left is rune)
......
...@@ -1086,6 +1086,47 @@ func typecheck1(n *Node, top int) *Node { ...@@ -1086,6 +1086,47 @@ func typecheck1(n *Node, top int) *Node {
n.Right = assignconv(r, t.Elem(), "send") n.Right = assignconv(r, t.Elem(), "send")
n.Type = nil n.Type = nil
case OSLICEHEADER:
// Errors here are Fatalf instead of yyerror because only the compiler
// can construct an OSLICEHEADER node.
// Components used in OSLICEHEADER that are supplied by parsed source code
// have already been typechecked in e.g. OMAKESLICE earlier.
ok |= Erv
t := n.Type
if !t.IsSlice() {
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
}
if !n.Left.Type.IsUnsafePtr() {
Fatalf("need unsafe.Pointer for OSLICEHEADER")
}
if x := n.List.Len(); x != 2 {
Fatalf("expected 2 params (len, cap) for OSLICEHEADER, got %d", x)
}
n.Left = typecheck(n.Left, Erv)
l := typecheck(n.List.First(), Erv)
c := typecheck(n.List.Second(), Erv)
l = defaultlit(l, types.Types[TINT])
c = defaultlit(c, types.Types[TINT])
if Isconst(l, CTINT) && l.Int64() < 0 {
Fatalf("len for OSLICEHEADER must be non-negative")
}
if Isconst(c, CTINT) && c.Int64() < 0 {
Fatalf("cap for OSLICEHEADER must be non-negative")
}
if Isconst(l, CTINT) && Isconst(c, CTINT) && l.Val().U.(*Mpint).Cmp(c.Val().U.(*Mpint)) > 0 {
Fatalf("len larger than cap for OSLICEHEADER")
}
n.List.SetFirst(l)
n.List.SetSecond(c)
case OSLICE, OSLICE3: case OSLICE, OSLICE3:
ok |= Erv ok |= Erv
n.Left = typecheck(n.Left, Erv) n.Left = typecheck(n.Left, Erv)
......
...@@ -1118,6 +1118,11 @@ opswitch: ...@@ -1118,6 +1118,11 @@ opswitch:
case ORECV: case ORECV:
Fatalf("walkexpr ORECV") // should see inside OAS only Fatalf("walkexpr ORECV") // should see inside OAS only
case OSLICEHEADER:
n.Left = walkexpr(n.Left, init)
n.List.SetFirst(walkexpr(n.List.First(), init))
n.List.SetSecond(walkexpr(n.List.Second(), init))
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
n.Left = walkexpr(n.Left, init) n.Left = walkexpr(n.Left, init)
low, high, max := n.SliceBounds() low, high, max := n.SliceBounds()
...@@ -1339,8 +1344,13 @@ opswitch: ...@@ -1339,8 +1344,13 @@ opswitch:
} }
fn := syslook(fnname) fn := syslook(fnname)
fn = substArgTypes(fn, t.Elem()) // any-1 n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)) n.Left.SetNonNil(true)
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
n.Op = OSLICEHEADER
n.Type = t
n = typecheck(n, Erv)
n = walkexpr(n, init)
} }
case ORUNESTR: case ORUNESTR:
......
...@@ -266,8 +266,11 @@ func testGdbPython(t *testing.T, cgo bool) { ...@@ -266,8 +266,11 @@ func testGdbPython(t *testing.T, cgo bool) {
infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`) infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
// Format output from gdb v8.2 // Format output from gdb v8.2
infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`) infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
// Format output from gdb v7.7
infoLocalsRe3 := regexp.MustCompile(`^mapvar = .*\nstrvar = "abc"\nslicevar *= *\[\]string`)
if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) && if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
!infoLocalsRe2.MatchString(bl) { !infoLocalsRe2.MatchString(bl) &&
!infoLocalsRe3.MatchString(bl) {
t.Fatalf("info locals failed: %s", bl) t.Fatalf("info locals failed: %s", bl)
} }
......
...@@ -31,7 +31,7 @@ func panicmakeslicecap() { ...@@ -31,7 +31,7 @@ func panicmakeslicecap() {
panic(errorString("makeslice: cap out of range")) panic(errorString("makeslice: cap out of range"))
} }
func makeslice(et *_type, len, cap int) slice { func makeslice(et *_type, len, cap int) unsafe.Pointer {
mem, overflow := math.MulUintptr(et.size, uintptr(cap)) mem, overflow := math.MulUintptr(et.size, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap { if overflow || mem > maxAlloc || len < 0 || len > cap {
// NOTE: Produce a 'len out of range' error instead of a // NOTE: Produce a 'len out of range' error instead of a
...@@ -45,12 +45,11 @@ func makeslice(et *_type, len, cap int) slice { ...@@ -45,12 +45,11 @@ func makeslice(et *_type, len, cap int) slice {
} }
panicmakeslicecap() panicmakeslicecap()
} }
p := mallocgc(mem, et, true)
return slice{p, len, cap} return mallocgc(mem, et, true)
} }
func makeslice64(et *_type, len64, cap64 int64) slice { func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
len := int(len64) len := int(len64)
if int64(len) != len64 { if int64(len) != len64 {
panicmakeslicelen() panicmakeslicelen()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment