Commit 1bdc5421 authored by Philip Chimento's avatar Philip Chimento 🚮

arg-cache: Store marshallers in predefined groups

The four marshaller function pointers cannot be just any functions.
There are a relatively small number of configurations of marshallers, so
it saves space to write them all out explicitly, and store only one
pointer in the argument cache instead of four.

It also prevents accidentally leaving a control flow path where one of
the marshaller function pointers remains unset.
parent adfb7dc3
Pipeline #200866 passed with stages
in 7 minutes and 13 seconds
This diff is collapsed.
......@@ -38,19 +38,23 @@
#include "gjs/macros.h"
struct GjsFunctionCallState;
struct GjsArgumentCache {
bool (*marshal_in)(JSContext* cx, GjsArgumentCache* cache,
GjsFunctionCallState* state, GIArgument* in_argument,
JS::HandleValue value);
bool (*marshal_out)(JSContext* cx, GjsArgumentCache* cache,
GjsFunctionCallState* state, GIArgument* out_argument,
JS::MutableHandleValue value);
struct GjsArgumentCache;
struct GjsArgumentMarshallers {
bool (*in)(JSContext* cx, GjsArgumentCache* cache,
GjsFunctionCallState* state, GIArgument* in_argument,
JS::HandleValue value);
bool (*out)(JSContext* cx, GjsArgumentCache* cache,
GjsFunctionCallState* state, GIArgument* out_argument,
JS::MutableHandleValue value);
bool (*release)(JSContext* cx, GjsArgumentCache* cache,
GjsFunctionCallState* state, GIArgument* in_argument,
GIArgument* out_argument);
void (*free)(GjsArgumentCache* cache);
};
struct GjsArgumentCache {
const GjsArgumentMarshallers* marshallers;
const char* arg_name;
GITypeInfo type_info;
......@@ -157,7 +161,7 @@ struct GjsArgumentCache {
#if defined(__x86_64__) && defined(__clang__)
// This isn't meant to be comprehensive, but should trip on at least one CI job
// if sizeof(GjsArgumentCache) is increased. */
static_assert(sizeof(GjsArgumentCache) <= 128,
static_assert(sizeof(GjsArgumentCache) <= 104,
"Think very hard before increasing the size of GjsArgumentCache. "
"One is allocated for every argument to every introspected "
"function.");
......
......@@ -784,7 +784,8 @@ static bool gjs_invoke_c_function(JSContext* context, Function* function,
GIArgument* in_value = &state.in_cvalues[-2];
JS::RootedValue in_js_value(context, JS::ObjectValue(*obj));
if (!cache->marshal_in(context, cache, &state, in_value, in_js_value))
if (!cache->marshallers->in(context, cache, &state, in_value,
in_js_value))
return false;
ffi_arg_pointers[ffi_arg_pos] = in_value;
......@@ -814,7 +815,7 @@ static bool gjs_invoke_c_function(JSContext* context, Function* function,
ffi_arg_pointers[ffi_arg_pos] = in_value;
if (!cache->marshal_in) {
if (!cache->marshallers->in) {
gjs_throw(context,
"Error invoking %s.%s: impossible to determine what "
"to pass to the '%s' argument. It may be that the "
......@@ -830,7 +831,8 @@ static bool gjs_invoke_c_function(JSContext* context, Function* function,
if (js_arg_pos < args.length())
js_in_arg = args[js_arg_pos];
if (!cache->marshal_in(context, cache, &state, in_value, js_in_arg)) {
if (!cache->marshallers->in(context, cache, &state, in_value,
js_in_arg)) {
failed = true;
break;
}
......@@ -899,8 +901,8 @@ static bool gjs_invoke_c_function(JSContext* context, Function* function,
JS::RootedValue js_out_arg(context);
if (!r_value) {
if (!cache->marshal_out(context, cache, &state, out_value,
&js_out_arg)) {
if (!cache->marshallers->out(context, cache, &state, out_value,
&js_out_arg)) {
failed = true;
break;
}
......@@ -959,7 +961,8 @@ release:
continue;
}
if (!cache->release(context, cache, &state, in_value, out_value)) {
if (!cache->marshallers->release(context, cache, &state, in_value,
out_value)) {
postinvoke_release_failed = true;
// continue with the release even if we fail, to avoid leaks
}
......@@ -1033,8 +1036,9 @@ uninit_cached_function_data (Function *function)
int start_index = g_callable_info_is_method(function->info) ? -2 : -1;
int gi_argc = g_callable_info_get_n_args(function->info);
for (int ix = start_index; ix < gi_argc; ix++) {
if (function->arguments[ix].free)
function->arguments[ix].free(&function->arguments[ix]);
if (function->arguments[ix].marshallers->free)
function->arguments[ix].marshallers->free(
&function->arguments[ix]);
}
g_free(&function->arguments[start_index]);
......
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