mirror of
https://github.com/corda/corda.git
synced 2025-06-16 06:08:13 +00:00
ensure reads and writes of volatile 64-bit fields are atomic
This commit is contained in:
@ -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)) {
|
switch (fieldCode(t, field)) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
case BooleanField:
|
case BooleanField:
|
||||||
@ -2676,8 +2690,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
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();
|
c->loadBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
@ -3416,15 +3439,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case monitorenter: {
|
case monitorenter: {
|
||||||
c->call
|
c->call
|
||||||
(c->constant(getThunk(t, acquireMonitorForObjectThunk)),
|
(c->constant(getThunk(t, acquireMonitorForObjectThunk)),
|
||||||
0,
|
0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject());
|
||||||
frame->trace(0, false), 0, 2, c->thread(), frame->popObject());
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case monitorexit: {
|
case monitorexit: {
|
||||||
c->call
|
c->call
|
||||||
(c->constant(getThunk(t, releaseMonitorForObjectThunk)),
|
(c->constant(getThunk(t, releaseMonitorForObjectThunk)),
|
||||||
0,
|
0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject());
|
||||||
frame->trace(0, false), 0, 2, c->thread(), frame->popObject());
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case multianewarray: {
|
case multianewarray: {
|
||||||
@ -3565,9 +3586,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
table = frame->popObject();
|
table = frame->popObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Compiler::Operand* fieldOperand = 0;
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
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();
|
c->storeStoreBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (fieldCode(t, field)) {
|
switch (fieldCode(t, field)) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
@ -3613,8 +3647,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
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();
|
c->storeLoadBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ret:
|
case ret:
|
||||||
|
@ -1456,11 +1456,26 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
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);
|
pushField(t, popObject(t), field);
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
loadMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
@ -1479,11 +1494,26 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
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);
|
pushField(t, classStaticTable(t, fieldClass(t, field)), field);
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
loadMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
@ -2411,9 +2441,16 @@ interpret(Thread* t)
|
|||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
storeStoreMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
||||||
|
|
||||||
@ -2445,7 +2482,6 @@ interpret(Thread* t)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -2457,7 +2493,6 @@ interpret(Thread* t)
|
|||||||
cast<int64_t>(o, fieldOffset(t, field)) = value;
|
cast<int64_t>(o, fieldOffset(t, field)) = value;
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -2468,16 +2503,26 @@ interpret(Thread* t)
|
|||||||
set(t, o, fieldOffset(t, field), value);
|
set(t, o, fieldOffset(t, field), value);
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
storeLoadMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(exception)) {
|
||||||
|
goto throw_;
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case putstatic: {
|
case putstatic: {
|
||||||
@ -2486,9 +2531,16 @@ interpret(Thread* t)
|
|||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
storeStoreMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
||||||
|
|
||||||
@ -2536,9 +2588,16 @@ interpret(Thread* t)
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
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();
|
storeLoadMemoryBarrier();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case ret: {
|
case ret: {
|
||||||
|
@ -3,6 +3,8 @@ public class Misc {
|
|||||||
private static int beta;
|
private static int beta;
|
||||||
private static byte byte1, byte2, byte3;
|
private static byte byte1, byte2, byte3;
|
||||||
|
|
||||||
|
private static volatile int volatileStatic;
|
||||||
|
|
||||||
private final int NonStaticConstant = 42;
|
private final int NonStaticConstant = 42;
|
||||||
|
|
||||||
private int gamma;
|
private int gamma;
|
||||||
@ -10,6 +12,7 @@ public class Misc {
|
|||||||
private boolean boolean1;
|
private boolean boolean1;
|
||||||
private boolean boolean2;
|
private boolean boolean2;
|
||||||
private long time;
|
private long time;
|
||||||
|
private volatile int volatileMember;
|
||||||
|
|
||||||
public Misc() {
|
public Misc() {
|
||||||
expect(! boolean1);
|
expect(! boolean1);
|
||||||
@ -132,13 +135,18 @@ public class Misc {
|
|||||||
int d = alpha;
|
int d = alpha;
|
||||||
beta = 42;
|
beta = 42;
|
||||||
alpha = 43;
|
alpha = 43;
|
||||||
|
volatileStatic = 55;
|
||||||
int e = beta;
|
int e = beta;
|
||||||
int f = alpha;
|
int f = alpha;
|
||||||
|
m.volatileMember = 23;
|
||||||
m.gamma = 44;
|
m.gamma = 44;
|
||||||
|
m.volatileMember = 27;
|
||||||
|
|
||||||
expect(beta == 42);
|
expect(beta == 42);
|
||||||
expect(alpha == 43);
|
expect(alpha == 43);
|
||||||
expect(m.gamma == 44);
|
expect(m.gamma == 44);
|
||||||
|
expect(volatileStatic == 55);
|
||||||
|
expect(m.volatileMember == 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(zip() == 47);
|
expect(zip() == 47);
|
||||||
|
Reference in New Issue
Block a user