When method is prepared in vm_method_prepare_jit() it is checked
whether native method is one of VM native methods and the address of
it is stored in the ->vm_native_ptr field. This field is used
to perform a quick check for a JNI method in vm_method_is_jni_method()
and to omit vm_native_lookup() in jit_native_trampoline().

When converting method invocation it is checked whether method is
a JNI native method. If this is the case then JNI environment
pointer is appended to call arguments. When static JNI method
is called the class->object pointer is also appended according
to the JNI specification.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/emit-code.c   |   23 -----------------------
 include/jit/compiler.h |    8 --------
 include/vm/method.h    |    9 ++++++++-
 jit/emit.c             |   27 ---------------------------
 jit/invoke-bc.c        |   39 +++++++++++++++++++++++++++++++++++++++
 jit/trace-jit.c        |    3 +++
 jit/trampoline.c       |   30 ++++++------------------------
 vm/method.c            |   21 ++++++++++++++++++++-
 8 files changed, 76 insertions(+), 84 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index 6020bac..0ed73d4 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -21,7 +21,6 @@
 #include "lib/list.h"
 #include "lib/buffer.h"
 
-#include "vm/jni.h"
 #include "vm/method.h"
 #include "vm/object.h"
 
@@ -1388,28 +1387,6 @@ void emit_trampoline(struct compilation_unit *cu,
        jit_text_unlock();
 }
 
-void emit_jni_trampoline(struct buffer *buf, struct vm_jni_env *jni_env,
-                        void *target)
-{
-       jit_text_lock();
-
-       buf->buf = jit_text_ptr();
-
-       /* save return address into caller-saved register */
-       __emit_pop_reg(buf, REG_ESI);
-
-       __emit_push_imm(buf, (unsigned long) jni_env);
-       __emit_call(buf, target);
-       __emit_add_imm_reg(buf, 4, REG_ESP);
-
-       /* return to caller*/
-       __emit_push_reg(buf, REG_ESI);
-       emit_ret(buf);
-
-       jit_text_reserve(buffer_offset(buf));
-       jit_text_unlock();
-}
-
 /* Note: a < b, always */
 static void emit_itable_bsearch(struct buffer *buf,
        struct itable_entry **table, unsigned int a, unsigned int b)
diff --git a/include/jit/compiler.h b/include/jit/compiler.h
index 8584954..11df1be 100644
--- a/include/jit/compiler.h
+++ b/include/jit/compiler.h
@@ -31,10 +31,6 @@ struct jit_trampoline {
        pthread_mutex_t mutex;
 };
 
-struct jni_trampoline {
-       struct buffer *objcode;
-};
-
 struct parse_context {
        struct compilation_unit *cu;
        struct basic_block *bb;
@@ -60,12 +56,8 @@ int emit_machine_code(struct compilation_unit *);
 void *jit_magic_trampoline(struct compilation_unit *);
 
 struct jit_trampoline *alloc_jit_trampoline(void);
-struct jni_trampoline *alloc_jni_trampoline(void);
 struct jit_trampoline *build_jit_trampoline(struct compilation_unit *);
-struct jni_trampoline *build_jni_trampoline(void *);
 void free_jit_trampoline(struct jit_trampoline *);
-void free_jni_trampoline(struct jni_trampoline *);
-
 struct fixup_site *alloc_fixup_site(void);
 void free_fixup_site(struct fixup_site *);
 void trampoline_add_fixup_site(struct jit_trampoline *, struct fixup_site *);
diff --git a/include/vm/method.h b/include/vm/method.h
index fd19c16..e86df11 100644
--- a/include/vm/method.h
+++ b/include/vm/method.h
@@ -35,7 +35,8 @@ struct vm_method {
 
        struct compilation_unit *compilation_unit;
        struct jit_trampoline *trampoline;
-       struct jni_trampoline *jni_trampoline;
+
+       void *vm_native_ptr;
 };
 
 int vm_method_init(struct vm_method *vmm,
@@ -80,6 +81,12 @@ static inline bool method_is_virtual(struct vm_method *vmm)
                | CAFEBABE_METHOD_ACC_PRIVATE)) == 0;
 }
 
+static inline bool vm_method_is_jni_method(struct vm_method *vmm)
+{
+       return vmm->method->access_flags & CAFEBABE_METHOD_ACC_NATIVE
+               && !vmm->vm_native_ptr;
+}
+
 static inline enum vm_type method_return_type(struct vm_method *method)
 {
        char *return_type = method->type + (strlen(method->type) - 1);
diff --git a/jit/emit.c b/jit/emit.c
index ec79c3e..9d5c46a 100644
--- a/jit/emit.c
+++ b/jit/emit.c
@@ -205,35 +205,8 @@ struct jit_trampoline *alloc_jit_trampoline(void)
        return NULL;
 }
 
-struct jni_trampoline *alloc_jni_trampoline(void)
-{
-       struct jni_trampoline *trampoline;
-
-       trampoline = malloc(sizeof(*trampoline));
-       if (!trampoline)
-               return NULL;
-
-       memset(trampoline, 0, sizeof(*trampoline));
-
-       trampoline->objcode = __alloc_buffer(&exec_buf_ops);
-       if (!trampoline->objcode)
-               goto failed;
-
-       return trampoline;
-
-  failed:
-       free_jni_trampoline(trampoline);
-       return NULL;
-}
-
 void free_jit_trampoline(struct jit_trampoline *trampoline)
 {
        free_buffer(trampoline->objcode);
        free(trampoline);
 }
-
-void free_jni_trampoline(struct jni_trampoline *trampoline)
-{
-       free_buffer(trampoline->objcode);
-       free(trampoline);
-}
diff --git a/jit/invoke-bc.c b/jit/invoke-bc.c
index e5e0ff4..3a4b2da 100644
--- a/jit/invoke-bc.c
+++ b/jit/invoke-bc.c
@@ -19,6 +19,7 @@
 #include "vm/method.h"
 #include "vm/stack.h"
 #include "vm/die.h"
+#include "vm/jni.h"
 
 #include <string.h>
 #include <errno.h>
@@ -204,6 +205,14 @@ int convert_invokevirtual(struct parse_context *ctx)
        return err;
 }
 
+static void append_arg(struct expression *expr, struct expression *arg)
+{
+       struct expression *args_list;
+
+       args_list = insert_arg(to_expr(expr->args_list), arg);
+       expr->args_list = &args_list->node;
+}
+
 int convert_invokespecial(struct parse_context *ctx)
 {
        struct vm_method *invoke_target;
@@ -228,6 +237,17 @@ int convert_invokespecial(struct parse_context *ctx)
 
        null_check_first_arg(to_expr(expr->args_list));
 
+       if (vm_method_is_jni_method(invoke_target)) {
+               struct expression *jni_env_expr;
+
+               jni_env_expr = value_expr(J_REFERENCE,
+                       (unsigned long)vm_jni_get_jni_env());
+               if (!jni_env_expr)
+                       goto failed;
+
+               append_arg(expr, jni_env_expr);
+       }
+
        err = insert_invoke_expr(ctx, expr);
        if (err)
                goto failed;
@@ -260,6 +280,25 @@ int convert_invokestatic(struct parse_context *ctx)
        if (err)
                goto failed;
 
+       if (vm_method_is_jni_method(invoke_target)) {
+               struct expression *jni_env_expr;
+               struct expression *class_expr;
+
+               class_expr = value_expr(J_REFERENCE,
+                       (unsigned long)invoke_target->class->object);
+               if (!class_expr)
+                       goto failed;
+
+               append_arg(expr, class_expr);
+
+               jni_env_expr = value_expr(J_REFERENCE,
+                       (unsigned long)vm_jni_get_jni_env());
+               if (!jni_env_expr)
+                       goto failed;
+
+               append_arg(expr, jni_env_expr);
+       }
+
        err = insert_invoke_expr(ctx, expr);
        if (err)
                goto failed;
diff --git a/jit/trace-jit.c b/jit/trace-jit.c
index 7f41006..a7b4d3a 100644
--- a/jit/trace-jit.c
+++ b/jit/trace-jit.c
@@ -324,6 +324,9 @@ static void trace_invoke_args(struct vm_method *vmm,
        const char *type_str;
        int arg_index;
 
+       if (vm_method_is_jni_method(vmm))
+               arg_index += 2;
+
        arg_index = 0;
 
        if (!vm_method_is_static(vmm)) {
diff --git a/jit/trampoline.c b/jit/trampoline.c
index 0de2db5..dd9658a 100644
--- a/jit/trampoline.c
+++ b/jit/trampoline.c
@@ -46,31 +46,24 @@ static void *jit_native_trampoline(struct compilation_unit 
*cu)
 {
        const char *method_name, *class_name, *method_type;
        struct vm_method *method;
-       struct string *msg;
        void *ret;
 
        method = cu->method;
+
+       if (method->vm_native_ptr)
+               return method->vm_native_ptr;
+
        class_name  = method->class->name;
        method_name = method->name;
        method_type = method->type;
 
-       ret = vm_lookup_native(class_name, method_name);
-       if (ret) {
-               add_cu_mapping((unsigned long)ret, cu);
-               return ret;
-       }
-
        ret = vm_jni_lookup_method(class_name, method_name, method_type);
        if (ret) {
                add_cu_mapping((unsigned long)ret, cu);
-
-               if (!method->jni_trampoline)
-                       method->jni_trampoline = build_jni_trampoline(ret);
-
-               return buffer_ptr(method->jni_trampoline->objcode);
+               return ret;
        }
 
-       msg = alloc_str();
+       struct string *msg = alloc_str();
        if (!msg)
                /* TODO: signal OutOfMemoryError */
                die("out of memory");
@@ -150,14 +143,3 @@ struct jit_trampoline *build_jit_trampoline(struct 
compilation_unit *cu)
                emit_trampoline(cu, jit_magic_trampoline, trampoline);
        return trampoline;
 }
-
-struct jni_trampoline *build_jni_trampoline(void *target)
-{
-       struct jni_trampoline *trampoline;
-
-       trampoline = alloc_jni_trampoline();
-       if (trampoline)
-               emit_jni_trampoline(trampoline->objcode, vm_jni_get_jni_env(),
-                                   target);
-       return trampoline;
-}
diff --git a/vm/method.c b/vm/method.c
index c4a7eb2..5a8b688 100644
--- a/vm/method.c
+++ b/vm/method.c
@@ -12,6 +12,9 @@
 
 #include "vm/class.h"
 #include "vm/method.h"
+#include "vm/natives.h"
+
+#include "jit/cu-mapping.h"
 
 int vm_method_init(struct vm_method *vmm,
        struct vm_class *vmc, unsigned int method_index)
@@ -129,8 +132,24 @@ int vm_method_prepare_jit(struct vm_method *vmm)
                return -1;
        }
 
-       vmm->jni_trampoline = NULL;
+       if (!vm_method_is_native(vmm))
+               goto link_later;
+
+       vmm->vm_native_ptr = NULL;
+
+       void *native_ptr = vm_lookup_native(vmm->class->name, vmm->name);
+       if (native_ptr) {
+               vmm->vm_native_ptr = native_ptr;
+
+               if (add_cu_mapping((unsigned long)native_ptr,
+                                  vmm->compilation_unit))
+               {
+                       NOT_IMPLEMENTED;
+                       return -1;
+               }
+       }
 
+link_later:
        vmm->trampoline = build_jit_trampoline(vmm->compilation_unit);
        if (!vmm->trampoline) {
                NOT_IMPLEMENTED;
-- 
1.6.0.6


------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to