From: sr Date: Tue, 17 Nov 2009 07:40:45 +0000 (+0100) Subject: merged volatile memory barriers X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=735bdda890a385d1fa9cc532faadbbc96f2d1218;hp=d62d56aa9150bb2156dac82966795fdcbd7562e0 merged volatile memory barriers --- diff --git a/src/native/jni.cpp b/src/native/jni.cpp index 431b2c9bc..6e850fd2b 100644 --- a/src/native/jni.cpp +++ b/src/native/jni.cpp @@ -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(); } diff --git a/src/vm/jit/codegen-common.cpp b/src/vm/jit/codegen-common.cpp index a44c52fb3..5536ba819 100644 --- a/src/vm/jit/codegen-common.cpp +++ b/src/vm/jit/codegen-common.cpp @@ -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 **********************************************/ diff --git a/src/vm/jit/codegen-common.hpp b/src/vm/jit/codegen-common.hpp index 68fc49bdf..ead70b880 100644 --- a/src/vm/jit/codegen-common.hpp +++ b/src/vm/jit/codegen-common.hpp @@ -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 diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index c364646be..6acd9687c 100644 --- a/src/vm/jit/patcher-common.cpp +++ b/src/vm/jit/patcher-common.cpp @@ -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(); } diff --git a/src/vm/jit/patcher-common.hpp b/src/vm/jit/patcher-common.hpp index 3f488809e..684b41c13 100644 --- a/src/vm/jit/patcher-common.hpp +++ b/src/vm/jit/patcher-common.hpp @@ -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); diff --git a/src/vm/jit/x86_64/arch.h b/src/vm/jit/x86_64/arch.h index 7e8457cce..ff74f82bb 100644 --- a/src/vm/jit/x86_64/arch.h +++ b/src/vm/jit/x86_64/arch.h @@ -127,6 +127,8 @@ #define CAS_PROVIDES_FULL_BARRIER 1 +#define USES_PATCHABLE_MEMORY_BARRIER 1 + #endif /* _ARCH_H */ @@ -141,4 +143,5 @@ * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */ diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index 61c86520a..89f12c251 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -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; diff --git a/src/vm/jit/x86_64/codegen.h b/src/vm/jit/x86_64/codegen.h index ce8576e3d..086502be5 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 + 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; \ @@ -98,8 +102,7 @@ #define PATCHER_NOPS \ do { \ - M_NOP; \ - M_NOP; \ + emit_nop(cd, 2); \ } while (0) @@ -335,6 +338,7 @@ /* 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)) @@ -360,4 +364,5 @@ * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */ diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 9f1a35f95..7a4c65a39 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -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: */ diff --git a/src/vm/jit/x86_64/emit.h b/src/vm/jit/x86_64/emit.h index 790f659a9..ebf6e361f 100644 --- a/src/vm/jit/x86_64/emit.h +++ b/src/vm/jit/x86_64/emit.h @@ -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: */ diff --git a/src/vm/jit/x86_64/patcher.c b/src/vm/jit/x86_64/patcher.c index ae4b7aa21..be4fd4e7a 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 + 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;