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
This commit is contained in:
parent
9ac55031c4
commit
e732b42485
@ -1,4 +1,4 @@
|
||||
91169ab206266361624236f0137668162ee8cb9b
|
||||
b361bec95927fd6209c286906f98deeedcfe1da3
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
|
||||
|
||||
Expression* cap_arg = NULL;
|
||||
bool cap_small = false;
|
||||
Numeric_constant nclen;
|
||||
Numeric_constant nccap;
|
||||
unsigned long vlen;
|
||||
unsigned long vcap;
|
||||
if (is_slice && parg != args->end())
|
||||
{
|
||||
cap_arg = *parg;
|
||||
@ -7503,10 +7507,6 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
|
||||
if (!this->check_int_value(cap_arg, false, &cap_small))
|
||||
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)
|
||||
&& cap_arg->numeric_constant_value(&nccap)
|
||||
&& nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
|
||||
@ -7531,19 +7531,25 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
|
||||
Expression* call;
|
||||
if (is_slice)
|
||||
{
|
||||
Type* et = type->array_type()->element_type();
|
||||
Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
|
||||
if (cap_arg == NULL)
|
||||
{
|
||||
Temporary_statement* temp = Statement::make_temporary(NULL,
|
||||
len_arg,
|
||||
loc);
|
||||
inserter->insert(temp);
|
||||
len_arg = Expression::make_temporary_reference(temp, loc);
|
||||
cap_arg = Expression::make_temporary_reference(temp, loc);
|
||||
cap_small = len_small;
|
||||
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,
|
||||
len_arg,
|
||||
loc);
|
||||
inserter->insert(temp);
|
||||
len_arg = Expression::make_temporary_reference(temp, loc);
|
||||
cap_arg = Expression::make_temporary_reference(temp, loc);
|
||||
}
|
||||
}
|
||||
|
||||
Type* et = type->array_type()->element_type();
|
||||
Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
|
||||
Runtime::Function code = Runtime::MAKESLICE;
|
||||
if (!len_small || !cap_small)
|
||||
code = Runtime::MAKESLICE64;
|
||||
|
@ -64,6 +64,47 @@ Mark_address_taken::expression(Expression** pexpr)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user