From: Luca Bruno Date: Fri, 6 Jan 2012 21:57:02 +0000 (+0100) Subject: codegen: Don't copy array parameters when captured X-Git-Tag: 0.15.1~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=15274701a10cb5425872cfc3d23ee62e6b660c84;p=thirdparty%2Fvala.git codegen: Don't copy array parameters when captured Also allow uncopiable compact classes to be captured. Fixes bug 639054. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 338a68547..002c79c88 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1709,19 +1709,27 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { return result; } + public bool no_implicit_copy (DataType type) { + // note: implicit copy of array is planned to be forbidden + var cl = type.data_type as Class; + return (type is DelegateType || + type.is_array () || + (cl != null && !cl.is_immutable && !is_reference_counting (cl) && !get_ccode_is_gboxed (cl))); + } + void capture_parameter (Parameter param, CCodeStruct data, int block_id) { generate_type_declaration (param.variable_type, cfile); var param_type = param.variable_type.copy (); - param_type.value_owned = true; + if (!param.variable_type.value_owned) { + param_type.value_owned = !no_implicit_copy (param.variable_type); + } data.add_field (get_ccode_name (param_type), get_variable_cname (param.name)); - bool is_unowned_delegate = param.variable_type is DelegateType && !param.variable_type.value_owned; - // create copy if necessary as captured variables may need to be kept alive param.captured = false; var value = load_parameter (param); - if (requires_copy (param_type) && !param.variable_type.value_owned && !is_unowned_delegate) { + if (requires_copy (param_type) && !param.variable_type.value_owned) { // directly access parameters in ref expressions value = copy_value (value, param); } @@ -1974,11 +1982,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { foreach (var param in m.get_parameters ()) { if (param.captured) { var param_type = param.variable_type.copy (); - param_type.value_owned = true; - - bool is_unowned_delegate = param.variable_type is DelegateType && !param.variable_type.value_owned; + if (!param_type.value_owned) { + param_type.value_owned = !no_implicit_copy (param_type); + } - if (requires_destroy (param_type) && !is_unowned_delegate) { + if (requires_destroy (param_type)) { bool old_coroutine = false; if (m != null) { old_coroutine = m.coroutine; @@ -1998,11 +2006,13 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { if (!acc.readable && acc.value_parameter.captured) { var param_type = acc.value_parameter.variable_type.copy (); - param_type.value_owned = true; + if (!param_type.value_owned) { + param_type.value_owned = !no_implicit_copy (param_type); + } bool is_unowned_delegate = acc.value_parameter.variable_type is DelegateType && !acc.value_parameter.variable_type.value_owned; - if (requires_destroy (param_type) && !is_unowned_delegate) { + if (requires_destroy (param_type)) { ccode.add_expression (destroy_parameter (acc.value_parameter)); } } diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index 64ec2b533..c9da7299b 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -107,12 +107,12 @@ public class Vala.GAsyncModule : GSignalModule { foreach (Parameter param in m.get_parameters ()) { if (param.direction != ParameterDirection.OUT) { - bool is_unowned_delegate = param.variable_type is DelegateType && !param.variable_type.value_owned; - var param_type = param.variable_type.copy (); - param_type.value_owned = true; + if (!param_type.value_owned) { + param_type.value_owned = !no_implicit_copy (param_type); + } - if (requires_destroy (param_type) && !is_unowned_delegate) { + if (requires_destroy (param_type)) { // do not try to access closure blocks bool old_captured = param.captured; param.captured = false; @@ -255,17 +255,17 @@ public class Vala.GAsyncModule : GSignalModule { emit_context.push_symbol (m); foreach (Parameter param in m.get_parameters ()) { if (param.direction != ParameterDirection.OUT) { - bool is_unowned_delegate = param.variable_type is DelegateType && !param.variable_type.value_owned; - var param_type = param.variable_type.copy (); - param_type.value_owned = true; + if (!param_type.value_owned) { + param_type.value_owned = !no_implicit_copy (param_type); + } // create copy if necessary as variables in async methods may need to be kept alive var old_captured = param.captured; param.captured = false; current_method.coroutine = false; var value = load_parameter (param); - if (requires_copy (param_type) && !param.variable_type.value_owned && !is_unowned_delegate) { + if (requires_copy (param_type) && !param.variable_type.value_owned) { value = copy_value (value, param); } current_method.coroutine = true; diff --git a/tests/Makefile.am b/tests/Makefile.am index 92b1ef057..fa5111e72 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,6 +42,7 @@ TESTS = \ methods/bug613483.vala \ methods/bug620673.vala \ methods/bug622570.vala \ + methods/bug639054.vala \ methods/bug642899.vala \ methods/bug646345.vala \ methods/bug648320.vala \ diff --git a/tests/methods/bug639054.vala b/tests/methods/bug639054.vala new file mode 100644 index 000000000..0ce93bdd7 --- /dev/null +++ b/tests/methods/bug639054.vala @@ -0,0 +1,22 @@ +[Compact] +public class Baz { +} + +public async void foo (uint8[] bar, Baz baz) { + SourceFunc f = () => { + bar[0] = 'b'; + baz = null; + return false; + }; + f (); +} + +void main () { + var loop = new MainLoop (); + var bar = "foo".data; + foo.begin (bar, new Baz (), () => { + assert (bar[0] == 'b'); + loop.quit (); + }); + loop.run (); +}