]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
gvariant: Optimize (de)serialization of arrays with type-signature "ay"
authorOle André Vadla Ravnås <oleavr@gmail.com>
Tue, 14 Mar 2017 18:17:15 +0000 (19:17 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 5 Oct 2017 20:28:57 +0000 (22:28 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=772426

codegen/valagvariantmodule.vala
tests/Makefile.am
tests/basic-types/bug772426.vala [new file with mode: 0644]

index f3113f4f45301d78139a2e62b9dc15d4519d0457..9cf642de11a4a34bceea8af3438e858d5848ea7d 100644 (file)
@@ -264,6 +264,10 @@ public class Vala.GVariantModule : GAsyncModule {
        }
 
        CCodeExpression deserialize_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) {
+               if (array_type.rank == 1 && get_type_signature (array_type) == "ay") {
+                       return deserialize_buffer_array (array_type, variant_expr, expr);
+               }
+
                string temp_name = "_tmp%d_".printf (next_temp_var_id++);
 
                var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new"));
@@ -343,6 +347,29 @@ public class Vala.GVariantModule : GAsyncModule {
                }
        }
 
+       CCodeExpression deserialize_buffer_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) {
+               string temp_name = "_tmp%d_".printf (next_temp_var_id++);
+
+               var get_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_data"));
+               get_data_call.add_argument (variant_expr);
+
+               var get_size_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_size"));
+               get_size_call.add_argument (variant_expr);
+               ccode.add_declaration ("gsize", new CCodeVariableDeclarator (temp_name + "_length", get_size_call));
+               var length = new CCodeIdentifier (temp_name + "_length");
+
+               var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+               dup_call.add_argument (get_data_call);
+               dup_call.add_argument (length);
+
+               ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (temp_name, dup_call));
+               if (expr != null) {
+                       ccode.add_assignment (get_array_length (expr, 1), length);
+               }
+
+               return new CCodeIdentifier (temp_name);
+       }
+
        CCodeExpression? deserialize_struct (Struct st, CCodeExpression variant_expr) {
                string temp_name = "_tmp%d_".printf (next_temp_var_id++);
                string subiter_name = "_tmp%d_".printf (next_temp_var_id++);
@@ -578,6 +605,10 @@ public class Vala.GVariantModule : GAsyncModule {
        }
 
        CCodeExpression? serialize_array (ArrayType array_type, CCodeExpression array_expr) {
+               if (array_type.rank == 1 && get_type_signature (array_type) == "ay") {
+                       return serialize_buffer_array (array_type, array_expr);
+               }
+
                string array_iter_name = "_tmp%d_".printf (next_temp_var_id++);
 
                ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (array_iter_name));
@@ -631,6 +662,28 @@ public class Vala.GVariantModule : GAsyncModule {
                return builder_end;
        }
 
+       CCodeExpression serialize_buffer_array (ArrayType array_type, CCodeExpression array_expr) {
+               string buffer_name = "_tmp%d_".printf (next_temp_var_id++);
+
+               var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE"));
+               gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (array_type))));
+
+               var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+               dup_call.add_argument (array_expr);
+               dup_call.add_argument (get_array_length (array_expr, 1));
+               ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (buffer_name, dup_call));
+
+               var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_from_data"));
+               new_call.add_argument (gvariant_type);
+               new_call.add_argument (new CCodeIdentifier (buffer_name));
+               new_call.add_argument (get_array_length (array_expr, 1));
+               new_call.add_argument (new CCodeConstant ("TRUE"));
+               new_call.add_argument (new CCodeIdentifier ("g_free"));
+               new_call.add_argument (new CCodeIdentifier (buffer_name));
+
+               return new_call;
+       }
+
        CCodeExpression? serialize_struct (Struct st, CCodeExpression struct_expr) {
                string builder_name = "_tmp%d_".printf (next_temp_var_id++);
 
index e78fbd2f2dbfffc30eb7b1a800d81ff1aed0cec6..2889ffea94578b3da76c9a7c7db2b8ac51048869 100644 (file)
@@ -43,6 +43,7 @@ TESTS = \
        basic-types/bug761307.vala \
        basic-types/bug761736.vala \
        basic-types/bug771626.test \
+       basic-types/bug772426.vala \
        basic-types/bug777697.test \
        namespaces.vala \
        methods/lambda.vala \
diff --git a/tests/basic-types/bug772426.vala b/tests/basic-types/bug772426.vala
new file mode 100644 (file)
index 0000000..43094e8
--- /dev/null
@@ -0,0 +1,18 @@
+int BUFFER_LENGTH = 1048576;
+
+void main () {
+       // Some reasonably sized memory block
+       void* buffer_p = malloc (BUFFER_LENGTH);
+       Memory.set (buffer_p, 0x55555555, BUFFER_LENGTH);
+       unowned uint8[] buffer = (uint8[]) buffer_p;
+       buffer.length = BUFFER_LENGTH;
+
+       // Serialize
+       Variant v = buffer;
+
+       // Deserialize
+       var result = (uint8[]) v;
+
+       assert (Memory.cmp (buffer, result, BUFFER_LENGTH) == 0);
+       free (buffer_p);
+}