This patch unifies the code pointer interface for all methods. The
->native_ptr field holds a pointer to the method's code. It's valid if
and only if ->is_compiled is set. For regular java methods
->native_ptr is set to buffer_ptr(cu->objcode) after compilation. For
native methods it holds a pointer to native function.

This also introduces vm_method_call_ptr() which returns either
trampoline pointer or native pointer depending on whether method is
compiled or not. This speeds up method calls done by VM because we can
call method's code directly when it's already compiled instead calling
trampoline first.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/insn-selector.brg     |   27 +++++++++------------------
 include/jit/compilation-unit.h |    9 +++++++++
 include/vm/method.h            |   26 +++++++++++++++++++++++---
 jit/compiler.c                 |    1 +
 jit/trampoline.c               |   16 +++++++++-------
 vm/call.c                      |    7 ++++---
 vm/class.c                     |    4 ++--
 vm/itable.c                    |    2 +-
 vm/method.c                    |   31 ++++++++++++++++++++-----------
 vm/object.c                    |    2 +-
 vm/stack-trace.c               |   24 ++++++++++++------------
 11 files changed, 91 insertions(+), 58 deletions(-)

diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index aa6f4ef..87bf8f9 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -2024,25 +2024,16 @@ static void invoke(struct basic_block *s, struct 
tree_node *tree, struct compila
        struct insn *call_insn;
        void *target;
 
-       if (pthread_mutex_trylock(&cu->mutex)) {
-               /*
-                * This is a recursive method invocation. Threfore, we are
-                * already holding cu->mutex here because we entered
-                * instruction selection through jit_magic_trampoline().
-                */
-               is_compiled = false;
+       /*
+        * We can't use vm_method_call_ptr() here because we
+        * later add fixup sites depending on whether target is
+        * trampoline or native.
+        */
+       is_compiled = cu->is_compiled;
+       if (is_compiled)
+               target = vm_method_native_ptr(method);
+       else
                target = vm_method_trampoline_ptr(method);
-       } else {
-               is_compiled = cu->is_compiled;
-
-               if (is_compiled)
-                       target = vm_method_native_ptr(method);
-               else
-                       target = vm_method_trampoline_ptr(method);
-
-               pthread_mutex_unlock(&cu->mutex);
-       }
-
 
        call_insn = rel_insn(INSN_CALL_REL, (unsigned long) target);
        select_insn(s, tree, call_insn);
diff --git a/include/jit/compilation-unit.h b/include/jit/compilation-unit.h
index 1066d4b..0ffc591 100644
--- a/include/jit/compilation-unit.h
+++ b/include/jit/compilation-unit.h
@@ -53,6 +53,15 @@ struct compilation_unit {
        unsigned char *unwind_past_unlock_ptr;
 
        struct list_head static_fixup_site_list;
+
+       /*
+        * This holds a pointer to the method's code. It's value is
+        * valid only when ->is_compiled is true.
+        * For non-native methods it's set to buffer_ptr(objcode). For
+        * native functions it points to the actuall native function's
+        * code (not trampoline).
+        */
+       void *native_ptr;
 };
 
 struct compilation_unit *compilation_unit_alloc(struct vm_method *);
diff --git a/include/vm/method.h b/include/vm/method.h
index c05c94c..4619cc8 100644
--- a/include/vm/method.h
+++ b/include/vm/method.h
@@ -39,7 +39,7 @@ struct vm_method {
        struct compilation_unit *compilation_unit;
        struct jit_trampoline *trampoline;
 
-       void *vm_native_ptr;
+       bool is_vm_native;
 };
 
 int vm_method_init(struct vm_method *vmm,
@@ -87,7 +87,13 @@ static inline bool method_is_virtual(struct vm_method *vmm)
 static inline bool vm_method_is_jni(struct vm_method *vmm)
 {
        return vmm->method->access_flags & CAFEBABE_METHOD_ACC_NATIVE
-               && !vmm->vm_native_ptr;
+               && !vmm->is_vm_native;
+}
+
+static inline bool vm_method_is_vm_native(struct vm_method *vmm)
+{
+       return vmm->method->access_flags & CAFEBABE_METHOD_ACC_NATIVE
+               && vmm->is_vm_native;
 }
 
 static inline enum vm_type method_return_type(struct vm_method *method)
@@ -100,7 +106,7 @@ int vm_method_prepare_jit(struct vm_method *vmm);
 
 static inline void *vm_method_native_ptr(struct vm_method *vmm)
 {
-       return buffer_ptr(vmm->compilation_unit->objcode);
+       return vmm->compilation_unit->native_ptr;
 }
 
 static inline void *vm_method_trampoline_ptr(struct vm_method *vmm)
@@ -108,4 +114,18 @@ static inline void *vm_method_trampoline_ptr(struct 
vm_method *vmm)
        return buffer_ptr(vmm->trampoline->objcode);
 }
 
+static inline void *vm_method_call_ptr(struct vm_method *vmm)
+{
+       /*
+        * We don't need to lock on compilation unit here because
+        * ->is_compiled can only change its value from false to true
+        * and before it is set to true the value of ->native_ptr is set
+        * and is constant after that.
+        */
+       if (vmm->compilation_unit->is_compiled)
+               return vm_method_native_ptr(vmm);
+
+       return vm_method_trampoline_ptr(vmm);
+}
+
 #endif
diff --git a/jit/compiler.c b/jit/compiler.c
index b1c3142..cb477cc 100644
--- a/jit/compiler.c
+++ b/jit/compiler.c
@@ -115,6 +115,7 @@ int compile(struct compilation_unit *cu)
        if (opt_trace_machine_code)
                trace_machine_code(cu);
 
+       cu->native_ptr = buffer_ptr(cu->objcode);
        cu->is_compiled = true;
 
        perf_append_cu(cu);
diff --git a/jit/trampoline.c b/jit/trampoline.c
index 40f3211..794b431 100644
--- a/jit/trampoline.c
+++ b/jit/trampoline.c
@@ -50,9 +50,6 @@ static void *jit_native_trampoline(struct compilation_unit 
*cu)
 
        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;
@@ -60,6 +57,10 @@ static void *jit_native_trampoline(struct compilation_unit 
*cu)
        ret = vm_jni_lookup_method(class_name, method_name, method_type);
        if (ret) {
                add_cu_mapping((unsigned long)ret, cu);
+
+               cu->native_ptr = ret;
+               cu->is_compiled = true;
+
                return ret;
        }
 
@@ -82,9 +83,6 @@ static void *jit_native_trampoline(struct compilation_unit 
*cu)
 
 static void *jit_java_trampoline(struct compilation_unit *cu)
 {
-       if (cu->is_compiled)
-               return buffer_ptr(cu->objcode);
-
        if (compile(cu)) {
                assert(exception_occurred() != NULL);
 
@@ -114,7 +112,11 @@ void *jit_magic_trampoline(struct compilation_unit *cu)
 
        pthread_mutex_lock(&cu->mutex);
 
-       if (vm_method_is_native(cu->method))
+       if (cu->is_compiled)
+               /* XXX: even if method is compiled we steel might need
+                * to fixup some call sites. */
+               ret = cu->native_ptr;
+       else if (vm_method_is_native(cu->method))
                ret = jit_native_trampoline(cu);
        else
                ret = jit_java_trampoline(cu);
diff --git a/vm/call.c b/vm/call.c
index cbd5177..cd8d7e6 100644
--- a/vm/call.c
+++ b/vm/call.c
@@ -35,15 +35,16 @@
 #include "vm/jni.h"
 #include "vm/method.h"
 #include "vm/object.h"
+#include "vm/stack-trace.h"
 
 static unsigned long
 vm_call_method_a(struct vm_method *method, unsigned long *args)
 {
        unsigned long result;
-       void *trampoline;
+       void *target;
 
-       trampoline = vm_method_trampoline_ptr(method);
-       native_call(trampoline, args, method->args_count, result);
+       target = vm_method_call_ptr(method);
+       native_call(target, args, method->args_count, result);
 
        return result;
 }
diff --git a/vm/class.c b/vm/class.c
index ee22da8..915e5e0 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -110,7 +110,7 @@ setup_vtable(struct vm_class *vmc)
 
                                vtable_setup_method(&vmc->vtable,
                                        vmm2->virtual_index,
-                                       vm_method_trampoline_ptr(vmm));
+                                       vm_method_call_ptr(vmm));
                                continue;
                        }
                }
@@ -119,7 +119,7 @@ setup_vtable(struct vm_class *vmc)
 
                vtable_setup_method(&vmc->vtable,
                        super_vtable_size + vtable_size,
-                       vm_method_trampoline_ptr(vmm));
+                       vm_method_call_ptr(vmm));
                ++vtable_size;
        }
 }
diff --git a/vm/itable.c b/vm/itable.c
index dcfc08d..c962211 100644
--- a/vm/itable.c
+++ b/vm/itable.c
@@ -144,7 +144,7 @@ static void *itable_create_conflict_resolver(struct 
vm_class *vmc,
                struct itable_entry *entry = list_first_entry(methods,
                        struct itable_entry, node);
 
-               return vm_method_trampoline_ptr(entry->c_method);
+               return vm_method_call_ptr(entry->c_method);
        }
 
        unsigned int nr_entries = 0;
diff --git a/vm/method.c b/vm/method.c
index 1c4befa..eb618f2 100644
--- a/vm/method.c
+++ b/vm/method.c
@@ -73,10 +73,10 @@ int vm_method_init(struct vm_method *vmm,
        if (!vm_method_is_static(vmm))
                ++vmm->args_count;
 
-       vmm->vm_native_ptr = NULL;
+       vmm->is_vm_native = false;
 
        if (vm_method_is_native(vmm)) {
-               vmm->vm_native_ptr =
+               vmm->is_vm_native =
                        vm_lookup_native(vmm->class->name, vmm->name);
 
                if (vm_method_is_jni(vmm)) {
@@ -144,21 +144,30 @@ int vm_method_init(struct vm_method *vmm,
 
 int vm_method_prepare_jit(struct vm_method *vmm)
 {
-       vmm->compilation_unit = compilation_unit_alloc(vmm);
-       if (!vmm->compilation_unit) {
+       struct compilation_unit *cu;
+
+       cu = compilation_unit_alloc(vmm);
+       if (!cu) {
                NOT_IMPLEMENTED;
                return -1;
        }
 
-       if (vmm->vm_native_ptr &&
-           add_cu_mapping((unsigned long)vmm->vm_native_ptr,
-                          vmm->compilation_unit))
-       {
-               NOT_IMPLEMENTED;
-               return -1;
+       vmm->compilation_unit = cu;
+
+       /*
+        * VM native methods are linked on initialization.
+        */
+       if (vm_method_is_vm_native(vmm)) {
+               cu->native_ptr = vm_lookup_native(vmm->class->name, vmm->name);
+               cu->is_compiled = true;
+
+               if (add_cu_mapping((unsigned long)cu->native_ptr, cu)) {
+                       NOT_IMPLEMENTED;
+                       return -1;
+               }
        }
 
-       vmm->trampoline = build_jit_trampoline(vmm->compilation_unit);
+       vmm->trampoline = build_jit_trampoline(cu);
        if (!vmm->trampoline) {
                NOT_IMPLEMENTED;
                return -1;
diff --git a/vm/object.c b/vm/object.c
index 0827bb9..fa90147 100644
--- a/vm/object.c
+++ b/vm/object.c
@@ -357,7 +357,7 @@ struct vm_object *new_exception(struct vm_class *vmc, const 
char *message)
        if (!mb)
                error("constructor not found");
 
-       init = vm_method_trampoline_ptr(mb);
+       init = vm_method_call_ptr(mb);
        init(obj, message_str);
 
        if (exception_occurred())
diff --git a/vm/stack-trace.c b/vm/stack-trace.c
index cabbfae..1ef45d5 100644
--- a/vm/stack-trace.c
+++ b/vm/stack-trace.c
@@ -72,10 +72,10 @@ void init_stack_trace_printing(void)
                vm_class_get_method_recursive(vm_java_lang_Throwable,
                        "stackTraceString", "()Ljava/lang/String;");
 
-       ste_init = vm_method_trampoline_ptr(ste_init_mb);
-       throwable_tostring = vm_method_trampoline_ptr(throwable_tostring_mb);
+       ste_init = vm_method_call_ptr(ste_init_mb);
+       throwable_tostring = vm_method_call_ptr(throwable_tostring_mb);
        throwable_stacktracestring =
-               vm_method_trampoline_ptr(throwable_stacktracestring_mb);
+               vm_method_call_ptr(throwable_stacktracestring_mb);
 
        if (!ste_init_mb ||
            !throwable_tostring ||
@@ -405,7 +405,7 @@ static void
 vm_throwable_to_string(struct vm_object *this, struct string *str)
 {
        vm_java_lang_Throwable_toString_fn toString =
-               vm_method_trampoline_ptr(vm_java_lang_Throwable_toString);
+               vm_method_call_ptr(vm_java_lang_Throwable_toString);
        struct vm_object *string_obj;
 
        string_obj = toString(this);
@@ -434,15 +434,15 @@ static void vm_stack_trace_element_to_string(struct 
vm_object *elem,
        int line_number;
        bool is_native;
 
-       getMethodName = vm_method_trampoline_ptr(
+       getMethodName = vm_method_call_ptr(
                vm_java_lang_StackTraceElement_getMethodName);
-       getFileName = vm_method_trampoline_ptr(
+       getFileName = vm_method_call_ptr(
                vm_java_lang_StackTraceElement_getFileName);
-       getClassName = vm_method_trampoline_ptr(
+       getClassName = vm_method_call_ptr(
                vm_java_lang_StackTraceElement_getClassName);
-       getLineNumber = vm_method_trampoline_ptr(
+       getLineNumber = vm_method_call_ptr(
                vm_java_lang_StackTraceElement_getLineNumber);
-       isNativeMethod = vm_method_trampoline_ptr(
+       isNativeMethod = vm_method_call_ptr(
                vm_java_lang_StackTraceElement_isNativeMethod);
 
        file_name = getFileName(elem);
@@ -520,11 +520,11 @@ vm_throwable_print_stack_trace(struct vm_object *this, 
struct string *str)
        struct vm_object *stack;
 
        getCause =
-               vm_method_trampoline_ptr(vm_java_lang_Throwable_getCause);
+               vm_method_call_ptr(vm_java_lang_Throwable_getCause);
        getStackTrace =
-               vm_method_trampoline_ptr(vm_java_lang_Throwable_getStackTrace);
+               vm_method_call_ptr(vm_java_lang_Throwable_getStackTrace);
        ste_equals =
-               vm_method_trampoline_ptr(vm_java_lang_StackTraceElement_equals);
+               vm_method_call_ptr(vm_java_lang_StackTraceElement_equals);
 
        stack = getStackTrace(this);
        vm_throwable_stack_trace(this, str, stack, 0);
-- 
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