The athrow instruction is supposed to push the exception object reference on java stack before control is treansferred to exception handler. Hence exception handlers expect that reference on top of java stack at exception handler entry. To handle this a special expresion is pushed onto mimic-stack before conversion of exception handler (EXPR_EXCEPTION_REF). The expression selects native pop instruction to obtain the reference. When exception manager will be implemented, it's supposed to push the exception object reference on native stack just before jumping to exception handler.
Signed-off-by: Tomek Grabiec <[email protected]> --- Makefile | 1 + arch/x86/emit-code_32.c | 13 +++++++------ arch/x86/include/arch/instruction.h | 1 + arch/x86/insn-selector_32.brg | 11 +++++++++++ arch/x86/lir-printer.c | 7 +++++++ arch/x86/use-def.c | 1 + include/jit/expression.h | 1 + jit/bytecode-to-ir.c | 9 ++------- jit/expression.c | 8 ++++++++ jit/tree-printer.c | 8 +++++++- regression/jvm/ExceptionsTest.java | 32 ++++++++++++++++++++++++++++++++ regression/run-suite.sh | 1 + 12 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 regression/jvm/ExceptionsTest.java diff --git a/Makefile b/Makefile index 2006636..12067db 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,7 @@ REGRESSION_TEST_SUITE_CLASSES = \ regression/jvm/PutfieldTest.class \ regression/jvm/TrampolineBackpatchingTest.class \ regression/jvm/RegisterAllocatorTortureTest.class \ + regression/jvm/ExceptionsTest.class lib: $(CLASSPATH_CONFIG) make -C lib/ JAVAC=$(JAVAC) GLIBJ=$(GLIBJ) diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c index 83a3573..b559dc3 100644 --- a/arch/x86/emit-code_32.c +++ b/arch/x86/emit-code_32.c @@ -378,9 +378,9 @@ void emit_prolog(struct buffer *buf, unsigned long nr_locals) emit_sub_imm_reg(buf, nr_locals * sizeof(unsigned long), REG_ESP); } -static void emit_pop_reg(struct buffer *buf, enum machine_reg reg) +static void emit_pop_reg(struct buffer *buf, struct operand *operand) { - emit(buf, 0x58 + __encode_reg(reg)); + __emit_pop_reg(buf, mach_reg(&operand->reg)); } static void __emit_push_imm(struct buffer *buf, long imm) @@ -426,12 +426,12 @@ void emit_epilog(struct buffer *buf, unsigned long nr_locals) if (nr_locals) emit(buf, 0xc9); else - emit_pop_reg(buf, REG_EBP); + __emit_pop_reg(buf, REG_EBP); /* Restore callee saved registers */ - emit_pop_reg(buf, REG_EBX); - emit_pop_reg(buf, REG_ESI); - emit_pop_reg(buf, REG_EDI); + __emit_pop_reg(buf, REG_EBX); + __emit_pop_reg(buf, REG_ESI); + __emit_pop_reg(buf, REG_EDI); emit_ret(buf); } @@ -801,6 +801,7 @@ static struct emitter emitters[] = { DECL_EMITTER(INSN_OR_REG_REG, emit_or_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_PUSH_IMM, emit_push_imm, SINGLE_OPERAND), DECL_EMITTER(INSN_PUSH_REG, emit_push_reg, SINGLE_OPERAND), + DECL_EMITTER(INSN_POP_REG, emit_pop_reg, SINGLE_OPERAND), DECL_EMITTER(INSN_SAR_IMM_REG, emit_sar_imm_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SAR_REG_REG, emit_sar_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SBB_MEMBASE_REG, emit_sbb_membase_reg, TWO_OPERANDS), diff --git a/arch/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index b8ab850..ec5f4cb 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -92,6 +92,7 @@ enum insn_type { INSN_OR_REG_REG, INSN_PUSH_IMM, INSN_PUSH_REG, + INSN_POP_REG, INSN_SAR_IMM_REG, INSN_SAR_REG_REG, INSN_SBB_MEMBASE_REG, diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg index c723526..8c3a7b4 100644 --- a/arch/x86/insn-selector_32.brg +++ b/arch/x86/insn-selector_32.brg @@ -818,6 +818,17 @@ arg: EXPR_ARGS_LIST(arg, arg) { } +reg: EXPR_EXCEPTION_REF +{ + struct var_info *result; + + result = get_var(s->b_parent); + state->reg1 = result; + + bb_add_insn(s, reg_insn(INSN_POP_REG, result)); +} + + stmt: STMT_RETURN(reg) { struct expression *expr; diff --git a/arch/x86/lir-printer.c b/arch/x86/lir-printer.c index 85eae94..9b69df2 100644 --- a/arch/x86/lir-printer.c +++ b/arch/x86/lir-printer.c @@ -369,6 +369,12 @@ static int print_push_reg(struct string *str, struct insn *insn) return print_reg(str, &insn->operand); } +static int print_pop_reg(struct string *str, struct insn *insn) +{ + print_func_name(str); + return print_reg(str, &insn->operand); +} + static int print_sar_imm_reg(struct string *str, struct insn *insn) { print_func_name(str); @@ -458,6 +464,7 @@ static print_insn_fn insn_printers[] = { [INSN_OR_REG_REG] = print_or_reg_reg, [INSN_PUSH_IMM] = print_push_imm, [INSN_PUSH_REG] = print_push_reg, + [INSN_POP_REG] = print_pop_reg, [INSN_SAR_IMM_REG] = print_sar_imm_reg, [INSN_SAR_REG_REG] = print_sar_reg_reg, [INSN_SBB_MEMBASE_REG] = print_sbb_membase_reg, diff --git a/arch/x86/use-def.c b/arch/x86/use-def.c index bc3ca4b..8bab6d8 100644 --- a/arch/x86/use-def.c +++ b/arch/x86/use-def.c @@ -65,6 +65,7 @@ static struct insn_info insn_infos[] = { DECLARE_INFO(INSN_OR_REG_REG, USE_SRC | DEF_DST), DECLARE_INFO(INSN_PUSH_IMM, USE_NONE | DEF_NONE), DECLARE_INFO(INSN_PUSH_REG, USE_SRC | DEF_NONE), + DECLARE_INFO(INSN_POP_REG, USE_NONE | DEF_SRC), DECLARE_INFO(INSN_SAR_IMM_REG, DEF_DST), DECLARE_INFO(INSN_SAR_REG_REG, USE_SRC | DEF_DST), DECLARE_INFO(INSN_SBB_MEMBASE_REG, USE_SRC | DEF_DST), diff --git a/include/jit/expression.h b/include/jit/expression.h index 834ce48..c131766 100644 --- a/include/jit/expression.h +++ b/include/jit/expression.h @@ -31,6 +31,7 @@ enum expression_type { EXPR_MULTIANEWARRAY, EXPR_ARRAYLENGTH, EXPR_INSTANCEOF, + EXPR_EXCEPTION_REF, EXPR_LAST, /* Not a real type. Keep this last. */ }; diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c index cde5024..0c8e699 100644 --- a/jit/bytecode-to-ir.c +++ b/jit/bytecode-to-ir.c @@ -262,18 +262,13 @@ static int parse_bytecode_insn(struct parse_context *ctx) goto error; } - /* - * Don't compile exception handlers because we don't support exception - * handling yet. - */ - if (ctx->bb->is_eh) - goto skip; + if (ctx->bb->is_eh && ctx->offset == ctx->bb->start) + stack_push(ctx->bb->mimic_stack, exception_ref_expr()); err = convert(ctx); if (err) goto error; -skip: ctx->offset += opc_size; error: return err; diff --git a/jit/expression.c b/jit/expression.c index 4669a19..38f7a0c 100644 --- a/jit/expression.c +++ b/jit/expression.c @@ -97,6 +97,9 @@ void free_expression(struct expression *expr) case EXPR_INSTANCEOF: expr_put(to_expr(expr->instanceof_ref)); break; + case EXPR_EXCEPTION_REF: + /* nothing to do */ + break; case EXPR_LAST: assert(!"EXPR_LAST is not a real type. Don't use it"); break; @@ -347,3 +350,8 @@ unsigned long nr_args(struct expression *args_list) return nr_args(left) + nr_args(right); } + +struct expression *exception_ref_expr() +{ + return alloc_expression(EXPR_EXCEPTION_REF, J_REFERENCE); +} diff --git a/jit/tree-printer.c b/jit/tree-printer.c index 38026c2..4d3e086 100644 --- a/jit/tree-printer.c +++ b/jit/tree-printer.c @@ -84,7 +84,7 @@ static int simple_expr(struct expression *expr) return type == EXPR_VALUE || type == EXPR_FVALUE || type == EXPR_LOCAL || type == EXPR_TEMPORARY || type == EXPR_CLASS_FIELD - || type == EXPR_NO_ARGS; + || type == EXPR_NO_ARGS || type == EXPR_EXCEPTION_REF; } static int __tree_print(int, struct tree_node *, struct string *); @@ -700,6 +700,11 @@ static int print_instanceof_expr(int lvl, struct string *str, struct expression return err; } +static int print_exception_ref_expr(int lvl, struct string *str, struct expression *expr) +{ + return str_append(str, "[exception object reference]\n"); +} + typedef int (*print_expr_fn) (int, struct string * str, struct expression *); static print_expr_fn expr_printers[] = { @@ -724,6 +729,7 @@ static print_expr_fn expr_printers[] = { [EXPR_MULTIANEWARRAY] = print_multianewarray_expr, [EXPR_ARRAYLENGTH] = print_arraylength_expr, [EXPR_INSTANCEOF] = print_instanceof_expr, + [EXPR_EXCEPTION_REF] = print_exception_ref_expr }; static int print_expr(int lvl, struct tree_node *root, struct string *str) diff --git a/regression/jvm/ExceptionsTest.java b/regression/jvm/ExceptionsTest.java new file mode 100644 index 0000000..6ef2a08 --- /dev/null +++ b/regression/jvm/ExceptionsTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009 Tomasz Grabiec + * + * This file is released under the GPL version 2. Please refer to the file + * LICENSE for details. + */ +package jvm; + +/** + * @author Tomasz Grabiec + */ +class ExceptionsTest extends TestCase { + + public static void testCatchCompilation() { + int i; + + i = 0; + try { + i = 2; + } catch (Exception e) { + i = 1; + } + + assertEquals(i, 2); + } + + public static void main(String args[]) { + testCatchCompilation(); + + Runtime.getRuntime().halt(retval); + } +}; \ No newline at end of file diff --git a/regression/run-suite.sh b/regression/run-suite.sh index 146d7a8..2098d41 100755 --- a/regression/run-suite.sh +++ b/regression/run-suite.sh @@ -64,6 +64,7 @@ if [ -z "$CLASS_LIST" ]; then run_java jvm.PutfieldTest 0 run_java jvm.TrampolineBackpatchingTest 0 run_java jvm.RegisterAllocatorTortureTest 0 + run_java jvm.ExceptionsTest 0 else for i in $CLASS_LIST; do run_java $i 0 -- 1.6.0.6 ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensign option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Jatovm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jatovm-devel
