diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-01-18 19:04:36 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-01-18 19:04:36 +0000 |
commit | 4f4a855d82a889cebcfca150a7a43909bcb6a346 (patch) | |
tree | f12bae0781920fa34669fe30b6f4615a86d9fb80 /libgo/go/runtime/slice.go | |
parent | 225220d668dafb8262db7012bced688acbe63b33 (diff) | |
download | gcc-4f4a855d82a889cebcfca150a7a43909bcb6a346.zip gcc-4f4a855d82a889cebcfca150a7a43909bcb6a346.tar.gz gcc-4f4a855d82a889cebcfca150a7a43909bcb6a346.tar.bz2 |
libgo: update to Go1.12beta2
Reviewed-on: https://go-review.googlesource.com/c/158019
gotools/:
* Makefile.am (go_cmd_vet_files): Update for Go1.12beta2 release.
(GOTOOLS_TEST_TIMEOUT): Increase to 600.
(check-runtime): Export LD_LIBRARY_PATH before computing GOARCH
and GOOS.
(check-vet): Copy golang.org/x/tools into check-vet-dir.
* Makefile.in: Regenerate.
gcc/testsuite/:
* go.go-torture/execute/names-1.go: Stop using debug/xcoff, which
is no longer externally visible.
From-SVN: r268084
Diffstat (limited to 'libgo/go/runtime/slice.go')
-rw-r--r-- | libgo/go/runtime/slice.go | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go index 7f9db4e..335532d 100644 --- a/libgo/go/runtime/slice.go +++ b/libgo/go/runtime/slice.go @@ -5,6 +5,7 @@ package runtime import ( + "runtime/internal/math" "runtime/internal/sys" "unsafe" ) @@ -31,28 +32,6 @@ type notInHeapSlice struct { cap int } -// maxElems is a lookup table containing the maximum capacity for a slice. -// The index is the size of the slice element. -var maxElems = [...]uintptr{ - ^uintptr(0), - maxAlloc / 1, maxAlloc / 2, maxAlloc / 3, maxAlloc / 4, - maxAlloc / 5, maxAlloc / 6, maxAlloc / 7, maxAlloc / 8, - maxAlloc / 9, maxAlloc / 10, maxAlloc / 11, maxAlloc / 12, - maxAlloc / 13, maxAlloc / 14, maxAlloc / 15, maxAlloc / 16, - maxAlloc / 17, maxAlloc / 18, maxAlloc / 19, maxAlloc / 20, - maxAlloc / 21, maxAlloc / 22, maxAlloc / 23, maxAlloc / 24, - maxAlloc / 25, maxAlloc / 26, maxAlloc / 27, maxAlloc / 28, - maxAlloc / 29, maxAlloc / 30, maxAlloc / 31, maxAlloc / 32, -} - -// maxSliceCap returns the maximum capacity for a slice. -func maxSliceCap(elemsize uintptr) uintptr { - if elemsize < uintptr(len(maxElems)) { - return maxElems[elemsize] - } - return maxAlloc / elemsize -} - func panicmakeslicelen() { panic(errorString("makeslice: len out of range")) } @@ -62,21 +41,21 @@ func panicmakeslicecap() { } func makeslice(et *_type, len, cap int) unsafe.Pointer { - // 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) - if len < 0 || uintptr(len) > maxElements { - panicmakeslicelen() - } - - if cap < len || uintptr(cap) > maxElements { + mem, overflow := math.MulUintptr(et.size, uintptr(cap)) + if overflow || mem > maxAlloc || len < 0 || len > cap { + // NOTE: Produce 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 golang.org/issue/4085. + mem, overflow := math.MulUintptr(et.size, uintptr(len)) + if overflow || mem > maxAlloc || len < 0 { + panicmakeslicelen() + } panicmakeslicecap() } - return mallocgc(et.size*uintptr(cap), et, true) + return mallocgc(mem, et, true) } func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer { @@ -107,10 +86,11 @@ func growslice(et *_type, old slice, cap int) slice { msanread(old.array, uintptr(old.len*int(et.size))) } + if cap < old.cap { + panic(errorString("growslice: cap out of range")) + } + if et.size == 0 { - if cap < old.cap { - panic(errorString("growslice: cap out of range")) - } // append should not create a slice with nil pointer but non-zero len. // We assume that append doesn't need to preserve old.array in this case. return slice{unsafe.Pointer(&zerobase), cap, cap} @@ -172,15 +152,14 @@ func growslice(et *_type, old slice, cap int) slice { default: lenmem = uintptr(old.len) * et.size newlenmem = uintptr(cap) * et.size - capmem = roundupsize(uintptr(newcap) * et.size) - overflow = uintptr(newcap) > maxSliceCap(et.size) + capmem, overflow = math.MulUintptr(et.size, uintptr(newcap)) + capmem = roundupsize(capmem) newcap = int(capmem / et.size) } - // The check of overflow (uintptr(newcap) > maxSliceCap(et.size)) - // in addition to capmem > _MaxMem is needed to prevent an overflow - // which can be used to trigger a segfault on 32bit architectures - // with this example program: + // The check of overflow in addition to capmem > maxAlloc is needed + // to prevent an overflow which can be used to trigger a segfault + // on 32bit architectures with this example program: // // type T [1<<27 + 1]int64 // @@ -191,28 +170,26 @@ func growslice(et *_type, old slice, cap int) slice { // s = append(s, d, d, d, d) // print(len(s), "\n") // } - if cap < old.cap || overflow || capmem > maxAlloc { + if overflow || capmem > maxAlloc { panic(errorString("growslice: cap out of range")) } var p unsafe.Pointer if et.kind&kindNoPointers != 0 { p = mallocgc(capmem, nil, false) - memmove(p, old.array, lenmem) // The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length). // Only clear the part that will not be overwritten. memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem) } else { // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory. p = mallocgc(capmem, et, true) - if !writeBarrier.enabled { - memmove(p, old.array, lenmem) - } else { - for i := uintptr(0); i < lenmem; i += et.size { - typedmemmove(et, add(p, i), add(old.array, i)) - } + if writeBarrier.enabled { + // Only shade the pointers in old.array since we know the destination slice p + // only contains nil pointers because it has been cleared during alloc. + bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem) } } + memmove(p, old.array, lenmem) return slice{p, cap, newcap} } |