[gjs/wip/gcampax/70-arg-cache: 12/14] arg-cache: Save space by not caching GType



commit 83dff21fa8ee005d21428c56ec2623e03d29e63a
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Jul 18 22:29:58 2020 -0700

    arg-cache: Save space by not caching GType
    
    The GType is fetchable from the GIRegisteredTypeInfo, and it is the only
    member keeping the GjsArgumentCache struct from being smaller. However,
    this is a bit of a tradeoff since g_registered_type_info_get_g_type()
    involves a call to g_module_symbol().
    
    Hopefully this doesn't have much of an effect on performance, compared
    to the net benefit of introducing the argument cache in the first place,
    since g_registered_type_info_get_type() is also used in the "old way" of
    marshalling values in arg.cpp.

 gi/arg-cache.cpp | 19 +++++++++----------
 gi/arg-cache.h   |  7 ++-----
 gi/function.cpp  | 10 +++++++---
 3 files changed, 18 insertions(+), 18 deletions(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index 026fde0e..36be6b43 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -595,7 +595,7 @@ static bool gjs_marshal_boxed_in_in(JSContext* cx, GjsArgumentCache* self,
     if (value.isNull())
         return self->handle_nullable(cx, arg);
 
-    GType gtype = self->contents.object.gtype;
+    GType gtype = g_registered_type_info_get_g_type(self->contents.info);
 
     if (!value.isObject())
         return report_object_primitive_type_mismatch(cx, self->arg_name, value,
@@ -609,7 +609,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.object.info);
+                                              self->contents.info);
 }
 
 // Unions include ClutterEvent and GdkEvent, which occur fairly often in an
@@ -622,7 +622,7 @@ static bool gjs_marshal_union_in_in(JSContext* cx, GjsArgumentCache* self,
     if (value.isNull())
         return self->handle_nullable(cx, arg);
 
-    GType gtype = self->contents.object.gtype;
+    GType gtype = g_registered_type_info_get_g_type(self->contents.info);
     g_assert(gtype != G_TYPE_NONE);
 
     if (!value.isObject())
@@ -632,7 +632,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.object.info);
+                                              self->contents.info);
 }
 
 GJS_JSAPI_RETURN_CONVENTION
@@ -676,7 +676,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.object.info);
+        self->contents.info);
 }
 
 GJS_JSAPI_RETURN_CONVENTION
@@ -686,7 +686,7 @@ static bool gjs_marshal_object_in_in(JSContext* cx, GjsArgumentCache* self,
     if (value.isNull())
         return self->handle_nullable(cx, arg);
 
-    GType gtype = self->contents.object.gtype;
+    GType gtype = g_registered_type_info_get_g_type(self->contents.info);
     g_assert(gtype != G_TYPE_NONE);
 
     if (!value.isObject())
@@ -945,7 +945,7 @@ static bool gjs_marshal_boxed_in_release(JSContext*, GjsArgumentCache* self,
                                          GjsFunctionCallState*,
                                          GIArgument* in_arg,
                                          GIArgument* out_arg G_GNUC_UNUSED) {
-    GType gtype = self->contents.object.gtype;
+    GType gtype = g_registered_type_info_get_g_type(self->contents.info);
     g_assert(g_type_is_a(gtype, G_TYPE_BOXED));
 
     if (!in_arg->v_pointer)
@@ -956,7 +956,7 @@ static bool gjs_marshal_boxed_in_release(JSContext*, GjsArgumentCache* self,
 }
 
 static void gjs_arg_cache_interface_free(GjsArgumentCache* self) {
-    g_clear_pointer(&self->contents.object.info, g_base_info_unref);
+    g_clear_pointer(&self->contents.info, g_base_info_unref);
 }
 
 static inline void gjs_arg_cache_set_skip_all(GjsArgumentCache* self) {
@@ -1097,8 +1097,7 @@ 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.object.gtype = gtype;
-            self->contents.object.info = g_base_info_ref(interface_info);
+            self->contents.info = g_base_info_ref(interface_info);
             self->free = gjs_arg_cache_interface_free;
 
             // Transfer handling is a bit complex here, because some of our _in
diff --git a/gi/arg-cache.h b/gi/arg-cache.h
index 0636cd93..07250aea 100644
--- a/gi/arg-cache.h
+++ b/gi/arg-cache.h
@@ -79,10 +79,7 @@ struct GjsArgumentCache {
         } number;
 
         // boxed / union / GObject
-        struct {
-            GType gtype;
-            GIBaseInfo* info;
-        } object;
+        GIRegisteredTypeInfo* info;
 
         // foreign structures
         GIStructInfo* tmp_foreign_info;
@@ -160,7 +157,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) <= 136,
+static_assert(sizeof(GjsArgumentCache) <= 128,
               "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 28c44952..c3424956 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -738,9 +738,13 @@ 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 (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;
+        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;
+        }
     }
 
     unsigned processed_c_args = ffi_arg_pos;


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