[gjs] gi: simplify gjs_invoke_c_function() argument bookkeeping
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] gi: simplify gjs_invoke_c_function() argument bookkeeping
- Date: Fri, 17 Jun 2011 15:04:45 +0000 (UTC)
commit a964d787f92adb82022c48c7814a188235b38c61
Author: Dan Winship <danw gnome org>
Date: Thu Jun 2 11:57:31 2011 -0400
gi: simplify gjs_invoke_c_function() argument bookkeeping
Make the out_arg_cvalues and inout_original_arg_cvalues arrays be the
same length as in_arg_cvalues, so that we don't need to keep a
separate counter for each. Rename the counter and length variables to
make it clearer what each one is counting.
https://bugzilla.gnome.org/show_bug.cgi?id=651558
gi/function.c | 181 ++++++++++++++++++++++++---------------------------------
1 files changed, 76 insertions(+), 105 deletions(-)
---
diff --git a/gi/function.c b/gi/function.c
index 5febed9..25f52e7 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -61,7 +61,6 @@ typedef struct {
guint8 expected_js_argc;
guint8 js_out_argc;
- guint8 inout_argc;
GIFunctionInvoker invoker;
} Function;
@@ -321,7 +320,7 @@ gjs_invoke_c_function(JSContext *context,
* @inout_original_arg_cvalues: For the special case of (inout) args, we need to
* keep track of the original values we passed into the function, in case we
* need to free it.
- * @in_arg_pointers: For passing data to FFI, we need to create another layer
+ * @ffi_arg_pointers: For passing data to FFI, we need to create another layer
* of indirection; this array is a pointer to an element in in_arg_cvalues
* or out_arg_cvalues.
* @return_value: The actual return value of the C function, i.e. not an (out) param
@@ -329,17 +328,17 @@ gjs_invoke_c_function(JSContext *context,
GArgument *in_arg_cvalues;
GArgument *out_arg_cvalues;
GArgument *inout_original_arg_cvalues;
- gpointer *in_arg_pointers;
+ gpointer *ffi_arg_pointers;
GArgument return_value;
- guint8 processed_in_args = 0;
- guint8 n_args, i, js_argv_pos;
- guint8 in_args_pos, out_args_pos, inout_args_pos;
- guint8 in_args_len, out_args_len, inout_args_len;
- guint8 can_throw_gerror;
+ guint8 processed_c_args = 0;
+ guint8 gi_argc, gi_arg_pos;
+ guint8 c_argc, c_arg_pos;
+ guint8 js_arg_pos;
+ gboolean can_throw_gerror;
gboolean did_throw_gerror = FALSE;
GError *local_error = NULL;
- guint8 failed, postinvoke_release_failed;
+ gboolean failed, postinvoke_release_failed;
GIFunctionInfoFlags flags;
gboolean is_method;
@@ -365,11 +364,22 @@ gjs_invoke_c_function(JSContext *context,
flags = g_function_info_get_flags(function->info);
is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
can_throw_gerror = (flags & GI_FUNCTION_THROWS) != 0;
- n_args = g_callable_info_get_n_args( (GICallableInfo*) function->info);
-
- /* We allow too many args; convenient for re-using a function as a callback.
- * But we don't allow too few args, since that would break.
+ c_argc = function->invoker.cif.nargs;
+ gi_argc = g_callable_info_get_n_args( (GICallableInfo*) function->info);
+
+ /* @c_argc is the number of arguments that the underlying C
+ * function takes. @gi_argc is the number of arguments the
+ * GICallableInfo describes (which does not include "this" or
+ * GError**). @function->expected_js_argc is the number of
+ * arguments we expect the JS function to take (which does not
+ * include PARAM_SKIPPED args).
+ *
+ * @js_argc is the number of arguments that were actually passed;
+ * we allow this to be larger than @expected_js_argc for
+ * convenience, and simply ignore the extra arguments. But we
+ * don't allow too few args, since that would break.
*/
+
if (js_argc < function->expected_js_argc) {
gjs_throw(context, "Too few arguments to %s %s.%s expected %d got %d",
is_method ? "method" : "function",
@@ -383,30 +393,21 @@ gjs_invoke_c_function(JSContext *context,
g_callable_info_load_return_type( (GICallableInfo*) function->info, &return_info);
return_tag = g_type_info_get_tag(&return_info);
- in_args_len = function->invoker.cif.nargs;
- out_args_len = function->js_out_argc;
- inout_args_len = function->inout_argc;
-
- if (return_tag != GI_TYPE_TAG_VOID) {
- --out_args_len;
- }
-
- in_arg_cvalues = g_newa(GArgument, in_args_len);
- in_arg_pointers = g_newa(gpointer, in_args_len);
- out_arg_cvalues = g_newa(GArgument, out_args_len);
- inout_original_arg_cvalues = g_newa(GArgument, inout_args_len);
+ in_arg_cvalues = g_newa(GArgument, c_argc);
+ ffi_arg_pointers = g_newa(gpointer, c_argc);
+ out_arg_cvalues = g_newa(GArgument, c_argc);
+ inout_original_arg_cvalues = g_newa(GArgument, c_argc);
failed = FALSE;
- in_args_pos = 0; /* index into in_arg_cvalues */
- out_args_pos = 0; /* index into out_arg_cvalues */
- inout_args_pos = 0; /* index into inout_original_arg_cvalues */
- js_argv_pos = 0; /* index into argv */
+ c_arg_pos = 0; /* index into in_arg_cvalues, etc */
+ gi_arg_pos = 0; /* index into function->info arguments */
+ js_arg_pos = 0; /* index into argv */
if (is_method) {
GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) function->info);
GIInfoType type = g_base_info_get_type(container);
- g_assert_cmpuint(0, <, in_args_len);
+ g_assert_cmpuint(0, <, c_argc);
if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
in_arg_cvalues[0].v_pointer = gjs_c_struct_from_boxed(context, obj);
@@ -428,28 +429,25 @@ gjs_invoke_c_function(JSContext *context,
goto release;
}
}
- in_arg_pointers[0] = &in_arg_cvalues[0];
- ++in_args_pos;
+ ffi_arg_pointers[0] = &in_arg_cvalues[0];
+ ++c_arg_pos;
}
- processed_in_args = in_args_pos;
- for (i = 0; i < n_args; i++) {
+ processed_c_args = c_arg_pos;
+ for (gi_arg_pos = 0; gi_arg_pos < gi_argc; gi_arg_pos++, c_arg_pos++) {
GIDirection direction;
GIArgInfo arg_info;
gboolean arg_removed = FALSE;
- /* gjs_debug(GJS_DEBUG_GFUNCTION, "i: %d in_args_pos: %d argv_pos: %d", i, in_args_pos, js_argv_pos); */
+ /* gjs_debug(GJS_DEBUG_GFUNCTION, "gi_arg_pos: %d c_arg_pos: %d js_arg_pos: %d", gi_arg_pos, c_arg_pos, js_arg_pos); */
- g_callable_info_load_arg( (GICallableInfo*) function->info, i, &arg_info);
+ g_callable_info_load_arg( (GICallableInfo*) function->info, gi_arg_pos, &arg_info);
direction = g_arg_info_get_direction(&arg_info);
- g_assert_cmpuint(in_args_pos, <, in_args_len);
- in_arg_pointers[in_args_pos] = &in_arg_cvalues[in_args_pos];
+ g_assert_cmpuint(c_arg_pos, <, c_argc);
+ ffi_arg_pointers[c_arg_pos] = &in_arg_cvalues[c_arg_pos];
if (direction == GI_DIRECTION_OUT) {
- g_assert_cmpuint(out_args_pos, <, out_args_len);
- g_assert_cmpuint(in_args_pos, <, in_args_len);
-
if (g_arg_info_is_caller_allocates(&arg_info)) {
GITypeTag type_tag;
GITypeInfo ainfo;
@@ -480,8 +478,8 @@ gjs_invoke_c_function(JSContext *context,
g_base_info_unref((GIBaseInfo*)interface_info);
if (!failed) {
- in_arg_cvalues[in_args_pos].v_pointer = g_slice_alloc0(size);
- out_arg_cvalues[out_args_pos].v_pointer = in_arg_cvalues[in_args_pos].v_pointer;
+ in_arg_cvalues[c_arg_pos].v_pointer = g_slice_alloc0(size);
+ out_arg_cvalues[c_arg_pos].v_pointer = in_arg_cvalues[c_arg_pos].v_pointer;
}
break;
}
@@ -491,10 +489,9 @@ gjs_invoke_c_function(JSContext *context,
if (failed)
gjs_throw(context, "Unsupported type %s for (out caller-allocates)", g_type_tag_to_string(type_tag));
} else {
- out_arg_cvalues[out_args_pos].v_pointer = NULL;
- in_arg_cvalues[in_args_pos].v_pointer = &out_arg_cvalues[out_args_pos];
+ out_arg_cvalues[c_arg_pos].v_pointer = NULL;
+ in_arg_cvalues[c_arg_pos].v_pointer = &out_arg_cvalues[c_arg_pos];
}
- out_args_pos++;
} else {
GArgument *in_value;
GITypeInfo ainfo;
@@ -502,10 +499,9 @@ gjs_invoke_c_function(JSContext *context,
g_arg_info_load_type(&arg_info, &ainfo);
- g_assert_cmpuint(in_args_pos, <, in_args_len);
- in_value = &in_arg_cvalues[in_args_pos];
+ in_value = &in_arg_cvalues[c_arg_pos];
- param_type = function->param_types[i];
+ param_type = function->param_types[gi_arg_pos];
switch (param_type) {
case PARAM_CALLBACK: {
@@ -513,7 +509,7 @@ gjs_invoke_c_function(JSContext *context,
GIScopeType scope = g_arg_info_get_scope(&arg_info);
GjsCallbackTrampoline *trampoline;
ffi_closure *closure;
- jsval value = js_argv[js_argv_pos];
+ jsval value = js_argv[js_arg_pos];
if (JSVAL_IS_NULL(value) && g_arg_info_may_be_null(&arg_info)) {
closure = NULL;
@@ -540,14 +536,14 @@ gjs_invoke_c_function(JSContext *context,
gint destroy_pos = g_arg_info_get_destroy(&arg_info);
gint closure_pos = g_arg_info_get_closure(&arg_info);
if (destroy_pos >= 0) {
- gint pos = is_method ? destroy_pos + 1 : destroy_pos;
+ gint c_pos = is_method ? destroy_pos + 1 : destroy_pos;
g_assert (function->param_types[destroy_pos] == PARAM_SKIPPED);
- in_arg_cvalues[pos].v_pointer = trampoline ? gjs_destroy_notify_callback : NULL;
+ in_arg_cvalues[c_pos].v_pointer = trampoline ? gjs_destroy_notify_callback : NULL;
}
if (closure_pos >= 0) {
- gint pos = is_method ? closure_pos + 1 : closure_pos;
+ gint c_pos = is_method ? closure_pos + 1 : closure_pos;
g_assert (function->param_types[closure_pos] == PARAM_SKIPPED);
- in_arg_cvalues[pos].v_pointer = trampoline;
+ in_arg_cvalues[c_pos].v_pointer = trampoline;
}
if (trampoline && scope != GI_SCOPE_TYPE_CALL) {
@@ -567,7 +563,7 @@ gjs_invoke_c_function(JSContext *context,
gint array_length_pos = g_type_info_get_array_length(&ainfo);
gsize length;
- if (!gjs_value_to_explicit_array(context, js_argv[js_argv_pos], &arg_info,
+ if (!gjs_value_to_explicit_array(context, js_argv[js_arg_pos], &arg_info,
in_value, &length)) {
failed = TRUE;
break;
@@ -584,8 +580,8 @@ gjs_invoke_c_function(JSContext *context,
}
case PARAM_NORMAL:
/* Ok, now just convert argument normally */
- g_assert_cmpuint(js_argv_pos, <, js_argc);
- if (!gjs_value_to_arg(context, js_argv[js_argv_pos], &arg_info,
+ g_assert_cmpuint(js_arg_pos, <, js_argc);
+ if (!gjs_value_to_arg(context, js_argv[js_arg_pos], &arg_info,
in_value)) {
failed = TRUE;
break;
@@ -593,14 +589,8 @@ gjs_invoke_c_function(JSContext *context,
}
if (!failed && direction == GI_DIRECTION_INOUT) {
- g_assert_cmpuint(in_args_pos, <, in_args_len);
- g_assert_cmpuint(out_args_pos, <, out_args_len);
- g_assert_cmpuint(inout_args_pos, <, inout_args_len);
-
- out_arg_cvalues[out_args_pos] = inout_original_arg_cvalues[inout_args_pos] = in_arg_cvalues[in_args_pos];
- in_arg_cvalues[in_args_pos].v_pointer = &out_arg_cvalues[out_args_pos];
- out_args_pos++;
- inout_args_pos++;
+ out_arg_cvalues[c_arg_pos] = inout_original_arg_cvalues[c_arg_pos] = in_arg_cvalues[c_arg_pos];
+ in_arg_cvalues[c_arg_pos].v_pointer = &out_arg_cvalues[c_arg_pos];
}
if (failed) {
@@ -608,15 +598,14 @@ gjs_invoke_c_function(JSContext *context,
break;
}
- if (!arg_removed)
- ++js_argv_pos;
+ if (!failed && !arg_removed)
+ ++js_arg_pos;
}
- ++in_args_pos;
- processed_in_args = in_args_pos;
-
if (failed)
break;
+
+ processed_c_args++;
}
/* Did argument conversion fail? In that case, skip invocation and jump to release
@@ -627,21 +616,20 @@ gjs_invoke_c_function(JSContext *context,
}
if (can_throw_gerror) {
- g_assert_cmpuint(in_args_pos, <, in_args_len);
- in_arg_cvalues[in_args_pos].v_pointer = &local_error;
- in_arg_pointers[in_args_pos] = &(in_arg_cvalues[in_args_pos]);
- in_args_pos++;
+ g_assert_cmpuint(c_arg_pos, <, c_argc);
+ in_arg_cvalues[c_arg_pos].v_pointer = &local_error;
+ ffi_arg_pointers[c_arg_pos] = &(in_arg_cvalues[c_arg_pos]);
+ c_arg_pos++;
- /* don't update processed_in_args as we deal with local_error
+ /* don't update processed_c_args as we deal with local_error
* separately */
}
gjs_runtime_push_context(JS_GetRuntime(context), context);
- g_assert_cmpuint(in_args_pos, ==, (guint8)function->invoker.cif.nargs);
- g_assert_cmpuint(inout_args_pos, ==, inout_args_len);
- g_assert_cmpuint(out_args_pos, ==, out_args_len);
- ffi_call(&(function->invoker.cif), function->invoker.native_address, &return_value, in_arg_pointers);
+ g_assert_cmpuint(c_arg_pos, ==, c_argc);
+ g_assert_cmpuint(gi_arg_pos, ==, gi_argc);
+ ffi_call(&(function->invoker.cif), function->invoker.native_address, &return_value, ffi_arg_pointers);
gjs_runtime_pop_context(JS_GetRuntime(context));
@@ -687,17 +675,14 @@ release:
/* We walk over all args, release in args (if allocated) and convert
* all out args to JS
*/
- in_args_pos = is_method ? 1 : 0; /* index into in_args */
- out_args_pos = 0;
- inout_args_pos = 0;
-
+ c_arg_pos = is_method ? 1 : 0;
postinvoke_release_failed = FALSE;
- for (i = 0; i < n_args && in_args_pos < processed_in_args; i++) {
+ for (gi_arg_pos = 0; gi_arg_pos < gi_argc && c_arg_pos < processed_c_args; gi_arg_pos++, c_arg_pos++) {
GIDirection direction;
GIArgInfo arg_info;
GITypeInfo arg_type_info;
- g_callable_info_load_arg( (GICallableInfo*) function->info, i, &arg_info);
+ g_callable_info_load_arg( (GICallableInfo*) function->info, gi_arg_pos, &arg_info);
direction = g_arg_info_get_direction(&arg_info);
g_arg_info_load_type(&arg_info, &arg_type_info);
@@ -708,14 +693,11 @@ release:
ParamType param_type = PARAM_NORMAL;
if (direction == GI_DIRECTION_IN) {
- g_assert_cmpuint(in_args_pos, <, in_args_len);
- arg = &in_arg_cvalues[in_args_pos];
+ arg = &in_arg_cvalues[c_arg_pos];
transfer = g_arg_info_get_ownership_transfer(&arg_info);
- param_type = function->param_types[i];
+ param_type = function->param_types[gi_arg_pos];
} else {
- g_assert_cmpuint(inout_args_pos, <, inout_args_len);
- arg = &inout_original_arg_cvalues[inout_args_pos];
- ++inout_args_pos;
+ arg = &inout_original_arg_cvalues[c_arg_pos];
/* For inout, transfer refers to what we get back from the function; for
* the temporary C value we allocated, clearly we're responsible for
* freeing it.
@@ -765,8 +747,6 @@ release:
}
}
- ++in_args_pos;
-
/* Don't free out arguments if function threw an exception or we failed
* earlier - note "postinvoke_release_failed" is separate from "failed". We
* sync them up after this loop.
@@ -780,8 +760,7 @@ release:
g_assert(next_rval < function->js_out_argc);
- g_assert_cmpuint(out_args_pos, <, out_args_len);
- arg = &out_arg_cvalues[out_args_pos];
+ arg = &out_arg_cvalues[c_arg_pos];
arg_failed = FALSE;
if (!gjs_value_from_g_argument(context,
@@ -819,7 +798,7 @@ release:
g_assert_not_reached();
}
- g_slice_free1(size, out_arg_cvalues[out_args_pos].v_pointer);
+ g_slice_free1(size, out_arg_cvalues[c_arg_pos].v_pointer);
g_base_info_unref((GIBaseInfo*)interface_info);
}
@@ -831,7 +810,6 @@ release:
arg);
++next_rval;
- ++out_args_pos;
}
}
@@ -839,12 +817,7 @@ release:
failed = TRUE;
g_assert(failed || did_throw_gerror || next_rval == (guint8)function->js_out_argc);
- g_assert_cmpuint(in_args_pos, ==, processed_in_args);
-
- if (!(did_throw_gerror || failed)) {
- g_assert_cmpuint(out_args_pos, ==, out_args_len);
- g_assert_cmpuint(inout_args_pos, ==, inout_args_len);
- }
+ g_assert_cmpuint(c_arg_pos, ==, processed_c_args);
if (function->js_out_argc > 0 && (!failed && !did_throw_gerror)) {
/* if we have 1 return value or out arg, return that item
@@ -1184,8 +1157,6 @@ init_cached_function_data (JSContext *context,
function->expected_js_argc += 1;
if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
function->js_out_argc += 1;
- if (direction == GI_DIRECTION_INOUT)
- function->inout_argc += 1;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]