[vala/0.36] gvariant: Optimize (de)serialization of arrays with type-signature "ay"



commit 8a54df746a5fdd3802e436d99a89c24bc4c5b396
Author: Ole André Vadla Ravnås <oleavr gmail com>
Date:   Tue Mar 14 19:17:15 2017 +0100

    gvariant: Optimize (de)serialization of arrays with type-signature "ay"
    
    https://bugzilla.gnome.org/show_bug.cgi?id=772426

 codegen/valagvariantmodule.vala  |   53 ++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am                |    1 +
 tests/basic-types/bug772426.vala |   18 +++++++++++++
 3 files changed, 72 insertions(+), 0 deletions(-)
---
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index b3ff1cf..bca03f1 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -267,6 +267,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"));
@@ -346,6 +350,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++);
@@ -581,6 +608,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));
@@ -634,6 +665,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++);
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 99077d0..dcd7579 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -44,6 +44,7 @@ TESTS = \
        basic-types/bug761307.vala \
        basic-types/bug761736.vala \
        basic-types/bug771626.test \
+       basic-types/bug772426.vala \
        basic-types/bug777697.test \
        basic-types/bug787152.vala \
        chainup/class-base.vala \
diff --git a/tests/basic-types/bug772426.vala b/tests/basic-types/bug772426.vala
new file mode 100644
index 0000000..43094e8
--- /dev/null
+++ b/tests/basic-types/bug772426.vala
@@ -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);
+}


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