]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: generate makeslice calls with int arguments
authorMartin Möhrmann <martisch@uos.de>
Thu, 25 Aug 2016 12:17:52 +0000 (14:17 +0200)
committerMartin Möhrmann <martisch@uos.de>
Mon, 29 Aug 2016 18:25:33 +0000 (18:25 +0000)
Where possible generate calls to runtime makeslice with int arguments
during compile time instead of makeslice with int64 arguments.

This eliminates converting arguments for calls to makeslice with
int64 arguments for platforms where int64 values do not fit into
arguments of type int.

godoc 386 binary shrinks by approximately 12 kilobyte.

amd64:
name         old time/op  new time/op  delta
MakeSlice-2  29.8ns ± 1%  29.8ns ± 1%   ~     (p=1.000 n=24+24)

386:
name         old time/op  new time/op  delta
MakeSlice-2  52.3ns ± 0%  45.9ns ± 0%  -12.17%  (p=0.000 n=25+22)

Fixes  #15357

Change-Id: Icb8701bb63c5a83877d26c8a4b78e782ba76de7c
Reviewed-on: https://go-review.googlesource.com/27851
Run-TryBot: Martin Möhrmann <martisch@uos.de>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/gc/builtin.go
src/cmd/compile/internal/gc/builtin/runtime.go
src/cmd/compile/internal/gc/walk.go
src/runtime/slice.go
test/fixedbugs/issue4085b.go

index 637a661cddeba96e61dc1eade0877ca6bd5a3f2e..c7223e03559a69b5dcf3d44291afdc196b080042 100644 (file)
@@ -83,27 +83,28 @@ const runtimeimport = "" +
        "\t\x15selectrecv2\x00\b\x17\"\xb4\x02\x00\x00\x1f\x02:\xfc\x01\x00\x00\x17:\xfe\x01\x00\x00\x17\x00\x15rec" +
        "eived·5\x00\x00\x02\x00\xb6\x02\x00\x00\t\x19selectdefault\x00\x02\x17\"\xb4\x02\x00\x00\x02" +
        "\x00\xb6\x02\x00\x00\t\x0fselectgo\x00\x02\x17\"\xac\x02\x00\x00\x00\t\tblock\x00\x00\x00\t\x11make" +
-       "slice\x00\x06\x17\"\x06\x00\x00\n\vnel·3\x00\x00\n\vcap·4\x00\x00\x02\x11:\vary\xc2" +
-       "\xb71\x00\x00\t\x11growslice\x00\x06\x17\"\x06\x00\x00\x11:\vold·3\x00\x00\x02\xc8\x02\x00\x00\x02\x11" +
-       ":\xca\x02\x00\x00\t\rmemmove\x00\x06\x17:\tto·1\x00\x00\x17:\vfrm·2\x00\x00\x16\x11l" +
-       "ength·3\x00b\x00\t\vmemclr\x00\x04\x17\"\vptr·1\x00\x00\x16\x11length" +
-       "·2\x00b\x00\t\x0fmemequal\x00\x06\x17:\ax·2\x00\x00\x17:\ay·3\x00\x00\x16\rsi" +
-       "ze·4\x00b\x01\x00\x00\t\x11memequal8\x00\x04\x17:\xe0\x02\x00\x00\x17:\xe2\x02\x00\x00\x01\x00\x00\t\x13" +
-       "memequal16\x00\x04\x17:\xe0\x02\x00\x00\x17:\xe2\x02\x00\x00\x01\x00\x00\t\x13memequal32\x00" +
-       "\x04\x17:\xe0\x02\x00\x00\x17:\xe2\x02\x00\x00\x01\x00\x00\t\x13memequal64\x00\x04\x17:\xe0\x02\x00\x00\x17:\xe2\x02" +
-       "\x00\x00\x01\x00\x00\t\x15memequal128\x00\x04\x17:\xe0\x02\x00\x00\x17:\xe2\x02\x00\x00\x01\x00\x00\t\x0fint" +
-       "64div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint6" +
-       "4mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat" +
-       "64toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64touint64\x00\x01\x1a\x00\x01\x14\x00" +
-       "\t\x1dfloat64touint32\x00\x01\x1a\x00\x01\x12\x00\t\x1bint64tofloat64" +
-       "\x00\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00\x01\x14\x00\x01\x1a\x00\t\x1duint32t" +
-       "ofloat64\x00\x01\x12\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e\vnum·2" +
-       "\x00\x00\x1e\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefuncenter\x00\x01" +
-       "\x16b\x00\t\x17racefuncexit\x00\x00\x00\t\x0fraceread\x00\x01\x16b\x00\t\x11rac" +
-       "ewrite\x00\x01\x16b\x00\t\x19racereadrange\x00\x04\x16\raddr·1\x00b\x16" +
-       "\rsize·2\x00b\x00\t\x1bracewriterange\x00\x04\x16\x96\x03\x00b\x16\x98\x03\x00b\x00" +
-       "\t\x0fmsanread\x00\x04\x16\x96\x03\x00b\x16\x98\x03\x00b\x00\t\x11msanwrite\x00\x04\x16\x96\x03\x00" +
-       "b\x16\x98\x03\x00b\x00\v\xf8\x01\v\x00\x01\x00\n$$\n"
+       "slice\x00\x06\x17\"\x06\x00\x00\x02\vlen·3\x00\x00\x02\vcap·4\x00\x00\x02\x11:\vary\xc2" +
+       "\xb71\x00\x00\t\x15makeslice64\x00\x06\x17\"\x06\x00\x00\n\xc6\x02\x00\x00\n\xc8\x02\x00\x00\x02\x11:\xca\x02\x00" +
+       "\x00\t\x11growslice\x00\x06\x17\"\x06\x00\x00\x11:\vold·3\x00\x00\x02\xc8\x02\x00\x00\x02\x11:\xca\x02" +
+       "\x00\x00\t\rmemmove\x00\x06\x17:\tto·1\x00\x00\x17:\vfrm·2\x00\x00\x16\x11leng" +
+       "th·3\x00b\x00\t\vmemclr\x00\x04\x17\"\vptr·1\x00\x00\x16\x11length·2" +
+       "\x00b\x00\t\x0fmemequal\x00\x06\x17:\ax·2\x00\x00\x17:\ay·3\x00\x00\x16\rsize\xc2" +
+       "\xb74\x00b\x01\x00\x00\t\x11memequal8\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13mem" +
+       "equal16\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal32\x00\x04\x17:" +
+       "\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal64\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01" +
+       "\x00\x00\t\x15memequal128\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x0fint64d" +
+       "iv\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint64mo" +
+       "d\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat64t" +
+       "oint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64touint64\x00\x01\x1a\x00\x01\x14\x00\t\x1df" +
+       "loat64touint32\x00\x01\x1a\x00\x01\x12\x00\t\x1bint64tofloat64\x00\x01\n" +
+       "\x00\x01\x1a\x00\t\x1duint64tofloat64\x00\x01\x14\x00\x01\x1a\x00\t\x1duint32tofl" +
+       "oat64\x00\x01\x12\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e\vnum·2\x00\x00\x1e" +
+       "\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefuncenter\x00\x01\x16b\x00" +
+       "\t\x17racefuncexit\x00\x00\x00\t\x0fraceread\x00\x01\x16b\x00\t\x11racewr" +
+       "ite\x00\x01\x16b\x00\t\x19racereadrange\x00\x04\x16\raddr·1\x00b\x16\rsi" +
+       "ze·2\x00b\x00\t\x1bracewriterange\x00\x04\x16\x98\x03\x00b\x16\x9a\x03\x00b\x00\t\x0fm" +
+       "sanread\x00\x04\x16\x98\x03\x00b\x16\x9a\x03\x00b\x00\t\x11msanwrite\x00\x04\x16\x98\x03\x00b\x16\x9a" +
+       "\x03\x00b\x00\v\xfa\x01\v\x00\x01\x00\n$$\n"
 
 const unsafeimport = "" +
        "version 2\n\n\x00\x00\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOff" +
index ef7e4089594151e20f961b6c007aa505793eeb6d..ee7010585ddf45c354be72d1d67522b3ce9534b3 100644 (file)
@@ -131,7 +131,8 @@ func selectdefault(sel *byte) (selected bool)
 func selectgo(sel *byte)
 func block()
 
-func makeslice(typ *byte, nel int64, cap int64) (ary []any)
+func makeslice(typ *byte, len int, cap int) (ary []any)
+func makeslice64(typ *byte, len int64, cap int64) (ary []any)
 func growslice(typ *byte, old []any, cap int) (ary []any)
 func memmove(to *any, frm *any, length uintptr)
 func memclr(ptr *byte, length uintptr)
index 8173a2e0cba396b6650ea820ebf7cd849d7747d7..91895dd8afba41fcccc4380bc28d34bc208d2e43 100644 (file)
@@ -1506,11 +1506,27 @@ opswitch:
                        r = walkexpr(r, init)
                        n = r
                } else {
-                       // makeslice(et *Type, nel int64, max int64) (ary []any)
-                       fn := syslook("makeslice")
+                       // n escapes; set up a call to makeslice.
+                       // When len and cap can fit into int, use makeslice instead of
+                       // makeslice64, which is faster and shorter on 32 bit platforms.
+
+                       len, cap := l, r
+
+                       fnname := "makeslice64"
+                       argtype := Types[TINT64]
+
+                       // typechecking guarantees that TIDEAL len/cap are positive and fit in an int.
+                       // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
+                       // will be handled by the negative range checks in makeslice during runtime.
+                       if (len.Type.IsKind(TIDEAL) || Maxintval[len.Type.Etype].Cmp(Maxintval[TUINT]) <= 0) &&
+                               (cap.Type.IsKind(TIDEAL) || Maxintval[cap.Type.Etype].Cmp(Maxintval[TUINT]) <= 0) {
+                               fnname = "makeslice"
+                               argtype = Types[TINT]
+                       }
 
+                       fn := syslook(fnname)
                        fn = substArgTypes(fn, t.Elem()) // any-1
-                       n = mkcall1(fn, n.Type, init, typename(t.Elem()), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
+                       n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
                }
 
        case ORUNESTR:
index e15e6c4dc65ad5667a212b1098dd5253a12e8717..dd8dcb18738148e77676d1fe2de54b41a20f8858 100644 (file)
@@ -36,21 +36,18 @@ func maxSliceCap(elemsize uintptr) uintptr {
        return _MaxMem / elemsize
 }
 
-// TODO: take uintptrs instead of int64s?
-func makeslice(et *_type, len64, cap64 int64) slice {
+func makeslice(et *_type, len, cap int) slice {
        // NOTE: The len > maxElements check here is not strictly necessary,
        // but it produces a 'len out of range' error instead of a 'cap out of range' error
        // when someone does make([]T, bignumber). 'cap out of range' is true too,
        // but since the cap is only being supplied implicitly, saying len is clearer.
        // See issue 4085.
        maxElements := maxSliceCap(et.size)
-       len := int(len64)
-       if len64 < 0 || int64(len) != len64 || uintptr(len) > maxElements {
+       if len < 0 || uintptr(len) > maxElements {
                panic(errorString("makeslice: len out of range"))
        }
 
-       cap := int(cap64)
-       if cap < len || int64(cap) != cap64 || uintptr(cap) > maxElements {
+       if cap < len || uintptr(cap) > maxElements {
                panic(errorString("makeslice: cap out of range"))
        }
 
@@ -58,6 +55,20 @@ func makeslice(et *_type, len64, cap64 int64) slice {
        return slice{p, len, cap}
 }
 
+func makeslice64(et *_type, len64, cap64 int64) slice {
+       len := int(len64)
+       if int64(len) != len64 {
+               panic(errorString("makeslice: len out of range"))
+       }
+
+       cap := int(cap64)
+       if int64(cap) != cap64 {
+               panic(errorString("makeslice: cap out of range"))
+       }
+
+       return makeslice(et, len, cap)
+}
+
 // growslice handles slice growth during append.
 // It is passed the slice element type, the old slice, and the desired new minimum capacity,
 // and it returns a new slice with at least that capacity, with the old data
index 583c417511985a051c4e9a8e343de921e40f4f3d..b91bbd748a3572932b981d6f72ea6163d24953ed 100644 (file)
@@ -15,21 +15,25 @@ type T []int
 
 func main() {
        n := -1
-       shouldPanic("len out of range", func() {_ = make(T, n)})
-       shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+       shouldPanic("len out of range", func() { _ = make(T, n) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
+       shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+       shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
        var t *byte
        if unsafe.Sizeof(t) == 8 {
-               n = 1<<20
+               n = 1 << 20
                n <<= 20
-               shouldPanic("len out of range", func() {_ = make(T, n)})
-               shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+               shouldPanic("len out of range", func() { _ = make(T, n) })
+               shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
                n <<= 20
-               shouldPanic("len out of range", func() {_ = make(T, n)})
-               shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+               shouldPanic("len out of range", func() { _ = make(T, n) })
+               shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
        } else {
                n = 1<<31 - 1
-               shouldPanic("len out of range", func() {_ = make(T, n)})
-               shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+               shouldPanic("len out of range", func() { _ = make(T, n) })
+               shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
+               shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+               shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
        }
 }
 
@@ -44,6 +48,6 @@ func shouldPanic(str string, f func()) {
                        panic("got panic " + s + ", want " + str)
                }
        }()
-       
+
        f()
 }