]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Avoid always splitting the stack when calling append and copy.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 17 Dec 2010 06:33:41 +0000 (06:33 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 17 Dec 2010 06:33:41 +0000 (06:33 +0000)
From-SVN: r167970

gcc/go/gofrontend/expressions.cc
libgo/Makefile.am
libgo/Makefile.in
libgo/runtime/go-append.c
libgo/runtime/go-copy.c [new file with mode: 0644]

index 553e6d662c31531504b79a445641784114962f2e..cb5c45c2eb19f548803eeff339be81d5f172429c 100644 (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:
index 46165dfb48fdd48e21f74ebbaee10d6be8b4e855..cddcd2439e7f7643a1afb474f13abed5dbc3876b 100644 (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 \
index ec0f3e2920d8f2727d999bc7a04464ec70b5fb82..4ccd863124c92d22d2dd3c187a0f8a876280e2be 100644 (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
index aa8f4a16d0c9303856c2e4db64bd25f39b1e9877..91493b1b78d7ecb4082e1f0f99b0ec723eaa43c9 100644 (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;
 }
diff --git a/libgo/runtime/go-copy.c b/libgo/runtime/go-copy.c
new file mode 100644 (file)
index 0000000..998aeb9
--- /dev/null
@@ -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);
+}