PR144 (aligned patchers on x86_64)
authorStefan Ring <stefan@complang.tuwien.ac.at>
Wed, 19 Jan 2011 10:20:43 +0000 (11:20 +0100)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Wed, 19 Jan 2011 10:20:43 +0000 (11:20 +0100)
* 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.

src/vm/jit/patcher-common.cpp
src/vm/jit/patcher-common.hpp
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/jit/x86_64/patcher.c
tests/regression/bugzilla/All.java
tests/regression/bugzilla/PR144.java [new file with mode: 0644]

index 6acd9687c493440c8548b4509a9c584a8642b4d6..2963cf62b28f47fb8ff0a4e58602dda4ed45664b 100644 (file)
@@ -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);
index 684b41c13a8c28f846aa398237af6ea390da78bd..1c6f7b7c62674f129e48f776817dc74cf20a7368 100644 (file)
@@ -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         */
index 3a4acd2ea61482646c34b3a4593e19de345d75de..c28050b843e65de52e5e27e262750b7dee414af4 100644 (file)
@@ -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*));
index 086502be5a2748742f75bf321558ae679d8765ec..19700d76cea55fdfd6118d1e2e4318334823cf9f 100644 (file)
@@ -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.
     } while (0)
 
 
+#define PATCH_ALIGNMENT(addr, offset, size) \
+       ((((addr)+(offset)+(size)-1) & ~((size)-1)) - ((addr)+(offset)))
+
+
 #define ICONST(r,c) \
     do { \
         if ((c) == 0) \
index 7a4c65a39d20537e2ec1d99604208695a9634156..12aaf1e1e5d754962ebfc05c355727d6ff80c4f6 100644 (file)
@@ -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)
 {
index ebf6e361f6a9d03eb85cf8af09436cacefc27c91..8d862fa1c48449c5909b87574f0d0eac935b1ebe 100644 (file)
@@ -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
 }
index 2d394fff212ef8392a6c6dd7c30878fab9f9af03..b7fcccb633ab59b995b90525b61df249ce37ee48 100644 (file)
@@ -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);
index 206d7c9b6046cf18629632abe8d0a255d7a21afd..937853d3466ac612e9280d9ec082802e69e7bd69 100644 (file)
@@ -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 (file)
index 0000000..70d3d38
--- /dev/null
@@ -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));
+    }
+}
+
+
+
+