compiler: delay escaping sliced arrays

Arrays that are sliced are set to escape in type checking, very
    early in compilation. The escape analysis runs later but cannot
    undo it. This CL changes it to not escape in the early stage.
    Later the escape analysis will make it escape when needed.
    
    Reviewed-on: https://go-review.googlesource.com/85635

From-SVN: r256403
This commit is contained in:
Ian Lance Taylor 2018-01-09 23:16:13 +00:00
parent 8080b14f01
commit 9ac55031c4
3 changed files with 24 additions and 14 deletions

View File

@ -1,4 +1,4 @@
cd422bacf0505e9656661d97a571668ad1bde0fe
91169ab206266361624236f0137668162ee8cb9b
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -10679,7 +10679,7 @@ Array_index_expression::do_determine_type(const Type_context*)
// Check types of an array index.
void
Array_index_expression::do_check_types(Gogo* gogo)
Array_index_expression::do_check_types(Gogo*)
{
Numeric_constant nc;
unsigned long v;
@ -10798,18 +10798,9 @@ Array_index_expression::do_check_types(Gogo* gogo)
if (!this->array_->is_addressable())
this->report_error(_("slice of unaddressable value"));
else
{
bool escapes = true;
// When compiling the runtime, a slice operation does not
// cause local variables to escape. When escape analysis
// becomes the default, this should be changed to make it an
// error if we have a slice operation that escapes.
if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
escapes = false;
this->array_->address_taken(escapes);
}
// Set the array address taken but not escape. The escape
// analysis will make it escape to heap when needed.
this->array_->address_taken(false);
}
}

View File

@ -45,6 +45,25 @@ Mark_address_taken::expression(Expression** pexpr)
Unary_expression* ue = expr->unary_expression();
if (ue != NULL)
ue->check_operand_address_taken(this->gogo_);
Array_index_expression* aie = expr->array_index_expression();
if (aie != NULL
&& aie->end() != NULL
&& !aie->array()->type()->is_slice_type())
{
// Slice of an array. The escape analysis models this with
// a child Node representing the address of the array.
bool escapes = false;
if (!this->gogo_->compiling_runtime()
|| this->gogo_->package_name() != "runtime")
{
Node* n = Node::make_node(expr);
if (n->child() == NULL
|| (n->child()->encoding() & ESCAPE_MASK) != Node::ESCAPE_NONE)
escapes = true;
}
aie->array()->address_taken(escapes);
}
return TRAVERSE_CONTINUE;
}