From 97408c9748640b078f801500620baec571dc6baa Mon Sep 17 00:00:00 2001 From: Stefan Ring Date: Mon, 8 Aug 2011 19:44:17 +0200 Subject: [PATCH] PR159: Exception handler blocks / register mixup * src/vm/jit/codegen-common.cpp: Fix register allocation at exception handler block boundaries. The concept of a block type is flawed because an exception handler block can also be reached via normal control flow. I guess subroutine blocks are safe because they expect a different type on the stack (returnAddress), and any attempt at reaching them normally would not get past the verifier, although I don't know how this is handled in CACAO. The conditional branches should be handled as well, but as there is a lot of platform-specific code involved as well as lots of register clobbering potential, I'll leave it at that for now. --- src/vm/jit/codegen-common.cpp | 36 ++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/vm/jit/codegen-common.cpp b/src/vm/jit/codegen-common.cpp index 9b1dad8cd..81c3c75c8 100644 --- a/src/vm/jit/codegen-common.cpp +++ b/src/vm/jit/codegen-common.cpp @@ -1,6 +1,6 @@ /* src/vm/jit/codegen-common.cpp - architecture independent code generator stuff - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2009 Theobroma Systems Ltd. @@ -989,6 +989,21 @@ s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum) return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum); } +/** + * Fix up register locations in the case where control is transferred to an + * exception handler block via normal control flow (no exception). + */ +static void fixup_exc_handler_interface(jitdata *jd, basicblock *bptr) +{ + // Exception handlers have exactly 1 in-slot + assert(bptr->indepth == 1); + varinfo *var = VAR(bptr->invars[0]); + int32_t d = codegen_reg_of_var(0, var, REG_ITMP1_XPTR); + emit_load(jd, NULL, var, d); + // Copy the interface variable to ITMP1 (XPTR) because that's where + // the handler expects it. + emit_imove(jd->cd, d, REG_ITMP1_XPTR); +} /** * Generates machine code. @@ -1695,12 +1710,15 @@ bool codegen_emit(jitdata *jd) codegen_emit_phi_moves(jd, bptr); } #endif + if (iptr->dst.block->type == BBTYPE_EXH) + fixup_exc_handler_interface(jd, iptr->dst.block); emit_br(cd, iptr->dst.block); ALIGNCODENOP; break; case ICMD_JSR: /* ... ==> ... */ + assert(iptr->sx.s23.s3.jsrtarget.block->type != BBTYPE_EXH); emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); ALIGNCODENOP; break; @@ -1708,6 +1726,7 @@ bool codegen_emit(jitdata *jd) case ICMD_IFNULL: /* ..., value ==> ... */ case ICMD_IFNONNULL: + assert(iptr->dst.block->type != BBTYPE_EXH); s1 = emit_load_s1(jd, iptr, REG_ITMP1); #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE); @@ -1730,6 +1749,8 @@ bool codegen_emit(jitdata *jd) // register directly. Reason is, that register content is // not 32-bit clean. Fix this! + assert(iptr->dst.block->type != BBTYPE_EXH); + #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER if (iptr->sx.val.i == 0) { s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -1754,6 +1775,8 @@ bool codegen_emit(jitdata *jd) case ICMD_IF_LGT: case ICMD_IF_LLE: + assert(iptr->dst.block->type != BBTYPE_EXH); + // Generate architecture specific instructions. codegen_emit_instruction(jd, iptr); break; @@ -1761,6 +1784,8 @@ bool codegen_emit(jitdata *jd) case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */ case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */ + assert(iptr->dst.block->type != BBTYPE_EXH); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS @@ -1793,6 +1818,8 @@ bool codegen_emit(jitdata *jd) case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ case ICMD_IF_ICMPNE: /* op1 = target JavaVM pc */ + assert(iptr->dst.block->type != BBTYPE_EXH); + #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -1814,6 +1841,8 @@ bool codegen_emit(jitdata *jd) case ICMD_IF_ICMPLE: case ICMD_IF_ICMPGE: + assert(iptr->dst.block->type != BBTYPE_EXH); + s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER @@ -1839,6 +1868,8 @@ bool codegen_emit(jitdata *jd) case ICMD_IF_LCMPLE: case ICMD_IF_LCMPGE: + assert(iptr->dst.block->type != BBTYPE_EXH); + // Generate architecture specific instructions. codegen_emit_instruction(jd, iptr); break; @@ -2274,6 +2305,9 @@ gen_method: } #endif + if (bptr->next && bptr->next->type == BBTYPE_EXH) + fixup_exc_handler_interface(jd, bptr->next); + } // for all basic blocks // Generate traps. -- 2.25.1