* src/threads/posix/thread-posix.cpp: Eliminated some easy-to-fix or pointless compil...
[cacao.git] / src / vm / jit / x86_64 / patcher.c
index 81cc09e0e8bbc78583471327af0d14c9203634c0..2d394fff212ef8392a6c6dd7c30878fab9f9af03 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
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010
    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 ***************************************
 
@@ -225,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);
 
@@ -274,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));
 
@@ -322,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));