From: Ole André Vadla Ravnås Date: Tue, 14 Mar 2017 18:17:15 +0000 (+0100) Subject: gvariant: Optimize (de)serialization of arrays with type-signature "ay" X-Git-Tag: 0.37.1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a282213f56bfd33dd8fe91c4e349ccc403fcc27;p=thirdparty%2Fvala.git gvariant: Optimize (de)serialization of arrays with type-signature "ay" https://bugzilla.gnome.org/show_bug.cgi?id=772426 --- diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala index b3ff1cf51..bca03f12c 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 c6341307c..765d26b13 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,7 @@ TESTS = \ basic-types/bug756376.vala \ basic-types/bug761307.vala \ basic-types/bug771626.test \ + basic-types/bug772426.vala \ basic-types/bug777697.test \ chainup/class-base.vala \ chainup/class-base-foo.vala \ diff --git a/tests/basic-types/bug772426.vala b/tests/basic-types/bug772426.vala new file mode 100644 index 000000000..43094e8df --- /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); +}