merged volatile memory barriers
authorsr <none@none>
Tue, 17 Nov 2009 07:40:45 +0000 (08:40 +0100)
committersr <none@none>
Tue, 17 Nov 2009 07:40:45 +0000 (08:40 +0100)
src/native/jni.cpp
src/vm/jit/codegen-common.cpp
src/vm/jit/codegen-common.hpp
src/vm/jit/patcher-common.cpp
src/vm/jit/patcher-common.hpp
src/vm/jit/x86_64/arch.h
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

index 431b2c9bcab03833889a0835e59aee91e7622751..6e850fd2bac0db539175b06ad3fe7c06ea6b6b8a 100644 (file)
@@ -2069,6 +2069,8 @@ jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
 #define SET_FIELD(o,type,f,value) \
     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
 
+#define GET_FIELDINFO(f) ((fieldinfo*) (f))
+
 #define JNI_SET_FIELD(name, type, intern)                                  \
 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
                                                          type value)                                  \
@@ -2079,7 +2081,10 @@ void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
                                                                            \
        SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
                                                                               \
-       LLNI_CRITICAL_START;                                                   \
+       LLNI_CRITICAL_END;                                                     \
+                                                                                                                                                  \
+       if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)                      \
+               Atomic::memory_barrier();                                          \
 }
 
 JNI_SET_FIELD(Boolean, jboolean, s4)
@@ -2102,6 +2107,9 @@ void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
        SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
 
        LLNI_CRITICAL_END;
+
+       if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)
+               Atomic::memory_barrier();
 }
 
 
@@ -2439,6 +2447,9 @@ void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
                        return;                                            \
                                                                \
        f->value->field = value;                                   \
+                                                                                                                          \
+       if (f->flags & ACC_VOLATILE)                               \
+               Atomic::memory_barrier();                              \
 }
 
 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
@@ -2467,6 +2478,9 @@ void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
                        return;
 
        f->value->a = LLNI_UNWRAP((java_handle_t *) value);
+
+       if (f->flags & ACC_VOLATILE)
+               Atomic::memory_barrier();
 }
 
 
index a44c52fb3b6da56571e88a9262d095303d62a255..5536ba819c29871a28a64885a8905814e161f586 100644 (file)
@@ -1507,16 +1507,20 @@ bool codegen_emit(jitdata *jd)
 #if defined(__I386__)
                                // Generate architecture specific instructions.
                                codegen_emit_instruction(jd, iptr);
+                               break;
 #else
+                       {
+                               fieldinfo* fi;
+                               patchref_t* pr;
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        unresolved_field* uf = iptr->sx.s23.s3.uf;
                                        fieldtype = uf->fieldref->parseddesc.fd->type;
                                        disp      = dseg_add_unique_address(cd, 0);
 
-                                       patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+                                       pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
                                }
                                else {
-                                       fieldinfo* fi = iptr->sx.s23.s3.fmiref->p.field;
+                                       fi        = iptr->sx.s23.s3.fmiref->p.field;
                                        fieldtype = fi->type;
                                        disp      = dseg_add_address(cd, fi->value);
 
@@ -1527,6 +1531,10 @@ bool codegen_emit(jitdata *jd)
                                        }
                                }
 
+#if defined(USES_PATCHABLE_MEMORY_BARRIER)
+                               codegen_emit_patchable_barrier(iptr, cd, pr, fi);
+#endif
+
                                // XXX X86_64: Here We had this:
                                /* This approach is much faster than moving the field
                                   address inline into a register. */
@@ -1556,24 +1564,30 @@ bool codegen_emit(jitdata *jd)
                                        break;
                                }
                                emit_store_dst(jd, iptr, d);
-#endif
                                break;
+                       }
+#endif
 
                        case ICMD_PUTSTATIC:  /* ..., value  ==> ...                      */
 
 #if defined(__I386__)
                                // Generate architecture specific instructions.
                                codegen_emit_instruction(jd, iptr);
+                               break;
 #else
+                       {
+                               fieldinfo* fi;
+                               patchref_t* pr;
+
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        unresolved_field* uf = iptr->sx.s23.s3.uf;
                                        fieldtype = uf->fieldref->parseddesc.fd->type;
                                        disp      = dseg_add_unique_address(cd, 0);
 
-                                       patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+                                       pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
                                }
                                else {
-                                       fieldinfo* fi = iptr->sx.s23.s3.fmiref->p.field;
+                                       fi = iptr->sx.s23.s3.fmiref->p.field;
                                        fieldtype = fi->type;
                                        disp      = dseg_add_address(cd, fi->value);
 
@@ -1612,8 +1626,12 @@ bool codegen_emit(jitdata *jd)
                                        M_DST(s1, REG_ITMP1, 0);
                                        break;
                                }
+#if defined(USES_PATCHABLE_MEMORY_BARRIER)
+                               codegen_emit_patchable_barrier(iptr, cd, pr, fi);
 #endif
                                break;
+                       }
+#endif
 
                        /* branch operations **********************************************/
 
index 68fc49bdff27c263109524fe155e1f75d8680ccb..ead70b880c053c91f3f0a73de8c17ed730d29bc2 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/codegen-common.hpp - architecture independent code generator stuff
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -34,6 +34,7 @@ typedef struct branch_label_ref_t     branch_label_ref_t;
 typedef struct jumpref                jumpref;
 typedef struct dataref                dataref;
 
+struct patchref_t;
 
 #include "config.h"
 #include "vm/types.h"
@@ -228,6 +229,10 @@ void codegen_emit_prolog(jitdata* jd);
 void codegen_emit_epilog(jitdata* jd);
 void codegen_emit_instruction(jitdata* jd, instruction* iptr);
 
+#if defined(USES_PATCHABLE_MEMORY_BARRIER)
+void codegen_emit_patchable_barrier(instruction *iptr, codegendata *cd, struct patchref_t *pr, fieldinfo *fi);
+#endif
+
 #if defined(ENABLE_INTRP)
 bool intrp_codegen(jitdata *jd);
 #endif
index c364646be172ee8b249bb4c4fcc860c6b581c741..6acd9687c493440c8548b4509a9c584a8642b4d6 100644 (file)
@@ -210,34 +210,37 @@ void patcher_list_show(codeinfo *code)
 
    Appends a new patcher reference to the list of patching positions.
 
+   Returns a pointer to the newly created patchref_t.
+
 *******************************************************************************/
 
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
+patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
 {
-       codegendata *cd;
-       codeinfo    *code;
-       s4           patchmpc;
-
-       cd       = jd->cd;
-       code     = jd->code;
-       patchmpc = cd->mcodeptr - cd->mcodebase;
+       codegendata *cd   = jd->cd;
+       codeinfo    *code = jd->code;
 
 #if defined(ALIGN_PATCHER_TRAP)
        emit_patcher_alignment(cd);
-       patchmpc = cd->mcodeptr - cd->mcodebase;
 #endif
 
+       int32_t patchmpc = cd->mcodeptr - cd->mcodebase;
+
 #if !defined(NDEBUG)
        if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
                os::abort("patcher_add_patch_ref: different patchers at same position.");
 #endif
 
+#if defined(USES_PATCHABLE_MEMORY_BARRIER)
+       PATCHER_NOPS;
+#endif
+
        // 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;
@@ -265,6 +268,8 @@ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
 
        cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
 #endif
+
+       return &code->patchers->back();
 }
 
 
index 3f488809e74e7e37e5cf46d8b294dd526654ba80..684b41c13a8c28f846aa398237af6ea390da78bd 100644 (file)
@@ -48,9 +48,10 @@ typedef struct patchref_t patchref_t;
 *******************************************************************************/
 
 struct patchref_t {
-       ptrint       mpc;           /* absolute position in code segment          */
-       ptrint       datap;         /* absolute position in data segment          */
-       s4           disp;          /* displacement of ref in the data segment    */
+       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)   */
        functionptr  patcher;       /* patcher function to call                   */
        void*        ref;           /* reference passed                           */
        uint32_t     mcode;         /* machine code to be patched back in         */
@@ -75,7 +76,7 @@ void patcher_list_free(codeinfo *code);
 void patcher_list_show(codeinfo *code);
 #endif
 
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
+patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
 
 void patcher_resolve(jitdata* jd);
 
index 7e8457cce12678f1684f6e821d8ae61c0d0f018f..ff74f82bbc5847bc9f75646066230cba39778139 100644 (file)
 
 #define CAS_PROVIDES_FULL_BARRIER        1
 
+#define USES_PATCHABLE_MEMORY_BARRIER    1
+
 #endif /* _ARCH_H */
 
 
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 61c86520adac4c06c365ecc0f722c52b250af9f2..89f12c251cdbaa9183b87bcd0ba28715238a6876 100644 (file)
@@ -187,6 +187,22 @@ void codegen_emit_epilog(jitdata* jd)
        M_RET;
 }
 
+/**
+ * Generates a memory barrier to be used after volatile writes. It can be
+ * patched out later if the field turns out not to be volatile.
+ */
+void codegen_emit_patchable_barrier(instruction *iptr, codegendata *cd, patchref_t *pr, fieldinfo *fi)
+{
+       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+               /* Align on word boundary */
+               if ((((intptr_t) cd->mcodeptr) & 3) >= 2)
+                       emit_nop(cd, 4 - (((intptr_t) cd->mcodeptr) & 3));
+               /* Displacement for patching out MFENCE */
+               pr->disp_mb = (cd->mcodeptr - cd->mcodebase - pr->mpc);
+       }
+       if (INSTRUCTION_IS_UNRESOLVED(iptr) || fi->flags & ACC_VOLATILE)
+               M_MFENCE;
+}
 
 /**
  * Generates machine code for one ICMD.
@@ -200,6 +216,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
        unresolved_method*  um;
        fieldinfo*          fi;
        unresolved_field*   uf;
+       patchref_t*         pr;
        int32_t             fieldtype;
        int32_t             s1, s2, s3, d;
        int32_t             disp;
@@ -1487,7 +1504,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
 
 /*                             PROFILE_CYCLE_STOP; */
 
-                               patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+                               pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
 
 /*                             PROFILE_CYCLE_START; */
                        }
@@ -1527,6 +1544,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                }
                                break;
                        }
+                       codegen_emit_patchable_barrier(iptr, cd, pr, fi);
                        break;
 
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
@@ -1585,7 +1603,7 @@ 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);
 
 /*                             PROFILE_CYCLE_START; */
                        } 
@@ -1611,6 +1629,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                M_DST32(s2, s1, disp);
                                break;
                        }
+                       codegen_emit_patchable_barrier(iptr, cd, pr, fi);
                        break;
 
                case ICMD_PUTFIELDCONST:  /* ..., objectref, value  ==> ...           */
@@ -1626,7 +1645,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
 
 /*                             PROFILE_CYCLE_STOP; */
 
-                               patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0);
+                               pr = patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0);
 
 /*                             PROFILE_CYCLE_START; */
                        } 
@@ -1653,6 +1672,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                        M_LST32(REG_ITMP2, s1, disp);
                                break;
                        }
+                       codegen_emit_patchable_barrier(iptr, cd, pr, fi);
                        break;
 
 
index ce8576e3d9bb421ef6e4e3ca246d2bad44bff592..086502be5a2748742f75bf321558ae679d8765ec 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
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -50,8 +50,9 @@
 
 #define ALIGNCODENOP \
     do { \
-        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
-            M_NOP; \
+        int len = (-(ptrint) cd->mcodeptr) & 7; \
+        if (len) \
+            emit_nop(cd, len); \
     } while (0)
 
 
@@ -81,6 +82,9 @@
 #define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
 #define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
 
+/* These NOPs are never executed; they are only used as placeholders during
+ * code generation.
+ */
 #define BRANCH_NOPS \
     do { \
         M_NOP; \
 
 #define PATCHER_NOPS \
     do { \
-        M_NOP; \
-        M_NOP; \
+        emit_nop(cd, 2); \
     } while (0)
 
 
 
 /* system instructions ********************************************************/
 
+#define M_MFENCE                emit_mfence(cd)
 #define M_RDTSC                 emit_rdtsc(cd)
 
 #define M_IINC_MEMBASE(a,b)     emit_incl_membase(cd, (a), (b))
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 9f1a35f957927e066c8dffc525698325ef438688..7a4c65a39d20537e2ec1d99604208695a9634156 100644 (file)
@@ -1205,6 +1205,76 @@ void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
 
 /* low-level code emitter functions *******************************************/
 
+void emit_nop(codegendata *cd, int length)
+{
+    assert(length >= 1 && length <= 9);
+    switch (length) {
+    case 1:
+        *(cd->mcodeptr++) = 0x90;
+        break;
+    case 2:
+        *(cd->mcodeptr++) = 0x66;
+        *(cd->mcodeptr++) = 0x90;
+        break;
+    case 3:
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 4:
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x40;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 5:
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x44;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 6:
+        *(cd->mcodeptr++) = 0x66;
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x44;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 7:
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x80;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 8:
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x84;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    case 9:
+        *(cd->mcodeptr++) = 0x66;
+        *(cd->mcodeptr++) = 0x0f;
+        *(cd->mcodeptr++) = 0x1f;
+        *(cd->mcodeptr++) = 0x84;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        *(cd->mcodeptr++) = 0x00;
+        break;
+    }
+}
+
 void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg)
 {
        emit_rex(1,(reg),0,(dreg));
@@ -2573,6 +2643,13 @@ void emit_rdtsc(codegendata *cd)
        *(cd->mcodeptr++) = 0x31;
 }
 
+void emit_mfence(codegendata *cd)
+{
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xae;
+       *(cd->mcodeptr++) = 0xf0;
+}
+
 
 /*
  * These are local overrides for various environment variables in Emacs.
@@ -2585,4 +2662,5 @@ void emit_rdtsc(codegendata *cd)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 790f659a9aa1b6e8889519066c64f63e1470a208..ebf6e361f6a9d03eb85cf8af09436cacefc27c91 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/x86_64/emit.h - machine dependent emit function prototypes
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -195,6 +193,7 @@ void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr);
 
 /* integer instructions */
 
+void emit_nop(codegendata *cd, int length);
 void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg);
 void emit_mov_imm_reg(codegendata *cd, s8 imm, s8 reg);
 void emit_movl_reg_reg(codegendata *cd, s8 reg, s8 dreg);
@@ -366,6 +365,7 @@ void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
 /* system instructions ********************************************************/
 
 void emit_rdtsc(codegendata *cd);
+void emit_mfence(codegendata *cd);
 
 
 /**
@@ -393,4 +393,5 @@ static inline void emit_recompute_pv(codegendata* cd) {}
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index ae4b7aa2131eb14c9949dca08ab808ba38f185ab..be4fd4e7a8c447f936875e22e0a07d59a280a5bf 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
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -74,6 +74,25 @@ bool patcher_is_valid_trap_instruction_at(void* pc)
        return (mcode == 0x0b0f);
 }
 
+/**
+ * Overwrites the MFENCE instruction at the indicated address with a 3-byte
+ * NOP. The MFENCE instruction is not allowed to cross a (4-byte) word
+ * boundary.
+ *
+ * @param pc Program counter.
+ */
+static void patch_out_mfence(void *pc)
+{
+       uint32_t *p = (uint32_t*) (((uintptr_t) pc) & ~3);
+
+       assert((((uintptr_t) pc) & 3) < 2);
+       if (((uintptr_t) pc) & 1)
+               *p = *p & 0x000000ff | 0x001f0f00;
+       else
+               *p = *p & 0xff000000 | 0x00001f0f;
+
+       md_icacheflush(p, 4);
+}
 
 /* patcher_resolve_classref_to_classinfo ***************************************
 
@@ -176,6 +195,8 @@ bool patcher_resolve_classref_to_flags(patchref_t *pr)
        if (c == NULL)
                return false;
 
+       ra += PATCHER_CALL_SIZE;
+
        // Patch class flags.
 /*     *datap = c->flags; */
        *((int32_t*) (ra + 2)) = c->flags;
@@ -205,6 +226,7 @@ bool patcher_get_putstatic(patchref_t *pr)
 {
        unresolved_field* uf    = (unresolved_field*) pr->ref;
        uintptr_t*        datap = (uintptr_t*)        pr->datap;
+       uint8_t*          ra    = (uint8_t*)          pr->mpc;
 
        // Resolve the field.
        fieldinfo* fi = resolve_field_eager(uf);
@@ -212,6 +234,8 @@ bool patcher_get_putstatic(patchref_t *pr)
        if (fi == NULL)
                return false;
 
+       ra += PATCHER_CALL_SIZE;
+
        // Check if the field's class is initialized/
        if (!(fi->clazz->state & CLASS_INITIALIZED))
                if (!initialize_class(fi->clazz))
@@ -220,6 +244,9 @@ bool patcher_get_putstatic(patchref_t *pr)
        // Patch the field value's address.
        *datap = (uintptr_t) fi->value;
 
+       if (pr->disp_mb && !(fi->flags & ACC_VOLATILE))
+               patch_out_mfence(ra + pr->disp_mb - 2);
+
        // Synchronize data cache.
        md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
 
@@ -250,6 +277,8 @@ bool patcher_get_putfield(patchref_t *pr)
        if (fi == NULL)
                return false;
 
+       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)) {
@@ -267,6 +296,9 @@ bool patcher_get_putfield(patchref_t *pr)
                        *((int32_t*) (pc + 5)) = 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));
 
@@ -297,6 +329,8 @@ bool patcher_putfieldconst(patchref_t *pr)
        if (fi == NULL)
                return false;
 
+       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.
@@ -313,6 +347,9 @@ bool patcher_putfieldconst(patchref_t *pr)
                        *((uint32_t*) (pc + 3)) = 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));
 
@@ -379,6 +416,8 @@ bool patcher_invokevirtual(patchref_t *pr)
        if (m == NULL)
                return false;
 
+       pc += PATCHER_CALL_SIZE;
+
        // Patch vftbl index.
        *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
 
@@ -415,6 +454,8 @@ bool patcher_invokeinterface(patchref_t *pr)
        if (m == NULL)
                return false;
 
+       pc += PATCHER_CALL_SIZE;
+
        // Patch interfacetable index.
        *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index);
 
@@ -455,6 +496,8 @@ bool patcher_checkcast_interface(patchref_t *pr)
        if (c == NULL)
                return false;
 
+       pc += PATCHER_CALL_SIZE;
+
        // Patch super class index.
        *((int32_t*) (pc + 7 + 3)) = c->index;
 
@@ -493,6 +536,8 @@ bool patcher_instanceof_interface(patchref_t *pr)
        if (c == NULL)
                return false;
 
+       pc += PATCHER_CALL_SIZE;
+
        // Patch super class index.
        *((int32_t*) (pc + 7 + 3)) = c->index;