[vala] codegen: Don't copy array parameters when captured



commit 15274701a10cb5425872cfc3d23ee62e6b660c84
Author: Luca Bruno <lucabru src gnome org>
Date:   Fri Jan 6 22:57:02 2012 +0100

    codegen: Don't copy array parameters when captured
    
    Also allow uncopiable compact classes to be captured.
    
    Fixes bug 639054.

 codegen/valaccodebasemodule.vala |   30 ++++++++++++++++++++----------
 codegen/valagasyncmodule.vala    |   16 ++++++++--------
 tests/Makefile.am                |    1 +
 tests/methods/bug639054.vala     |   22 ++++++++++++++++++++++
 4 files changed, 51 insertions(+), 18 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 338a685..002c79c 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 64ec2b5..c9da729 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 92b1ef0..fa5111e 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 0000000..0ce93bd
--- /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 ();
+}



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