From: Juerg Billeter Date: Thu, 26 Jul 2007 14:24:22 +0000 (+0000) Subject: free array elements X-Git-Tag: VALA_0_1_2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a98c980b77cae8e3963b9b80f1470fa5e4efaf0e;p=thirdparty%2Fvala.git free array elements 2007-07-26 Juerg Billeter * gobject/valacodegenerator.vala, gobject/valacodegeneratorassignment.vala, gobject/valacodegeneratorsourcefile.vala: free array elements svn path=/trunk/; revision=391 --- diff --git a/ChangeLog b/ChangeLog index ba958a93b..c22a4e759 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-07-26 Jürg Billeter + + * gobject/valacodegenerator.vala, + gobject/valacodegeneratorassignment.vala, + gobject/valacodegeneratorsourcefile.vala: free array elements + 2007-07-26 Jürg Billeter * vala/valamemorymanager.vala, vala/valasemanticanalyzer.vala, diff --git a/gobject/valacodegenerator.vala b/gobject/valacodegenerator.vala index 812ddd361..431df5207 100644 --- a/gobject/valacodegenerator.vala +++ b/gobject/valacodegenerator.vala @@ -97,6 +97,7 @@ public class Vala.CodeGenerator : CodeVisitor { TypeReference double_type; DataType glist_type; DataType gslist_type; + DataType gstring_type; TypeReference mutex_type; DataType type_module_type; DataType iterable_type; @@ -110,6 +111,8 @@ public class Vala.CodeGenerator : CodeVisitor { private string module_init_param_name; private bool string_h_needed; + private bool requires_free_checked; + private bool requires_array_free; public CodeGenerator (bool manage_memory = true) { memory_management = manage_memory; @@ -240,6 +243,7 @@ public class Vala.CodeGenerator : CodeVisitor { glist_type = (DataType) glib_ns.scope.lookup ("List"); gslist_type = (DataType) glib_ns.scope.lookup ("SList"); + gstring_type = (DataType) glib_ns.scope.lookup ("String"); mutex_type = new TypeReference (); mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex"); @@ -346,6 +350,7 @@ public class Vala.CodeGenerator : CodeVisitor { get_symbol_lock_name (m)), new CCodeFunctionCall (new CCodeIdentifier (((Struct)mutex_type.data_type).default_construction_method.get_cname ()))))); + requires_free_checked = true; var fc = new CCodeFunctionCall (new CCodeIdentifier ("VALA_FREE_CHECKED")); fc.add_argument ( new CCodeMemberAccess.pointer ( @@ -439,7 +444,9 @@ public class Vala.CodeGenerator : CodeVisitor { } if (f.type_reference.takes_ownership && instance_dispose_fragment != null) { - instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference))); + var ma = new MemberAccess.simple (f.name); + ma.symbol_reference = f; + instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference, ma))); } } } @@ -719,7 +726,9 @@ public class Vala.CodeGenerator : CodeVisitor { if (memory_management) { foreach (VariableDeclarator decl in local_vars) { if (decl.type_reference.takes_ownership) { - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference))); + var ma = new MemberAccess.simple (decl.name); + ma.symbol_reference = decl; + cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma))); } } } @@ -921,7 +930,7 @@ public class Vala.CodeGenerator : CodeVisitor { } } - private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) { + private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type, Expression expr) { /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */ /* can be simplified to @@ -950,33 +959,54 @@ public class Vala.CodeGenerator : CodeVisitor { /* set freed references to NULL to prevent further use */ var ccomma = new CCodeCommaExpression (); - // TODO cleanup - if (type.data_type != null && !type.data_type.is_reference_counting ()) { - string unref_function = type.data_type.get_free_function (); - if (unref_function == "g_list_free") { - bool is_ref = false; - bool is_class = false; - bool is_interface = false; + if (type.data_type == glist_type) { + bool is_ref = false; + bool is_class = false; + bool is_interface = false; - foreach (TypeReference type_arg in type.get_type_arguments ()) { - is_ref |= type_arg.takes_ownership; - is_class |= type_arg.data_type is Class; - is_interface |= type_arg.data_type is Interface; + foreach (TypeReference type_arg in type.get_type_arguments ()) { + is_ref |= type_arg.takes_ownership; + is_class |= type_arg.data_type is Class; + is_interface |= type_arg.data_type is Interface; + } + + if (is_ref) { + var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach")); + cunrefcall.add_argument (cvar); + if (is_class || is_interface) { + cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref")); + } else { + cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free")); } - - if (is_ref) { - var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach")); - cunrefcall.add_argument (cvar); - if (is_class || is_interface) { - cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref")); + cunrefcall.add_argument (new CCodeConstant ("NULL")); + ccomma.append_expression (cunrefcall); + } + } else if (type.data_type == gstring_type) { + ccall.add_argument (new CCodeConstant ("TRUE")); + } else if (type.data_type is Array) { + var arr = (Array) type.data_type; + if (arr.element_type == string_type.data_type) { + ccall.call = new CCodeIdentifier ("g_strfreev"); + } else if (arr.element_type == null || arr.element_type.is_reference_type ()) { + requires_array_free = true; + + bool first = true; + CCodeExpression csizeexpr = null; + for (int dim = 1; dim <= arr.rank; dim++) { + if (first) { + csizeexpr = get_array_length_cexpression (expr, dim); + first = false; } else { - cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free")); + csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, get_array_length_cexpression (expr, dim)); } - cunrefcall.add_argument (new CCodeConstant ("NULL")); - ccomma.append_expression (cunrefcall); } - } else if (unref_function == "g_string_free") { - ccall.add_argument (new CCodeConstant ("TRUE")); + + ccall.call = new CCodeIdentifier ("_vala_array_free"); + ccall.add_argument (csizeexpr); + var element_type = new TypeReference (); + element_type.data_type = arr.element_type; + element_type.type_parameter = arr.element_type_parameter; + ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (element_type), "GDestroyNotify")); } } @@ -1032,7 +1062,9 @@ public class Vala.CodeGenerator : CodeVisitor { expr_list.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_decl.name), (CCodeExpression) expr.ccodenode)); foreach (VariableDeclarator decl in temp_ref_vars) { - expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference)); + var ma = new MemberAccess.simple (decl.name); + ma.symbol_reference = decl; + expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma)); } expr_list.append_expression (new CCodeIdentifier (full_expr_decl.name)); @@ -1158,7 +1190,9 @@ public class Vala.CodeGenerator : CodeVisitor { cfrag.append (stmt.ccodenode); foreach (VariableDeclarator decl in temp_ref_vars) { - cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference))); + var ma = new MemberAccess.simple (decl.name); + ma.symbol_reference = decl; + cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma))); } stmt.ccodenode = cfrag; @@ -1450,7 +1484,9 @@ public class Vala.CodeGenerator : CodeVisitor { } if (memory_management && stmt.collection.static_type.transfers_ownership) { - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type))); + var ma = new MemberAccess.simple (collection_backup.name); + ma.symbol_reference = collection_backup; + cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type, ma))); } } @@ -1468,7 +1504,9 @@ public class Vala.CodeGenerator : CodeVisitor { var local_vars = b.get_local_variables (); foreach (VariableDeclarator decl in local_vars) { if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) { - cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference))); + var ma = new MemberAccess.simple (decl.name); + ma.symbol_reference = decl; + cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma))); } } @@ -1499,7 +1537,9 @@ public class Vala.CodeGenerator : CodeVisitor { foreach (VariableDeclarator decl in local_vars) { if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) { found = true; - ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference)); + var ma = new MemberAccess.simple (decl.name); + ma.symbol_reference = decl; + ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma)); } } @@ -1816,6 +1856,9 @@ public class Vala.CodeGenerator : CodeVisitor { array_expr = unary_expr.inner; is_out = true; } + } else if (array_expr is ReferenceTransferExpression) { + var reftransfer_expr = (ReferenceTransferExpression) array_expr; + array_expr = reftransfer_expr.inner; } if (array_expr is ArrayCreationExpression) { diff --git a/gobject/valacodegeneratorassignment.vala b/gobject/valacodegeneratorassignment.vala index 3e027ccd3..062dd0715 100644 --- a/gobject/valacodegeneratorassignment.vala +++ b/gobject/valacodegeneratorassignment.vala @@ -259,7 +259,7 @@ public class Vala.CodeGenerator { ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs)); if (unref_old) { /* unref old value */ - ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type)); + ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type, a.left)); } if (array) { diff --git a/gobject/valacodegeneratorsourcefile.vala b/gobject/valacodegeneratorsourcefile.vala index 14b8cc1ed..ae0cecb9c 100644 --- a/gobject/valacodegeneratorsourcefile.vala +++ b/gobject/valacodegeneratorsourcefile.vala @@ -45,6 +45,8 @@ public class Vala.CodeGenerator { next_temp_var_id = 0; string_h_needed = false; + requires_free_checked = false; + requires_array_free = false; header_begin.append (new CCodeIncludeDirective ("glib.h")); header_begin.append (new CCodeIncludeDirective ("glib-object.h")); @@ -97,10 +99,6 @@ public class Vala.CodeGenerator { } } } - - /* generate hardcoded "well-known" macros */ - source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))")); - source_begin.append (new CCodeMacroReplacement ("VALA_FREE_UNCHECKED(o,f)", "((o) = (f (o), NULL))")); source_file.accept_children (this); @@ -110,6 +108,49 @@ public class Vala.CodeGenerator { source_include_directives.append (new CCodeIncludeDirective ("string.h")); } + /* generate hardcoded "well-known" macros */ + if (requires_free_checked) { + source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))")); + } + if (requires_array_free) { + var fun = new CCodeFunction ("_vala_array_free", "void"); + fun.modifiers = CCodeModifiers.STATIC; + fun.add_parameter (new CCodeFormalParameter ("array", "gpointer")); + fun.add_parameter (new CCodeFormalParameter ("array_length", "gint")); + fun.add_parameter (new CCodeFormalParameter ("destroy_func", "GDestroyNotify")); + source_type_member_declaration.append (fun.copy ()); + + var cdofree = new CCodeBlock (); + + var citdecl = new CCodeDeclaration ("int"); + citdecl.add_declarator (new CCodeVariableDeclarator ("i")); + cdofree.add_statement (citdecl); + + var cbody = new CCodeBlock (); + + var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "gpointer*"); + var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i")); + var cfreecond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant ("NULL")); + var cfreecall = new CCodeFunctionCall (new CCodeIdentifier ("destroy_func")); + cfreecall.add_argument (cea); + cbody.add_statement (new CCodeIfStatement (cfreecond, new CCodeExpressionStatement (cfreecall))); + + var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length")); + + var cfor = new CCodeForStatement (cforcond, cbody); + cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"))); + cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1")))); + cdofree.add_statement (cfor); + + var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL")); + var ccondfunc = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("destroy_func"), new CCodeConstant ("NULL")); + var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccondarr, ccondfunc), cdofree); + fun.block = new CCodeBlock (); + fun.block.add_statement (cif); + + source_type_member_definition.append (fun); + } + CCodeComment comment = null; if (source_file.comment != null) { comment = new CCodeComment (source_file.comment);