Avoid always splitting the stack when calling append and copy.

From-SVN: r167970
This commit is contained in:
Ian Lance Taylor 2010-12-17 06:33:41 +00:00
parent 94c4ae3215
commit b5343013fe
5 changed files with 103 additions and 34 deletions

View File

@ -7785,9 +7785,23 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
bytecount, element_size);
bytecount = fold_convert_loc(location, size_type_node, bytecount);
tree call = build_call_expr_loc(location,
built_in_decls[BUILT_IN_MEMMOVE],
3, arg1_val, arg2_val, bytecount);
arg1_val = fold_convert_loc(location, ptr_type_node, arg1_val);
arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
static tree copy_fndecl;
tree call = Gogo::call_builtin(&copy_fndecl,
location,
"__go_copy",
3,
void_type_node,
ptr_type_node,
arg1_val,
ptr_type_node,
arg2_val,
size_type_node,
bytecount);
if (call == error_mark_node)
return error_mark_node;
return fold_build2_loc(location, COMPOUND_EXPR, TREE_TYPE(len),
call, len);
@ -7800,12 +7814,29 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
Expression* arg1 = args->front();
Expression* arg2 = args->back();
Array_type* at = arg1->type()->array_type();
Type* element_type = at->element_type();
tree arg1_tree = arg1->get_tree(context);
tree arg2_tree = arg2->get_tree(context);
if (arg1_tree == error_mark_node || arg2_tree == error_mark_node)
return error_mark_node;
tree descriptor_tree = arg1->type()->type_descriptor_pointer(gogo);
Array_type* at2 = arg2->type()->array_type();
arg2_tree = save_expr(arg2_tree);
tree arg2_val = at2->value_pointer_tree(gogo, arg2_tree);
tree arg2_len = at2->length_tree(gogo, arg2_tree);
if (arg2_val == error_mark_node || arg2_len == error_mark_node)
return error_mark_node;
arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
arg2_len = fold_convert_loc(location, size_type_node, arg2_len);
tree element_type_tree = element_type->get_tree(gogo);
if (element_type_tree == error_mark_node)
return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
element_size = fold_convert_loc(location, size_type_node,
element_size);
// We rebuild the decl each time since the slice types may
// change.
@ -7813,14 +7844,16 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
return Gogo::call_builtin(&append_fndecl,
location,
"__go_append",
3,
4,
TREE_TYPE(arg1_tree),
TREE_TYPE(descriptor_tree),
descriptor_tree,
TREE_TYPE(arg1_tree),
arg1_tree,
TREE_TYPE(arg2_tree),
arg2_tree);
ptr_type_node,
arg2_val,
size_type_node,
arg2_len,
size_type_node,
element_size);
}
case BUILTIN_REAL:

View File

@ -319,6 +319,7 @@ runtime_files = \
runtime/go-closed.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
runtime/go-defer.c \
runtime/go-deferred-recover.c \
runtime/go-eface-compare.c \

View File

@ -129,10 +129,10 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-chan-cap.c runtime/go-chan-len.c \
runtime/go-check-interface.c runtime/go-close.c \
runtime/go-closed.c runtime/go-construct-map.c \
runtime/go-convert-interface.c runtime/go-defer.c \
runtime/go-deferred-recover.c runtime/go-eface-compare.c \
runtime/go-eface-val-compare.c runtime/go-getgoroot.c \
runtime/go-go.c runtime/go-gomaxprocs.c \
runtime/go-convert-interface.c runtime/go-copy.c \
runtime/go-defer.c runtime/go-deferred-recover.c \
runtime/go-eface-compare.c runtime/go-eface-val-compare.c \
runtime/go-getgoroot.c runtime/go-go.c runtime/go-gomaxprocs.c \
runtime/go-int-array-to-string.c runtime/go-int-to-string.c \
runtime/go-interface-compare.c \
runtime/go-interface-val-compare.c runtime/go-lock-os-thread.c \
@ -174,8 +174,8 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
go-can-convert-interface.lo go-chan-cap.lo go-chan-len.lo \
go-check-interface.lo go-close.lo go-closed.lo \
go-construct-map.lo go-convert-interface.lo go-defer.lo \
go-deferred-recover.lo go-eface-compare.lo \
go-construct-map.lo go-convert-interface.lo go-copy.lo \
go-defer.lo go-deferred-recover.lo go-eface-compare.lo \
go-eface-val-compare.lo go-getgoroot.lo go-go.lo \
go-gomaxprocs.lo go-int-array-to-string.lo go-int-to-string.lo \
go-interface-compare.lo go-interface-val-compare.lo \
@ -685,6 +685,7 @@ runtime_files = \
runtime/go-closed.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
runtime/go-defer.c \
runtime/go-deferred-recover.c \
runtime/go-eface-compare.c \
@ -1892,6 +1893,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-closed.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-convert-interface.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-eface-compare.Plo@am__quote@
@ -2109,6 +2111,13 @@ go-convert-interface.lo: runtime/go-convert-interface.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-convert-interface.lo `test -f 'runtime/go-convert-interface.c' || echo '$(srcdir)/'`runtime/go-convert-interface.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

View File

@ -4,37 +4,43 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
#include "go-assert.h"
#include "go-type.h"
#include "go-panic.h"
#include "array.h"
#include "runtime.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 *, size_t, size_t)
__attribute__ ((no_split_stack));
struct __go_open_array
__go_append (const struct __go_slice_type *type,
struct __go_open_array a, struct __go_open_array b)
__go_append (struct __go_open_array a, void *bvalues, size_t bcount,
size_t element_size)
{
size_t element_size;
unsigned int ucount;
size_t ucount;
int count;
if (b.__values == NULL || b.__count == 0)
if (bvalues == NULL || bcount == 0)
return a;
__go_assert (type->__common.__code == GO_SLICE);
element_size = type->__element_type->__size;
ucount = (unsigned int) a.__count + (unsigned int) b.__count;
ucount = (size_t) a.__count + bcount;
count = (int) ucount;
__go_assert (ucount == (unsigned int) count && count >= a.__count);
if ((size_t) count != ucount || count <= a.__count)
__go_panic_msg ("append: slice overflow");
if (count > a.__capacity)
{
int m;
struct __go_open_array n;
void *n;
m = a.__capacity;
if (m == 0)
m = b.__count;
m = (int) bcount;
else
{
do
@ -47,16 +53,15 @@ __go_append (const struct __go_slice_type *type,
while (m < count);
}
n.__values = __go_alloc (m * element_size);
n.__count = a.__count;
n.__capacity = m;
__builtin_memcpy (n.__values, a.__values, n.__count * element_size);
n = __go_alloc (m * element_size);
__builtin_memcpy (n, a.__values, a.__count * element_size);
a = n;
a.__values = n;
a.__capacity = m;
}
__builtin_memmove ((char *) a.__values + a.__count * element_size,
b.__values, b.__count * element_size);
bvalues, bcount * element_size);
a.__count = count;
return a;
}

21
libgo/runtime/go-copy.c Normal file
View File

@ -0,0 +1,21 @@
/* 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>
/* 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 *, size_t)
__attribute__ ((no_split_stack));
void
__go_copy (void *a, void *b, size_t len)
{
__builtin_memmove (a, b, len);
}