]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Fix memory management when assigning to captured parameters
authorJürg Billeter <j@bitron.ch>
Sun, 9 Sep 2012 19:55:12 +0000 (21:55 +0200)
committerJürg Billeter <j@bitron.ch>
Sun, 9 Sep 2012 21:13:15 +0000 (23:13 +0200)
Fixes bug 683646.

codegen/valaccodeassignmentmodule.vala
codegen/valaccodebasemodule.vala
codegen/valagasyncmodule.vala
tests/Makefile.am
tests/objects/bug683646.vala [new file with mode: 0644]
vala/valacodegenerator.vala

index b25bd8dd2bd155d0739077b36397a67f789c162f..21a2d426edcd613f2794ce57e040b90f28447d93 100644 (file)
@@ -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));
                }
index 5881751b288d13458017fb1f2c8f1e689b11c252..a81afeca4f31e1508db3264c84cecfc7d4359fd7 100644 (file)
@@ -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) {
index 1716b717a50205cf399a4f42c69df68d1f76a084..9e2a1b4daacf448fd296b6b55dc95ae1f527b938 100644 (file)
@@ -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;
index 41cea9eadbf5a39abd89c8fafe21d2abc0cd73bc..c1a8296fdcdcd9508e6b1a3ab11e37e32f269a01 100644 (file)
@@ -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 (file)
index 0000000..de8981f
--- /dev/null
@@ -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 ());
+}
index f76ea2013cf81d75a2d26ecdd37eece256bda89e..fc0ea9ee6684d566d55ec1779ea86d6677a38757 100644 (file)
@@ -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);