ensure reads and writes of volatile 64-bit fields are atomic

This commit is contained in:
Joel Dice 2009-03-03 18:02:11 -07:00
parent 2ca8132d97
commit 8410e1d683
3 changed files with 132 additions and 22 deletions

View File

@ -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;

View File

@ -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<int64_t>(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;

View File

@ -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);