[vala/emit-let: 1/2] codegen: Replace get_unref_expression_ with destroy_variable.
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/emit-let: 1/2] codegen: Replace get_unref_expression_ with destroy_variable.
- Date: Sun, 23 Jan 2011 10:28:21 +0000 (UTC)
commit 1d6eb03e043172a2bd3eb82f331effc6432418f7
Author: Luca Bruno <lucabru src gnome org>
Date: Sat Jan 22 12:26:03 2011 +0100
codegen: Replace get_unref_expression_ with destroy_variable.
codegen/valaccodebasemodule.vala | 180 +++++++++++++++++++++++++++---
codegen/valaccodecontrolflowmodule.vala | 2 +-
codegen/valaccodememberaccessmodule.vala | 3 +-
codegen/valadbusclientmodule.vala | 2 +-
codegen/valadbusservermodule.vala | 2 +-
codegen/valagasyncmodule.vala | 4 +-
codegen/valagdbusclientmodule.vala | 2 +-
codegen/valagdbusservermodule.vala | 2 +-
8 files changed, 175 insertions(+), 22 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 14258bc..2684b83 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -991,7 +991,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
foreach (LocalVariable local in temp_ref_vars) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
temp_ref_vars.clear ();
@@ -1045,7 +1045,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
ccode.add_assignment (lhs, rhs);
foreach (LocalVariable local in temp_ref_vars) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
temp_ref_vars.clear ();
@@ -1710,7 +1710,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
current_method.coroutine = false;
}
- free_block.add_statement (new CCodeExpressionStatement (get_unref_expression_ (param)));
+ free_block.add_statement (new CCodeExpressionStatement (destroy_variable (param)));
if (old_coroutine) {
current_method.coroutine = true;
@@ -1803,7 +1803,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
current_method.coroutine = false;
}
- free_block.add_statement (new CCodeExpressionStatement (get_unref_expression_ (local)));
+ free_block.add_statement (new CCodeExpressionStatement (destroy_variable (local)));
if (old_coroutine) {
current_method.coroutine = true;
@@ -1929,7 +1929,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
var local = local_vars[i];
local.active = false;
if (!local.unreachable && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
}
@@ -1937,7 +1937,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
var m = (Method) b.parent_symbol;
foreach (Parameter param in m.get_parameters ()) {
if (!param.captured && !param.ellipsis && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) {
- ccode.add_expression (get_unref_expression_ (param));
+ ccode.add_expression (destroy_variable (param));
} else if (param.direction == ParameterDirection.OUT && !m.coroutine) {
return_out_parameter (param);
}
@@ -2789,13 +2789,161 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return null;
}
- public CCodeExpression get_unref_expression_ (Variable variable, CCodeExpression? inner = null) {
- return destroy_value (get_variable_cvalue (variable, inner));
+ public CCodeExpression destroy_variable (Variable variable, CCodeExpression? inner = null) {
+ var type = variable.variable_type;
+ var target_lvalue = get_variable_cvalue (variable, inner);
+ var cvar = get_cvalue_ (target_lvalue);
+
+ if (type is DelegateType) {
+ var delegate_target = get_delegate_target_cvalue (target_lvalue);
+ var delegate_target_destroy_notify = get_delegate_target_destroy_notify_cvalue (target_lvalue);
+
+ var ccall = new CCodeFunctionCall (delegate_target_destroy_notify);
+ ccall.add_argument (delegate_target);
+
+ var destroy_call = new CCodeCommaExpression ();
+ destroy_call.append_expression (ccall);
+ destroy_call.append_expression (new CCodeConstant ("NULL"));
+
+ var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, delegate_target_destroy_notify, new CCodeConstant ("NULL"));
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.append_expression (new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), destroy_call));
+ ccomma.append_expression (new CCodeAssignment (cvar, new CCodeConstant ("NULL")));
+ ccomma.append_expression (new CCodeAssignment (delegate_target, new CCodeConstant ("NULL")));
+ ccomma.append_expression (new CCodeAssignment (delegate_target_destroy_notify, new CCodeConstant ("NULL")));
+
+ return ccomma;
+ }
+
+ var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
+
+ if (type is ValueType && !type.nullable) {
+ // normal value type, no null check
+ var st = type.data_type as Struct;
+ if (st != null && st.is_simple_type ()) {
+ // used for va_list
+ ccall.add_argument (cvar);
+ } else {
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
+ }
+
+ if (gvalue_type != null && type.data_type == gvalue_type) {
+ // g_value_unset must not be called for already unset values
+ var cisvalid = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_VALUE"));
+ cisvalid.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.append_expression (ccall);
+ ccomma.append_expression (new CCodeConstant ("NULL"));
+
+ return new CCodeConditionalExpression (cisvalid, ccomma, new CCodeConstant ("NULL"));
+ } else {
+ return ccall;
+ }
+ }
+
+ if (ccall.call is CCodeIdentifier && !(type is ArrayType)) {
+ // generate and use NULL-aware free macro to simplify code
+
+ var freeid = (CCodeIdentifier) ccall.call;
+ string free0_func = "_%s0".printf (freeid.name);
+
+ if (add_wrapper (free0_func)) {
+ var macro = destroy_value (new GLibValue (type, new CCodeIdentifier ("var")), true);
+ cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("%s(var)".printf (free0_func), macro));
+ }
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier (free0_func));
+ ccall.add_argument (cvar);
+ return ccall;
+ }
+
+ /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */
+
+ /* can be simplified to
+ * foo = (unref (foo), NULL)
+ * if foo is of static type non-null
+ */
+
+ var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
+ if (type.type_parameter != null) {
+ if (!(current_type_symbol is Class) || current_class.is_compact) {
+ return new CCodeConstant ("NULL");
+ }
+
+ // unref functions are optional for type parameters
+ var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
+ cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
+ }
+
+ ccall.add_argument (cvar);
+
+ /* set freed references to NULL to prevent further use */
+ var ccomma = new CCodeCommaExpression ();
+
+ if (context.profile == Profile.GOBJECT) {
+ if (type.data_type != null && !type.data_type.is_reference_counting () &&
+ (type.data_type == gstringbuilder_type
+ || type.data_type == garray_type
+ || type.data_type == gbytearray_type
+ || type.data_type == gptrarray_type)) {
+ ccall.add_argument (new CCodeConstant ("TRUE"));
+ } else if (type.data_type == gthreadpool_type) {
+ ccall.add_argument (new CCodeConstant ("FALSE"));
+ ccall.add_argument (new CCodeConstant ("TRUE"));
+ } else if (type is ArrayType) {
+ var array_type = (ArrayType) type;
+ if (requires_destroy (array_type.element_type) && !variable.no_array_length) {
+ CCodeExpression csizeexpr = null;
+ TargetValue access_value = null;
+ if (variable is LocalVariable) {
+ access_value = load_local ((LocalVariable) variable);
+ } else if (variable is Parameter) {
+ access_value = load_parameter ((Parameter) variable);
+ }
+ bool first = true;
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ if (first) {
+ csizeexpr = get_array_length_cvalue (access_value, dim);
+ first = false;
+ } else {
+ csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, get_array_length_cvalue (access_value, dim));
+ }
+ }
+
+ var st = array_type.element_type.data_type as Struct;
+ if (st != null && !array_type.element_type.nullable) {
+ ccall.call = new CCodeIdentifier (append_struct_array_free (st));
+ ccall.add_argument (csizeexpr);
+ } else {
+ requires_array_free = true;
+ ccall.call = new CCodeIdentifier ("_vala_array_free");
+ ccall.add_argument (csizeexpr);
+ ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
+ }
+ }
+ }
+ }
+
+ ccomma.append_expression (ccall);
+ ccomma.append_expression (new CCodeConstant ("NULL"));
+
+ var cassign = new CCodeAssignment (cvar, ccomma);
+
+ // g_free (NULL) is allowed
+ bool uses_gfree = (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free");
+ uses_gfree = uses_gfree || type is ArrayType;
+ if (uses_gfree) {
+ return cassign;
+ }
+
+ return new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), cassign);
}
public CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression? expr, bool is_macro_definition = false) {
if (expr != null && (expr.symbol_reference is LocalVariable || expr.symbol_reference is Parameter)) {
- return get_unref_expression_ ((Variable) expr.symbol_reference);
+ return destroy_variable ((Variable) expr.symbol_reference);
}
var value = new GLibValue (type, cvar);
if (expr != null && expr.target_value != null) {
@@ -2984,7 +3132,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
foreach (LocalVariable local in temp_ref_vars) {
- expr_list.append_expression (get_unref_expression_ (local));
+ expr_list.append_expression (destroy_variable (local));
}
if (full_expr_var != null) {
@@ -3060,7 +3208,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
/* free temporary objects and handle errors */
foreach (LocalVariable local in temp_ref_vars) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
@@ -3079,7 +3227,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
for (int i = local_vars.size - 1; i >= 0; i--) {
var local = local_vars[i];
if (!local.unreachable && local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
}
@@ -3114,7 +3262,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
private void append_param_free (Method m) {
foreach (Parameter param in m.get_parameters ()) {
if (!param.ellipsis && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) {
- ccode.add_expression (get_unref_expression_ (param));
+ ccode.add_expression (destroy_variable (param));
}
}
}
@@ -3154,7 +3302,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
if (param.variable_type.is_disposable ()){
ccode.add_else ();
- ccode.add_expression (get_unref_expression_ (param));
+ ccode.add_expression (destroy_variable (param));
}
ccode.close ();
@@ -3516,6 +3664,10 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
assert_not_reached ();
}
+ public virtual TargetValue load_parameter (Parameter param) {
+ assert_not_reached ();
+ }
+
public virtual string get_delegate_target_cname (string delegate_cname) {
assert_not_reached ();
}
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index 6ad5f01..8602372 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -380,7 +380,7 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
foreach (LocalVariable local in stmt.get_local_variables ()) {
if (requires_destroy (local.variable_type)) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
}
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 882109d..f1937c2 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -704,7 +704,8 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
return load_variable (local, result);
}
- public TargetValue load_parameter (Parameter param) {
+ /* Returns unowned access to the given parameter */
+ public override TargetValue load_parameter (Parameter param) {
var result = (GLibValue) get_parameter_cvalue (param);
if (result.value_type is DelegateType) {
result.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
diff --git a/codegen/valadbusclientmodule.vala b/codegen/valadbusclientmodule.vala
index 7428ac2..0744152 100644
--- a/codegen/valadbusclientmodule.vala
+++ b/codegen/valadbusclientmodule.vala
@@ -1577,7 +1577,7 @@ public class Vala.DBusClientModule : DBusModule {
if (requires_destroy (owned_type)) {
// keep local alive (symbol_reference is weak)
var local = new LocalVariable (owned_type, param.name);
- var stmt = new CCodeExpressionStatement (get_unref_expression_ (local));
+ var stmt = new CCodeExpressionStatement (destroy_variable (local));
postfragment.append (stmt);
}
}
diff --git a/codegen/valadbusservermodule.vala b/codegen/valadbusservermodule.vala
index 3cc1c89..cbae8cf 100644
--- a/codegen/valadbusservermodule.vala
+++ b/codegen/valadbusservermodule.vala
@@ -252,7 +252,7 @@ public class Vala.DBusServerModule : DBusClientModule {
if (requires_destroy (owned_type)) {
// keep local alive (symbol_reference is weak)
var local = new LocalVariable (owned_type, param.name);
- var stmt = new CCodeExpressionStatement (get_unref_expression_ (local));
+ var stmt = new CCodeExpressionStatement (destroy_variable (local));
if (param.direction == ParameterDirection.IN) {
in_postfragment.append (stmt);
} else {
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index 9971817..5aafe8d 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -111,7 +111,7 @@ public class Vala.GAsyncModule : GSignalModule {
bool old_captured = param.captured;
param.captured = false;
- freeblock.add_statement (new CCodeExpressionStatement (get_unref_expression_ (param)));
+ freeblock.add_statement (new CCodeExpressionStatement (destroy_variable (param)));
param.captured = old_captured;
}
@@ -593,7 +593,7 @@ public class Vala.GAsyncModule : GSignalModule {
/* free temporary objects */
foreach (LocalVariable local in temp_ref_vars) {
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
temp_ref_vars.clear ();
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 666ac19..054047a 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -395,7 +395,7 @@ public class Vala.GDBusClientModule : GDBusModule {
if (requires_destroy (owned_type)) {
// keep local alive (symbol_reference is weak)
var local = new LocalVariable (owned_type, param.name);
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
}
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
index 7514c1d..2f71857 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -389,7 +389,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
if (requires_destroy (owned_type)) {
// keep local alive (symbol_reference is weak)
var local = new LocalVariable (owned_type, param.name);
- ccode.add_expression (get_unref_expression_ (local));
+ ccode.add_expression (destroy_variable (local));
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]