diff --git a/src/compile.cpp b/src/compile.cpp index 1e3a18e49d..6198eb37d3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2631,6 +2631,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } } + Compiler::Operand* fieldOperand = 0; + + if ((fieldFlags(t, field) & ACC_VOLATILE) + and BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + fieldOperand = frame->append(field); + + c->call + (c->constant(getThunk(t, acquireMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), fieldOperand); + } + switch (fieldCode(t, field)) { case ByteField: case BooleanField: @@ -2676,7 +2690,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } if (fieldFlags(t, field) & ACC_VOLATILE) { - c->loadBarrier(); + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + c->call + (c->constant(getThunk(t, releaseMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), fieldOperand); + } else { + c->loadBarrier(); + } } } break; @@ -3416,15 +3439,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case monitorenter: { c->call (c->constant(getThunk(t, acquireMonitorForObjectThunk)), - 0, - frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case monitorexit: { c->call (c->constant(getThunk(t, releaseMonitorForObjectThunk)), - 0, - frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case multianewarray: { @@ -3565,8 +3586,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, table = frame->popObject(); } + Compiler::Operand* fieldOperand = 0; + if (fieldFlags(t, field) & ACC_VOLATILE) { - c->storeStoreBarrier(); + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + fieldOperand = frame->append(field); + + c->call + (c->constant(getThunk(t, acquireMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), fieldOperand); + } else { + c->storeStoreBarrier(); + } } switch (fieldCode(t, field)) { @@ -3613,7 +3647,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } if (fieldFlags(t, field) & ACC_VOLATILE) { - c->storeLoadBarrier(); + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + c->call + (c->constant(getThunk(t, releaseMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), fieldOperand); + } else { + c->storeLoadBarrier(); + } } } break; diff --git a/src/interpret.cpp b/src/interpret.cpp index 74ae8f55bf..75021974c6 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -1456,10 +1456,25 @@ interpret(Thread* t) assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); + if (UNLIKELY((fieldFlags(t, field) & ACC_VOLATILE) + and BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField))) + { + acquire(t, field); + } + pushField(t, popObject(t), field); - if (fieldFlags(t, field) & ACC_VOLATILE) { - loadMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + release(t, field); + } else { + loadMemoryBarrier(); + } } } else { exception = makeNullPointerException(t); @@ -1479,10 +1494,25 @@ interpret(Thread* t) if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke; + if (UNLIKELY((fieldFlags(t, field) & ACC_VOLATILE) + and BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField))) + { + acquire(t, field); + } + pushField(t, classStaticTable(t, fieldClass(t, field)), field); - if (fieldFlags(t, field) & ACC_VOLATILE) { - loadMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + release(t, field); + } else { + loadMemoryBarrier(); + } } } goto loop; @@ -2411,8 +2441,15 @@ interpret(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (fieldFlags(t, field) & ACC_VOLATILE) { - storeStoreMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + acquire(t, field); + } else { + storeStoreMemoryBarrier(); + } } assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); @@ -2445,7 +2482,6 @@ interpret(Thread* t) } } else { exception = makeNullPointerException(t); - goto throw_; } } break; @@ -2457,7 +2493,6 @@ interpret(Thread* t) cast(o, fieldOffset(t, field)) = value; } else { exception = makeNullPointerException(t); - goto throw_; } } break; @@ -2468,15 +2503,25 @@ interpret(Thread* t) set(t, o, fieldOffset(t, field), value); } else { exception = makeNullPointerException(t); - goto throw_; } } break; default: abort(t); } - if (fieldFlags(t, field) & ACC_VOLATILE) { - storeLoadMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + release(t, field); + } else { + storeLoadMemoryBarrier(); + } + } + + if (UNLIKELY(exception)) { + goto throw_; } } goto loop; @@ -2486,8 +2531,15 @@ interpret(Thread* t) object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; - if (fieldFlags(t, field) & ACC_VOLATILE) { - storeStoreMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + acquire(t, field); + } else { + storeStoreMemoryBarrier(); + } } assert(t, fieldFlags(t, field) & ACC_STATIC); @@ -2536,8 +2588,15 @@ interpret(Thread* t) default: abort(t); } - if (fieldFlags(t, field) & ACC_VOLATILE) { - storeLoadMemoryBarrier(); + if (UNLIKELY(fieldFlags(t, field) & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (fieldCode(t, field) == DoubleField + or fieldCode(t, field) == LongField)) + { + release(t, field); + } else { + storeLoadMemoryBarrier(); + } } } goto loop; diff --git a/test/Misc.java b/test/Misc.java index d27f96a735..455a52a008 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -3,6 +3,8 @@ public class Misc { private static int beta; private static byte byte1, byte2, byte3; + private static volatile int volatileStatic; + private final int NonStaticConstant = 42; private int gamma; @@ -10,6 +12,7 @@ public class Misc { private boolean boolean1; private boolean boolean2; private long time; + private volatile int volatileMember; public Misc() { expect(! boolean1); @@ -132,13 +135,18 @@ public class Misc { int d = alpha; beta = 42; alpha = 43; + volatileStatic = 55; int e = beta; int f = alpha; + m.volatileMember = 23; m.gamma = 44; + m.volatileMember = 27; expect(beta == 42); expect(alpha == 43); expect(m.gamma == 44); + expect(volatileStatic == 55); + expect(m.volatileMember == 27); } expect(zip() == 47);