Avoid always splitting the stack when calling append and copy.
From-SVN: r167970
This commit is contained in:
parent
94c4ae3215
commit
b5343013fe
5 changed files with 103 additions and 34 deletions
|
@ -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(©_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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
21
libgo/runtime/go-copy.c
Normal 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);
|
||||
}
|
Loading…
Add table
Reference in a new issue