From b5343013fe2755e0ce86306e17ba316cddcc6e24 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 17 Dec 2010 06:33:41 +0000 Subject: [PATCH] Avoid always splitting the stack when calling append and copy. From-SVN: r167970 --- gcc/go/gofrontend/expressions.cc | 51 ++++++++++++++++++++++++++------ libgo/Makefile.am | 1 + libgo/Makefile.in | 21 +++++++++---- libgo/runtime/go-append.c | 43 +++++++++++++++------------ libgo/runtime/go-copy.c | 21 +++++++++++++ 5 files changed, 103 insertions(+), 34 deletions(-) create mode 100644 libgo/runtime/go-copy.c diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 553e6d662c3..cb5c45c2eb1 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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: diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 46165dfb48f..cddcd2439e7 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -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 \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index ec0f3e2920d..4ccd863124c 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -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 diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c index aa8f4a16d0c..91493b1b78d 100644 --- a/libgo/runtime/go-append.c +++ b/libgo/runtime/go-append.c @@ -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; } diff --git a/libgo/runtime/go-copy.c b/libgo/runtime/go-copy.c new file mode 100644 index 00000000000..998aeb927d4 --- /dev/null +++ b/libgo/runtime/go-copy.c @@ -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 + +/* 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); +}