Commit 94f56408 by Ian Lance Taylor

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
parent 21f1031d
5ddcdfb0b2bb992a70b391ab34bf15291a514e48
fe38baff61b9b9426a4f60ff078cf3c8722bf94d
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -284,20 +284,19 @@ Node::op_format() const
op << "panic";
break;
case Runtime::APPEND:
case Runtime::GROWSLICE:
op << "append";
break;
case Runtime::COPY:
case Runtime::SLICECOPY:
case Runtime::SLICESTRINGCOPY:
case Runtime::TYPEDSLICECOPY:
op << "copy";
break;
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
case Runtime::MAKESLICE1:
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
case Runtime::MAKESLICE:
op << "make";
break;
......@@ -419,10 +418,7 @@ Node::is_big(Escape_context* context) const
Func_expression* fn = call->fn()->func_expression();
if (fn != NULL
&& fn->is_runtime_function()
&& (fn->runtime_code() == Runtime::MAKESLICE1
|| fn->runtime_code() == Runtime::MAKESLICE2
|| fn->runtime_code() == Runtime::MAKESLICE1BIG
|| fn->runtime_code() == Runtime::MAKESLICE2BIG))
&& fn->runtime_code() == Runtime::MAKESLICE)
{
// Second argument is length.
Expression_list::iterator p = call->args()->begin();
......@@ -1201,13 +1197,25 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
case Runtime::APPEND:
case Runtime::GROWSLICE:
{
// Unlike gc/esc.go, a call to append has already had its
// varargs lowered into a slice of arguments.
// The content of the appended slice leaks.
Node* appended = Node::make_node(call->args()->back());
this->assign_deref(this->context_->sink(), appended);
// The contents being appended leak.
if (call->is_varargs())
{
Node* appended = Node::make_node(call->args()->back());
this->assign_deref(this->context_->sink(), appended);
}
else
{
for (Expression_list::const_iterator pa =
call->args()->begin();
pa != call->args()->end();
++pa)
{
Node* arg = Node::make_node(*pa);
this->assign(this->context_->sink(), arg);
}
}
if (debug_level > 2)
go_error_at((*pexpr)->location(),
......@@ -1219,7 +1227,9 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
case Runtime::COPY:
case Runtime::SLICECOPY:
case Runtime::SLICESTRINGCOPY:
case Runtime::TYPEDSLICECOPY:
{
// Lose track of the copied content.
Node* copied = Node::make_node(call->args()->back());
......@@ -1229,10 +1239,7 @@ Escape_analysis_assign::expression(Expression** pexpr)
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
case Runtime::MAKESLICE1:
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
case Runtime::MAKESLICE:
case Runtime::SLICEBYTETOSTRING:
case Runtime::SLICERUNETOSTRING:
case Runtime::STRINGTOSLICEBYTE:
......@@ -1829,7 +1836,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
{
switch (fe->runtime_code())
{
case Runtime::APPEND:
case Runtime::GROWSLICE:
{
// Append returns the first argument.
// The subsequent arguments are already leaked because
......@@ -1841,10 +1848,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
case Runtime::MAKESLICE1:
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
case Runtime::MAKESLICE:
// DST = make(...).
case Runtime::SLICEBYTETOSTRING:
// DST = string([]byte{...}).
......@@ -2608,7 +2612,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
switch (func->runtime_code())
{
case Runtime::APPEND:
case Runtime::GROWSLICE:
{
// Propagate escape information to appendee.
Expression* appendee = call->args()->front();
......@@ -2618,10 +2622,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
case Runtime::MAKESLICE1:
case Runtime::MAKESLICE2:
case Runtime::MAKESLICE1BIG:
case Runtime::MAKESLICE2BIG:
case Runtime::MAKESLICE:
case Runtime::SLICEBYTETOSTRING:
case Runtime::SLICERUNETOSTRING:
case Runtime::STRINGTOSLICEBYTE:
......
......@@ -425,9 +425,9 @@ Runtime::name_to_code(const std::string& name)
else if (name == "close")
code = Runtime::CLOSE;
else if (name == "copy")
code = Runtime::COPY;
code = Runtime::SLICECOPY;
else if (name == "append")
code = Runtime::APPEND;
code = Runtime::GROWSLICE;
else if (name == "delete")
code = Runtime::MAPDELETE;
else
......
......@@ -87,12 +87,7 @@ DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
// Make a slice.
DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE1BIG, "__go_make_slice1_big", P2(TYPE, UINT64),
R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE2BIG, "__go_make_slice2_big", P3(TYPE, UINT64, UINT64),
DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT64, INT64),
R1(SLICE))
......@@ -211,11 +206,20 @@ DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0())
// Copy.
DEF_GO_RUNTIME(COPY, "__go_copy", P3(POINTER, POINTER, UINTPTR), R0())
DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR),
R1(INT))
// Append.
DEF_GO_RUNTIME(APPEND, "__go_append", P4(SLICE, POINTER, UINTPTR, UINTPTR),
R1(SLICE))
// Copy from string.
DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING),
R1(INT))
// Copy of value containing pointers.
DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
P3(TYPE, SLICE, SLICE), R1(INT))
// Grow a slice for append.
DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice", P3(TYPE, SLICE, INT), R1(SLICE))
// Register roots (global variables) for the garbage collector.
......
......@@ -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 \
......
......@@ -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
......
// 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
}
......@@ -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
}
/* 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;
}
/* 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);
}
/* 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);
}
......@@ -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() {
......
......@@ -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;
......
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