[vala] Keep input parameters alive in closures and async methods



commit 75c3eeed3559f4a25092920aada4216c1dbd15eb
Author: Jürg Billeter <j bitron ch>
Date:   Thu Sep 17 20:26:43 2009 +0200

    Keep input parameters alive in closures and async methods

 codegen/valaccodebasemodule.vala |   56 +++++++++++++++++++++++++++++---------
 codegen/valagasyncmodule.vala    |   44 ++++++++++++++++++++++++++---
 2 files changed, 82 insertions(+), 18 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e907155..051651a 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 cc69d26..acc68de 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));



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