diff mbox

[gccgo] Mark memory which can not contain pointers

Message ID mcrbp9yywo4.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor July 23, 2010, 4:45 p.m. UTC
This patch uses a different allocation routine for memory which can not
contain pointers (e.g., []byte).  The marking already exists in the
memory allocator, this just changes the compiler to use it.  This is in
preparation for garbage collection.  Committed to gccgo branch.

Ian
diff mbox

Patch

diff -r 640e5a4f513f go/expressions.cc
--- a/go/expressions.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/expressions.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -10252,8 +10252,9 @@ 
 {
   tree type_tree = this->type_->get_tree(context->gogo());
   tree size_tree = TYPE_SIZE_UNIT(type_tree);
-  tree space = context->gogo()->allocate_memory(size_tree, this->location());
-  return fold_convert(build_pointer_type (type_tree), space);
+  tree space = context->gogo()->allocate_memory(this->type_, size_tree,
+						this->location());
+  return fold_convert(build_pointer_type(type_tree), space);
 }
 
 // Make an allocation expression.
@@ -11122,7 +11123,8 @@ 
   else
     {
       tree memsize = TYPE_SIZE_UNIT(TREE_TYPE(values));
-      space = context->gogo()->allocate_memory(memsize, this->location());
+      space = context->gogo()->allocate_memory(element_type, memsize,
+					       this->location());
       space = save_expr(space);
 
       tree s = fold_convert(build_pointer_type(TREE_TYPE(values)), space);
@@ -12106,7 +12108,8 @@ 
     return error_mark_node;
   tree expr_size = TYPE_SIZE_UNIT(TREE_TYPE(expr_tree));
   gcc_assert(TREE_CODE(expr_size) == INTEGER_CST);
-  tree space = context->gogo()->allocate_memory(expr_size, this->location());
+  tree space = context->gogo()->allocate_memory(this->expr_->type(),
+						expr_size, this->location());
   space = fold_convert(build_pointer_type(TREE_TYPE(expr_tree)), space);
   space = save_expr(space);
   tree ret = build2(COMPOUND_EXPR, TREE_TYPE(space),
diff -r 640e5a4f513f go/gogo-tree.cc
--- a/go/gogo-tree.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo-tree.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -666,6 +666,12 @@ 
 
   // Pass everything back to the middle-end.
 
+  if (this->imported_unsafe_)
+    {
+      // Importing the "unsafe" package automatically disables TBAA.
+      flag_strict_aliasing = false;
+    }
+
   wrapup_global_declarations(vec, count);
 
   cgraph_finalize_compilation_unit();
@@ -918,7 +924,8 @@ 
 	      init = type->get_init_tree(gogo, false);
 	    else
 	      {
-		tree space = gogo->allocate_memory(TYPE_SIZE_UNIT(result_type),
+		tree space = gogo->allocate_memory(type,
+						   TYPE_SIZE_UNIT(result_type),
 						   loc);
 		result_type = build_pointer_type(result_type);
 		tree subinit = type->get_init_tree(gogo, true);
@@ -1265,7 +1272,8 @@ 
   if (is_in_heap)
     {
       tree size = TYPE_SIZE_UNIT(val_type);
-      tree space = gogo->allocate_memory(size, DECL_SOURCE_LOCATION(var_decl));
+      tree space = gogo->allocate_memory(no->var_value()->type(), size,
+					 no->location());
       space = save_expr(space);
       space = fold_convert(build_pointer_type(val_type), space);
       init = build2(COMPOUND_EXPR, TREE_TYPE(space),
@@ -1285,7 +1293,7 @@ 
 // indirection.
 
 tree
-Function::copy_parm_to_heap(Gogo* gogo, tree ref)
+Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree ref)
 {
   gcc_assert(TREE_CODE(ref) == INDIRECT_REF);
 
@@ -1306,7 +1314,7 @@ 
   DECL_ARG_TYPE(parm_decl) = type;
 
   tree size = TYPE_SIZE_UNIT(type);
-  tree space = gogo->allocate_memory(size, loc);
+  tree space = gogo->allocate_memory(no->var_value()->type(), size, loc);
   space = save_expr(space);
   space = fold_convert(TREE_TYPE(var_decl), space);
   tree init = build2(COMPOUND_EXPR, TREE_TYPE(space),
@@ -1359,7 +1367,7 @@ 
 	    {
 	      // If we take the address of a parameter, then we need
 	      // to copy it into the heap.
-	      tree parm_decl = this->copy_parm_to_heap(gogo, *pp);
+	      tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp);
 	      gcc_assert(TREE_CODE(*pp) == INDIRECT_REF);
 	      tree var_decl = TREE_OPERAND(*pp, 0);
 	      gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
@@ -1927,19 +1935,36 @@ 
     return NULL_TREE;
 }
 
-// Return a tree which allocates SIZE bytes.
+// Return a tree which allocates SIZE bytes which will holds value of
+// type TYPE.
 
 tree
-Gogo::allocate_memory(tree size, source_location location)
+Gogo::allocate_memory(Type* type, tree size, source_location location)
 {
-  static tree new_fndecl;
-  return Gogo::call_builtin(&new_fndecl,
-			    location,
-			    "__go_new",
-			    1,
-			    ptr_type_node,
-			    sizetype,
-			    size);
+  // If the package imports unsafe, then it may play games with
+  // pointers that look like integers.
+  if (this->imported_unsafe_ || type->has_pointer())
+    {
+      static tree new_fndecl;
+      return Gogo::call_builtin(&new_fndecl,
+				location,
+				"__go_new",
+				1,
+				ptr_type_node,
+				sizetype,
+				size);
+    }
+  else
+    {
+      static tree new_nopointers_fndecl;
+      return Gogo::call_builtin(&new_nopointers_fndecl,
+				location,
+				"__go_new_nopointers",
+				1,
+				ptr_type_node,
+				sizetype,
+				size);
+    }
 }
 
 // Build a builtin struct with a list of fields.  The name is
diff -r 640e5a4f513f go/gogo.cc
--- a/go/gogo.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -27,6 +27,7 @@ 
     functions_(),
     globals_(new Bindings(NULL)),
     imports_(),
+    imported_unsafe_(false),
     packages_(),
     map_descriptors_(NULL),
     type_descriptor_decls_(NULL),
diff -r 640e5a4f513f go/gogo.h
--- a/go/gogo.h	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo.h	Fri Jul 23 09:36:21 2010 -0700
@@ -520,9 +520,10 @@ 
   tree
   interface_method_table_for_type(const Interface_type*, const Named_type*);
 
-  // Return a tree which allocates SIZE bytes.
+  // Return a tree which allocate SIZE bytes to hold values of type
+  // TYPE.
   tree
-  allocate_memory(tree size, source_location);
+  allocate_memory(Type *type, tree size, source_location);
 
   // Return a type to use for pointer to const char.
   static tree
@@ -761,6 +762,8 @@ 
   Bindings* globals_;
   // Mapping from import file names to packages.
   Imports imports_;
+  // Whether the magic unsafe package was imported.
+  bool imported_unsafe_;
   // Mapping from package names we have seen to packages.  This does
   // not include the package we are compiling.
   Packages packages_;
@@ -1084,7 +1087,7 @@ 
   make_receiver_parm_decl(Gogo*, Named_object*, tree);
 
   tree
-  copy_parm_to_heap(Gogo*, tree);
+  copy_parm_to_heap(Gogo*, Named_object*, tree);
 
   void
   build_defer_wrapper(Gogo*, Named_object*, tree, tree*, tree*);
diff -r 640e5a4f513f go/statements.cc
--- a/go/statements.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/statements.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -267,7 +267,8 @@ 
       tree type = TREE_TYPE(decl);
       gcc_assert(POINTER_TYPE_P(type));
       tree size = TYPE_SIZE_UNIT(TREE_TYPE(type));
-      tree space = context->gogo()->allocate_memory(size, this->location());
+      tree space = context->gogo()->allocate_memory(variable->type(), size,
+						    this->location());
       space = fold_convert(TREE_TYPE(decl), space);
       DECL_INITIAL(decl) = space;
       return build2(COMPOUND_EXPR, void_type_node,
diff -r 640e5a4f513f go/types.cc
--- a/go/types.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/types.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -2492,6 +2492,10 @@ 
   { }
 
  protected:
+  bool
+  do_has_pointer() const
+  { gcc_unreachable(); }
+
   tree
   do_get_tree(Gogo*);
 
@@ -2649,6 +2653,24 @@ 
   return true;
 }
 
+// Whether this contains a pointer.
+
+bool
+Struct_type::do_has_pointer() const
+{
+  const Struct_field_list* fields = this->fields();
+  if (fields == NULL)
+    return false;
+  for (Struct_field_list::const_iterator p = fields->begin();
+       p != fields->end();
+       ++p)
+    {
+      if (p->type()->has_pointer())
+	return true;
+    }
+  return false;
+}
+
 // Whether this contains a reference counted component.
 
 bool
@@ -3621,7 +3643,8 @@ 
   tree size_tree = fold_build2_loc(location, MULT_EXPR, TREE_TYPE(count_field),
 				   element_size_tree, capacity_tree);
 
-  tree space = context->gogo()->allocate_memory(size_tree, location);
+  tree space = context->gogo()->allocate_memory(this->element_type_,
+						size_tree, location);
 
   if (value != NULL_TREE)
     space = save_expr(space);
diff -r 640e5a4f513f go/types.h
--- a/go/types.h	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/types.h	Fri Jul 23 09:36:21 2010 -0700
@@ -583,6 +583,13 @@ 
   Type*
   make_non_abstract_type();
 
+  // Return true if this type is or contains a pointer.  This
+  // determines whether the garbage collector needs to look at a value
+  // of this type.
+  bool
+  has_pointer() const
+  { return this->do_has_pointer(); }
+
   // Return true if this type requires reference counting: if copying
   // or destroying a value of this type requires adjusting a reference
   // count.
@@ -888,6 +895,10 @@ 
   { return true; }
 
   virtual bool
+  do_has_pointer() const
+  { return false; }
+
+  virtual bool
   do_is_refcounted() const
   { return false; }
 
@@ -1488,6 +1499,10 @@ 
 
  protected:
   bool
+  do_has_pointer() const
+  { return true; }
+
+  bool
   do_is_refcounted() const
   { return true; }
 
@@ -1600,6 +1615,11 @@ 
   int
   do_traverse(Traverse*);
 
+  // A trampoline function has a pointer which matters for GC.
+  bool
+  do_has_pointer() const
+  { return true; }
+
   // Function types are really pointers, and they are reference
   // counted in case that pointer points to a trampoline.
   bool
@@ -1670,6 +1690,10 @@ 
   do_traverse(Traverse*);
 
   bool
+  do_has_pointer() const
+  { return true; }
+
+  bool
   do_is_refcounted() const
   { return !this->is_unsafe_pointer_type(); }
 
@@ -1922,6 +1946,9 @@ 
   do_verify();
 
   bool
+  do_has_pointer() const;
+
+  bool
   do_has_refcounted_component() const;
 
   void
@@ -2015,6 +2042,12 @@ 
   do_traverse(Traverse* traverse);
 
   bool
+  do_has_pointer() const
+  {
+    return this->length_ == NULL || this->element_type_->has_pointer();
+  }
+
+  bool
   do_is_refcounted() const
   {
     return (this->length_ == NULL
@@ -2108,6 +2141,10 @@ 
   do_verify();
 
   bool
+  do_has_pointer() const
+  { return true; }
+
+  bool
   do_is_refcounted() const
   { return true; }
 
@@ -2189,6 +2226,10 @@ 
   { return Type::traverse(this->element_type_, traverse); }
 
   bool
+  do_has_pointer() const
+  { return true; }
+
+  bool
   do_is_refcounted() const
   { return true; }
 
@@ -2293,6 +2334,10 @@ 
   do_traverse(Traverse*);
 
   bool
+  do_has_pointer() const
+  { return true; }
+
+  bool
   do_is_refcounted() const
   { return true; }
 
@@ -2493,6 +2538,10 @@ 
   do_verify();
 
   bool
+  do_has_pointer() const
+  { return this->type_->has_pointer(); }
+
+  bool
   do_is_refcounted() const
   { return this->type_->is_refcounted(); }
 
@@ -2626,6 +2675,10 @@ 
   do_traverse(Traverse* traverse);
 
   bool
+  do_has_pointer() const
+  { return this->base()->has_pointer(); }
+
+  bool
   do_is_refcounted() const
   { return this->base()->is_refcounted(); }
 
diff -r 640e5a4f513f go/unsafe.cc
--- a/go/unsafe.cc	Fri Jul 23 03:59:55 2010 -0700
+++ b/go/unsafe.cc	Fri Jul 23 09:36:21 2010 -0700
@@ -18,9 +18,6 @@ 
 {
   location_t bloc = BUILTINS_LOCATION;
 
-  // Importing the "unsafe" package automatically disables TBAA.
-  flag_strict_aliasing = false;
-
   bool add_to_globals;
   Package* package = this->add_imported_package("unsafe", local_name,
 						is_local_name_exported,
@@ -132,4 +129,6 @@ 
   no = bindings->add_function_declaration("NewArray", package, fntype, bloc);
   if (add_to_globals)
     this->add_named_object(no);
+
+  this->imported_unsafe_ = true;
 }
diff -r 640e5a4f513f libgo/runtime/go-new.c
--- a/libgo/runtime/go-new.c	Fri Jul 23 03:59:55 2010 -0700
+++ b/libgo/runtime/go-new.c	Fri Jul 23 09:36:21 2010 -0700
@@ -5,13 +5,17 @@ 
    license that can be found in the LICENSE file.  */
 
 #include "go-alloc.h"
+#include "runtime.h"
+#include "malloc.h"
 
 void *
 __go_new (size_t size)
 {
-  void *ret;
+  return __go_alloc (size);
+}
 
-  ret = __go_alloc (size);
-  __builtin_memset (ret, 0, size);
-  return ret;
+void *
+__go_new_nopointers (size_t size)
+{
+  return mallocgc (size, RefNoPointers, 1, 1);
 }