Installing signal bottom half doesn't work well in valgrind
environment (it causes an error and application is killed). This
introduces a workaround for this situation when caused by exception
guards. Exception guards are used to catch signalled exceptions via
SIGSEGV handler and transfer control to the exception handler or
unwind. The workaround is to inline exception check and don't use
signal handlers when run on valgrind.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/insn-selector.brg |    9 +++++++--
 arch/x86/unwind_32.S       |   27 +++++++++++++++++++++++++++
 include/jit/exception.h    |    5 ++++-
 jit/exception.c            |   10 ++++++++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index 5383368..c2d06c3 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -2778,6 +2778,11 @@ static void select_exception_test(struct basic_block *bb,
        unsigned long exception_guard_offset;
        struct var_info *reg;
 
+       if (running_on_valgrind) {
+               select_insn(bb, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
exception_check));
+               return;
+       }
+
        reg = get_var(bb->b_parent, GPR_VM_TYPE);
 
        exception_guard_offset = get_thread_local_offset(&exception_guard);
@@ -2970,11 +2975,11 @@ emulate_op_64(struct _MBState *state, struct 
basic_block *s,
        else
                method_args_cleanup(s, tree, 3);
 
-       select_exception_test(s, tree);
-
        select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1));
        if (edx)
                select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx, 
state->reg2));
+
+       select_exception_test(s, tree);
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/unwind_32.S b/arch/x86/unwind_32.S
index 6b78563..e35ae46 100644
--- a/arch/x86/unwind_32.S
+++ b/arch/x86/unwind_32.S
@@ -1,4 +1,5 @@
 .global unwind
+.global exception_check
 .text
 
 /*
@@ -39,3 +40,29 @@ unwind:
 
        pushl %eax
        ret
+
+/*
+ * exception_check - is a part of valgrind workaround for exception guards.
+ * it checks whether exception has occurred and if it has control
+ * is transfered directly to exception handler (possibly unwind block).
+ */
+exception_check:
+       /* push return address - 1 */
+       pushl   (%esp)
+       decl    (%esp)
+
+       pushl   %ebp
+
+       pushl   4(%esp) # return address
+       call    jit_lookup_cu
+       add     $4, %esp
+       push    %eax
+
+       call throw_from_jit_checked
+       addl $12, %esp
+       test %eax, %eax
+       jz 1f
+       pushl %eax
+       ret
+1:
+       ret
\ No newline at end of file
diff --git a/include/jit/exception.h b/include/jit/exception.h
index aeb6843..cadb6a1 100644
--- a/include/jit/exception.h
+++ b/include/jit/exception.h
@@ -50,12 +50,15 @@ lookup_eh_entry(struct vm_method *method, unsigned long 
target);
 unsigned char *throw_from_jit(struct compilation_unit *cu,
                              struct jit_stack_frame *frame,
                              unsigned char *native_ptr);
-
+unsigned char *throw_from_jit_checked(struct compilation_unit *cu,
+                                     struct jit_stack_frame *frame,
+                                     unsigned char *native_ptr);
 int insert_exception_spill_insns(struct compilation_unit *cu);
 unsigned char *throw_exception(struct compilation_unit *cu,
                               struct vm_object *exception);
 void throw_from_trampoline(void *ctx, struct vm_object *exception);
 void unwind(void);
+void exception_check(void);
 void signal_exception(struct vm_object *obj);
 void signal_new_exception(struct vm_class *vmc, const char *msg);
 void signal_new_exception_with_cause(struct vm_class *vmc,
diff --git a/jit/exception.c b/jit/exception.c
index 0171ca8..b412e25 100644
--- a/jit/exception.c
+++ b/jit/exception.c
@@ -362,3 +362,13 @@ print_exception_table(const struct vm_method *method,
                trace_printf("Class %s\n", catch_class->name);
        }
 }
+
+unsigned char *
+throw_from_jit_checked(struct compilation_unit *cu, struct jit_stack_frame 
*frame,
+                      unsigned char *native_ptr)
+{
+       if (exception_occurred())
+               return throw_from_jit(cu, frame, native_ptr);
+
+       return NULL;
+}
-- 
1.6.0.4


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to