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
