diff mbox series

[RFC,06/48] tcg: use QHT for helper_table

Message ID 20181025172057.20414-7-cota@braap.org
State New
Headers show
Series Plugin support | expand

Commit Message

Emilio Cota Oct. 25, 2018, 5:20 p.m. UTC
This will allow us to add TCG helpers at run-time.

While at it, rename tcg_find_helper to tcg_helper_find for consistency
with the added tcg_helper_foo functions.

Signed-off-by: Emilio G. Cota <cota@braap.org>
---
 tcg/tcg.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 49 insertions(+), 10 deletions(-)

Comments

Alex Bennée Nov. 14, 2018, 2:41 p.m. UTC | #1
Emilio G. Cota <cota@braap.org> writes:

> This will allow us to add TCG helpers at run-time.
>
> While at it, rename tcg_find_helper to tcg_helper_find for consistency
> with the added tcg_helper_foo functions.
>
> Signed-off-by: Emilio G. Cota <cota@braap.org>
> ---
>  tcg/tcg.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 49 insertions(+), 10 deletions(-)
>
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index e85133ef05..65da3c5dbf 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -33,6 +33,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/cutils.h"
>  #include "qemu/host-utils.h"
> +#include "qemu/xxhash.h"
>  #include "qemu/timer.h"
>
>  /* Note: the long term plan is to reduce the dependencies on the QEMU
> @@ -879,13 +880,46 @@ typedef struct TCGHelperInfo {
>  static const TCGHelperInfo all_helpers[] = {
>  #include "exec/helper-tcg.h"
>  };
> -static GHashTable *helper_table;
> +static struct qht helper_table;
> +static bool helper_table_inited;

Having a flag for initialisation seems a little excessive considering
we've moved that initialisation into tcg_context_init() which has to be
called before we do anything TCG related.

>  static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
>  static void process_op_defs(TCGContext *s);
>  static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
>                                              TCGReg reg, const char *name);
>
> +static inline uint32_t tcg_helper_func_hash(const void *func)
> +{
> +    return qemu_xxhash2((uint64_t)func);
> +}
> +
> +static bool tcg_helper_cmp(const void *ap, const void *bp)
> +{
> +    const TCGHelperInfo *a = ap;
> +    const TCGHelperInfo *b = bp;
> +
> +    return a->func == b->func &&
> +        a->flags == b->flags &&
> +        a->sizemask == b->sizemask &&
> +        !strcmp(a->name, b->name);
> +}
> +
> +static bool tcg_helper_lookup_cmp(const void *obj, const void *func)
> +{
> +    const TCGHelperInfo *info = obj;
> +
> +    return info->func == func;
> +}
> +
> +static void tcg_helper_insert(const TCGHelperInfo *info)
> +{
> +    uint32_t hash = tcg_helper_func_hash(info->func);
> +    bool inserted;
> +
> +    inserted = qht_insert(&helper_table, (void *)info, hash, NULL);
> +    g_assert(inserted);
> +}
> +
>  void tcg_context_init(TCGContext *s)
>  {
>      int op, total_args, n, i;
> @@ -919,13 +953,13 @@ void tcg_context_init(TCGContext *s)
>      }
>
>      /* Register helpers.  */
> -    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
> -    helper_table = g_hash_table_new(NULL, NULL);
> +    qht_init(&helper_table, tcg_helper_cmp, ARRAY_SIZE(all_helpers),
> +             QHT_MODE_AUTO_RESIZE);
>
>      for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
> -        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
> -                            (gpointer)&all_helpers[i]);
> +        tcg_helper_insert(&all_helpers[i]);
>      }
> +    helper_table_inited = true;

so I think we can drop this and...

>
>      tcg_target_init(s);
>      process_op_defs(s);
> @@ -1620,9 +1654,10 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
>      int i, real_args, nb_rets, pi;
>      unsigned sizemask, flags;
>      TCGHelperInfo *info;
> +    uint32_t hash = tcg_helper_func_hash(func);
>      TCGOp *op;
>
> -    info = g_hash_table_lookup(helper_table, (gpointer)func);
> +    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
>      flags = info->flags;
>      sizemask = info->sizemask;
>
> @@ -1825,11 +1860,15 @@ static char *tcg_get_arg_str(TCGContext *s, char *buf,
>  }
>
>  /* Find helper name.  */
> -static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
> +static inline const char *tcg_helper_find(TCGContext *s, uintptr_t val)
>  {
>      const char *ret = NULL;
> -    if (helper_table) {
> -        TCGHelperInfo *info = g_hash_table_lookup(helper_table, (gpointer)val);
> +    if (helper_table_inited) {

change this to a assert(helper_table.cmp) if you really want to.

> +        uint32_t hash = tcg_helper_func_hash((void *)val);
> +        TCGHelperInfo *info;
> +
> +        info = qht_lookup_custom(&helper_table, (void *)val, hash,
> +                                 tcg_helper_lookup_cmp);
>          if (info) {
>              ret = info->name;
>          }
> @@ -1919,7 +1958,7 @@ void tcg_dump_ops(TCGContext *s)
>
>              /* function name, flags, out args */
>              col += qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
> -                            tcg_find_helper(s, op->args[nb_oargs + nb_iargs]),
> +                            tcg_helper_find(s, op->args[nb_oargs + nb_iargs]),
>                              op->args[nb_oargs + nb_iargs + 1], nb_oargs);
>              for (i = 0; i < nb_oargs; i++) {
>                  col += qemu_log(",%s", tcg_get_arg_str(s, buf, sizeof(buf),

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée
Alex Bennée Nov. 14, 2018, 4:11 p.m. UTC | #2
Emilio G. Cota <cota@braap.org> writes:

> This will allow us to add TCG helpers at run-time.
>
> While at it, rename tcg_find_helper to tcg_helper_find for consistency
> with the added tcg_helper_foo functions.
>
> Signed-off-by: Emilio G. Cota <cota@braap.org>
> ---
>  tcg/tcg.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 49 insertions(+), 10 deletions(-)
>
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index e85133ef05..65da3c5dbf 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -33,6 +33,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/cutils.h"
>  #include "qemu/host-utils.h"
> +#include "qemu/xxhash.h"
>  #include "qemu/timer.h"
>
>  /* Note: the long term plan is to reduce the dependencies on the QEMU
> @@ -879,13 +880,46 @@ typedef struct TCGHelperInfo {
>  static const TCGHelperInfo all_helpers[] = {
>  #include "exec/helper-tcg.h"
>  };
> -static GHashTable *helper_table;
> +static struct qht helper_table;
> +static bool helper_table_inited;
>
>  static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
>  static void process_op_defs(TCGContext *s);
>  static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
>                                              TCGReg reg, const char *name);
>
> +static inline uint32_t tcg_helper_func_hash(const void *func)
> +{
> +    return qemu_xxhash2((uint64_t)func);
> +}

I needed to do this:

modified   tcg/tcg.c
@@ -884,7 +884,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,

 static inline uint32_t tcg_helper_func_hash(const void *func)
 {
-    return qemu_xxhash2((uint64_t)func);
+    return qemu_xxhash2((uint64_t)(uintptr_t)func);
 }

To prevent the compiler complaining about:

 tcg.c:887:25: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]

> +
> +static bool tcg_helper_cmp(const void *ap, const void *bp)
> +{
> +    const TCGHelperInfo *a = ap;
> +    const TCGHelperInfo *b = bp;
> +
> +    return a->func == b->func &&
> +        a->flags == b->flags &&
> +        a->sizemask == b->sizemask &&
> +        !strcmp(a->name, b->name);
> +}
> +
> +static bool tcg_helper_lookup_cmp(const void *obj, const void *func)
> +{
> +    const TCGHelperInfo *info = obj;
> +
> +    return info->func == func;
> +}
> +
> +static void tcg_helper_insert(const TCGHelperInfo *info)
> +{
> +    uint32_t hash = tcg_helper_func_hash(info->func);
> +    bool inserted;
> +
> +    inserted = qht_insert(&helper_table, (void *)info, hash, NULL);
> +    g_assert(inserted);
> +}
> +
>  void tcg_context_init(TCGContext *s)
>  {
>      int op, total_args, n, i;
> @@ -919,13 +953,13 @@ void tcg_context_init(TCGContext *s)
>      }
>
>      /* Register helpers.  */
> -    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
> -    helper_table = g_hash_table_new(NULL, NULL);
> +    qht_init(&helper_table, tcg_helper_cmp, ARRAY_SIZE(all_helpers),
> +             QHT_MODE_AUTO_RESIZE);
>
>      for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
> -        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
> -                            (gpointer)&all_helpers[i]);
> +        tcg_helper_insert(&all_helpers[i]);
>      }
> +    helper_table_inited = true;
>
>      tcg_target_init(s);
>      process_op_defs(s);
> @@ -1620,9 +1654,10 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
>      int i, real_args, nb_rets, pi;
>      unsigned sizemask, flags;
>      TCGHelperInfo *info;
> +    uint32_t hash = tcg_helper_func_hash(func);
>      TCGOp *op;
>
> -    info = g_hash_table_lookup(helper_table, (gpointer)func);
> +    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
>      flags = info->flags;
>      sizemask = info->sizemask;
>
> @@ -1825,11 +1860,15 @@ static char *tcg_get_arg_str(TCGContext *s, char *buf,
>  }
>
>  /* Find helper name.  */
> -static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
> +static inline const char *tcg_helper_find(TCGContext *s, uintptr_t val)
>  {
>      const char *ret = NULL;
> -    if (helper_table) {
> -        TCGHelperInfo *info = g_hash_table_lookup(helper_table, (gpointer)val);
> +    if (helper_table_inited) {
> +        uint32_t hash = tcg_helper_func_hash((void *)val);
> +        TCGHelperInfo *info;
> +
> +        info = qht_lookup_custom(&helper_table, (void *)val, hash,
> +                                 tcg_helper_lookup_cmp);
>          if (info) {
>              ret = info->name;
>          }
> @@ -1919,7 +1958,7 @@ void tcg_dump_ops(TCGContext *s)
>
>              /* function name, flags, out args */
>              col += qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
> -                            tcg_find_helper(s, op->args[nb_oargs + nb_iargs]),
> +                            tcg_helper_find(s, op->args[nb_oargs + nb_iargs]),
>                              op->args[nb_oargs + nb_iargs + 1], nb_oargs);
>              for (i = 0; i < nb_oargs; i++) {
>                  col += qemu_log(",%s", tcg_get_arg_str(s, buf, sizeof(buf),


--
Alex Bennée
Emilio Cota Nov. 14, 2018, 5:50 p.m. UTC | #3
On Wed, Nov 14, 2018 at 14:41:53 +0000, Alex Bennée wrote:
> Emilio G. Cota <cota@braap.org> writes:
(snip)
> > -static GHashTable *helper_table;
> > +static struct qht helper_table;
> > +static bool helper_table_inited;
> 
> Having a flag for initialisation seems a little excessive considering
> we've moved that initialisation into tcg_context_init() which has to be
> called before we do anything TCG related.

(snip)
> > +    helper_table_inited = true;
> 
> so I think we can drop this and...

(snip)
> > +static inline const char *tcg_helper_find(TCGContext *s, uintptr_t val)
> >  {
> >      const char *ret = NULL;
> > -    if (helper_table) {
> > -        TCGHelperInfo *info = g_hash_table_lookup(helper_table, (gpointer)val);
> > +    if (helper_table_inited) {
> 
> change this to a assert(helper_table.cmp) if you really want to.

I like this suggestion. The only caller of tcg_helper_find
is tcg_dump_ops, which is unlikely to be called on an
uninitialized TCGContext.

I have added this to v2, without the assert.

(snip)
> Otherwise:
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

Thanks!

		E.
Emilio Cota Nov. 14, 2018, 5:52 p.m. UTC | #4
On Wed, Nov 14, 2018 at 16:11:35 +0000, Alex Bennée wrote:
> 
> Emilio G. Cota <cota@braap.org> writes:
(snip)
> I needed to do this:
> 
> modified   tcg/tcg.c
> @@ -884,7 +884,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
> 
>  static inline uint32_t tcg_helper_func_hash(const void *func)
>  {
> -    return qemu_xxhash2((uint64_t)func);
> +    return qemu_xxhash2((uint64_t)(uintptr_t)func);
>  }
> 
> To prevent the compiler complaining about:
> 
>  tcg.c:887:25: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]

Fixed, thanks.

		E.
diff mbox series

Patch

diff --git a/tcg/tcg.c b/tcg/tcg.c
index e85133ef05..65da3c5dbf 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -33,6 +33,7 @@ 
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
 #include "qemu/host-utils.h"
+#include "qemu/xxhash.h"
 #include "qemu/timer.h"
 
 /* Note: the long term plan is to reduce the dependencies on the QEMU
@@ -879,13 +880,46 @@  typedef struct TCGHelperInfo {
 static const TCGHelperInfo all_helpers[] = {
 #include "exec/helper-tcg.h"
 };
-static GHashTable *helper_table;
+static struct qht helper_table;
+static bool helper_table_inited;
 
 static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
 static void process_op_defs(TCGContext *s);
 static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
                                             TCGReg reg, const char *name);
 
+static inline uint32_t tcg_helper_func_hash(const void *func)
+{
+    return qemu_xxhash2((uint64_t)func);
+}
+
+static bool tcg_helper_cmp(const void *ap, const void *bp)
+{
+    const TCGHelperInfo *a = ap;
+    const TCGHelperInfo *b = bp;
+
+    return a->func == b->func &&
+        a->flags == b->flags &&
+        a->sizemask == b->sizemask &&
+        !strcmp(a->name, b->name);
+}
+
+static bool tcg_helper_lookup_cmp(const void *obj, const void *func)
+{
+    const TCGHelperInfo *info = obj;
+
+    return info->func == func;
+}
+
+static void tcg_helper_insert(const TCGHelperInfo *info)
+{
+    uint32_t hash = tcg_helper_func_hash(info->func);
+    bool inserted;
+
+    inserted = qht_insert(&helper_table, (void *)info, hash, NULL);
+    g_assert(inserted);
+}
+
 void tcg_context_init(TCGContext *s)
 {
     int op, total_args, n, i;
@@ -919,13 +953,13 @@  void tcg_context_init(TCGContext *s)
     }
 
     /* Register helpers.  */
-    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
-    helper_table = g_hash_table_new(NULL, NULL);
+    qht_init(&helper_table, tcg_helper_cmp, ARRAY_SIZE(all_helpers),
+             QHT_MODE_AUTO_RESIZE);
 
     for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
-        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
-                            (gpointer)&all_helpers[i]);
+        tcg_helper_insert(&all_helpers[i]);
     }
+    helper_table_inited = true;
 
     tcg_target_init(s);
     process_op_defs(s);
@@ -1620,9 +1654,10 @@  void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
     int i, real_args, nb_rets, pi;
     unsigned sizemask, flags;
     TCGHelperInfo *info;
+    uint32_t hash = tcg_helper_func_hash(func);
     TCGOp *op;
 
-    info = g_hash_table_lookup(helper_table, (gpointer)func);
+    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
     flags = info->flags;
     sizemask = info->sizemask;
 
@@ -1825,11 +1860,15 @@  static char *tcg_get_arg_str(TCGContext *s, char *buf,
 }
 
 /* Find helper name.  */
-static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
+static inline const char *tcg_helper_find(TCGContext *s, uintptr_t val)
 {
     const char *ret = NULL;
-    if (helper_table) {
-        TCGHelperInfo *info = g_hash_table_lookup(helper_table, (gpointer)val);
+    if (helper_table_inited) {
+        uint32_t hash = tcg_helper_func_hash((void *)val);
+        TCGHelperInfo *info;
+
+        info = qht_lookup_custom(&helper_table, (void *)val, hash,
+                                 tcg_helper_lookup_cmp);
         if (info) {
             ret = info->name;
         }
@@ -1919,7 +1958,7 @@  void tcg_dump_ops(TCGContext *s)
 
             /* function name, flags, out args */
             col += qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
-                            tcg_find_helper(s, op->args[nb_oargs + nb_iargs]),
+                            tcg_helper_find(s, op->args[nb_oargs + nb_iargs]),
                             op->args[nb_oargs + nb_iargs + 1], nb_oargs);
             for (i = 0; i < nb_oargs; i++) {
                 col += qemu_log(",%s", tcg_get_arg_str(s, buf, sizeof(buf),