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.34.11~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0fa25d16ae9515207b5840a37bd7ef36418a90d2;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 f3113f4f4..9cf642de1 100644 --- a/codegen/valagvariantmodule.vala +++ b/codegen/valagvariantmodule.vala @@ -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++); diff --git a/tests/Makefile.am b/tests/Makefile.am index e78fbd2f2..2889ffea9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 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); +}