It is possible that we're fixing calls to method X() and another
thread is compiling method Y() which calls X(). Call sites from Y
might be added to X's trampoline but Y's ->objcode might not be set
yet. We should skip fixing call sites coming from not yet compiled
methods.

This causes the folowing crash to occurre:
[thread: Thread-1] SIGSEGV at EIP 0805eaa7 while accessing memory address 
00000000.
Registers:
 eax: 00000000   ebx: 08308a74   ecx: 08ba2b98   edx: a6210c10
 esi: a6210c88   edi: a6212be0   ebp: a7b312f0   esp: a7b312c4
Native and JAVA stack trace:
 [<0805eaa7>] native     : fixup_site_addr+f (jato/jit/fixup-site.c:59)
 [<08062d4e>] native     : jit_magic_trampoline+1b6 
(jato/jato/jit/trampoline.c:143)
 [<a7bd3bcc>] trampoline : java/lang/System.currentTimeMillis(System.java:222)
 [<a7be96ad>] jit        : java/lang/VMThread.sleep(VMThread.java:393)
 [<a7be9471>] jit        : java/lang/Thread.sleep(Thread.java:896)
 [<a7be926b>] jit        : java/lang/Thread.sleep(Thread.java:861)
 [<a7be9209>] jit        : Test.run(Test.java:11)
 [<a7be8f05>] jit        : java/lang/VMThread.run(VMThread.java:120)
 [<0806db07>] native     : vm_call_method_a+147 (jato/jato/vm/call.c:76)
 [<0806dbd4>] native     : vm_call_method_v+57 (jato/jato/vm/call.c:114)
 [<0806c956>] native     : vm_call_method+e792 (jato/jato/include/vm/call.h:33)
 [<0806c986>] native     : vm_thread_entry+2a (jato/jato/vm/thread.c:207)
 [<b7ed018a>] native     : <unknown>
 [<b7d2486d>] native     : <unknown>

For the following test case. Method which is being compiled is
java/lang/VMThread.sleep() and method to which calls are being fixed
up (in another thread) is java/lang/System.currentTimeMillis():

public class Test extends Thread {
    public static Object syn;

    static class A {
        public static int x = 0;
    };

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }

        A.x++;
    }

    public static void main(String[] args) {
        Thread t[] = new Thread[20];

        syn = new Object();

        for (int i = 0; i < t.length; i++) {
            t[i] = new Test();
        }

        for (int i = 0; i < t.length; i++) {
            t[i].start();
        }

        for (int i = 0; i < t.length; i++) {
            try {
                t[i].join();
            } catch (Exception e) {}
        }
    }
}

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/emit-code.c |   16 ++++++++++++++++
 jit/trampoline.c     |   18 +++++++++++-------
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index 1e57d8a..57de052 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -392,6 +392,22 @@ void fixup_direct_calls(struct jit_trampoline *t, unsigned 
long target)
                                 fixup_list_node) {
                unsigned char *site_addr;
                uint32_t new_target;
+               bool is_compiled;
+
+               /*
+                * XXX: it is possible that we're fixing calls to
+                * method X() and another thread is compiling method
+                * Y() which calls X(). Call sites from Y might be
+                * added to X's trampoline but Y's ->objcode might not
+                * be set yet. We should skip fixing callsites coming
+                * from not yet compiled methods.  .
+                */
+               pthread_mutex_lock(&this->cu->mutex);
+               is_compiled = this->cu->is_compiled;
+               pthread_mutex_unlock(&this->cu->mutex);
+
+               if (!is_compiled)
+                       continue;
 
                site_addr = fixup_site_addr(this);
                new_target = target - ((unsigned long) site_addr + 
CALL_INSN_SIZE);
diff --git a/jit/trampoline.c b/jit/trampoline.c
index 122b58a..fef9dd1 100644
--- a/jit/trampoline.c
+++ b/jit/trampoline.c
@@ -139,15 +139,19 @@ void *jit_magic_trampoline(struct compilation_unit *cu)
         * Therefore, do fixup for direct call sites unconditionally and fixup
         * vtables if method can be invoked via invokevirtual.
         */
-       if (ret)
-               fixup_direct_calls(method->trampoline, (unsigned long) ret);
-
        pthread_mutex_unlock(&cu->mutex);
 
-       /* XXX: this must be done with cu->mutex unlocked because fixup_static()
-        * might need to lock it. */
-       if (ret && vm_method_is_static(cu->method))
-               fixup_static(cu->method->class);
+       /*
+        * XXX: this must be done with cu->mutex unlocked because both
+        * fixup_static() and fixup_direct_calls() might need to lock
+        * on this compilation unit.
+        */
+       if (ret) {
+               fixup_direct_calls(method->trampoline, (unsigned long) ret);
+
+               if (vm_method_is_static(cu->method))
+                       fixup_static(cu->method->class);
+       }
 
        return ret;
 }
-- 
1.6.0.6


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to