After every jato function call which may signal exception there should
be exception test to check for it.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/Makefile_32           |    1 +
 arch/x86/include/arch/thread.h |    6 ++++
 arch/x86/insn-selector_32.brg  |   36 ++++++++++++++++++++++++++++
 arch/x86/thread.c              |   51 ++++++++++++++++++++++++++++++++++++++++
 test/arch-x86/Makefile         |    1 +
 5 files changed, 95 insertions(+), 0 deletions(-)
 create mode 100644 arch/x86/include/arch/thread.h
 create mode 100644 arch/x86/thread.c

diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32
index 9defb97..78be589 100644
--- a/arch/x86/Makefile_32
+++ b/arch/x86/Makefile_32
@@ -11,6 +11,7 @@ ARCH_OBJS = \
        arch/x86/stack-frame.o          \
        arch/x86/unwind_32.o            \
        arch/x86/use-def.o              \
+       arch/x86/thread.o               \
        jamvm/os/$(OS)/i386/dll_md.o    \
        jamvm/os/$(OS)/i386/init.o      \
        jamvm/os/$(OS)/os.o
diff --git a/arch/x86/include/arch/thread.h b/arch/x86/include/arch/thread.h
new file mode 100644
index 0000000..723d4e1
--- /dev/null
+++ b/arch/x86/include/arch/thread.h
@@ -0,0 +1,6 @@
+#ifndef ARCH_THREAD_H
+#define ARCH_THREAD_H
+
+unsigned long get_thread_local_offset(void *thread_local_ptr);
+
+#endif /* ARCH_THREAD_H */
diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 78d3013..5cbb562 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -18,6 +18,7 @@
 
 #include <arch/instruction.h>
 #include <arch/stack-frame.h>
+#include <arch/thread.h>
 
 #include <assert.h>
 #include <errno.h>
@@ -44,6 +45,8 @@
 
 static void select_insn(struct basic_block *bb, struct tree_node *tree,
                        struct insn *instruction);
+static void select_exception_test(struct basic_block *bb,
+                                 struct tree_node *tree);
 
 static unsigned char type_to_scale(enum vm_type vm_type)
 {
@@ -570,6 +573,7 @@ reg:        OP_CMP(reg, EXPR_VALUE) 1
 
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
emulate_lcmp));
        method_args_cleanup(s, tree, 4);
+       select_exception_test(s, tree);
 
        select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1));
 }
@@ -722,6 +726,7 @@ reg:        EXPR_NEW
        select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) 
expr->class));
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
allocObject));
        method_args_cleanup(s, tree, 1);
+       select_exception_test(s, tree);
 }
 
 reg:   EXPR_NEWARRAY(reg)
@@ -741,6 +746,7 @@ reg:        EXPR_NEWARRAY(reg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
allocTypeArray));
 
        method_args_cleanup(s, tree, 2);
+       select_exception_test(s, tree);
 }
 
 reg:   EXPR_NULL_CHECK(reg)
@@ -794,6 +800,7 @@ reg:        EXPR_MULTIANEWARRAY(arg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
allocMultiArray));
 
        method_args_cleanup(s, tree, dimension + 3);
+       select_exception_test(s, tree);
 }
 
 reg:    EXPR_ANEWARRAY(reg)
@@ -814,6 +821,7 @@ reg:    EXPR_ANEWARRAY(reg)
         select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
allocArray));
 
         method_args_cleanup(s, tree, 3);
+       select_exception_test(s, tree);
 }
 
 reg:    EXPR_ARRAYLENGTH(reg)
@@ -845,6 +853,7 @@ reg:        EXPR_INSTANCEOF(reg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
is_object_instance_of));
 
        method_args_cleanup(s, tree, 2);
+       select_exception_test(s, tree);
 }
 
 reg:   EXPR_CONVERSION(reg)
@@ -1175,6 +1184,7 @@ stmt:     STMT_ARRAY_CHECK(array_check)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
check_array));
 
        method_args_cleanup(s, tree, 2);
+       select_exception_test(s, tree);
 }
 
 stmt:  STMT_IF(reg)
@@ -1208,6 +1218,7 @@ stmt:     STMT_MONITOR_ENTER(reg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
objectLock));
 
        method_args_cleanup(s, tree, 1);
+       select_exception_test(s, tree);
 }
 
 stmt:  STMT_MONITOR_EXIT(reg)
@@ -1219,6 +1230,7 @@ stmt:     STMT_MONITOR_EXIT(reg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
objectUnlock));
 
        method_args_cleanup(s, tree, 1);
+       select_exception_test(s, tree);
 }
 
 stmt:  STMT_CHECKCAST(reg)
@@ -1235,6 +1247,7 @@ stmt:     STMT_CHECKCAST(reg)
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned 
long)check_cast));
 
        method_args_cleanup(s, tree, 2);
+       select_exception_test(s, tree);
 }
 
 %%
@@ -1246,6 +1259,28 @@ static void select_insn(struct basic_block *bb, struct 
tree_node *tree,
        bb_add_insn(bb, instruction);
 }
 
+/*
+ * Selects code checking whether exception occured. When this is the case
+ * exception will be thrown.
+ *
+ * NOTICE: exception test should be always selected _after_
+ * method args cleanup or stack overflow may occure if exceptions
+ * are thrown locally in a loop.
+ */
+static void select_exception_test(struct basic_block *bb,
+                                 struct tree_node *tree)
+{
+       unsigned long exception_guard_offset;
+       struct var_info *reg;
+
+       reg = get_var(bb->b_parent);
+
+       exception_guard_offset = get_thread_local_offset(&exception_guard);
+
+       select_insn(bb, tree, imm_reg_insn(INSN_MOV_THREAD_LOCAL_MEMDISP_REG, 
exception_guard_offset, reg));
+       select_insn(bb, tree, membase_reg_insn(INSN_TEST_MEMBASE_REG, reg, 0, 
reg));
+}
+
 static void __binop_reg_local(struct _MBState *state, struct basic_block *bb,
                              struct tree_node *tree, enum insn_type insn_type,
                              struct var_info *result, long disp_offset)
@@ -1394,6 +1429,7 @@ emulate_op_64(struct _MBState *state, struct basic_block 
*s,
 
        select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) func));
        method_args_cleanup(s, tree, 4);
+       select_exception_test(s, tree);
 
        select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1));
        if (edx)
diff --git a/arch/x86/thread.c b/arch/x86/thread.c
new file mode 100644
index 0000000..c9e0f17
--- /dev/null
+++ b/arch/x86/thread.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009 Tomasz Grabiec
+ *
+ * This file is released under the GPL version 2 with the following
+ * clarification and special exception:
+ *
+ *     Linking this library statically or dynamically with other modules is
+ *     making a combined work based on this library. Thus, the terms and
+ *     conditions of the GNU General Public License cover the whole
+ *     combination.
+ *
+ *     As a special exception, the copyright holders of this library give you
+ *     permission to link this library with independent modules to produce an
+ *     executable, regardless of the license terms of these independent
+ *     modules, and to copy and distribute the resulting executable under terms
+ *     of your choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module. An
+ *     independent module is a module which is not derived from or based on
+ *     this library. If you modify this library, you may extend this exception
+ *     to your version of the library, but you are not obligated to do so. If
+ *     you do not wish to do so, delete this exception statement from your
+ *     version.
+ *
+ * Please refer to the file LICENSE for details.
+ */
+
+#include <arch/thread.h>
+
+static unsigned long get_tls_address(void)
+{
+       unsigned long result;
+
+#ifdef CONFIG_X86_32
+       __asm__(
+               "movl %%gs:(0x0), %0 \n"
+               : "=r"(result) );
+#else
+ #error not implemented
+#endif
+
+       return result;
+}
+
+unsigned long get_thread_local_offset(void *thread_local_ptr)
+{
+#ifdef CONFIG_X86_32
+       return (unsigned long)thread_local_ptr - get_tls_address();
+#else
+ #error not implemented
+#endif
+}
diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile
index 91e27c2..cdbcbe0 100644
--- a/test/arch-x86/Makefile
+++ b/test/arch-x86/Makefile
@@ -59,6 +59,7 @@ OBJS = \
        ../../arch/x86/use-def.o \
        ../../arch/x86/exception.o \
        ../../arch/x86/unwind$(ARCH_POSTFIX).o \
+       ../../arch/x86/thread.o \
        $(TESTS)
 
 TESTS = \
-- 
1.6.0.6


------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to