From: Stefan Ring Date: Wed, 19 Jan 2011 10:20:43 +0000 (+0100) Subject: PR144 (aligned patchers on x86_64) X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=c414f560a7e0b7636a780e6b933e91e441f80503 PR144 (aligned patchers on x86_64) * src/vm/jit/patcher-common.cpp, src/vm/jit/patcher-common.h (patchref_t): Added yet another field - patch_align. * src/vm/jit/x86_64/codegen.c, src/vm/jit/x86_64/codegen.h: Make all patched code instances aligned. * src/vm/jit/x86_64/emit.c (emit_arbitrary_nop): Added. * src/vm/jit/x86_64/emit.h: Likewise. * src/vm/jit/x86_64/patcher.c: Adapted to new code layout, verify alignment. * tests/regression/bugzilla/PR144.java: Added new test case exercising the new code paths. * tests/regression/bugzilla/All.java: Likewise. --- diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index 6acd9687c..2963cf62b 100644 --- a/src/vm/jit/patcher-common.cpp +++ b/src/vm/jit/patcher-common.cpp @@ -1,6 +1,6 @@ /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff - Copyright (C) 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2008 Theobroma Systems Ltd. @@ -237,14 +237,15 @@ patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s // Set patcher information (mpc is resolved later). patchref_t pr; - pr.mpc = patchmpc; - pr.datap = 0; - pr.disp = disp; - pr.disp_mb = 0; - pr.patcher = patcher; - pr.ref = ref; - pr.mcode = 0; - pr.done = false; + pr.mpc = patchmpc; + pr.datap = 0; + pr.disp = disp; + pr.disp_mb = 0; + pr.patch_align = 0; + pr.patcher = patcher; + pr.ref = ref; + pr.mcode = 0; + pr.done = false; // Store patcher in the list (NOTE: structure is copied). code->patchers->push_back(pr); diff --git a/src/vm/jit/patcher-common.hpp b/src/vm/jit/patcher-common.hpp index 684b41c13..1c6f7b7c6 100644 --- a/src/vm/jit/patcher-common.hpp +++ b/src/vm/jit/patcher-common.hpp @@ -1,6 +1,6 @@ /* src/vm/jit/patcher-common.hpp - architecture independent code patching stuff - Copyright (C) 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -51,7 +51,8 @@ struct patchref_t { uintptr_t mpc; /* absolute position in code segment */ uintptr_t datap; /* absolute position in data segment */ int32_t disp; /* displacement of ref in the data segment */ - int32_t disp_mb; /* auxiliary code displacement (for membar) */ + int16_t disp_mb; /* auxiliary code displacement (for membar) */ + int16_t patch_align; /* auxiliary displacement for alignment */ functionptr patcher; /* patcher function to call */ void* ref; /* reference passed */ uint32_t mcode; /* machine code to be patched back in */ diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index 3a4acd2ea..c28050b84 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -1,6 +1,6 @@ /* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64 - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -204,6 +204,21 @@ void codegen_emit_patchable_barrier(instruction *iptr, codegendata *cd, patchref M_MFENCE; } +/** + * Ensures that the patched location (an int32_t) is aligned. + */ +static void codegen_fixup_alignment(codegendata *cd, patchref_t *pr, u1 *mcodeptr_save) +{ + u1 *codeptr = cd->mcodeptr; + int disp = PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 0, sizeof(int32_t)); + memmove(mcodeptr_save + disp, mcodeptr_save, cd->mcodeptr - mcodeptr_save); + pr->patch_align += cd->mcodeptr - mcodeptr_save + disp; + + cd->mcodeptr = mcodeptr_save; + emit_arbitrary_nop(cd, disp); + cd->mcodeptr = codeptr + disp; +} + /** * Generates machine code for one ICMD. */ @@ -220,6 +235,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) int32_t fieldtype; int32_t s1, s2, s3, d; int32_t disp; + u1* mcodeptr_save; // Get required compiler data. codegendata* cd = jd->cd; @@ -1562,7 +1578,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) /* PROFILE_CYCLE_STOP; */ - patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + mcodeptr_save = cd->mcodeptr; /* PROFILE_CYCLE_START; */ @@ -1572,6 +1589,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; disp = fi->offset; + + pr = 0; } /* implicit null-pointer check */ @@ -1597,6 +1616,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) // Silence compiler warning. d = 0; } + if (pr) + codegen_fixup_alignment(cd, pr, mcodeptr_save); emit_store_dst(jd, iptr, d); break; @@ -1613,6 +1634,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) /* PROFILE_CYCLE_STOP; */ pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + mcodeptr_save = cd->mcodeptr; /* PROFILE_CYCLE_START; */ @@ -1642,6 +1664,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) M_DST32(s2, s1, disp); break; } + if (pr) + codegen_fixup_alignment(cd, pr, mcodeptr_save); codegen_emit_patchable_barrier(iptr, cd, pr, fi); break; @@ -1659,6 +1683,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) /* PROFILE_CYCLE_STOP; */ pr = patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0); + mcodeptr_save = cd->mcodeptr; /* PROFILE_CYCLE_START; */ @@ -1685,10 +1710,14 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2); if (disp) /* resolved, disp can never be 0 */ M_LST(REG_ITMP2, s1, disp); - else /* unresolved */ + else { /* unresolved */ M_LST32(REG_ITMP2, s1, disp); + pr->patch_align = 4; + } break; } + if (pr) + codegen_fixup_alignment(cd, pr, mcodeptr_save); codegen_emit_patchable_barrier(iptr, cd, pr, fi); break; @@ -1813,6 +1842,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { um = iptr->sx.s23.s3.um; patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t))); s1 = 0; } @@ -1832,6 +1862,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { um = iptr->sx.s23.s3.um; patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t))); s1 = 0; s2 = 0; @@ -1847,6 +1878,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) /* implicit null-pointer check */ M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); M_ALD32(REG_METHODPTR, REG_METHODPTR, s1); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t))); M_ALD32(REG_ITMP3, REG_METHODPTR, s2); M_CALL(REG_ITMP3); break; @@ -1879,6 +1912,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t))); + M_IMOV_IMM(0, REG_ITMP2); /* super->flags */ M_IAND_IMM(ACC_INTERFACE, REG_ITMP2); emit_label_beq(cd, BRANCH_LABEL_2); @@ -1898,6 +1933,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) patcher_add_patch_ref(jd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t))); } M_ILD32(REG_ITMP3, @@ -1905,6 +1941,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) M_ICMP_IMM32(superindex, REG_ITMP3); emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1); + if (super == NULL) + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t))); M_ALD32(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); @@ -2055,6 +2093,8 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t))); + M_IMOV_IMM(0, REG_ITMP3); /* super->flags */ M_IAND_IMM(ACC_INTERFACE, REG_ITMP3); emit_label_beq(cd, BRANCH_LABEL_2); @@ -2063,6 +2103,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) /* interface instanceof code */ if ((super == NULL) || (super->flags & ACC_INTERFACE)) { + int nops; if (super != NULL) { M_TEST(s1); emit_label_beq(cd, BRANCH_LABEL_3); @@ -2073,15 +2114,19 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr) if (super == NULL) { patcher_add_patch_ref(jd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); + emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t))); } M_ILD32(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); M_ICMP_IMM32(superindex, REG_ITMP3); - int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */; + nops = super == NULL ? PATCH_ALIGNMENT((uintptr_t) (cd->mcodeptr + 6), 3, sizeof(int32_t)) : 0; + + int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */ + nops; M_BLE(a); + emit_arbitrary_nop(cd, nops); M_ALD32(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*)); diff --git a/src/vm/jit/x86_64/codegen.h b/src/vm/jit/x86_64/codegen.h index 086502be5..19700d76c 100644 --- a/src/vm/jit/x86_64/codegen.h +++ b/src/vm/jit/x86_64/codegen.h @@ -1,6 +1,6 @@ /* src/vm/jit/x86_64/codegen.h - code generation macros for x86_64 - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -56,6 +56,10 @@ } while (0) +#define PATCH_ALIGNMENT(addr, offset, size) \ + ((((addr)+(offset)+(size)-1) & ~((size)-1)) - ((addr)+(offset))) + + #define ICONST(r,c) \ do { \ if ((c) == 0) \ diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 7a4c65a39..12aaf1e1e 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -1,6 +1,6 @@ /* src/vm/jit/x86_64/emit.c - x86_64 code emitter functions - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -1274,6 +1274,15 @@ void emit_nop(codegendata *cd, int length) break; } } + +void emit_arbitrary_nop(codegendata *cd, int disp) +{ + while (disp) { + int x = disp < 9 ? disp : 9; + emit_nop(cd, x); + disp -= x; + } +} void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg) { diff --git a/src/vm/jit/x86_64/emit.h b/src/vm/jit/x86_64/emit.h index ebf6e361f..8d862fa1c 100644 --- a/src/vm/jit/x86_64/emit.h +++ b/src/vm/jit/x86_64/emit.h @@ -1,6 +1,6 @@ /* src/vm/jit/x86_64/emit.h - machine dependent emit function prototypes - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -374,6 +374,7 @@ void emit_mfence(codegendata *cd); */ static inline void emit_recompute_pv(codegendata* cd) {} +void emit_arbitrary_nop(codegendata *cd, int disp); #ifdef __cplusplus } diff --git a/src/vm/jit/x86_64/patcher.c b/src/vm/jit/x86_64/patcher.c index 2d394fff2..b7fcccb63 100644 --- a/src/vm/jit/x86_64/patcher.c +++ b/src/vm/jit/x86_64/patcher.c @@ -1,6 +1,6 @@ /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions - Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -59,6 +59,21 @@ void patcher_patch_code(patchref_t *pr) md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE); } +static int32_t *patch_checked_location(int32_t *p, int32_t val) +{ + assert(*p == 0); + // verify that it's aligned + assert((((uintptr_t) p) & (4-1)) == 0); + *p = val; + return p; +} + +static void checked_icache_flush(int32_t *addr, int nbytes, int32_t *check_loc) +{ + assert((int8_t*) addr + nbytes - sizeof(int32_t) >= (int8_t*) check_loc); + md_icacheflush(addr, nbytes); +} + /** * Check if the trap instruction at the given PC is valid. * @@ -196,10 +211,11 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr) return false; ra += PATCHER_CALL_SIZE; + ra += PATCH_ALIGNMENT((uintptr_t) ra, 2, sizeof(int32_t)); // Patch class flags. /* *datap = c->flags; */ - *((int32_t*) (ra + 2)) = c->flags; + patch_checked_location((int32_t*) (ra + 2), c->flags); // Synchronize data cache. /* md_dcacheflush(datap, sizeof(int32_t)); */ @@ -279,28 +295,14 @@ bool patcher_get_putfield(patchref_t *pr) pc += PATCHER_CALL_SIZE; - // Patch the field's offset: we check for the field type, because - // the instructions have different lengths. - if (IS_INT_LNG_TYPE(fi->type)) { - // Check for special case: %rsp or %r12 as base register. - if (pc[3] == 0x24) - *((int32_t*) (pc + 4)) = fi->offset; - else - *((int32_t*) (pc + 3)) = fi->offset; - } - else { - // Check for special case: %rsp or %r12 as base register. - if (pc[5] == 0x24) - *((int32_t*) (pc + 6)) = fi->offset; - else - *((int32_t*) (pc + 5)) = fi->offset; - } + int disp = -sizeof(int32_t) + pr->patch_align; + patch_checked_location((int32_t*) (pc + disp), fi->offset); if (pr->disp_mb && !(fi->flags & ACC_VOLATILE)) patch_out_mfence(pc + pr->disp_mb - 2); // Synchronize instruction cache. - md_icacheflush(pc, 6 + sizeof(int32_t)); + md_icacheflush(pc, disp + sizeof(int32_t)); // Patch back the original code. patcher_patch_code(pr); @@ -331,27 +333,14 @@ bool patcher_putfieldconst(patchref_t *pr) pc += PATCHER_CALL_SIZE; - // Patch the field's offset. - if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) { - // Handle special case when the base register is %r12. - if (pc[12] == 0x94) - *((uint32_t*) (pc + 14)) = fi->offset; - else - *((uint32_t*) (pc + 13)) = fi->offset; - } - else { - // Handle special case when the base register is %r12. - if (pc[2] == 0x84) - *((uint32_t*) (pc + 4)) = fi->offset; - else - *((uint32_t*) (pc + 3)) = fi->offset; - } + int disp = -2*sizeof(int32_t) + pr->patch_align; + patch_checked_location((int32_t*) (pc + disp), fi->offset); if (pr->disp_mb && !(fi->flags & ACC_VOLATILE)) patch_out_mfence(pc + pr->disp_mb - 2); // Synchronize instruction cache. - md_icacheflush(pc, 14 + sizeof(int32_t)); + md_icacheflush(pc, disp + sizeof(int32_t)); // Patch back the original code. patcher_patch_code(pr); @@ -417,9 +406,10 @@ bool patcher_invokevirtual(patchref_t *pr) return false; pc += PATCHER_CALL_SIZE; + pc += PATCH_ALIGNMENT((uintptr_t) pc, 6, sizeof(int32_t)); // Patch vftbl index. - *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex); + patch_checked_location((int32_t*) (pc + 6), (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex)); // Synchronize instruction cache. md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P); @@ -455,15 +445,18 @@ bool patcher_invokeinterface(patchref_t *pr) return false; pc += PATCHER_CALL_SIZE; + pc += PATCH_ALIGNMENT((uintptr_t) pc, 6, sizeof(int32_t)); // Patch interfacetable index. - *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index); + patch_checked_location((int32_t*) (pc + 6), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index)); + int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 3 + 7), 3, sizeof(int32_t)); + pc += disp; // Patch method offset. - *((int32_t*) (pc + 3 + 7 + 3)) = (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)); + int32_t *loc = patch_checked_location((int32_t*) (pc + 3 + 7 + 3), (int32_t) (sizeof(methodptr) * (m - m->clazz->methods))); // Synchronize instruction cache. - md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P); + checked_icache_flush(pc + 6, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P + disp, loc); // Patch back the original code. patcher_patch_code(pr); @@ -497,14 +490,17 @@ bool patcher_checkcast_interface(patchref_t *pr) return false; pc += PATCHER_CALL_SIZE; + pc += PATCH_ALIGNMENT((uintptr_t) pc, 10, sizeof(int32_t)); // Patch super class index. - *((int32_t*) (pc + 7 + 3)) = c->index; + patch_checked_location((int32_t*) (pc + 10), c->index); - *((int32_t*) (pc + 7 + 7 + 6 + 8 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)); + int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 7 + 7 + 6 + 8), 3, sizeof(int32_t)); + pc += disp; + int32_t *loc = patch_checked_location((int32_t*) (pc + 7 + 7 + 6 + 8 + 3), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))); // Synchronize instruction cache. - md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t)); + checked_icache_flush(pc + 10, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t) + disp, loc); // Patch back the original code. patcher_patch_code(pr); @@ -537,14 +533,17 @@ bool patcher_instanceof_interface(patchref_t *pr) return false; pc += PATCHER_CALL_SIZE; + pc += PATCH_ALIGNMENT((uintptr_t) pc, 10, sizeof(int32_t)); // Patch super class index. - *((int32_t*) (pc + 7 + 3)) = c->index; + patch_checked_location((int32_t*) (pc + 10), c->index); - *((int32_t*) (pc + 7 + 7 + 6 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)); + int disp = PATCH_ALIGNMENT((uintptr_t) (pc + 7 + 7 + 6), 3, sizeof(int32_t)); + pc += disp; + int32_t *loc = patch_checked_location((int32_t*) (pc + 7 + 7 + 6 + 3), (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*))); // Synchronize instruction cache. - md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 3 + sizeof(int32_t)); + checked_icache_flush(pc + 10, sizeof(int32_t) + 6 + 3 + sizeof(int32_t) + disp, loc); // Patch back the original code. patcher_patch_code(pr); diff --git a/tests/regression/bugzilla/All.java b/tests/regression/bugzilla/All.java index 206d7c9b6..937853d34 100644 --- a/tests/regression/bugzilla/All.java +++ b/tests/regression/bugzilla/All.java @@ -1,6 +1,6 @@ /* tests/regression/bugzilla/All.java - runs all CACAO regression unit tests - Copyright (C) 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -42,6 +42,7 @@ PR116.class, PR119.class, PR125.class, PR131.class, +PR144.class, PR148.class }) diff --git a/tests/regression/bugzilla/PR144.java b/tests/regression/bugzilla/PR144.java new file mode 100644 index 000000000..70d3d38bb --- /dev/null +++ b/tests/regression/bugzilla/PR144.java @@ -0,0 +1,67 @@ +/* tests/regression/bugzilla/PR144.java + + Copyright (C) 1996-2011 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +interface test_summable { + long sum(); +} + +class y implements test_summable { + public long l; + public int i; + public long sum() { + return l+i; + } +} + +public class PR144 { + static long do_test(Object o, int val) { + y vy = (y) o; + test_summable sm = null; + if (o instanceof test_summable) + sm = (test_summable) o; + vy.l = 0x123456789L; + vy.i = 0x98765; + long r = sm.sum(); + vy.l = val; + vy.i = val; + return r + sm.sum(); + } + + @Test + public void test() { + try { + do_test(null, 0); + } catch (NullPointerException e) { + } + assertEquals(4887631770L, do_test(new y(), 0x23456)); + } +} + + + +