diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-10-28 22:34:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-10-28 22:34:47 +0000 |
commit | 94f56408db96e2e12f6e1322ed2c1c465df934f6 (patch) | |
tree | f5eaac76bc47cc2637e5e30b9ff6c27499fac2d9 /libgo | |
parent | 21f1031d6cc228e2b468338b3dfa4303d54ac207 (diff) | |
download | gcc-94f56408db96e2e12f6e1322ed2c1c465df934f6.zip gcc-94f56408db96e2e12f6e1322ed2c1c465df934f6.tar.gz gcc-94f56408db96e2e12f6e1322ed2c1c465df934f6.tar.bz2 |
compiler, runtime: copy slice code from Go 1.7 runtime
Change the compiler handle append as the gc compiler does: call a
function to grow the slice, but otherwise assign the new elements
directly to the final slice.
For the current gccgo memory allocator the slice code has to call
runtime_newarray, not mallocgc directly, so that the allocator sets the
TypeInfo_Array bit in the type pointer.
Rename the static function cnew to runtime_docnew, so that the stack
trace ignores it when ignoring runtime functions. This was needed to
fix the runtime/pprof tests on 386.
Reviewed-on: https://go-review.googlesource.com/32218
From-SVN: r241667
Diffstat (limited to 'libgo')
-rw-r--r-- | libgo/Makefile.am | 3 | ||||
-rw-r--r-- | libgo/Makefile.in | 60 | ||||
-rw-r--r-- | libgo/go/runtime/slice.go | 212 | ||||
-rw-r--r-- | libgo/go/runtime/stubs.go | 25 | ||||
-rw-r--r-- | libgo/runtime/go-append.c | 74 | ||||
-rw-r--r-- | libgo/runtime/go-copy.c | 22 | ||||
-rw-r--r-- | libgo/runtime/go-make-slice.c | 99 | ||||
-rw-r--r-- | libgo/runtime/malloc.goc | 8 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 3 |
9 files changed, 254 insertions, 252 deletions
diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 2e46ecd..8237bb6 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -428,7 +428,6 @@ endif endif runtime_files = \ - runtime/go-append.c \ runtime/go-assert.c \ runtime/go-breakpoint.c \ runtime/go-caller.c \ @@ -436,12 +435,10 @@ runtime_files = \ runtime/go-cdiv.c \ runtime/go-cgo.c \ runtime/go-construct-map.c \ - runtime/go-copy.c \ runtime/go-defer.c \ runtime/go-deferred-recover.c \ runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-make-slice.c \ runtime/go-matherr.c \ runtime/go-memclr.c \ runtime/go-memcmp.c \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 25b5a7b..50fc3f6 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -237,23 +237,22 @@ libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_4 = \ @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo @LIBGO_IS_LINUX_TRUE@am__objects_4 = getncpu-linux.lo -am__objects_5 = go-append.lo go-assert.lo go-breakpoint.lo \ - go-caller.lo go-callers.lo go-cdiv.lo go-cgo.lo \ - go-construct-map.lo go-copy.lo go-defer.lo \ - go-deferred-recover.lo go-ffi.lo go-fieldtrack.lo \ - go-make-slice.lo go-matherr.lo go-memclr.lo go-memcmp.lo \ - go-memequal.lo go-memmove.lo go-nanotime.lo go-now.lo \ - go-new.lo go-nosys.lo go-panic.lo go-recover.lo \ - go-reflect-call.lo go-runtime-error.lo go-setenv.lo \ - go-signal.lo go-strslice.lo go-type-complex.lo \ - go-type-float.lo go-type-identity.lo go-type-string.lo \ - go-typedesc-equal.lo go-unsafe-new.lo go-unsafe-newarray.lo \ - go-unsafe-pointer.lo go-unsetenv.lo go-unwind.lo go-varargs.lo \ - env_posix.lo heapdump.lo mcache.lo mcentral.lo \ - $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo msize.lo \ - panic.lo parfor.lo print.lo proc.lo runtime.lo signal_unix.lo \ - thread.lo $(am__objects_2) yield.lo $(am__objects_3) malloc.lo \ - runtime1.lo sigqueue.lo $(am__objects_4) +am__objects_5 = go-assert.lo go-breakpoint.lo go-caller.lo \ + go-callers.lo go-cdiv.lo go-cgo.lo go-construct-map.lo \ + go-defer.lo go-deferred-recover.lo go-ffi.lo go-fieldtrack.lo \ + go-matherr.lo go-memclr.lo go-memcmp.lo go-memequal.lo \ + go-memmove.lo go-nanotime.lo go-now.lo go-new.lo go-nosys.lo \ + go-panic.lo go-recover.lo go-reflect-call.lo \ + go-runtime-error.lo go-setenv.lo go-signal.lo go-strslice.lo \ + go-type-complex.lo go-type-float.lo go-type-identity.lo \ + go-type-string.lo go-typedesc-equal.lo go-unsafe-new.lo \ + go-unsafe-newarray.lo go-unsafe-pointer.lo go-unsetenv.lo \ + go-unwind.lo go-varargs.lo env_posix.lo heapdump.lo mcache.lo \ + mcentral.lo $(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo \ + msize.lo panic.lo parfor.lo print.lo proc.lo runtime.lo \ + signal_unix.lo thread.lo $(am__objects_2) yield.lo \ + $(am__objects_3) malloc.lo runtime1.lo sigqueue.lo \ + $(am__objects_4) am_libgo_llgo_la_OBJECTS = $(am__objects_5) libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS) libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -824,7 +823,6 @@ toolexeclibgounicode_DATA = \ @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c @LIBGO_IS_LINUX_TRUE@runtime_getncpu_file = runtime/getncpu-linux.c runtime_files = \ - runtime/go-append.c \ runtime/go-assert.c \ runtime/go-breakpoint.c \ runtime/go-caller.c \ @@ -832,12 +830,10 @@ runtime_files = \ runtime/go-cdiv.c \ runtime/go-cgo.c \ runtime/go-construct-map.c \ - runtime/go-copy.c \ runtime/go-defer.c \ runtime/go-deferred-recover.c \ runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-make-slice.c \ runtime/go-matherr.c \ runtime/go-memclr.c \ runtime/go-memcmp.c \ @@ -1519,7 +1515,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-none.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-solaris.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-append.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-breakpoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@ @@ -1527,12 +1522,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cdiv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-defer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-deferred-recover.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-fieldtrack.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-make-slice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-matherr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-memclr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-memcmp.Plo@am__quote@ @@ -1650,13 +1643,6 @@ libgolibbegin_a-go-libmain.obj: runtime/go-libmain.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgolibbegin_a_CFLAGS) $(CFLAGS) -c -o libgolibbegin_a-go-libmain.obj `if test -f 'runtime/go-libmain.c'; then $(CYGPATH_W) 'runtime/go-libmain.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-libmain.c'; fi` -go-append.lo: runtime/go-append.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-append.lo -MD -MP -MF $(DEPDIR)/go-append.Tpo -c -o go-append.lo `test -f 'runtime/go-append.c' || echo '$(srcdir)/'`runtime/go-append.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-append.Tpo $(DEPDIR)/go-append.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-append.c' object='go-append.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-append.lo `test -f 'runtime/go-append.c' || echo '$(srcdir)/'`runtime/go-append.c - go-assert.lo: runtime/go-assert.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-assert.lo -MD -MP -MF $(DEPDIR)/go-assert.Tpo -c -o go-assert.lo `test -f 'runtime/go-assert.c' || echo '$(srcdir)/'`runtime/go-assert.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-assert.Tpo $(DEPDIR)/go-assert.Plo @@ -1706,13 +1692,6 @@ go-construct-map.lo: runtime/go-construct-map.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-construct-map.lo `test -f 'runtime/go-construct-map.c' || echo '$(srcdir)/'`runtime/go-construct-map.c -go-copy.lo: runtime/go-copy.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-copy.lo -MD -MP -MF $(DEPDIR)/go-copy.Tpo -c -o go-copy.lo `test -f 'runtime/go-copy.c' || echo '$(srcdir)/'`runtime/go-copy.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-copy.Tpo $(DEPDIR)/go-copy.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-copy.c' object='go-copy.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-copy.lo `test -f 'runtime/go-copy.c' || echo '$(srcdir)/'`runtime/go-copy.c - go-defer.lo: runtime/go-defer.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-defer.lo -MD -MP -MF $(DEPDIR)/go-defer.Tpo -c -o go-defer.lo `test -f 'runtime/go-defer.c' || echo '$(srcdir)/'`runtime/go-defer.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-defer.Tpo $(DEPDIR)/go-defer.Plo @@ -1741,13 +1720,6 @@ go-fieldtrack.lo: runtime/go-fieldtrack.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c -go-make-slice.lo: runtime/go-make-slice.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-make-slice.lo -MD -MP -MF $(DEPDIR)/go-make-slice.Tpo -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-make-slice.Tpo $(DEPDIR)/go-make-slice.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-make-slice.c' object='go-make-slice.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c - go-matherr.lo: runtime/go-matherr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-matherr.lo -MD -MP -MF $(DEPDIR)/go-matherr.Tpo -c -o go-matherr.lo `test -f 'runtime/go-matherr.c' || echo '$(srcdir)/'`runtime/go-matherr.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-matherr.Tpo $(DEPDIR)/go-matherr.Plo diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go new file mode 100644 index 0000000..4548a5b --- /dev/null +++ b/libgo/go/runtime/slice.go @@ -0,0 +1,212 @@ +// Copyright 2009 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 runtime + +import ( + "unsafe" +) + +// For gccgo, use go:linkname to rename compiler-called functions to +// themselves, so that the compiler will export them. +// +//go:linkname makeslice runtime.makeslice +//go:linkname growslice runtime.growslice +//go:linkname slicecopy runtime.slicecopy +//go:linkname slicestringcopy runtime.slicestringcopy + +type slice struct { + array unsafe.Pointer + len int + 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), + _MaxMem / 1, _MaxMem / 2, _MaxMem / 3, _MaxMem / 4, + _MaxMem / 5, _MaxMem / 6, _MaxMem / 7, _MaxMem / 8, + _MaxMem / 9, _MaxMem / 10, _MaxMem / 11, _MaxMem / 12, + _MaxMem / 13, _MaxMem / 14, _MaxMem / 15, _MaxMem / 16, + _MaxMem / 17, _MaxMem / 18, _MaxMem / 19, _MaxMem / 20, + _MaxMem / 21, _MaxMem / 22, _MaxMem / 23, _MaxMem / 24, + _MaxMem / 25, _MaxMem / 26, _MaxMem / 27, _MaxMem / 28, + _MaxMem / 29, _MaxMem / 30, _MaxMem / 31, _MaxMem / 32, +} + +// maxSliceCap returns the maximum capacity for a slice. +func maxSliceCap(elemsize uintptr) uintptr { + if elemsize < uintptr(len(maxElems)) { + return maxElems[elemsize] + } + return _MaxMem / elemsize +} + +// TODO: take uintptrs instead of int64s? +func makeslice(et *_type, len64, cap64 int64) 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 { + panic(errorString("makeslice: len out of range")) + } + + cap := int(cap64) + if cap < len || int64(cap) != cap64 || uintptr(cap) > maxElements { + panic(errorString("makeslice: cap out of range")) + } + + // gccgo's current garbage collector requires using newarray, + // not mallocgc here. This can change back to mallocgc when + // we port the garbage collector. + p := newarray(et, cap) + return slice{p, 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 +// copied into it. +// The new slice's length is set to the requested capacity. +func growslice(et *_type, old slice, cap int) slice { + if raceenabled { + callerpc := getcallerpc(unsafe.Pointer(&et)) + racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice)) + } + if msanenabled { + msanread(old.array, uintptr(old.len*int(et.size))) + } + + 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} + } + + newcap := old.cap + doublecap := newcap + newcap + if cap > doublecap { + newcap = cap + } else { + if old.len < 1024 { + newcap = doublecap + } else { + for newcap < cap { + newcap += newcap / 4 + } + } + } + + var lenmem, capmem uintptr + const ptrSize = unsafe.Sizeof((*byte)(nil)) + switch et.size { + case 1: + lenmem = uintptr(old.len) + capmem = roundupsize(uintptr(newcap)) + newcap = int(capmem) + case ptrSize: + lenmem = uintptr(old.len) * ptrSize + capmem = roundupsize(uintptr(newcap) * ptrSize) + newcap = int(capmem / ptrSize) + default: + lenmem = uintptr(old.len) * et.size + capmem = roundupsize(uintptr(newcap) * et.size) + newcap = int(capmem / et.size) + } + + if cap < old.cap || uintptr(newcap) > maxSliceCap(et.size) { + panic(errorString("growslice: cap out of range")) + } + + var p unsafe.Pointer + if et.kind&kindNoPointers != 0 { + // gccgo's current GC requires newarray, not mallocgc. + p = newarray(et, newcap) + memmove(p, old.array, lenmem) + // The call to memclr is not needed for gccgo since + // the newarray function will zero the memory. + // Calling memclr is also wrong since we allocated + // newcap*et.size bytes, which is not the same as capmem. + // memclr(add(p, lenmem), capmem-lenmem) + } else { + // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory. + // gccgo's current GC requires newarray, not mallocgc. + p = newarray(et, newcap) + 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)) + } + } + } + + return slice{p, cap, newcap} +} + +func slicecopy(to, fm slice, width uintptr) int { + if fm.len == 0 || to.len == 0 { + return 0 + } + + n := fm.len + if to.len < n { + n = to.len + } + + if width == 0 { + return n + } + + if raceenabled { + callerpc := getcallerpc(unsafe.Pointer(&to)) + pc := funcPC(slicecopy) + racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc) + racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc) + } + if msanenabled { + msanwrite(to.array, uintptr(n*int(width))) + msanread(fm.array, uintptr(n*int(width))) + } + + size := uintptr(n) * width + if size == 1 { // common case worth about 2x to do here + // TODO: is this still worth it with new memmove impl? + *(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer + } else { + memmove(to.array, fm.array, size) + } + return n +} + +func slicestringcopy(to []byte, fm string) int { + if len(fm) == 0 || len(to) == 0 { + return 0 + } + + n := len(fm) + if len(to) < n { + n = len(to) + } + + if raceenabled { + callerpc := getcallerpc(unsafe.Pointer(&to)) + pc := funcPC(slicestringcopy) + racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc) + } + if msanenabled { + msanwrite(unsafe.Pointer(&to[0]), uintptr(n)) + } + + memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n)) + return n +} diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go index 5924ee6..755933d 100644 --- a/libgo/go/runtime/stubs.go +++ b/libgo/go/runtime/stubs.go @@ -253,11 +253,18 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) { memmove(dst, src, typ.size) } -// Here for gccgo unless and until we port slice.go. -type slice struct { - array unsafe.Pointer - len int - cap int +// Temporary for gccgo until we port mbarrier.go. +//go:linkname typedslicecopy runtime.typedslicecopy +func typedslicecopy(typ *_type, dst, src slice) int { + n := dst.len + if n > src.len { + n = src.len + } + if n == 0 { + return 0 + } + memmove(dst.array, src.array, uintptr(n)*typ.size) + return n } // Here for gccgo until we port malloc.go. @@ -474,3 +481,11 @@ func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) { func writebarrierptr(dst *uintptr, src uintptr) { *dst = src } + +// Temporary for gccgo until we port malloc.go +var zerobase uintptr + +//go:linkname getZerobase runtime.getZerobase +func getZerobase() *uintptr { + return &zerobase +} diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c deleted file mode 100644 index 1b2d49e..0000000 --- a/libgo/runtime/go-append.c +++ /dev/null @@ -1,74 +0,0 @@ -/* go-append.c -- the go builtin append function. - - Copyright 2010 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. */ - -#include "runtime.h" -#include "go-panic.h" -#include "go-type.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -/* We should be OK if we don't split the stack here, since the only - libc functions we call are memcpy and memmove. If we don't do - this, we will always split the stack, because of memcpy and - memmove. */ -extern struct __go_open_array -__go_append (struct __go_open_array, void *, uintptr_t, uintptr_t) - __attribute__ ((no_split_stack)); - -struct __go_open_array -__go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount, - uintptr_t element_size) -{ - uintptr_t ucount; - intgo count; - - if (bvalues == NULL || bcount == 0) - return a; - - ucount = (uintptr_t) a.__count + bcount; - count = (intgo) ucount; - if ((uintptr_t) count != ucount || count <= a.__count) - runtime_panicstring ("append: slice overflow"); - - if (count > a.__capacity) - { - intgo m; - uintptr capmem; - void *n; - - m = a.__capacity; - if (m + m < count) - m = count; - else - { - do - { - if (a.__count < 1024) - m += m; - else - m += m / 4; - } - while (m < count); - } - - if (element_size > 0 && (uintptr) m > MaxMem / element_size) - runtime_panicstring ("growslice: cap out of range"); - - capmem = runtime_roundupsize (m * element_size); - - n = __go_alloc (capmem); - __builtin_memcpy (n, a.__values, a.__count * element_size); - - a.__values = n; - a.__capacity = m; - } - - __builtin_memmove ((char *) a.__values + a.__count * element_size, - bvalues, bcount * element_size); - a.__count = count; - return a; -} diff --git a/libgo/runtime/go-copy.c b/libgo/runtime/go-copy.c deleted file mode 100644 index 05e16acb..0000000 --- a/libgo/runtime/go-copy.c +++ /dev/null @@ -1,22 +0,0 @@ -/* go-append.c -- the go builtin copy function. - - Copyright 2010 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. */ - -#include <stddef.h> -#include <stdint.h> - -/* We should be OK if we don't split the stack here, since we are just - calling memmove which shouldn't need much stack. If we don't do - this we will always split the stack, because of memmove. */ - -extern void -__go_copy (void *, void *, uintptr_t) - __attribute__ ((no_split_stack)); - -void -__go_copy (void *a, void *b, uintptr_t len) -{ - __builtin_memmove (a, b, len); -} diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c deleted file mode 100644 index ccd07e5..0000000 --- a/libgo/runtime/go-make-slice.c +++ /dev/null @@ -1,99 +0,0 @@ -/* go-make-slice.c -- make a slice. - - Copyright 2011 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. */ - -#include <stdint.h> - -#include "runtime.h" -#include "go-alloc.h" -#include "go-assert.h" -#include "go-panic.h" -#include "go-type.h" -#include "array.h" -#include "arch.h" -#include "malloc.h" - -/* Dummy word to use as base pointer for make([]T, 0). - Since you cannot take the address of such a slice, - you can't tell that they all have the same base pointer. */ -uintptr runtime_zerobase; - -struct __go_open_array -__go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len, - uintptr_t cap) -{ - const struct __go_slice_type* std; - intgo ilen; - intgo icap; - uintptr_t size; - struct __go_open_array ret; - - __go_assert ((td->__code & GO_CODE_MASK) == GO_SLICE); - std = (const struct __go_slice_type *) td; - - ilen = (intgo) len; - if (ilen < 0 - || (uintptr_t) ilen != len - || (std->__element_type->__size > 0 - && len > MaxMem / std->__element_type->__size)) - runtime_panicstring ("makeslice: len out of range"); - - icap = (intgo) cap; - if (cap < len - || (uintptr_t) icap != cap - || (std->__element_type->__size > 0 - && cap > MaxMem / std->__element_type->__size)) - runtime_panicstring ("makeslice: cap out of range"); - - ret.__count = ilen; - ret.__capacity = icap; - - size = cap * std->__element_type->__size; - - if (size == 0) - ret.__values = &runtime_zerobase; - else if ((std->__element_type->__code & GO_NO_POINTERS) != 0) - ret.__values = - runtime_mallocgc (size, - (uintptr) std->__element_type | TypeInfo_Array, - FlagNoScan); - else - ret.__values = - runtime_mallocgc (size, - (uintptr) std->__element_type | TypeInfo_Array, - 0); - - return ret; -} - -struct __go_open_array -__go_make_slice1 (const struct __go_type_descriptor *td, uintptr_t len) -{ - return __go_make_slice2 (td, len, len); -} - -struct __go_open_array -__go_make_slice2_big (const struct __go_type_descriptor *td, uint64_t len, - uint64_t cap) -{ - uintptr_t slen; - uintptr_t scap; - - slen = (uintptr_t) len; - if ((uint64_t) slen != len) - runtime_panicstring ("makeslice: len out of range"); - - scap = (uintptr_t) cap; - if ((uint64_t) scap != cap) - runtime_panicstring ("makeslice: cap out of range"); - - return __go_make_slice2 (td, slen, scap); -} - -struct __go_open_array -__go_make_slice1_big (const struct __go_type_descriptor *td, uint64_t len) -{ - return __go_make_slice2_big (td, len, len); -} diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc index 1fd4461..5cbdc46 100644 --- a/libgo/runtime/malloc.goc +++ b/libgo/runtime/malloc.goc @@ -81,7 +81,7 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag) // All 0-length allocations use this pointer. // The language does not require the allocations to // have distinct values. - return &runtime_zerobase; + return runtime_getZerobase(); } g = runtime_g(); @@ -881,7 +881,7 @@ func new(typ *Type) (ret *uint8) { } static void* -cnew(const Type *typ, intgo n, int32 objtyp) +runtime_docnew(const Type *typ, intgo n, int32 objtyp) { if((objtyp&(PtrSize-1)) != objtyp) runtime_throw("runtime: invalid objtyp"); @@ -894,13 +894,13 @@ cnew(const Type *typ, intgo n, int32 objtyp) void* runtime_cnew(const Type *typ) { - return cnew(typ, 1, TypeInfo_SingleObject); + return runtime_docnew(typ, 1, TypeInfo_SingleObject); } void* runtime_cnewarray(const Type *typ, intgo n) { - return cnew(typ, n, TypeInfo_Array); + return runtime_docnew(typ, n, TypeInfo_Array); } func GC() { diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 8be0df4..501f1b4 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -234,7 +234,8 @@ enum /* * external data */ -extern uintptr runtime_zerobase; +extern uintptr* runtime_getZerobase(void) + __asm__(GOSYM_PREFIX "runtime.getZerobase"); extern G** runtime_allg; extern uintptr runtime_allglen; extern G* runtime_lastg; |