Commit e732b424 by Ian Lance Taylor

compiler: stack allocate non-escaping makeslice

    
    If we're making a slice of constant size that does not need to
    escape, allocate it on stack.
    
    In lower, do not create temporaries for constant size makeslice,
    so that it is easier to detect the slice is constant size later.
    
    Reviewed-on: https://go-review.googlesource.com/85636

From-SVN: r256404
parent 9ac55031
91169ab206266361624236f0137668162ee8cb9b b361bec95927fd6209c286906f98deeedcfe1da3
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.
...@@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) ...@@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
Expression* cap_arg = NULL; Expression* cap_arg = NULL;
bool cap_small = false; bool cap_small = false;
Numeric_constant nclen;
Numeric_constant nccap;
unsigned long vlen;
unsigned long vcap;
if (is_slice && parg != args->end()) if (is_slice && parg != args->end())
{ {
cap_arg = *parg; cap_arg = *parg;
...@@ -7503,10 +7507,6 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) ...@@ -7503,10 +7507,6 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
if (!this->check_int_value(cap_arg, false, &cap_small)) if (!this->check_int_value(cap_arg, false, &cap_small))
return Expression::make_error(this->location()); return Expression::make_error(this->location());
Numeric_constant nclen;
Numeric_constant nccap;
unsigned long vlen;
unsigned long vcap;
if (len_arg->numeric_constant_value(&nclen) if (len_arg->numeric_constant_value(&nclen)
&& cap_arg->numeric_constant_value(&nccap) && cap_arg->numeric_constant_value(&nccap)
&& nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
...@@ -7531,19 +7531,25 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter) ...@@ -7531,19 +7531,25 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
Expression* call; Expression* call;
if (is_slice) if (is_slice)
{ {
Type* et = type->array_type()->element_type();
Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
if (cap_arg == NULL) if (cap_arg == NULL)
{ {
cap_small = len_small;
if (len_arg->numeric_constant_value(&nclen)
&& nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID)
cap_arg = Expression::make_integer_ul(vlen, len_arg->type(), loc);
else
{
Temporary_statement* temp = Statement::make_temporary(NULL, Temporary_statement* temp = Statement::make_temporary(NULL,
len_arg, len_arg,
loc); loc);
inserter->insert(temp); inserter->insert(temp);
len_arg = Expression::make_temporary_reference(temp, loc); len_arg = Expression::make_temporary_reference(temp, loc);
cap_arg = Expression::make_temporary_reference(temp, loc); cap_arg = Expression::make_temporary_reference(temp, loc);
cap_small = len_small; }
} }
Type* et = type->array_type()->element_type();
Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
Runtime::Function code = Runtime::MAKESLICE; Runtime::Function code = Runtime::MAKESLICE;
if (!len_small || !cap_small) if (!len_small || !cap_small)
code = Runtime::MAKESLICE64; code = Runtime::MAKESLICE64;
......
...@@ -64,6 +64,47 @@ Mark_address_taken::expression(Expression** pexpr) ...@@ -64,6 +64,47 @@ Mark_address_taken::expression(Expression** pexpr)
} }
aie->array()->address_taken(escapes); aie->array()->address_taken(escapes);
} }
// Rewrite non-escaping makeslice with constant size to stack allocation.
Unsafe_type_conversion_expression* uce =
expr->unsafe_conversion_expression();
if (uce != NULL
&& uce->type()->is_slice_type()
&& Node::make_node(uce->expr())->encoding() == Node::ESCAPE_NONE
&& uce->expr()->call_expression() != NULL)
{
Call_expression* call = uce->expr()->call_expression();
if (call->fn()->func_expression() != NULL
&& call->fn()->func_expression()->runtime_code() == Runtime::MAKESLICE)
{
Expression* len_arg = call->args()->at(1);
Expression* cap_arg = call->args()->at(2);
Numeric_constant nclen;
Numeric_constant nccap;
unsigned long vlen;
unsigned long vcap;
if (len_arg->numeric_constant_value(&nclen)
&& cap_arg->numeric_constant_value(&nccap)
&& nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
&& nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID)
{
// Turn it into a slice expression of an addressable array,
// which is allocated on stack.
Location loc = expr->location();
Type* elmt_type = expr->type()->array_type()->element_type();
Expression* len_expr =
Expression::make_integer_ul(vcap, cap_arg->type(), loc);
Type* array_type = Type::make_array_type(elmt_type, len_expr);
Expression* alloc = Expression::make_allocation(array_type, loc);
alloc->allocation_expression()->set_allocate_on_stack();
Expression* array = Expression::make_unary(OPERATOR_MULT, alloc, loc);
Expression* zero = Expression::make_integer_ul(0, len_arg->type(), loc);
Expression* slice =
Expression::make_array_index(array, zero, len_arg, cap_arg, loc);
*pexpr = slice;
}
}
}
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
} }
......
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