@@ -25,6 +25,10 @@
#ifndef TCG_INTERNAL_H
#define TCG_INTERNAL_H
+#ifdef CONFIG_TCG_INTERPRETER
+#include <ffi.h>
+#endif
+
#define TCG_HIGHWATER 1024
/*
@@ -57,6 +61,9 @@ typedef struct TCGCallArgumentLoc {
typedef struct TCGHelperInfo {
void *func;
const char *name;
+#ifdef CONFIG_TCG_INTERPRETER
+ ffi_cif *cif;
+#endif
unsigned typemask : 32;
unsigned flags : 8;
unsigned nr_in : 8;
@@ -62,10 +62,6 @@
#include "tcg/tcg-ldst.h"
#include "tcg-internal.h"
-#ifdef CONFIG_TCG_INTERPRETER
-#include <ffi.h>
-#endif
-
/* Forward declarations for functions declared in tcg-target.c.inc and
used here. */
static void tcg_target_init(TCGContext *s);
@@ -552,17 +548,76 @@ static TCGHelperInfo all_helpers[] = {
static GHashTable *helper_table;
#ifdef CONFIG_TCG_INTERPRETER
-static GHashTable *ffi_table;
+static ffi_type *typecode_to_ffi(int argmask)
+{
+ switch (argmask) {
+ case dh_typecode_void:
+ return &ffi_type_void;
+ case dh_typecode_i32:
+ return &ffi_type_uint32;
+ case dh_typecode_s32:
+ return &ffi_type_sint32;
+ case dh_typecode_i64:
+ return &ffi_type_uint64;
+ case dh_typecode_s64:
+ return &ffi_type_sint64;
+ case dh_typecode_ptr:
+ return &ffi_type_pointer;
+ }
+ g_assert_not_reached();
+}
-static ffi_type * const typecode_to_ffi[8] = {
- [dh_typecode_void] = &ffi_type_void,
- [dh_typecode_i32] = &ffi_type_uint32,
- [dh_typecode_s32] = &ffi_type_sint32,
- [dh_typecode_i64] = &ffi_type_uint64,
- [dh_typecode_s64] = &ffi_type_sint64,
- [dh_typecode_ptr] = &ffi_type_pointer,
-};
-#endif
+static void init_ffi_layouts(void)
+{
+ /* g_direct_hash/equal for direct comparisons on uint32_t. */
+ GHashTable *ffi_table = g_hash_table_new(NULL, NULL);
+
+ for (int i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
+ TCGHelperInfo *info = &all_helpers[i];
+ unsigned typemask = info->typemask;
+ gpointer hash = (gpointer)(uintptr_t)typemask;
+ struct {
+ ffi_cif cif;
+ ffi_type *args[];
+ } *ca;
+ ffi_status status;
+ int nargs;
+ ffi_cif *cif;
+
+ cif = g_hash_table_lookup(ffi_table, hash);
+ if (cif) {
+ info->cif = cif;
+ continue;
+ }
+
+ /* Ignoring the return type, find the last non-zero field. */
+ nargs = 32 - clz32(typemask >> 3);
+ nargs = DIV_ROUND_UP(nargs, 3);
+
+ ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
+ ca->cif.rtype = typecode_to_ffi(typemask & 7);
+ ca->cif.nargs = nargs;
+
+ if (nargs != 0) {
+ ca->cif.arg_types = ca->args;
+ for (int j = 0; j < nargs; ++j) {
+ int typecode = extract32(typemask, (j + 1) * 3, 3);
+ ca->args[j] = typecode_to_ffi(typecode);
+ }
+ }
+
+ status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
+ ca->cif.rtype, ca->cif.arg_types);
+ assert(status == FFI_OK);
+
+ cif = &ca->cif;
+ info->cif = cif;
+ g_hash_table_insert(ffi_table, hash, (gpointer)cif);
+ }
+
+ g_hash_table_destroy(ffi_table);
+}
+#endif /* CONFIG_TCG_INTERPRETER */
typedef struct TCGCumulativeArgs {
int arg_idx; /* tcg_gen_callN args[] */
@@ -743,44 +798,7 @@ static void tcg_context_init(unsigned max_cpus)
}
#ifdef CONFIG_TCG_INTERPRETER
- /* g_direct_hash/equal for direct comparisons on uint32_t. */
- ffi_table = g_hash_table_new(NULL, NULL);
- for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
- struct {
- ffi_cif cif;
- ffi_type *args[];
- } *ca;
- uint32_t typemask = all_helpers[i].typemask;
- gpointer hash = (gpointer)(uintptr_t)typemask;
- ffi_status status;
- int nargs;
-
- if (g_hash_table_lookup(ffi_table, hash)) {
- continue;
- }
-
- /* Ignoring the return type, find the last non-zero field. */
- nargs = 32 - clz32(typemask >> 3);
- nargs = DIV_ROUND_UP(nargs, 3);
-
- ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
- ca->cif.rtype = typecode_to_ffi[typemask & 7];
- ca->cif.nargs = nargs;
-
- if (nargs != 0) {
- ca->cif.arg_types = ca->args;
- for (int j = 0; j < nargs; ++j) {
- int typecode = extract32(typemask, (j + 1) * 3, 3);
- ca->args[j] = typecode_to_ffi[typecode];
- }
- }
-
- status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
- ca->cif.rtype, ca->cif.arg_types);
- assert(status == FFI_OK);
-
- g_hash_table_insert(ffi_table, hash, (gpointer)&ca->cif);
- }
+ init_ffi_layouts();
#endif
tcg_target_init(s);
@@ -4398,12 +4416,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
}
#ifdef CONFIG_TCG_INTERPRETER
- {
- gpointer hash = (gpointer)(uintptr_t)info->typemask;
- ffi_cif *cif = g_hash_table_lookup(ffi_table, hash);
- assert(cif != NULL);
- tcg_out_call(s, tcg_call_func(op), cif);
- }
+ tcg_out_call(s, tcg_call_func(op), info->cif);
#else
tcg_out_call(s, tcg_call_func(op));
#endif
Instead of requiring a separate hash table lookup, put a pointer to the CIF into TCGHelperInfo. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/tcg-internal.h | 7 +++ tcg/tcg.c | 129 +++++++++++++++++++++++++-------------------- 2 files changed, 78 insertions(+), 58 deletions(-)