Commit 3ba155dd by Ian Lance Taylor

compiler: check for 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 is not
    notinheap.  This caused an invalid write barrier error when building
    the 1.13 version of the runtime.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/192279

From-SVN: r275240
parent c70ff9f9
289d94b9e6303ec74649d1f08d418300f2b4d0fd 3b8a505824abb2a69f4c04c555a4ba29ab8b102b
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -733,6 +733,31 @@ Gogo::assign_needs_write_barrier( ...@@ -733,6 +733,31 @@ Gogo::assign_needs_write_barrier(
&& !lhs->type()->points_to()->in_heap()) && !lhs->type()->points_to()->in_heap())
return false; 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(); Field_reference_expression* fre = lhs->field_reference_expression();
if (fre != NULL) if (fre != NULL)
{ {
...@@ -788,31 +813,6 @@ Gogo::assign_needs_write_barrier( ...@@ -788,31 +813,6 @@ Gogo::assign_needs_write_barrier(
&& this->is_nonwb_pointer(ue->operand(), nonwb_pointers)) && this->is_nonwb_pointer(ue->operand(), nonwb_pointers))
return false; 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. // Write barrier needed in other cases.
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment