Commit c19bed69 authored by Simon Feltman's avatar Simon Feltman

cache refactoring: Use GPtrArray for callable arg cache

Replace manual management of the C array holding individual
argument caches with usage of GPtrArray. This provides storage
of the array length along with item memory management.

https://bugzilla.gnome.org/show_bug.cgi?id=640812
parent 52ea3afb
......@@ -103,23 +103,17 @@ _callback_cache_free_func (PyGICallbackCache *cache)
void
_pygi_callable_cache_free (PyGICallableCache *cache)
{
gssize i;
if (cache == NULL)
return;
g_slist_free (cache->to_py_args);
g_slist_free (cache->arg_name_list);
g_hash_table_destroy (cache->arg_name_hash);
g_ptr_array_unref (cache->args_cache);
for (i = 0; i < cache->n_args; i++) {
PyGIArgCache *tmp = cache->args_cache[i];
_pygi_arg_cache_free (tmp);
}
if (cache->return_cache != NULL)
_pygi_arg_cache_free (cache->return_cache);
g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
g_slice_free (PyGICallableCache, cache);
}
......@@ -314,7 +308,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *child_cache =
callable_cache->args_cache[seq_cache->len_arg_index];
_pygi_callable_cache_get_arg (callable_cache, seq_cache->len_arg_index);
if (child_cache == NULL) {
child_cache = _arg_cache_alloc ();
......@@ -333,7 +327,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
child_cache->to_py_marshaller = NULL;
child_cache->from_py_marshaller = NULL;
callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
_pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
}
arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
......@@ -356,7 +350,8 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
seq_cache->array_type = g_type_info_get_array_type (type_info);
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
seq_cache->len_arg_index);
if (seq_cache->len_arg_index < arg_index)
callable_cache->n_to_py_child_args++;
......@@ -376,7 +371,7 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
child_cache->to_py_marshaller = NULL;
child_cache->from_py_marshaller = NULL;
callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
_pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
}
return TRUE;
......@@ -509,14 +504,16 @@ _arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
_pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
user_data_arg_cache);
}
if (callback_cache->destroy_notify_index >= 0) {
PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
_pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
destroy_arg_cache);
}
arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
......@@ -780,19 +777,19 @@ _arg_cache_new (GITypeInfo *type_info,
* need to update indexes if this happens
*/
if (seq_cache->len_arg_index > -1 &&
callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
_pygi_callable_cache_get_arg (callable_cache,
seq_cache->len_arg_index)->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
gssize i;
PyGIArgCache *child_cache =
callable_cache->args_cache[seq_cache->len_arg_index];
PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
seq_cache->len_arg_index);
child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
py_arg_index -= 1;
callable_cache->n_py_args -= 1;
for (i = seq_cache->len_arg_index + 1;
i < callable_cache->n_args;
i < _pygi_callable_cache_args_len (callable_cache);
i++) {
PyGIArgCache *update_cache = callable_cache->args_cache[i];
PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
if (update_cache == NULL)
break;
......@@ -914,10 +911,10 @@ _arg_name_list_generate (PyGICallableCache *callable_cache)
g_hash_table_remove_all (callable_cache->arg_name_hash);
}
for (i=0; i < callable_cache->n_args; i++) {
for (i=0; i < _pygi_callable_cache_args_len (callable_cache); i++) {
PyGIArgCache *arg_cache = NULL;
arg_cache = callable_cache->args_cache[i];
arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);
if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
......@@ -1016,7 +1013,7 @@ _args_cache_generate (GICallableInfo *callable_info,
if (instance_cache == NULL)
return FALSE;
callable_cache->args_cache[arg_index] = instance_cache;
_pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
arg_index++;
callable_cache->n_from_py_args++;
......@@ -1024,7 +1021,7 @@ _args_cache_generate (GICallableInfo *callable_info,
}
for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
PyGIArgCache *arg_cache = NULL;
GIArgInfo *arg_info;
GITypeInfo *type_info;
......@@ -1039,7 +1036,7 @@ _args_cache_generate (GICallableInfo *callable_info,
if (g_arg_info_get_closure (arg_info) == i) {
arg_cache = _arg_cache_alloc ();
callable_cache->args_cache[arg_index] = arg_cache;
_pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
......@@ -1066,8 +1063,8 @@ _args_cache_generate (GICallableInfo *callable_info,
* and continue
* fill in it's c_arg_index, add to the in count
*/
if (callable_cache->args_cache[arg_index] != NULL) {
arg_cache = callable_cache->args_cache[arg_index];
arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
if (arg_cache != NULL) {
if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
arg_cache->py_arg_index = callable_cache->n_py_args;
callable_cache->n_py_args++;
......@@ -1122,7 +1119,7 @@ _args_cache_generate (GICallableInfo *callable_info,
g_slist_append (callable_cache->to_py_args, arg_cache);
}
callable_cache->args_cache[arg_index] = arg_cache;
_pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
g_base_info_unref( (GIBaseInfo *)type_info);
g_base_info_unref( (GIBaseInfo *)arg_info);
......@@ -1141,6 +1138,7 @@ arg_err:
PyGICallableCache *
_pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
{
gint n_args;
PyGICallableCache *cache;
GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
......@@ -1185,15 +1183,17 @@ _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
}
cache->n_args = g_callable_info_get_n_args (callable_info);
n_args = g_callable_info_get_n_args (callable_info);
/* if we are a method or vfunc make sure the instance parameter is counted */
if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
cache->n_args++;
n_args++;
if (cache->n_args > 0)
cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof (PyGIArgCache *));
if (n_args >= 0) {
cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) _pygi_arg_cache_free);
g_ptr_array_set_size (cache->args_cache, n_args);
}
if (!_args_cache_generate (callable_info, cache))
goto err;
......
......@@ -172,7 +172,7 @@ struct _PyGICallableCache
PyGIFunctionType function_type;
PyGIArgCache *return_cache;
PyGIArgCache **args_cache;
GPtrArray *args_cache;
GSList *to_py_args;
GSList *arg_name_list; /* for keyword arg matching */
GHashTable *arg_name_hash;
......@@ -191,8 +191,6 @@ struct _PyGICallableCache
*/
gssize n_to_py_child_args;
gssize n_args;
/* Number of Python arguments expected for invoking the gi function. */
gssize n_py_args;
};
......@@ -203,6 +201,18 @@ void _pygi_callable_cache_free (PyGICallableCache *cache);
PyGICallableCache *_pygi_callable_cache_new (GICallableInfo *callable_info,
gboolean is_ccallback);
#define _pygi_callable_cache_args_len(cache) ((cache)->args_cache)->len
inline static PyGIArgCache *
_pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) {
return (PyGIArgCache *) g_ptr_array_index (cache->args_cache, index);
}
inline static void
_pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) {
cache->args_cache->pdata[index] = arg_cache;
}
G_END_DECLS
#endif /* __PYGI_CACHE_H__ */
......@@ -299,14 +299,14 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
}
state->n_py_in_args = PyTuple_Size (state->py_in_args);
state->args = g_slice_alloc0 (cache->n_args * sizeof (GIArgument *));
if (state->args == NULL && cache->n_args != 0) {
state->args = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (GIArgument *));
if (state->args == NULL && _pygi_callable_cache_args_len (cache) != 0) {
PyErr_NoMemory();
return FALSE;
}
state->args_data = g_slice_alloc0 (cache->n_args * sizeof (gpointer));
if (state->args_data == NULL && cache->n_args != 0) {
state->args_data = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (gpointer));
if (state->args_data == NULL && _pygi_callable_cache_args_len (cache) != 0) {
PyErr_NoMemory();
return FALSE;
}
......@@ -337,8 +337,8 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
static inline void
_invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
{
g_slice_free1 (cache->n_args * sizeof(GIArgument *), state->args);
g_slice_free1 (cache->n_args * sizeof(gpointer), state->args_data);
g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(GIArgument *), state->args);
g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(gpointer), state->args_data);
g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
......@@ -408,9 +408,9 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
return FALSE;
}
for (i = 0; i < cache->n_args; i++) {
for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
GIArgument *c_arg;
PyGIArgCache *arg_cache = cache->args_cache[i];
PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
PyObject *py_arg = NULL;
switch (arg_cache->direction) {
......
......@@ -93,8 +93,8 @@ pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state,
gssize i;
/* For in success, call cleanup for all GI_DIRECTION_IN values only. */
for (i = 0; i < cache->n_args; i++) {
PyGIArgCache *arg_cache = cache->args_cache[i];
for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
if (cleanup_func &&
......@@ -157,8 +157,8 @@ pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState *state,
state->failed = TRUE;
for (i = 0; i < cache->n_args && i <= failed_arg_index; i++) {
PyGIArgCache *arg_cache = cache->args_cache[i];
for (i = 0; i < _pygi_callable_cache_args_len (cache) && i <= failed_arg_index; i++) {
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
gpointer data = state->args[i]->v_pointer;
......
......@@ -887,7 +887,7 @@ array_success:
if (sequence_cache->len_arg_index >= 0) {
/* we have an child arg to handle */
PyGIArgCache *child_cache =
callable_cache->args_cache[sequence_cache->len_arg_index];
_pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index);
if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
......@@ -1249,7 +1249,7 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
callback_cache = (PyGICallbackCache *)arg_cache;
if (callback_cache->user_data_index > 0) {
user_data_cache = callable_cache->args_cache[callback_cache->user_data_index];
user_data_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->user_data_index);
if (user_data_cache->py_arg_index < state->n_py_in_args) {
/* py_user_data is a borrowed reference. */
py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index);
......@@ -1297,7 +1297,7 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
* later on in _pygi_destroy_notify_callback_closure.
*/
if (callback_cache->destroy_notify_index > 0) {
destroy_cache = callable_cache->args_cache[callback_cache->destroy_notify_index];
destroy_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->destroy_notify_index);
}
if (destroy_cache) {
......
......@@ -296,10 +296,10 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
}
} else {
GIArgument *len_arg = state->args[seq_cache->len_arg_index];
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
seq_cache->len_arg_index);
if (!gi_argument_to_gsize (len_arg,
&len,
callable_cache->args_cache[seq_cache->len_arg_index]->type_tag)) {
if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
return NULL;
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment