compiler: make heap expression's write barrier conditional
Heap_expression::do_get_backend emits an unconditional write
barrier if the type has pointers and it is not a stack allocation.
This CL changes it to use a write barrier for the assignment only
when write barriers are enabled. While here, also change it to
call gcWriteBarrier instead of typedmemmove for pointer-shaped
types.
For this to work, Function::build needs to be adjusted so that
Heap_expression::do_get_backend is called when there is a parent
block.
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/181540
From-SVN: r272132
This commit is contained in:
parent
fc917b4265
commit
35c19de696
@ -1,4 +1,4 @@
|
||||
11d96c36198b75b0485d16524d521e558cf03312
|
||||
764fe6702f2bb8650622d4102de31058e484ecb5
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
||||
@ -16387,17 +16387,43 @@ Heap_expression::do_get_backend(Translate_context* context)
|
||||
&edecl);
|
||||
Bexpression* btempref = gogo->backend()->var_expression(btemp,
|
||||
loc);
|
||||
Bexpression* addr = gogo->backend()->address_expression(btempref, loc);
|
||||
|
||||
Expression* td = Expression::make_type_descriptor(etype, loc);
|
||||
Type* etype_ptr = Type::make_pointer_type(etype);
|
||||
space = gogo->backend()->var_expression(space_temp, loc);
|
||||
Type* etype_ptr = Type::make_pointer_type(etype);
|
||||
Expression* elhs = Expression::make_backend(space, etype_ptr, loc);
|
||||
Expression* erhs = Expression::make_backend(addr, etype_ptr, loc);
|
||||
Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
|
||||
td, elhs, erhs);
|
||||
Bexpression* bcall = call->get_backend(context);
|
||||
Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall);
|
||||
Expression* erhs;
|
||||
Expression* call;
|
||||
if (etype->is_direct_iface_type())
|
||||
{
|
||||
// Single pointer.
|
||||
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
||||
erhs = Expression::make_backend(btempref, etype, loc);
|
||||
erhs = Expression::unpack_direct_iface(erhs, loc);
|
||||
erhs = Expression::make_unsafe_cast(uintptr_type, erhs, loc);
|
||||
call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2,
|
||||
elhs, erhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression* td = Expression::make_type_descriptor(etype, loc);
|
||||
Bexpression* addr =
|
||||
gogo->backend()->address_expression(btempref, loc);
|
||||
erhs = Expression::make_backend(addr, etype_ptr, loc);
|
||||
call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
|
||||
td, elhs, erhs);
|
||||
}
|
||||
Statement* cs = Statement::make_statement(call, false);
|
||||
|
||||
space = gogo->backend()->var_expression(space_temp, loc);
|
||||
Bexpression* ref =
|
||||
gogo->backend()->indirect_expression(expr_btype, space, true, loc);
|
||||
Expression* eref = Expression::make_backend(ref, etype, loc);
|
||||
btempref = gogo->backend()->var_expression(btemp, loc);
|
||||
erhs = Expression::make_backend(btempref, etype, loc);
|
||||
Statement* as = Statement::make_assignment(eref, erhs, loc);
|
||||
|
||||
as = gogo->check_write_barrier(context->block(), as, cs);
|
||||
Bstatement* s = as->get_backend(context);
|
||||
|
||||
assn = gogo->backend()->compound_statement(edecl, s);
|
||||
}
|
||||
decl = gogo->backend()->compound_statement(decl, assn);
|
||||
|
||||
@ -6323,7 +6323,7 @@ Function::build(Gogo* gogo, Named_object* named_function)
|
||||
// Variables that need to be declared for this function and their
|
||||
// initial values.
|
||||
std::vector<Bvariable*> vars;
|
||||
std::vector<Bexpression*> var_inits;
|
||||
std::vector<Expression*> var_inits;
|
||||
std::vector<Statement*> var_decls_stmts;
|
||||
for (Bindings::const_definitions_iterator p =
|
||||
this->block_->bindings()->begin_definitions();
|
||||
@ -6366,7 +6366,7 @@ Function::build(Gogo* gogo, Named_object* named_function)
|
||||
loc);
|
||||
if ((*p)->var_value()->is_in_heap())
|
||||
parm_ref = Expression::make_heap_expression(parm_ref, loc);
|
||||
var_inits.push_back(parm_ref->get_backend(&context));
|
||||
var_inits.push_back(parm_ref);
|
||||
}
|
||||
else if ((*p)->var_value()->is_in_heap())
|
||||
{
|
||||
@ -6383,7 +6383,7 @@ Function::build(Gogo* gogo, Named_object* named_function)
|
||||
Expression* var_ref =
|
||||
Expression::make_var_reference(parm_no, loc);
|
||||
var_ref = Expression::make_heap_expression(var_ref, loc);
|
||||
var_inits.push_back(var_ref->get_backend(&context));
|
||||
var_inits.push_back(var_ref);
|
||||
}
|
||||
param_vars.push_back(parm_bvar);
|
||||
}
|
||||
@ -6392,15 +6392,15 @@ Function::build(Gogo* gogo, Named_object* named_function)
|
||||
Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
|
||||
|
||||
Type* type = (*p)->result_var_value()->type();
|
||||
Bexpression* init;
|
||||
Expression* init;
|
||||
if (!(*p)->result_var_value()->is_in_heap())
|
||||
{
|
||||
Btype* btype = type->get_backend(gogo);
|
||||
init = gogo->backend()->zero_expression(btype);
|
||||
Bexpression* binit = gogo->backend()->zero_expression(btype);
|
||||
init = Expression::make_backend(binit, type, loc);
|
||||
}
|
||||
else
|
||||
init = Expression::make_allocation(type,
|
||||
loc)->get_backend(&context);
|
||||
init = Expression::make_allocation(type, loc);
|
||||
|
||||
vars.push_back(bvar);
|
||||
var_inits.push_back(init);
|
||||
@ -6473,13 +6473,16 @@ Function::build(Gogo* gogo, Named_object* named_function)
|
||||
Bblock* code_block = this->block_->get_backend(&context);
|
||||
|
||||
// Initialize variables if necessary.
|
||||
Translate_context icontext(gogo, named_function, this->block_,
|
||||
var_decls);
|
||||
std::vector<Bstatement*> init;
|
||||
go_assert(vars.size() == var_inits.size());
|
||||
for (size_t i = 0; i < vars.size(); ++i)
|
||||
{
|
||||
Bexpression* binit = var_inits[i]->get_backend(&icontext);
|
||||
Bstatement* init_stmt =
|
||||
gogo->backend()->init_statement(this->fndecl_, vars[i],
|
||||
var_inits[i]);
|
||||
binit);
|
||||
init.push_back(init_stmt);
|
||||
}
|
||||
Bstatement* var_init = gogo->backend()->statement_list(init);
|
||||
|
||||
@ -765,6 +765,12 @@ class Gogo
|
||||
assign_with_write_barrier(Function*, Block*, Statement_inserter*,
|
||||
Expression* lhs, Expression* rhs, Location);
|
||||
|
||||
// Return a statement that tests whether write barriers are enabled
|
||||
// and executes either the efficient code (WITHOUT) or the write
|
||||
// barrier function call (WITH), depending.
|
||||
Statement*
|
||||
check_write_barrier(Block*, Statement* without, Statement* with);
|
||||
|
||||
// Flatten parse tree.
|
||||
void
|
||||
flatten();
|
||||
@ -999,9 +1005,6 @@ class Gogo
|
||||
Named_object*
|
||||
write_barrier_variable();
|
||||
|
||||
Statement*
|
||||
check_write_barrier(Block*, Statement*, Statement*);
|
||||
|
||||
// Type used to map import names to packages.
|
||||
typedef std::map<std::string, Package*> Imports;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user