summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Dreßler <verdre@v0yd.nl>2020-10-22 18:04:03 +0200
committerJonas Dreßler <verdre@v0yd.nl>2020-10-22 18:19:16 +0200
commitd526bf8980c5ab9e779ce6e6e74ecaf88c559950 (patch)
tree3a590c3e1bb139469efe407a5b9502a243661bbf
parenta1d0d5b630e77a773810e45c368a1db5c3702128 (diff)
downloadgjs-wip/verdre/cache-gtype.tar.gz
Revert "arg-cache: Save space by not caching GType"wip/verdre/cache-gtype
As found in https://gitlab.gnome.org/GNOME/gjs/-/issues/361, getting the GType using g_registered_type_info_get_g_type() is very expensive and can make up for a significant part of the overhead when calling into a C function. Since the argument cache seems to be fairly small in a typical gnome-shell session (about 1300 entries), the total increased memory usage of about 10kB seems very reasonable given the benefits of the caching. This reverts commit adfb7dc3ba79b17b0cefa47f5249e9da917217ad.
-rw-r--r--gi/arg-cache.cpp25
-rw-r--r--gi/arg-cache.h8
-rw-r--r--gi/function.cpp10
3 files changed, 22 insertions, 21 deletions
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index 90d8d0ce..fca5836a 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -10,7 +10,6 @@
#include <ffi.h>
#include <girepository.h>
-#include <glib-object.h>
#include <glib.h>
#include <js/Conversions.h>
@@ -579,7 +578,7 @@ static bool gjs_marshal_boxed_in_in(JSContext* cx, GjsArgumentCache* self,
if (value.isNull())
return self->handle_nullable(cx, arg);
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
if (!value.isObject())
return report_gtype_mismatch(cx, self->arg_name, value, gtype);
@@ -592,7 +591,7 @@ static bool gjs_marshal_boxed_in_in(JSContext* cx, GjsArgumentCache* self,
return BoxedBase::transfer_to_gi_argument(cx, object, arg, GI_DIRECTION_IN,
self->transfer, gtype,
- self->contents.info);
+ self->contents.object.info);
}
// Unions include ClutterEvent and GdkEvent, which occur fairly often in an
@@ -605,7 +604,7 @@ static bool gjs_marshal_union_in_in(JSContext* cx, GjsArgumentCache* self,
if (value.isNull())
return self->handle_nullable(cx, arg);
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
g_assert(gtype != G_TYPE_NONE);
if (!value.isObject())
@@ -614,7 +613,7 @@ static bool gjs_marshal_union_in_in(JSContext* cx, GjsArgumentCache* self,
JS::RootedObject object(cx, &value.toObject());
return UnionBase::transfer_to_gi_argument(cx, object, arg, GI_DIRECTION_IN,
self->transfer, gtype,
- self->contents.info);
+ self->contents.object.info);
}
GJS_JSAPI_RETURN_CONVENTION
@@ -657,7 +656,7 @@ static bool gjs_marshal_gbytes_in_in(JSContext* cx, GjsArgumentCache* self,
// ownership, so we need to do the same here.
return BoxedBase::transfer_to_gi_argument(
cx, object, arg, GI_DIRECTION_IN, GI_TRANSFER_EVERYTHING, G_TYPE_BYTES,
- self->contents.info);
+ self->contents.object.info);
}
GJS_JSAPI_RETURN_CONVENTION
@@ -667,7 +666,7 @@ static bool gjs_marshal_interface_in_in(JSContext* cx, GjsArgumentCache* self,
if (value.isNull())
return self->handle_nullable(cx, arg);
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
g_assert(gtype != G_TYPE_NONE);
if (!value.isObject())
@@ -696,7 +695,7 @@ static bool gjs_marshal_object_in_in(JSContext* cx, GjsArgumentCache* self,
if (value.isNull())
return self->handle_nullable(cx, arg);
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
g_assert(gtype != G_TYPE_NONE);
if (!value.isObject())
@@ -715,7 +714,7 @@ static bool gjs_marshal_fundamental_in_in(JSContext* cx, GjsArgumentCache* self,
if (value.isNull())
return self->handle_nullable(cx, arg);
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
g_assert(gtype != G_TYPE_NONE);
if (!value.isObject())
@@ -970,7 +969,8 @@ static bool gjs_marshal_boxed_in_release(JSContext*, GjsArgumentCache* self,
GjsFunctionCallState*,
GIArgument* in_arg,
GIArgument* out_arg [[maybe_unused]]) {
- GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ GType gtype = self->contents.object.gtype;
+
g_assert(g_type_is_a(gtype, G_TYPE_BOXED));
if (!gjs_arg_get<void*>(in_arg))
@@ -993,7 +993,7 @@ static bool gjs_marshal_gvalue_in_maybe_release(JSContext* cx,
}
static void gjs_arg_cache_interface_free(GjsArgumentCache* self) {
- g_clear_pointer(&self->contents.info, g_base_info_unref);
+ g_clear_pointer(&self->contents.object.info, g_base_info_unref);
}
static const GjsArgumentMarshallers skip_all_marshallers = {
@@ -1383,7 +1383,8 @@ static bool gjs_arg_cache_build_interface_in_arg(JSContext* cx,
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_UNION: {
GType gtype = g_registered_type_info_get_g_type(interface_info);
- self->contents.info = g_base_info_ref(interface_info);
+ self->contents.object.gtype = gtype;
+ self->contents.object.info = g_base_info_ref(interface_info);
// Transfer handling is a bit complex here, because some of our _in
// marshallers know not to copy stuff if we don't need to.
diff --git a/gi/arg-cache.h b/gi/arg-cache.h
index d6e293df..058d686a 100644
--- a/gi/arg-cache.h
+++ b/gi/arg-cache.h
@@ -11,6 +11,7 @@
#include <stdint.h>
#include <girepository.h>
+#include <glib-object.h>
#include <glib.h> // for g_assert
#include <js/RootingAPI.h>
@@ -64,7 +65,10 @@ struct GjsArgumentCache {
} number;
// boxed / union / GObject
- GIRegisteredTypeInfo* info;
+ struct {
+ GType gtype;
+ GIBaseInfo* info;
+ } object;
// foreign structures
GIStructInfo* tmp_foreign_info;
@@ -144,7 +148,7 @@ struct GjsArgumentCache {
// if sizeof(GjsArgumentCache) is increased.
// Note that this check is not applicable for clang-cl builds, as Windows is
// an LLP64 system
-static_assert(sizeof(GjsArgumentCache) <= 104,
+static_assert(sizeof(GjsArgumentCache) <= 112,
"Think very hard before increasing the size of GjsArgumentCache. "
"One is allocated for every argument to every introspected "
"function.");
diff --git a/gi/function.cpp b/gi/function.cpp
index 5b74fde0..4cc950a1 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -799,13 +799,9 @@ static bool gjs_invoke_c_function(JSContext* context, Function* function,
// Callback lifetimes will be attached to the instance object if it is
// a GObject or GInterface
- if (cache->contents.info) {
- GType gtype =
- g_registered_type_info_get_g_type(cache->contents.info);
- if (g_type_is_a(gtype, G_TYPE_OBJECT) ||
- g_type_is_a(gtype, G_TYPE_INTERFACE))
- state.instance_object = obj;
- }
+ if (g_type_is_a(cache->contents.object.gtype, G_TYPE_OBJECT) ||
+ g_type_is_a(cache->contents.object.gtype, G_TYPE_INTERFACE))
+ state.instance_object = obj;
}
unsigned processed_c_args = ffi_arg_pos;