]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Don't copy array parameters when captured
authorLuca Bruno <lucabru@src.gnome.org>
Fri, 6 Jan 2012 21:57:02 +0000 (22:57 +0100)
committerLuca Bruno <lucabru@src.gnome.org>
Sat, 7 Jan 2012 19:24:00 +0000 (20:24 +0100)
Also allow uncopiable compact classes to be captured.

Fixes bug 639054.

codegen/valaccodebasemodule.vala
codegen/valagasyncmodule.vala
tests/Makefile.am
tests/methods/bug639054.vala [new file with mode: 0644]

index 338a685479eda2a2dae2c52ee015fe0e1f68beab..002c79c887a260e58fd184b966797912060f3810 100644 (file)
@@ -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));
                                        }
                                }
index 64ec2b533d9593a50a03ac32ef59be5be5ba9416..c9da7299b76992c3e7090e69a5e8f8d1af048f4a 100644 (file)
@@ -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;
index 92b1ef057fc5c190734ef6cfcad2c4a41a9b089f..fa5111e727275e4e68fc4fc9a18ed50a5def5298 100644 (file)
@@ -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 (file)
index 0000000..0ce93bd
--- /dev/null
@@ -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 ();
+}