[gjs] Don't release too much when releasing arrays
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Don't release too much when releasing arrays
- Date: Thu, 18 Aug 2011 13:20:38 +0000 (UTC)
commit fa8b8447fbbf1fd421621751b57a4d2e11f7bb2d
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sat Jul 2 16:58:16 2011 +0200
Don't release too much when releasing arrays
The functions that released out arrays were iterating over
pointer sized values, irrespective of the actual element size.
Fix that by checking that the element is actually a pointer
(everything else requires no release, except for the actual array
block)
https://bugzilla.gnome.org/show_bug.cgi?id=652753
gi/arg.c | 103 ++++++++++++++++++++++++++++++++-------
test/js/testEverythingBasic.js | 17 ++++++-
2 files changed, 100 insertions(+), 20 deletions(-)
---
diff --git a/gi/arg.c b/gi/arg.c
index 0170845..c8d769b 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -198,6 +198,7 @@ type_needs_release (GITypeInfo *type_info,
case GI_INFO_TYPE_STRUCT:
case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
case GI_INFO_TYPE_OBJECT:
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_UNION:
@@ -233,6 +234,49 @@ type_needs_release (GITypeInfo *type_info,
}
}
+/* Check if an argument of the given needs to be released if we obtained it
+ * from out argument (or the return value), and we're transferring ownership
+ */
+static JSBool
+type_needs_out_release(GITypeInfo *type_info,
+ GITypeTag type_tag)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_GHASH:
+ return TRUE;
+ case GI_TYPE_TAG_INTERFACE: {
+ GIBaseInfo* interface_info;
+ GIInfoType interface_type;
+ gboolean needs_release;
+
+ interface_info = g_type_info_get_interface(type_info);
+ g_assert(interface_info != NULL);
+
+ interface_type = g_base_info_get_type(interface_info);
+
+ switch(interface_type) {
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ needs_release = FALSE;
+
+ default:
+ needs_release = TRUE;
+ }
+
+ g_base_info_unref(interface_info);
+
+ return needs_release;
+ }
+ default:
+ return FALSE;
+ }
+}
+
static JSBool
gjs_array_to_g_list(JSContext *context,
jsval array_value,
@@ -2576,19 +2620,38 @@ gjs_g_arg_release_internal(JSContext *context,
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_GHASH:
- if (transfer != GI_TRANSFER_CONTAINER) {
- g_assert (g_type_info_is_zero_terminated (type_info));
- gpointer *array;
- GArgument elem;
-
- for (array = arg->v_pointer; *array; array++) {
- elem.v_pointer = *array;
- if (!gjs_g_arg_release_internal(context,
- GI_TRANSFER_EVERYTHING,
- param_info,
- element_type,
- &elem)) {
- failed = JS_TRUE;
+ if (transfer != GI_TRANSFER_CONTAINER
+ && type_needs_out_release(param_info, element_type)) {
+ if (g_type_info_is_zero_terminated (type_info)) {
+ gpointer *array;
+ GArgument elem;
+
+ for (array = arg->v_pointer; *array; array++) {
+ elem.v_pointer = *array;
+ if (!gjs_g_arg_release_internal(context,
+ GI_TRANSFER_EVERYTHING,
+ param_info,
+ element_type,
+ &elem)) {
+ failed = JS_TRUE;
+ }
+ }
+ } else {
+ gint len = g_type_info_get_array_fixed_size(type_info);
+ gint i;
+ GArgument elem;
+
+ g_assert(len != -1);
+
+ for (i = 0; i < len; i++) {
+ elem.v_pointer = ((gpointer*)arg->v_pointer)[i];
+ if (!gjs_g_arg_release_internal(context,
+ GI_TRANSFER_EVERYTHING,
+ param_info,
+ element_type,
+ &elem)) {
+ failed = TRUE;
+ }
}
}
}
@@ -2632,7 +2695,7 @@ gjs_g_arg_release_internal(JSContext *context,
case GI_TYPE_TAG_GHASH:
if (transfer == GI_TRANSFER_CONTAINER) {
g_array_free((GArray*) arg->v_pointer, TRUE);
- } else {
+ } else if (type_needs_out_release (param_info, element_type)) {
GArray *array = arg->v_pointer;
guint i;
@@ -2640,10 +2703,11 @@ gjs_g_arg_release_internal(JSContext *context,
GArgument arg;
arg.v_pointer = g_array_index (array, gpointer, i);
- gjs_g_argument_release(context,
- transfer,
- param_info,
- &arg);
+ gjs_g_arg_release_internal(context,
+ transfer,
+ param_info,
+ element_type,
+ &arg);
}
g_array_free (array, TRUE);
@@ -2876,7 +2940,8 @@ gjs_g_argument_release_out_array (JSContext *context,
param_type = g_type_info_get_param_type(type_info, 0);
type_tag = g_type_info_get_tag(param_type);
- if (transfer != GI_TRANSFER_CONTAINER) {
+ if (transfer != GI_TRANSFER_CONTAINER &&
+ type_needs_out_release(param_type, type_tag)) {
for (i = 0; i < length; i++) {
elem.v_pointer = array[i];
if (!gjs_g_arg_release_internal(context,
diff --git a/test/js/testEverythingBasic.js b/test/js/testEverythingBasic.js
index 264b216..9e49cbf 100644
--- a/test/js/testEverythingBasic.js
+++ b/test/js/testEverythingBasic.js
@@ -295,6 +295,12 @@ function testArrayIn() {
}
function testArrayOut() {
+ function arrayEqual(ref, res) {
+ assertEquals(ref.length, res.length);
+ for (let i = 0; i < ref.length; i++)
+ assertEquals(ref[i], res[i]);
+ }
+
let array = Everything.test_array_fixed_size_int_out();
assertEquals(0, array[0]);
assertEquals(4, array[4]);
@@ -302,7 +308,16 @@ function testArrayOut() {
assertEquals(0, array[0]);
assertEquals(4, array[4]);
- // FIXME: test_array_int_full_out and test_array_int_none_out unimplemented
+ array = Everything.test_array_int_none_out();
+ arrayEqual([1, 2, 3, 4, 5], array);
+
+ array = Everything.test_array_int_full_out();
+ arrayEqual([0, 1, 2, 3, 4], array);
+
+ array = Everything.test_array_int_null_out();
+ assertEquals(0, array.length);
+
+ Everything.test_array_int_null_in(null);
}
/* GHash type */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]