Go patch committed: Check for notinheap struct at each struct field

Message ID CAOyqgcVO_KSHa82+mFQuENBq+ozLipMBx430DgyL03wB5+JrDw@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Check for notinheap struct at each struct field
Related show

Commit Message

Ian Lance Taylor Aug. 31, 2019, 3:07 a.m.
This patch to the Go frontend checks for a notinheap struct at each
struct field.  When generating write barriers, we were only checking
for a notinheap struct at the outermost struct.  That mishandled the
case of setting a pointer to a notinheap struct as a field of another
struct that not notinheap.  This caused an invalid write barrier error
when building the 1.13 version of the runtime.  Bootstrapped and ran
Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 275239)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-289d94b9e6303ec74649d1f08d418300f2b4d0fd
+3b8a505824abb2a69f4c04c555a4ba29ab8b102b
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/wb.cc
===================================================================
--- gcc/go/gofrontend/wb.cc	(revision 274890)
+++ gcc/go/gofrontend/wb.cc	(working copy)
@@ -733,6 +733,31 @@  Gogo::assign_needs_write_barrier(
 	  && !lhs->type()->points_to()->in_heap())
 	return false;
 
+      // For a struct assignment, we don't need a write barrier if all
+      // the field types can not be in the heap.
+      Struct_type* st = lhs->type()->struct_type();
+      if (st != NULL)
+	{
+	  bool in_heap = false;
+	  const Struct_field_list* fields = st->fields();
+	  for (Struct_field_list::const_iterator p = fields->begin();
+	       p != fields->end();
+	       p++)
+	    {
+	      Type* ft = p->type();
+	      if (!ft->has_pointer())
+		continue;
+	      if (!ft->in_heap())
+		continue;
+	      if (ft->points_to() != NULL && !ft->points_to()->in_heap())
+		continue;
+	      in_heap = true;
+	      break;
+	    }
+	  if (!in_heap)
+	    return false;
+	}
+
       Field_reference_expression* fre = lhs->field_reference_expression();
       if (fre != NULL)
 	{
@@ -788,31 +813,6 @@  Gogo::assign_needs_write_barrier(
       && this->is_nonwb_pointer(ue->operand(), nonwb_pointers))
     return false;
 
-  // For a struct assignment, we don't need a write barrier if all the
-  // pointer types can not be in the heap.
-  Struct_type* st = lhs->type()->struct_type();
-  if (st != NULL)
-    {
-      bool in_heap = false;
-      const Struct_field_list* fields = st->fields();
-      for (Struct_field_list::const_iterator p = fields->begin();
-	   p != fields->end();
-	   p++)
-	{
-	  Type* ft = p->type();
-	  if (!ft->has_pointer())
-	    continue;
-	  if (!ft->in_heap())
-	    continue;
-	  if (ft->points_to() != NULL && !ft->points_to()->in_heap())
-	    continue;
-	  in_heap = true;
-	  break;
-	}
-      if (!in_heap)
-	return false;
-    }
-
   // Write barrier needed in other cases.
   return true;
 }