This refactoring introduces a general mechanism usable by other arches
to provide argument passing in registers. Developers of other arches
where this applies need only write a parser that allocates registers for
arguments. The additional code and data structure support is controlled
by CONFIG_ARGS_MAP.

Signed-off-by: Eduard - Gabriel Munteanu <eduard.munte...@linux360.ro>
---
 arch/x86/args.c                   |  144 +++++++++++++++++--------------------
 arch/x86/include/arch/args.h      |   63 ++++-------------
 arch/x86/include/arch/config_64.h |    2 +-
 arch/x86/insn-selector.brg        |   51 +++++++------
 include/jit/args.h                |   20 +++++-
 include/jit/expression.h          |    2 +-
 include/vm/method.h               |   11 +++-
 jit/args.c                        |   61 ++++++++++------
 vm/method.c                       |   11 ++-
 9 files changed, 185 insertions(+), 180 deletions(-)
 rewrite arch/x86/include/arch/args.h (83%)

diff --git a/arch/x86/args.c b/arch/x86/args.c
index 715b38d..65d6522 100644
--- a/arch/x86/args.c
+++ b/arch/x86/args.c
@@ -26,25 +26,66 @@
 
 #include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "arch/args.h"
 
 #include "jit/args.h"
-#include "jit/expression.h"
 
 #include "vm/method.h"
 #include "vm/types.h"
 
 #ifdef CONFIG_X86_64
 
-int args_init(unsigned long *state,
-             struct vm_method *method,
-             unsigned long nr_args)
+static enum machine_reg args_map_alloc_gpr(int gpr)
+{
+       switch (gpr) {
+       case 0:
+               return REG_RDI;
+       case 1:
+               return REG_RSI;
+       case 2:
+               return REG_RDX;
+       case 3:
+               return REG_RCX;
+       case 4:
+               return REG_R8;
+       case 5:
+               return REG_R9;
+       default:
+               assert(gpr > 5);
+               return REG_UNASSIGNED;
+       }
+}
+
+int args_map_init(struct vm_method *method)
 {
        const char *type;
        enum vm_type vm_type;
-
+       int idx, gpr_count = 0, stack_count = 0;
+       struct vm_args_map *map;
+       size_t size;
+
+       /* If the method isn't static, we have a *this. */
+       size = method->args_count + !vm_method_is_static(method);
+
+       method->args_map = malloc(sizeof(*map) * size);
+       if (!method->args_map)
+               return -1;
+
+       /* We know *this is a J_REFERENCE, so allocate a GPR. */
+       if (!vm_method_is_static(method)) {
+               map = &method->args_map[0];
+               map->reg = args_map_alloc_gpr(gpr_count++);
+               map->stack_index = -1;
+               idx = 1;
+       } else
+               idx = 0;
+
+       /* Scan the real parameters and assign registers and stack slots. */
        for (type = method->type + 1; *type != ')'; skip_type(&type)) {
+               map = &method->args_map[idx];
+
                vm_type = str_to_type(type);
                switch (vm_type) {
                case J_BYTE:
@@ -54,90 +95,39 @@ int args_init(unsigned long *state,
                case J_SHORT:
                case J_BOOLEAN:
                case J_REFERENCE:
-                       method->reg_args_count++;
+                       map->reg = args_map_alloc_gpr(gpr_count++);
+                       map->stack_index = -1;
+                       break;
+               case J_FLOAT:
+               case J_DOUBLE:
+                       /*
+                        * FIXME: This is wrong, but let's us
+                        * not worry about the status of FP.
+                        */
+                       map->reg = REG_UNASSIGNED;
+                       map->stack_index = stack_count++;
                        break;
                default:
-                       NOT_IMPLEMENTED;
+                       map->reg = REG_UNASSIGNED;
+                       map->stack_index = stack_count++;
                        break;
                }
 
-               if (method->reg_args_count == 6)
+               idx++;
+
+               if (gpr_count == 6)
                        break;
        }
 
-       if (vm_method_is_jni(method))
-               method->reg_args_count += 2;
-
-       method->reg_args_count = min(method->reg_args_count, 6);
-       method->args_count -= method->reg_args_count;
+       /* We're out of GPRs, so the remaining args go on the stack. */
+       for (; idx < method->args_count; idx++) {
+               map = &method->args_map[idx];
 
-       *state = 1;
-
-       return 0;
-}
-
-int args_set(unsigned long *state,
-            struct vm_method *method,
-            struct expression *expr)
-{
-       struct expression *value_expr = to_expr(expr->arg_expression);
-       unsigned long reg;
-
-       if ((int) *state <= method->args_count) {
-               (*state)++;
-               expr->arg_private = NULL;
-               return 0;
+               map->reg = REG_UNASSIGNED;
+               map->stack_index = stack_count++;
        }
 
-       assert((value_expr->vm_type == J_INT ||
-               value_expr->vm_type == J_LONG ||
-               value_expr->vm_type == J_REFERENCE));
-
-       reg = (6 - method->reg_args_count) + (*state)++ - method->args_count;
-       expr->arg_private = (void *) reg;
-
        return 0;
 }
 
-static enum machine_reg __args_select_reg(unsigned long arg_idx)
-{
-       switch (arg_idx) {
-       case 0:
-               return REG_UNASSIGNED;
-       case 6:
-               return REG_RDI;
-       case 5:
-               return REG_RSI;
-       case 4:
-               return REG_RDX;
-       case 3:
-               return REG_RCX;
-       case 2:
-               return REG_R8;
-       case 1:
-               return REG_R9;
-       default:
-               assert(arg_idx > 6);
-               return REG_UNASSIGNED;
-       }
-}
-
-enum machine_reg args_select_reg(struct expression *expr)
-{
-       return __args_select_reg((unsigned long) expr->arg_private);
-}
-
-enum machine_reg args_local_to_reg(struct vm_method *method, int local_idx)
-{
-       local_idx++;
-
-       /* Check if local_idx refers to *this or stack parameters. */
-       if (local_idx > method->reg_args_count)
-               return REG_UNASSIGNED;
-
-       return __args_select_reg(local_idx);
-}
-
-#else /* CONFIG_X86_64 */
-
 #endif /* CONFIG_X86_64 */
diff --git a/arch/x86/include/arch/args.h b/arch/x86/include/arch/args.h
dissimilarity index 83%
index 12b7efa..e3d3732 100644
--- a/arch/x86/include/arch/args.h
+++ b/arch/x86/include/arch/args.h
@@ -1,49 +1,14 @@
-#ifndef __X86_ARGS_H
-#define __X86_ARGS_H
-
-#include "arch/registers.h"
-
-#include "jit/expression.h"
-
-#include "vm/method.h"
-
-static inline void args_finish(unsigned long *state)
-{
-}
-
-#ifdef CONFIG_X86_64
-
-extern int args_init(unsigned long *state,
-                    struct vm_method *method,
-                    unsigned long nr_args);
-extern int args_set(unsigned long *state,
-                   struct vm_method *method,
-                   struct expression *expr);
-extern enum machine_reg args_select_reg(struct expression *expr);
-extern enum machine_reg args_local_to_reg(struct vm_method *method,
-                                         int local_idx);
-
-static inline int args_stack_index(struct vm_method *method, int local_idx)
-{
-       return local_idx - method->reg_args_count;
-}
-
-#else /* CONFIG_X86_64 */
-
-static inline int args_init(unsigned long *state,
-                           struct vm_method *method,
-                           unsigned long nr_args)
-{
-       return 0;
-}
-
-static inline int args_set(unsigned long *state,
-                          struct vm_method *method,
-                          struct expression *expr)
-{
-       return 0;
-}
-
-#endif /* CONFIG_X86_64 */
-
-#endif /* __X86_ARGS_H */
+#ifndef __X86_ARGS_H
+#define __X86_ARGS_H
+
+#include "arch/registers.h"
+
+#include "vm/method.h"
+
+#ifdef CONFIG_X86_64
+
+extern int args_map_init(struct vm_method *method);
+
+#endif /* CONFIG_X86_64 */
+
+#endif /* __X86_ARGS_H */
diff --git a/arch/x86/include/arch/config_64.h 
b/arch/x86/include/arch/config_64.h
index 80d752c..d15ae07 100644
--- a/arch/x86/include/arch/config_64.h
+++ b/arch/x86/include/arch/config_64.h
@@ -1,5 +1,5 @@
 #define CONFIG_X86_64 1
 #define CONFIG_64_BIT 1
 #define USE_FFI 1
-#define CONFIG_REGPARM 1
+#define CONFIG_ARGS_MAP 1
 
diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index 516306e..231bf57 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -7,6 +7,7 @@
  * LICENSE for details.
  */
 
+#include <jit/args.h>
 #include <jit/basic-block.h>
 #include <jit/compilation-unit.h>
 #include <jit/compiler.h>
@@ -233,16 +234,18 @@ reg:      EXPR_LOCAL      1
        struct expression *expr;
        struct stack_slot *slot;
        struct var_info *result;
+       struct vm_method *method;
        enum machine_reg reg;
        int index;
 
        expr = to_expr(tree);
-       slot = get_local_slot(cu->stack_frame, expr->local_index);
 
-       reg = args_local_to_reg(s->b_parent->method, expr->local_index + 1);
+       method = cu->method;
+
+       reg = method->args_map[expr->local_index].reg;
        if (reg == REG_UNASSIGNED) {
-               index = args_stack_index(cu->method, expr->local_index);
-               slot = get_local_slot(cu->stack_frame, index);
+               index = method->args_map[expr->local_index].stack_index;
+               slot = get_local_slot(s->b_parent->stack_frame, index);
                result = get_var(s->b_parent, J_LONG);
                select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG,
                                                       slot, result));
@@ -636,6 +639,7 @@ reg:        EXPR_INVOKEINTERFACE(arg) 1
        unsigned long method_offset;
        struct vm_method *method;
        struct expression *expr;
+       int nr_stack_args;
 
        expr    = to_expr(tree);
        method  = expr->target_method;
@@ -677,8 +681,9 @@ reg:        EXPR_INVOKEINTERFACE(arg) 1
        /* invoke method */
        select_insn(s, tree, reg_insn(INSN_CALL_REG, call_target));
 
-       if (method->args_count)
-               method_args_cleanup(s, tree, method->args_count);
+       nr_stack_args = get_stack_args_count(method);
+       if (nr_stack_args)
+               method_args_cleanup(s, tree, nr_stack_args);
 
        select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1));
        if (edx != NULL)
@@ -1283,7 +1288,6 @@ arg:      EXPR_ARG(EXPR_VALUE) 1
 arg:   EXPR_ARG(EXPR_VALUE) 1
 {
        struct expression *expr, *arg_expr;
-       enum machine_reg reg;
        struct var_info *dst;
        unsigned long imm;
 
@@ -1291,10 +1295,8 @@ arg:     EXPR_ARG(EXPR_VALUE) 1
        arg_expr = to_expr(expr->arg_expression);
        imm  = arg_expr->value;
 
-       reg = args_select_reg(expr);
-
-       if (reg != REG_UNASSIGNED) {
-               dst = get_fixed_var(s->b_parent, reg);
+       if (expr->arg_reg != REG_UNASSIGNED) {
+               dst = get_fixed_var(s->b_parent, expr->arg_reg);
                select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, imm, dst));
        } else
                select_insn(s, tree, imm_insn(INSN_PUSH_IMM, imm));
@@ -1337,17 +1339,14 @@ arg:    EXPR_ARG(reg) 1
 {
        struct var_info *src, *dst;
        struct expression *expr, *arg_expr;
-       enum machine_reg reg;
 
        expr = to_expr(tree);
        arg_expr = to_expr(expr->arg_expression);
 
        src = state->left->reg1;
 
-       reg = args_select_reg(expr);
-
-       if (reg != REG_UNASSIGNED) {
-               dst = get_fixed_var(s->b_parent, reg);
+       if (expr->arg_reg != REG_UNASSIGNED) {
+               dst = get_fixed_var(s->b_parent, expr->arg_reg);
                select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, src, dst));
                state->reg1 = dst;
        } else {
@@ -1573,6 +1572,7 @@ stmt:  STMT_STORE(EXPR_TEMPORARY, EXPR_LOCAL) 1
        struct stack_slot *slot;
        struct statement *stmt;
        struct var_info *src, *dest;
+       struct vm_method *method;
        enum machine_reg reg;
        int index;
 
@@ -1583,10 +1583,11 @@ stmt:  STMT_STORE(EXPR_TEMPORARY, EXPR_LOCAL) 1
 
        dest = exprdest->tmp_low;
 
-       reg = args_local_to_reg(s->b_parent->method, exprsrc->local_index);
+       method = s->b_parent->method;
+
+       reg = method->args_map[exprsrc->local_index].reg;
        if (reg == REG_UNASSIGNED) {
-               index = args_stack_index(s->b_parent->method,
-                                        exprsrc->local_index);
+               index = method->args_map[exprsrc->local_index].stack_index;
                slot = get_local_slot(s->b_parent->stack_frame, index);
                select_insn(s, tree, memlocal_reg_insn(INSN_MOV_MEMLOCAL_REG,
                                                       slot, dest));
@@ -2233,6 +2234,7 @@ static void invoke(struct basic_block *s, struct 
tree_node *tree, struct compila
        bool is_compiled;
        struct insn *call_insn;
        void *target;
+       int nr_stack_args;
 
        if (cu == s->b_parent) {
                /*
@@ -2272,8 +2274,9 @@ static void invoke(struct basic_block *s, struct 
tree_node *tree, struct compila
                trampoline_add_fixup_site(method->trampoline, fixup);
        }
 
-       if (method->args_count)
-               method_args_cleanup(s, tree, method->args_count);
+       nr_stack_args = get_stack_args_count(method);
+       if (nr_stack_args)
+               method_args_cleanup(s, tree, nr_stack_args);
 
        if (vm_method_is_jni(method))
                select_exception_test(s, tree);
@@ -2287,6 +2290,7 @@ static void invokevirtual(struct _MBState *state, struct 
basic_block *s, struct
        struct var_info *call_target;
        unsigned long method_offset;
        struct vm_method *method;
+       int nr_stack_args;
 
        expr    = to_expr(tree);
        method_offset = expr_method_index(expr) * sizeof(void *);
@@ -2315,8 +2319,9 @@ static void invokevirtual(struct _MBState *state, struct 
basic_block *s, struct
 
        method  = expr->target_method;
 
-       if (method->args_count)
-               method_args_cleanup(s, tree, method->args_count);
+       nr_stack_args = get_stack_args_count(method);
+       if (nr_stack_args)
+               method_args_cleanup(s, tree, nr_stack_args);
 }
 
 static void emit_code(struct basic_block *bb, MBState *state, int goal)
diff --git a/include/jit/args.h b/include/jit/args.h
index 7ec20b7..0047925 100644
--- a/include/jit/args.h
+++ b/include/jit/args.h
@@ -1,6 +1,8 @@
 #ifndef __ARGS_H
 #define __ARGS_H
 
+#include "arch/args.h"
+
 #include "jit/expression.h"
 
 #include "vm/method.h"
@@ -8,11 +10,25 @@
 
 struct expression *insert_arg(struct expression *root,
                              struct expression *expr,
-                             unsigned long *args_state,
-                             struct vm_method *method);
+                             struct vm_method *method,
+                             int index);
 struct expression *convert_args(struct stack *mimic_stack,
                                unsigned long nr_args,
                                struct vm_method *method);
 const char *parse_method_args(const char *type_str, enum vm_type *vmtype);
 
+#ifndef CONFIG_ARGS_MAP
+static inline int args_map_init(struct vm_method *method)
+{
+       return 0;
+}
+
+static inline int get_stack_args_count(struct vm_method *method)
+{
+       return method->args_count;
+}
+#else
+extern int get_stack_args_count(struct vm_method *method);
+#endif /* CONFIG_ARGS_MAP */
+
 #endif
diff --git a/include/jit/expression.h b/include/jit/expression.h
index e029b3d..be53649 100644
--- a/include/jit/expression.h
+++ b/include/jit/expression.h
@@ -203,7 +203,7 @@ struct expression {
                    instruction selection only.  */
                struct {
                        struct tree_node *arg_expression;
-                       void *arg_private;
+                       enum machine_reg arg_reg;
                };
 
                /*  EXPR_NO_ARGS is used for EXPR_INVOKE expression type when
diff --git a/include/vm/method.h b/include/vm/method.h
index c4ebff5..b246e64 100644
--- a/include/vm/method.h
+++ b/include/vm/method.h
@@ -19,6 +19,13 @@
 
 struct vm_class;
 
+#ifdef CONFIG_ARGS_MAP
+struct vm_args_map {
+       int                     reg;
+       int                     stack_index;
+};
+#endif
+
 struct vm_method {
        struct vm_class *class;
        unsigned int method_index;
@@ -29,8 +36,8 @@ struct vm_method {
        char *name;
        char *type;
        int args_count;
-#ifdef CONFIG_REGPARM
-       int reg_args_count;
+#ifdef CONFIG_ARGS_MAP
+       struct vm_args_map *args_map;
 #endif
 
        struct cafebabe_code_attribute code_attribute;
diff --git a/jit/args.c b/jit/args.c
index 3122e66..5c6ddaa 100644
--- a/jit/args.c
+++ b/jit/args.c
@@ -35,23 +35,43 @@
 #include "vm/stack.h"
 #include "vm/jni.h"
 
+#ifdef CONFIG_ARGS_MAP
+int get_stack_args_count(struct vm_method *method)
+{
+       int i, count = 0;
+
+       for (i = 0; i < method->args_count; i++)
+               if (method->args_map[i].reg == REG_UNASSIGNED)
+                       count++;
+
+       return count;
+}
+
+static inline void set_expr_arg_reg(struct expression *expr,
+                                   struct vm_method *method,
+                                   int index)
+{
+       expr->arg_reg = method->args_map[index].reg;
+}
+#else /* CONFIG_ARGS_MAP */
+static void set_expr_arg_reg(struct expression *expr,
+                            struct vm_method *method,
+                            int index)
+{
+}
+#endif /* CONFIG_ARGS_MAP */
+
 struct expression *
 insert_arg(struct expression *root,
           struct expression *expr,
-          unsigned long *args_state,
-          struct vm_method *method)
+          struct vm_method *method,
+          int index)
 {
        struct expression *_expr;
-       int err;
 
        _expr = arg_expr(expr);
        _expr->bytecode_offset = expr->bytecode_offset;
-
-       if (args_state && method) {
-               err = args_set(args_state, method, _expr);
-               if (err)
-                       return NULL;
-       }
+       set_expr_arg_reg(_expr, method, index);
 
        if (!root)
                return _expr;
@@ -64,18 +84,13 @@ struct expression *convert_args(struct stack *mimic_stack,
                                struct vm_method *method)
 {
        struct expression *args_list = NULL;
-       unsigned long args_state, i;
-       int err;
+       unsigned long i;
 
        if (nr_args == 0) {
                args_list = no_args_expr();
                goto out;
        }
 
-       err = args_init(&args_state, method, nr_args);
-       if (err)
-               return NULL;
-
        if (vm_method_is_jni(method)) {
                if (vm_method_is_static(method))
                        --nr_args;
@@ -83,9 +98,14 @@ struct expression *convert_args(struct stack *mimic_stack,
                --nr_args;
        }
 
+       /*
+        * We scan the args map in reverse order,
+        * since the order of arguments is already reversed.
+        */
        for (i = 0; i < nr_args; i++) {
                struct expression *expr = stack_pop(mimic_stack);
-               args_list = insert_arg(args_list, expr, &args_state, method);
+               args_list = insert_arg(args_list, expr,
+                                      method, nr_args - i - 1);
        }
 
        if (vm_method_is_jni(method)) {
@@ -102,8 +122,9 @@ struct expression *convert_args(struct stack *mimic_stack,
                                return NULL;
                        }
 
+                       /* FIXME: Set index correctly */
                        args_list = insert_arg(args_list, class_expr,
-                                              &args_state, method);
+                                              method, 0);
                }
 
                jni_env_expr = value_expr(J_REFERENCE,
@@ -113,12 +134,10 @@ struct expression *convert_args(struct stack *mimic_stack,
                        return NULL;
                }
 
-               args_list = insert_arg(args_list, jni_env_expr, &args_state,
-                                      method);
+               /* FIXME: Set index correctly */
+               args_list = insert_arg(args_list, jni_env_expr, method, 0);
        }
 
-       args_finish(&args_state);
-
   out:
        return args_list;
 }
diff --git a/vm/method.c b/vm/method.c
index 37bd54d..ffdc021 100644
--- a/vm/method.c
+++ b/vm/method.c
@@ -1,5 +1,6 @@
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "cafebabe/attribute_array.h"
 #include "cafebabe/attribute_info.h"
@@ -14,6 +15,7 @@
 #include "vm/method.h"
 #include "vm/natives.h"
 
+#include "jit/args.h"
 #include "jit/cu-mapping.h"
 
 int vm_method_init(struct vm_method *vmm,
@@ -66,10 +68,6 @@ int vm_method_init(struct vm_method *vmm,
                return -1;
        }
 
-#ifdef CONFIG_REGPARM
-       vmm->reg_args_count = 0;        /* Updated later. */
-#endif
-
        if (!vm_method_is_static(vmm))
                ++vmm->args_count;
 
@@ -87,6 +85,11 @@ int vm_method_init(struct vm_method *vmm,
                }
        }
 
+       if (args_map_init(vmm)) {
+               abort();
+               return -1;
+       }
+
        /*
         * Note: We can return here because the rest of the function deals
         * with loading attributes which native and abstract methods don't have.
-- 
1.6.0.6


------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to