From b624a18f3cf9c9876419ab1f557b5d288763cfa9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Mon, 29 Sep 2008 21:35:39 +0000 Subject: [PATCH] Add experimental memory management support for structs that use reference MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2008-09-29 Jürg Billeter * vala/valadatatype.vala: * vala/valastruct.vala: * vala/valavaluetype.vala: * gobject/valaccodegenerator.vala: * gobject/valaccodegeneratorstruct.vala: Add experimental memory management support for structs that use reference types in fields, fixes bug 526552 svn path=/trunk/; revision=1814 --- ChangeLog | 11 ++++++++ gobject/valaccodegenerator.vala | 40 ++++++++++++++++++++++---- gobject/valaccodegeneratorstruct.vala | 51 +++++++++++++++++++++++++++++++++ vala/valadatatype.vala | 3 -- vala/valastruct.vala | 53 +++++++++++++++++++++++++++++++++++ vala/valavaluetype.vala | 18 ++++++++++++ 6 files changed, 167 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ec88ff..9a7034f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-09-29 Jürg Billeter + + * vala/valadatatype.vala: + * vala/valastruct.vala: + * vala/valavaluetype.vala: + * gobject/valaccodegenerator.vala: + * gobject/valaccodegeneratorstruct.vala: + + Add experimental memory management support for structs that use + reference types in fields, fixes bug 526552 + 2008-09-28 Jürg Billeter * vapi/glib-2.0.vapi: diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 925b4f1..5dd32d9 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -1486,6 +1486,9 @@ public class Vala.CCodeGenerator : CodeGenerator { if (unref_function == null) { unref_function = "g_free"; } + } else { + var st = (Struct) type.data_type; + unref_function = st.get_destroy_function (); } } if (unref_function == null) { @@ -1551,6 +1554,14 @@ public class Vala.CCodeGenerator : CodeGenerator { } public CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) { + var ccall = new CCodeFunctionCall (get_destroy_func_expression (type)); + + if (type is ValueType && !type.nullable) { + // normal value type, no null check + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar)); + return ccall; + } + /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */ /* can be simplified to @@ -1569,9 +1580,8 @@ public class Vala.CCodeGenerator : CodeGenerator { cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull); } - var ccall = new CCodeFunctionCall (get_destroy_func_expression (type)); ccall.add_argument (cvar); - + /* set freed references to NULL to prevent further use */ var ccomma = new CCodeCommaExpression (); @@ -3027,11 +3037,29 @@ public class Vala.CCodeGenerator : CodeGenerator { return true; } - private CCodeExpression? get_ref_expression (Expression expr) { - return get_ref_cexpression (expr.value_type, (CCodeExpression) expr.ccodenode, expr, expr); - } - private CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) { + if (expression_type is ValueType && !expression_type.nullable) { + // normal value type, no null check + // (copy (&expr, &temp), temp) + + var decl = get_temp_variable (expression_type, false, node); + temp_vars.insert (0, decl); + + var ctemp = new CCodeIdentifier (decl.name); + + var vt = (ValueType) expression_type; + var st = (Struct) vt.type_symbol; + var copy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_copy_function ())); + copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr)); + copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); + + var ccomma = new CCodeCommaExpression (); + ccomma.append_expression (copy_call); + ccomma.append_expression (ctemp); + + return ccomma; + } + /* (temp = expr, temp == NULL ? NULL : ref (temp)) * * can be simplified to diff --git a/gobject/valaccodegeneratorstruct.vala b/gobject/valaccodegeneratorstruct.vala index 03de0b2..8fd89a4 100644 --- a/gobject/valaccodegeneratorstruct.vala +++ b/gobject/valaccodegeneratorstruct.vala @@ -53,8 +53,59 @@ public class Vala.CCodeGenerator { st.accept_children (this); + if (st.is_disposable ()) { + add_struct_copy_function (st); + add_struct_destroy_function (st); + } + current_type_symbol = old_type_symbol; instance_struct = old_instance_struct; instance_finalize_fragment = old_instance_finalize_fragment; } + + void add_struct_copy_function (Struct st) { + var function = new CCodeFunction (st.get_copy_function (), "void"); + if (st.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("dest", st.get_cname () + "*")); + + if (st.access != SymbolAccessibility.PRIVATE) { + header_type_member_declaration.append (function.copy ()); + } else { + source_type_member_declaration.append (function.copy ()); + } + + var cblock = new CCodeBlock (); + + function.block = cblock; + + source_type_member_definition.append (function); + } + + void add_struct_destroy_function (Struct st) { + var function = new CCodeFunction (st.get_destroy_function (), "void"); + if (st.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*")); + + if (st.access != SymbolAccessibility.PRIVATE) { + header_type_member_declaration.append (function.copy ()); + } else { + source_type_member_declaration.append (function.copy ()); + } + + var cblock = new CCodeBlock (); + + cblock.add_statement (instance_finalize_fragment); + + function.block = cblock; + + source_type_member_definition.append (function); + } } + diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 9d35659..a3c2144 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -461,9 +461,6 @@ public abstract class Vala.DataType : CodeNode { if (is_reference_type_or_type_parameter ()) { return true; - } else if (this is ValueType) { - // nullable structs are heap allocated - return nullable; } return false; } diff --git a/vala/valastruct.vala b/vala/valastruct.vala index 0876429..74d8297 100644 --- a/vala/valastruct.vala +++ b/vala/valastruct.vala @@ -50,6 +50,8 @@ public class Vala.Struct : TypeSymbol { private string default_value = null; private bool simple_type; private string? type_signature; + private string copy_function; + private string destroy_function; /** * Specifies the default construction method. @@ -340,6 +342,12 @@ public class Vala.Struct : TypeSymbol { if (a.has_argument ("type_signature")) { type_signature = a.get_string ("type_signature"); } + if (a.has_argument ("copy_function")) { + set_copy_function (a.get_string ("copy_function")); + } + if (a.has_argument ("destroy_function")) { + set_destroy_function (a.get_string ("destroy_function")); + } } private void process_integer_type_attribute (Attribute a) { @@ -556,4 +564,49 @@ public class Vala.Struct : TypeSymbol { return false; } + + public string get_default_copy_function () { + return get_lower_case_cprefix () + "copy"; + } + + public override string? get_copy_function () { + if (copy_function == null) { + copy_function = get_default_copy_function (); + } + return copy_function; + } + + public void set_copy_function (string name) { + this.copy_function = name; + } + + public string get_default_destroy_function () { + return get_lower_case_cprefix () + "destroy"; + } + + public override string? get_destroy_function () { + if (destroy_function == null) { + destroy_function = get_default_destroy_function (); + } + return destroy_function; + } + + public void set_destroy_function (string name) { + this.destroy_function = name; + } + + public bool is_disposable () { + if (destroy_function != null) { + return true; + } + + foreach (Field f in fields) { + if (f.binding == MemberBinding.INSTANCE + && f.field_type.is_disposable ()) { + return true; + } + } + + return false; + } } diff --git a/vala/valavaluetype.vala b/vala/valavaluetype.vala index 9e5296c..87741d4 100644 --- a/vala/valavaluetype.vala +++ b/vala/valavaluetype.vala @@ -59,4 +59,22 @@ public class Vala.ValueType : DataType { } return type_symbol.get_cname () + ptr; } + + public override bool is_disposable () { + if (!value_owned) { + return false; + } + + // nullable structs are heap allocated + if (nullable) { + return true; + } + + var st = type_symbol as Struct; + if (st != null) { + return st.is_disposable (); + } + + return false; + } } -- 2.7.4