[perl-Glib-Object-Introspection/ppc64-fixes: 3/6] Handle arg and type infos in the common invocation code



commit 5caa700fb67f8c201d085ba97388d88b54354195
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Sun Sep 7 18:40:06 2014 +0200

    Handle arg and type infos in the common invocation code
    
    Also, rename a struct field to avoid confusion.

 GObjectIntrospection.xs  |    7 ++++-
 gperl-i11n-invoke-c.c    |   56 ++++++++++++++--------------------------------
 gperl-i11n-invoke-perl.c |   27 +++++-----------------
 gperl-i11n-invoke.c      |   22 +++++++++++++++++-
 4 files changed, 49 insertions(+), 63 deletions(-)
---
diff --git a/GObjectIntrospection.xs b/GObjectIntrospection.xs
index 21327c7..2f72c2b 100644
--- a/GObjectIntrospection.xs
+++ b/GObjectIntrospection.xs
@@ -100,6 +100,10 @@ typedef struct {
         * args. */
        guint current_pos;
 
+       /* Information about the args from the typelib. */
+       GIArgInfo ** arg_infos;
+       GITypeInfo ** arg_types;
+
        /* An array of places for storing out out/in-out or automatic args. */
        GIArgument * aux_args;
 
@@ -137,10 +141,9 @@ typedef struct {
        guint n_given_args;
 
        gpointer * args;
-       ffi_type ** arg_types;
+       ffi_type ** arg_types_ffi;
        GIArgument * in_args;
        GIArgument * out_args;
-       GITypeInfo ** out_arg_infos;
        gboolean * is_automatic_arg;
 
        guint method_offset;
diff --git a/gperl-i11n-invoke-c.c b/gperl-i11n-invoke-c.c
index 075fe95..b15df84 100644
--- a/gperl-i11n-invoke-c.c
+++ b/gperl-i11n-invoke-c.c
@@ -45,7 +45,7 @@ invoke_c_code (GICallableInfo *info,
 
        if (iinfo.is_method) {
                instance = instance_sv_to_pointer (info, ST (0 + iinfo.stack_offset));
-               iinfo.arg_types[0] = &ffi_type_pointer;
+               iinfo.arg_types_ffi[0] = &ffi_type_pointer;
                iinfo.args[0] = &instance;
        }
 
@@ -61,10 +61,8 @@ invoke_c_code (GICallableInfo *info,
                gint perl_stack_pos, ffi_stack_pos;
                SV *current_sv;
 
-               arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
-               /* In case of out and in-out args, arg_type is unref'ed after
-                * the function has been invoked */
-               arg_type = g_arg_info_get_type (arg_info);
+               arg_info = iinfo.base.arg_infos[i];
+               arg_type = iinfo.base.arg_types[i];
                transfer = g_arg_info_get_ownership_transfer (arg_info);
                may_be_null = g_arg_info_may_be_null (arg_info);
 #if GI_CHECK_VERSION (1, 29, 0)
@@ -106,10 +104,9 @@ invoke_c_code (GICallableInfo *info,
                                           &iinfo.in_args[i], arg_info, arg_type,
                                           transfer, may_be_null, &iinfo.base);
                        }
-                       iinfo.arg_types[ffi_stack_pos] =
+                       iinfo.arg_types_ffi[ffi_stack_pos] =
                                g_type_info_get_ffi_type (arg_type);
                        iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
-                       g_base_info_unref ((GIBaseInfo *) arg_type);
                        break;
 
                    case GI_DIRECTION_OUT:
@@ -122,8 +119,7 @@ invoke_c_code (GICallableInfo *info,
                                iinfo.out_args[i].v_pointer = &iinfo.base.aux_args[i];
                                iinfo.args[ffi_stack_pos] = &iinfo.out_args[i];
                        }
-                       iinfo.out_arg_infos[i] = arg_type;
-                       iinfo.arg_types[ffi_stack_pos] = &ffi_type_pointer;
+                       iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
                        /* Adjust the dynamic stack offset so that this out
                         * argument doesn't inadvertedly eat up an in argument. */
                        iinfo.dynamic_stack_offset--;
@@ -145,13 +141,10 @@ invoke_c_code (GICallableInfo *info,
                                           iinfo.in_args[i].v_pointer, arg_info, arg_type,
                                           transfer, may_be_null, &iinfo.base);
                        }
-                       iinfo.out_arg_infos[i] = arg_type;
-                       iinfo.arg_types[ffi_stack_pos] = &ffi_type_pointer;
+                       iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
                        iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
                        break;
                }
-
-               g_base_info_unref ((GIBaseInfo *) arg_info);
        }
 
        /* do another pass to handle automatic args */
@@ -159,7 +152,7 @@ invoke_c_code (GICallableInfo *info,
                GIArgInfo * arg_info;
                if (!iinfo.is_automatic_arg[i])
                        continue;
-               arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
+               arg_info = iinfo.base.arg_infos[i];
                switch (g_arg_info_get_direction (arg_info)) {
                    case GI_DIRECTION_IN:
                        _handle_automatic_arg (i, &iinfo.in_args[i], &iinfo);
@@ -171,12 +164,11 @@ invoke_c_code (GICallableInfo *info,
                        /* handled later */
                        break;
                }
-               g_base_info_unref ((GIBaseInfo *) arg_info);
        }
 
        if (iinfo.throws) {
                iinfo.args[iinfo.n_invoke_args - 1] = &local_error_address;
-               iinfo.arg_types[iinfo.n_invoke_args - 1] = &ffi_type_pointer;
+               iinfo.arg_types_ffi[iinfo.n_invoke_args - 1] = &ffi_type_pointer;
        }
 
        /*
@@ -185,7 +177,7 @@ invoke_c_code (GICallableInfo *info,
 
        /* prepare and call the function */
        if (FFI_OK != ffi_prep_cif (&cif, FFI_DEFAULT_ABI, iinfo.n_invoke_args,
-                                   iinfo.base.return_type_ffi, iinfo.arg_types))
+                                   iinfo.base.return_type_ffi, iinfo.arg_types_ffi))
        {
                _clear_c_invocation_info (&iinfo);
                ccroak ("Could not prepare a call interface");
@@ -248,10 +240,9 @@ invoke_c_code (GICallableInfo *info,
                GIArgInfo * arg_info;
                if (iinfo.is_automatic_arg[i])
                        continue;
-               arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
+               arg_info = iinfo.base.arg_infos[i];
 #if GI_CHECK_VERSION (1, 29, 0)
                if (g_arg_info_is_skip (arg_info)) {
-                       g_base_info_unref ((GIBaseInfo *) arg_info);
                        continue;
                }
 #endif
@@ -266,21 +257,19 @@ invoke_c_code (GICallableInfo *info,
                                 ? GI_TRANSFER_CONTAINER
                                 : g_arg_info_get_ownership_transfer (arg_info);
                        sv = SAVED_STACK_SV (arg_to_sv (iinfo.out_args[i].v_pointer,
-                                                       iinfo.out_arg_infos[i],
+                                                       iinfo.base.arg_types[i],
                                                        transfer,
                                                        &iinfo.base));
                        if (sv) {
                                XPUSHs (sv_2mortal (sv));
                                n_return_values++;
                        }
-                       g_base_info_unref ((GIBaseInfo*) iinfo.out_arg_infos[i]);
                        break;
                    }
 
                    default:
                        break;
                }
-               g_base_info_unref ((GIBaseInfo *) arg_info);
        }
 
        _clear_c_invocation_info (&iinfo);
@@ -371,8 +360,7 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                gint n = iinfo->n_invoke_args;
                iinfo->in_args = gperl_alloc_temp (sizeof (GIArgument) * n);
                iinfo->out_args = gperl_alloc_temp (sizeof (GIArgument) * n);
-               iinfo->out_arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * n);
-               iinfo->arg_types = gperl_alloc_temp (sizeof (ffi_type *) * n);
+               iinfo->arg_types_ffi = gperl_alloc_temp (sizeof (ffi_type *) * n);
                iinfo->args = gperl_alloc_temp (sizeof (gpointer) * n);
                iinfo->is_automatic_arg = gperl_alloc_temp (sizeof (gboolean) * n);
        }
@@ -383,9 +371,8 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
        /* Make a first pass to mark args that are filled in automatically, and
         * thus have no counterpart on the Perl side. */
        for (i = 0 ; i < iinfo->base.n_args ; i++) {
-               GIArgInfo * arg_info =
-                       g_callable_info_get_arg ((GICallableInfo *) info, i);
-               GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
+               GIArgInfo * arg_info = iinfo->base.arg_infos[i];
+               GITypeInfo * arg_type = iinfo->base.arg_types[i];
                GITypeTag arg_tag = g_type_info_get_tag (arg_type);
 
                if (arg_tag == GI_TYPE_TAG_ARRAY) {
@@ -408,18 +395,14 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                        }
                        g_base_info_unref ((GIBaseInfo *) interface);
                }
-
-               g_base_info_unref ((GIBaseInfo *) arg_type);
-               g_base_info_unref ((GIBaseInfo *) arg_info);
        }
 
        /* Make another pass to count the expected args. */
        iinfo->n_expected_args = iinfo->method_offset;
        iinfo->n_nullable_args = 0;
        for (i = 0 ; i < iinfo->base.n_args ; i++) {
-               GIArgInfo * arg_info =
-                       g_callable_info_get_arg ((GICallableInfo *) info, i);
-               GITypeInfo * arg_type = g_arg_info_get_type (arg_info);
+               GIArgInfo * arg_info = iinfo->base.arg_infos[i];
+               GITypeInfo * arg_type = iinfo->base.arg_types[i];
                GITypeTag arg_tag = g_type_info_get_tag (arg_type);
                gboolean is_out = GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info);
                gboolean is_automatic = iinfo->is_automatic_arg[i];
@@ -433,9 +416,6 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
                /* Callback user data may always be NULL. */
                if (g_arg_info_may_be_null (arg_info) || arg_tag == GI_TYPE_TAG_VOID)
                        iinfo->n_nullable_args++;
-
-               g_base_info_unref ((GIBaseInfo *) arg_type);
-               g_base_info_unref ((GIBaseInfo *) arg_info);
        }
 
        /* If the return value is an array which comes with an outbound length
@@ -443,13 +423,11 @@ _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
        if (g_type_info_get_tag (iinfo->base.return_type_info) == GI_TYPE_TAG_ARRAY) {
                gint pos = g_type_info_get_array_length (iinfo->base.return_type_info);
                if (pos >= 0) {
-                       GIArgInfo * arg_info =
-                               g_callable_info_get_arg ((GICallableInfo *) info, pos);
+                       GIArgInfo * arg_info = iinfo->base.arg_infos[pos];
                        if (GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info)) {
                                dwarn ("  pos %d is automatic (array length)\n", pos);
                                iinfo->is_automatic_arg[pos] = TRUE;
                        }
-                       g_base_info_unref (arg_info);
                }
        }
 
diff --git a/gperl-i11n-invoke-perl.c b/gperl-i11n-invoke-perl.c
index 2e74372..49c855f 100644
--- a/gperl-i11n-invoke-perl.c
+++ b/gperl-i11n-invoke-perl.c
@@ -73,8 +73,8 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
         * stack */
        in_inout = 0;
        for (i = 0; i < iinfo.base.n_args; i++) {
-               GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
-               GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+               GIArgInfo *arg_info = iinfo.base.arg_infos[i];
+               GITypeInfo *arg_type = iinfo.base.arg_types[i];
                GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
                GIDirection direction = g_arg_info_get_direction (arg_info);
 
@@ -126,9 +126,6 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                {
                        in_inout++;
                }
-
-               g_base_info_unref ((GIBaseInfo *) arg_info);
-               g_base_info_unref ((GIBaseInfo *) arg_type);
        }
 
        /* push the last SV onto the stack; this might be the user data or the
@@ -195,15 +192,13 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
 
                out_index = 0;
                for (i = 0; i < iinfo.base.n_args; i++) {
-                       GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
-                       GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+                       GIArgInfo *arg_info = iinfo.base.arg_infos[i];
+                       GITypeInfo *arg_type = iinfo.base.arg_types[i];
                        GIDirection direction = g_arg_info_get_direction (arg_info);
                        gpointer out_pointer = * (gpointer *) args[i+args_offset];
 
                        if (!out_pointer) {
                                dwarn ("skipping out arg %d\n", i);
-                               g_base_info_unref (arg_info);
-                               g_base_info_unref (arg_type);
                                continue;
                        }
 
@@ -232,9 +227,6 @@ invoke_perl_code (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata
                                }
                                out_index++;
                        }
-
-                       g_base_info_unref (arg_info);
-                       g_base_info_unref (arg_type);
                }
 
                g_free (returned_values);
@@ -361,25 +353,18 @@ _prepare_perl_invocation_info (GPerlI11nPerlInvocationInfo *iinfo,
        /* Find array length arguments and store their value in aux_args so
         * that array_to_sv can later fetch them. */
        for (i = 0 ; i < iinfo->base.n_args ; i++) {
-               GIArgInfo *arg_info = g_callable_info_get_arg (info, i);
-               GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
+               GITypeInfo *arg_type = iinfo->base.arg_types[i];
                GITypeTag arg_tag = g_type_info_get_tag (arg_type);
 
                if (arg_tag == GI_TYPE_TAG_ARRAY) {
                        gint pos = g_type_info_get_array_length (arg_type);
                        if (pos >= 0) {
-                               GIArgInfo *length_arg_info = g_callable_info_get_arg (info, i);
-                               GITypeInfo *length_arg_type = g_arg_info_get_type (arg_info);
+                               GITypeInfo *length_arg_type = iinfo->base.arg_types[i];
                                raw_to_arg (args[pos], &iinfo->base.aux_args[pos], length_arg_type);
                                dwarn ("  pos %d is array length => %"G_GSIZE_FORMAT"\n",
                                       pos, iinfo->aux_args[pos].v_size);
-                               g_base_info_unref (length_arg_type);
-                               g_base_info_unref (length_arg_info);
                        }
                }
-
-               g_base_info_unref (arg_type);
-               g_base_info_unref (arg_info);
        }
 }
 
diff --git a/gperl-i11n-invoke.c b/gperl-i11n-invoke.c
index e52b6fe..2eb8ea3 100644
--- a/gperl-i11n-invoke.c
+++ b/gperl-i11n-invoke.c
@@ -4,6 +4,8 @@ static void
 prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
                          GICallableInfo *info)
 {
+       guint i;
+
        dwarn ("invoke: %s\n"
               "  n_args: %d\n",
               g_base_info_get_name (info),
@@ -20,9 +22,19 @@ prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
 
        iinfo->n_args = g_callable_info_get_n_args (info);
 
-       iinfo->aux_args = NULL;
        if (iinfo->n_args) {
+               iinfo->arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
+               iinfo->arg_types = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
                iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * iinfo->n_args);
+       } else {
+               iinfo->arg_infos = NULL;
+               iinfo->arg_types = NULL;
+               iinfo->aux_args = NULL;
+       }
+
+       for (i = 0 ; i < iinfo->n_args ; i++) {
+               iinfo->arg_infos[i] = g_callable_info_get_arg (info, i);
+               iinfo->arg_types[i] = g_arg_info_get_type (iinfo->arg_infos[i]);
        }
 
        iinfo->return_type_info = g_callable_info_get_return_type (info);
@@ -33,12 +45,20 @@ prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
 
        iinfo->callback_infos = NULL;
        iinfo->array_infos = NULL;
+
        iinfo->free_after_call = NULL;
 }
 
 static void
 clear_invocation_info (GPerlI11nInvocationInfo *iinfo)
 {
+       guint i;
+
+       for (i = 0 ; i < iinfo->n_args ; i++) {
+               g_base_info_unref ((GIBaseInfo *) iinfo->arg_types[i]);
+               g_base_info_unref ((GIBaseInfo *) iinfo->arg_infos[i]);
+       }
+
        g_slist_free (iinfo->free_after_call);
        iinfo->free_after_call = NULL;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]