summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2008-09-29 21:35:39 +0000
committerJürg Billeter <juergbi@src.gnome.org>2008-09-29 21:35:39 +0000
commitb624a18f3cf9c9876419ab1f557b5d288763cfa9 (patch)
tree6b7b274329c5586fe9395a80390140209e94569c
parent9c44de6bc711d77b6758394b39b37f85e894ffe7 (diff)
downloadvala-b624a18f3cf9c9876419ab1f557b5d288763cfa9.tar.gz
Add experimental memory management support for structs that use reference
2008-09-29 Jürg Billeter <j@bitron.ch> * 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
-rw-r--r--ChangeLog11
-rw-r--r--gobject/valaccodegenerator.vala40
-rw-r--r--gobject/valaccodegeneratorstruct.vala51
-rw-r--r--vala/valadatatype.vala3
-rw-r--r--vala/valastruct.vala53
-rw-r--r--vala/valavaluetype.vala18
6 files changed, 167 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ec88ff25..9a7034f54 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-09-29 Jürg Billeter <j@bitron.ch>
+
+ * 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 <j@bitron.ch>
* vapi/glib-2.0.vapi:
diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala
index 925b4f1c3..5dd32d935 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 03de0b291..8fd89a4c3 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 9d356593d..a3c2144a7 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 0876429d6..74d8297da 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 9e5296c58..87741d4ed 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;
+ }
}