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
This commit is contained in:
parent
c70ff9f9be
commit
3ba155dd19
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user