From: Jürg Billeter Date: Sun, 9 Sep 2012 19:55:12 +0000 (+0200) Subject: codegen: Fix memory management when assigning to captured parameters X-Git-Tag: 0.17.7~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65f994c6c15eddcac7c679677c1c3f0911154548;p=thirdparty%2Fvala.git codegen: Fix memory management when assigning to captured parameters Fixes bug 683646. --- diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala index b25bd8dd2..21a2d426e 100644 --- a/codegen/valaccodeassignmentmodule.vala +++ b/codegen/valaccodeassignmentmodule.vala @@ -165,8 +165,36 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule { store_value (get_local_cvalue (local), value); } - public override void store_parameter (Parameter param, TargetValue value) { - if (requires_destroy (param.variable_type)) { + public override void store_parameter (Parameter param, TargetValue _value, bool capturing_parameter = false) { + var value = _value; + + bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine (); + + var param_type = param.variable_type.copy (); + if (param.captured || is_in_coroutine ()) { + if (!param_type.value_owned && !no_implicit_copy (param_type)) { + // parameter value has been implicitly copied into a heap data structure + // treat parameter as owned + param_type.value_owned = true; + + var old_coroutine = is_in_coroutine (); + if (old_coroutine) { + current_method.coroutine = false; + } + + if (requires_copy (param_type) && !capturing_parameter_in_coroutine) { + // do not copy value when capturing parameter in coroutine + // as the value was already copied on coroutine initialization + value = copy_value (value, param); + } + + if (old_coroutine) { + current_method.coroutine = true; + } + } + } + + if (requires_destroy (param_type)) { /* unref old value */ ccode.add_expression (destroy_parameter (param)); } diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 5881751b2..a81afeca4 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1768,9 +1768,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { void capture_parameter (Parameter param, CCodeStruct data, int block_id) { generate_type_declaration (param.variable_type, cfile); - var m = param.parent_symbol as Method; - bool coroutine = m != null && m.coroutine; - var param_type = param.variable_type.copy (); if (!param.variable_type.value_owned) { param_type.value_owned = !no_implicit_copy (param.variable_type); @@ -1780,10 +1777,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { // 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 && !coroutine) { - // directly access parameters in ref expressions - value = copy_value (value, param); - } var array_type = param.variable_type as ArrayType; var deleg_type = param.variable_type as DelegateType; @@ -1803,7 +1796,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } param.captured = true; - store_parameter (param, value); + store_parameter (param, value, true); } public override void visit_block (Block b) { diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index 1716b717a..9e2a1b4da 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -255,11 +255,6 @@ public class Vala.GAsyncModule : GSignalModule { emit_context.push_symbol (m); foreach (Parameter param in m.get_parameters ()) { if (param.direction != ParameterDirection.OUT) { - var param_type = param.variable_type.copy (); - 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; @@ -272,9 +267,6 @@ public class Vala.GAsyncModule : GSignalModule { value = get_parameter_cvalue (param); } else { value = load_parameter (param); - if (requires_copy (param_type)) { - value = copy_value (value, param); - } } current_method.coroutine = true; diff --git a/tests/Makefile.am b/tests/Makefile.am index 41cea9ead..c1a8296fd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -127,6 +127,7 @@ TESTS = \ objects/bug663134.vala \ objects/bug664529.vala \ objects/bug667668.vala \ + objects/bug683646.vala \ errors/errors.vala \ errors/bug567181.vala \ errors/bug579101.vala \ diff --git a/tests/objects/bug683646.vala b/tests/objects/bug683646.vala new file mode 100644 index 000000000..de8981f35 --- /dev/null +++ b/tests/objects/bug683646.vala @@ -0,0 +1,14 @@ +delegate void Func (); + +void foo (Object a, Object? b = null) { + b = a; + + Func sub = () => { + var c = a; + var d = b; + }; +} + +void main () { + foo (new Object ()); +} diff --git a/vala/valacodegenerator.vala b/vala/valacodegenerator.vala index f76ea2013..fc0ea9ee6 100644 --- a/vala/valacodegenerator.vala +++ b/vala/valacodegenerator.vala @@ -40,7 +40,7 @@ public abstract class Vala.CodeGenerator : CodeVisitor { public abstract TargetValue load_parameter (Parameter param); - public abstract void store_parameter (Parameter param, TargetValue value); + public abstract void store_parameter (Parameter param, TargetValue value, bool capturing_parameter = false); public abstract TargetValue load_field (Field field, TargetValue? instance);