From: Jürg Billeter Date: Thu, 17 Sep 2009 18:26:43 +0000 (+0200) Subject: Keep input parameters alive in closures and async methods X-Git-Tag: 0.7.6~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=75c3eeed3559f4a25092920aada4216c1dbd15eb;p=thirdparty%2Fvala.git Keep input parameters alive in closures and async methods --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index e9071557c..051651aeb 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1628,27 +1628,32 @@ internal class Vala.CCodeBaseModule : CCodeModule { data.add_field ("Block%dData *".printf (parent_block_id), "_data%d_".printf (parent_block_id)); var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id))); - unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_data%d_".printf (parent_block_id))); + unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id))); free_block.add_statement (new CCodeExpressionStatement (unref_call)); } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE)) { data.add_field ("%s *".printf (current_class.get_cname ()), "self"); var ma = new MemberAccess.simple ("this"); ma.symbol_reference = current_class; - free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "self"), new ObjectType (current_class), ma))); + free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"), new ObjectType (current_class), ma))); } foreach (var local in local_vars) { if (local.captured) { data.add_field (local.variable_type.get_cname (), get_variable_cname (local.name) + local.variable_type.get_cdeclarator_suffix ()); - if (local.variable_type is DelegateType) { + if (local.variable_type is ArrayType) { + var array_type = (ArrayType) local.variable_type; + for (int dim = 1; dim <= array_type.rank; dim++) { + data.add_field ("gint", get_array_length_cname (get_variable_cname (local.name), dim)); + } + } else if (local.variable_type is DelegateType) { data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (local.name))); } if (requires_destroy (local.variable_type)) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; - free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), local.variable_type, ma))); + free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (local.name)), local.variable_type, ma))); } } } @@ -1690,8 +1695,22 @@ internal class Vala.CCodeBaseModule : CCodeModule { // parameters are captured with the top-level block of the method foreach (var param in ((Method) b.parent_symbol).get_parameters ()) { if (param.captured) { - data.add_field (param.parameter_type.get_cname (), get_variable_cname (param.name)); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), new CCodeIdentifier (get_variable_cname (param.name))))); + var param_type = param.parameter_type.copy (); + param_type.value_owned = true; + data.add_field (param_type.get_cname (), get_variable_cname (param.name)); + + // create copy if necessary as captured variables may need to be kept alive + CCodeExpression cparam = get_variable_cexpression (param.name); + if (requires_copy (param_type) && !param.parameter_type.value_owned) { + var ma = new MemberAccess.simple (param.name); + ma.symbol_reference = param; + // directly access parameters in ref expressions + param.captured = false; + cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param); + param.captured = true; + } + + cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam))); if (param.parameter_type is ArrayType) { var array_type = (ArrayType) param.parameter_type; @@ -1703,31 +1722,42 @@ internal class Vala.CCodeBaseModule : CCodeModule { data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name))); cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)))))); } + + if (requires_destroy (param_type)) { + var ma = new MemberAccess.simple (param.name); + ma.symbol_reference = param; + free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma))); + } } } + + var cfrag = new CCodeFragment (); + append_temp_decl (cfrag, temp_vars); + temp_vars.clear (); + cblock.add_statement (cfrag); } var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); data_free.add_argument (new CCodeIdentifier (struct_name)); - data_free.add_argument (new CCodeIdentifier ("data")); + data_free.add_argument (new CCodeIdentifier ("_data%d_".printf (block_id))); free_block.add_statement (new CCodeExpressionStatement (data_free)); // create ref/unref functions var ref_fun = new CCodeFunction ("block%d_data_ref".printf (block_id), struct_name + "*"); - ref_fun.add_parameter (new CCodeFormalParameter ("data", struct_name + "*")); + ref_fun.add_parameter (new CCodeFormalParameter ("_data%d_".printf (block_id), struct_name + "*")); ref_fun.modifiers = CCodeModifiers.STATIC; source_declarations.add_type_member_declaration (ref_fun.copy ()); ref_fun.block = new CCodeBlock (); - ref_fun.block.add_statement (new CCodeExpressionStatement (new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_INCREMENT, new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_ref_count_")))); - ref_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("data"))); + ref_fun.block.add_statement (new CCodeExpressionStatement (new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_INCREMENT, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_")))); + ref_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_data%d_".printf (block_id)))); source_type_member_definition.append (ref_fun); var unref_fun = new CCodeFunction ("block%d_data_unref".printf (block_id), struct_name + "*"); - unref_fun.add_parameter (new CCodeFormalParameter ("data", struct_name + "*")); + unref_fun.add_parameter (new CCodeFormalParameter ("_data%d_".printf (block_id), struct_name + "*")); unref_fun.modifiers = CCodeModifiers.STATIC; source_declarations.add_type_member_declaration (unref_fun.copy ()); unref_fun.block = new CCodeBlock (); - var dec = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_ref_count_")), new CCodeConstant ("0")); + var dec = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_")), new CCodeConstant ("0")); unref_fun.block.add_statement (new CCodeIfStatement (dec, free_block)); source_type_member_definition.append (unref_fun); } @@ -1757,7 +1787,7 @@ internal class Vala.CCodeBaseModule : CCodeModule { if (b.parent_symbol is Method) { var m = (Method) b.parent_symbol; foreach (FormalParameter param in m.get_parameters ()) { - if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) { + if (!param.captured && requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) { var ma = new MemberAccess.simple (param.name); ma.symbol_reference = param; cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.parameter_type, ma))); diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index cc69d26f9..acc68def1 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -42,7 +42,10 @@ internal class Vala.GAsyncModule : GSignalModule { } foreach (FormalParameter param in m.get_parameters ()) { - data.add_field (param.parameter_type.get_cname (), get_variable_cname (param.name)); + var param_type = param.parameter_type.copy (); + param_type.value_owned = true; + data.add_field (param_type.get_cname (), get_variable_cname (param.name)); + if (param.parameter_type is ArrayType) { var array_type = (ArrayType) param.parameter_type; for (int dim = 1; dim <= array_type.rank; dim++) { @@ -82,18 +85,33 @@ internal class Vala.GAsyncModule : GSignalModule { datadecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("_data"))); freeblock.add_statement (datadecl); + var old_symbol = current_symbol; + current_symbol = m; + + foreach (FormalParameter param in m.get_parameters ()) { + if (param.direction != ParameterDirection.OUT) { + var param_type = param.parameter_type.copy (); + param_type.value_owned = true; + + if (requires_destroy (param_type)) { + var ma = new MemberAccess.simple (param.name); + ma.symbol_reference = param; + freeblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (param.name)), param.parameter_type, ma))); + } + } + } + if (requires_destroy (m.return_type)) { /* this is very evil. */ var v = new LocalVariable (m.return_type, ".result"); var ma = new MemberAccess.simple (".result"); ma.symbol_reference = v; - var old_symbol = current_symbol; - current_symbol = m; var unref_expr = get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "result"), m.return_type, ma); freeblock.add_statement (new CCodeExpressionStatement (unref_expr)); - current_symbol = old_symbol; } + current_symbol = old_symbol; + var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); freecall.add_argument (new CCodeIdentifier (dataname)); freecall.add_argument (new CCodeIdentifier ("data")); @@ -170,7 +188,18 @@ internal class Vala.GAsyncModule : GSignalModule { foreach (FormalParameter param in m.get_parameters ()) { if (param.direction != ParameterDirection.OUT) { - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeIdentifier (get_variable_cname (param.name))))); + var param_type = param.parameter_type.copy (); + param_type.value_owned = true; + + // create copy if necessary as variables in async methods may need to be kept alive + CCodeExpression cparam = get_variable_cexpression (param.name); + if (requires_copy (param_type) && !param.parameter_type.value_owned) { + var ma = new MemberAccess.simple (param.name); + ma.symbol_reference = param; + cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param); + } + + asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam))); if (param.parameter_type is ArrayType) { var array_type = (ArrayType) param.parameter_type; for (int dim = 1; dim <= array_type.rank; dim++) { @@ -182,6 +211,11 @@ internal class Vala.GAsyncModule : GSignalModule { } } + var cfrag = new CCodeFragment (); + append_temp_decl (cfrag, temp_vars); + temp_vars.clear (); + asyncblock.add_statement (cfrag); + var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname () + "_co")); ccall.add_argument (data_var); asyncblock.add_statement (new CCodeExpressionStatement (ccall));