[gjs] arg: Allocate hash values that don't fit in pointers



commit 28bbd24cd9d06b1580603bc771ae98357d42d516
Author: Philip Chimento <philip endlessm com>
Date:   Wed Nov 2 14:52:55 2016 -0700

    arg: Allocate hash values that don't fit in pointers
    
    For GHashTables with value types that can't be stuffed into pointers, we
    use heap-allocated values instead. Since the types we are concerned with
    here are all primitive types, they are always copied, so the hash table
    can always own the values, and they can be freed unconditionally when the
    hash table GIArgument is released.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773763

 gi/arg.cpp                              |   41 ++++++++++++++++++++++++++----
 installed-tests/js/testGIMarshalling.js |   20 +++++++++++++++
 2 files changed, 55 insertions(+), 6 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 764bd06..f6d8d13 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -507,7 +507,7 @@ gjs_object_to_g_hash(JSContext   *context,
 
     JS::RootedValue key_js(context), val_js(context);
     for (id_ix = 0, id_len = ids.length(); id_ix < id_len; id_ix++) {
-        gpointer key_ptr;
+        gpointer key_ptr, val_ptr;
         GIArgument val_arg = { 0 };
 
         if (!JS_IdToValue(context, ids[id_ix], key_js.address()))
@@ -528,7 +528,30 @@ gjs_object_to_g_hash(JSContext   *context,
                                      &val_arg))
             goto free_hash_and_fail;
 
-        g_hash_table_insert(result, key_ptr, val_arg.v_pointer);
+        GITypeTag val_type = g_type_info_get_tag(val_param_info);
+        /* Use heap-allocated values for types that don't fit in a pointer */
+        if (val_type == GI_TYPE_TAG_INT64) {
+            int64_t *heap_val = g_new(int64_t, 1);
+            *heap_val = val_arg.v_int64;
+            val_ptr = heap_val;
+        } else if (val_type == GI_TYPE_TAG_UINT64) {
+            uint64_t *heap_val = g_new(uint64_t, 1);
+            *heap_val = val_arg.v_uint64;
+            val_ptr = heap_val;
+        } else if (val_type == GI_TYPE_TAG_FLOAT) {
+            float *heap_val = g_new(float, 1);
+            *heap_val = val_arg.v_float;
+            val_ptr = heap_val;
+        } else if (val_type == GI_TYPE_TAG_DOUBLE) {
+            double *heap_val = g_new(double, 1);
+            *heap_val = val_arg.v_double;
+            val_ptr = heap_val;
+        } else {
+            /* Other types are simply stuffed inside v_pointer */
+            val_ptr = val_arg.v_pointer;
+        }
+
+        g_hash_table_insert(result, key_ptr, val_ptr);
     }
 
     *hash_p = result;
@@ -3008,11 +3031,17 @@ gjs_ghr_helper(gpointer key, gpointer val, gpointer user_data) {
                                     &key_arg))
         c->failed = true;
 
-    if (!gjs_g_arg_release_internal(c->context, c->transfer,
-                                    c->val_param_info,
-                                    g_type_info_get_tag(c->val_param_info),
-                                    &val_arg))
+    GITypeTag val_type = g_type_info_get_tag(c->val_param_info);
+    if (val_type == GI_TYPE_TAG_INT64 ||
+        val_type == GI_TYPE_TAG_UINT64 ||
+        val_type == GI_TYPE_TAG_FLOAT ||
+        val_type == GI_TYPE_TAG_DOUBLE) {
+        g_free(val_arg.v_pointer);
+    } else if (!gjs_g_arg_release_internal(c->context, c->transfer,
+                                           c->val_param_info, val_type,
+                                           &val_arg)) {
         c->failed = true;
+    }
     return true;
 }
 
diff --git a/installed-tests/js/testGIMarshalling.js b/installed-tests/js/testGIMarshalling.js
index 70cc18b..afab8ac 100644
--- a/installed-tests/js/testGIMarshalling.js
+++ b/installed-tests/js/testGIMarshalling.js
@@ -266,6 +266,12 @@ function testGHashTable() {
         1: '-1',
         2: '-2',
     };
+    const NUMBER_DICT = {
+        '-1': -0.1,
+        0: 0,
+        1: 0.1,
+        2: 0.2,
+    };
     const STRING_DICT_OUT = {
         '-1': '1',
         0: '0',
@@ -279,6 +285,20 @@ function testGHashTable() {
 
     GIMarshallingTests.ghashtable_int_none_in(INT_DICT);
     GIMarshallingTests.ghashtable_utf8_none_in(STRING_DICT);
+    GIMarshallingTests.ghashtable_double_in(NUMBER_DICT);
+    GIMarshallingTests.ghashtable_float_in(NUMBER_DICT);
+    GIMarshallingTests.ghashtable_int64_in({
+        '-1': -1,
+        0: 0,
+        1: 1,
+        2: 0x100000000,
+    });
+    GIMarshallingTests.ghashtable_uint64_in({
+        '-1': 0x100000000,
+        0: 0,
+        1: 1,
+        2: 2,
+    });
 
     dictEquals(GIMarshallingTests.ghashtable_utf8_none_out(), STRING_DICT);
     dictEquals(GIMarshallingTests.ghashtable_utf8_container_out(), STRING_DICT);


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