[vala] codegen: Fix memory management when assigning to captured parameters



commit 65f994c6c15eddcac7c679677c1c3f0911154548
Author: JÃrg Billeter <j bitron ch>
Date:   Sun Sep 9 21:55:12 2012 +0200

    codegen: Fix memory management when assigning to captured parameters
    
    Fixes bug 683646.

 codegen/valaccodeassignmentmodule.vala |   32 ++++++++++++++++++++++++++++++--
 codegen/valaccodebasemodule.vala       |    9 +--------
 codegen/valagasyncmodule.vala          |    8 --------
 tests/Makefile.am                      |    1 +
 tests/objects/bug683646.vala           |   14 ++++++++++++++
 vala/valacodegenerator.vala            |    2 +-
 6 files changed, 47 insertions(+), 19 deletions(-)
---
diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala
index b25bd8d..21a2d42 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 5881751..a81afec 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 1716b71..9e2a1b4 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 41cea9e..c1a8296 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 0000000..de8981f
--- /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 f76ea20..fc0ea9e 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);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]