fix handling of volatile longs and doubles on PowerPC

We were miscompiling methods which contained getfield, getstatic,
putfield, or putstatic instructions for volatile 64-bit primitives on
32-bit PowerPC due to not noticing that values in registers are clobbered
across function calls.

The solution is to create a separate Compiler::Operand instance for each
object monitor reference before and after the function call to avoid
confusing the compiler.  To avoid duplicate entries in the constant pool,
we add code look for and, if found, reuse any existing entry for the same
constant.
This commit is contained in:
Joel Dice 2010-01-27 17:46:04 -07:00
parent 2868413b51
commit 45476eb591
2 changed files with 14 additions and 12 deletions

View File

@ -1101,6 +1101,12 @@ class Frame {
return c->promiseConstant(p, Compiler::ObjectType);
} else {
for (PoolElement* e = context->objectPool; e; e = e->next) {
if (o == e->target) {
return c->address(e);
}
}
context->objectPool = new
(context->zone.allocate(sizeof(PoolElement)))
PoolElement(t, o, context->objectPool);
@ -3555,21 +3561,17 @@ 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), Compiler::AddressType),
0, frame->trace(0, 0), 0, Compiler::VoidType, 2,
c->register_(t->arch->thread()),
fieldOperand);
frame->append(field));
}
switch (fieldCode(t, field)) {
@ -3652,7 +3654,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::AddressType),
0, frame->trace(0, 0), 0, Compiler::VoidType, 2,
c->register_(t->arch->thread()),
fieldOperand);
frame->append(field));
} else {
c->loadBarrier();
}
@ -4571,21 +4573,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
table = frame->popObject();
}
Compiler::Operand* fieldOperand = 0;
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),
Compiler::AddressType),
0, frame->trace(0, 0), 0, Compiler::VoidType, 2,
c->register_(t->arch->thread()), fieldOperand);
c->register_(t->arch->thread()), frame->append(field));
} else {
c->storeStoreBarrier();
}
@ -4663,7 +4661,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
(getThunk(t, releaseMonitorForObjectThunk),
Compiler::AddressType),
0, frame->trace(0, 0), 0, Compiler::VoidType, 2,
c->register_(t->arch->thread()), fieldOperand);
c->register_(t->arch->thread()), frame->append(field));
} else {
c->storeLoadBarrier();
}

View File

@ -5,6 +5,8 @@ public class Misc {
private static volatile int volatileStatic;
private static volatile long volatileStaticLong;
private final int NonStaticConstant = 42;
private int gamma;
@ -131,6 +133,7 @@ public class Misc {
beta = 42;
alpha = 43;
volatileStatic = 55;
volatileStaticLong = 9L;
int e = beta;
int f = alpha;
m.volatileMember = 23;
@ -141,6 +144,7 @@ public class Misc {
expect(alpha == 43);
expect(m.gamma == 44);
expect(volatileStatic == 55);
expect(volatileStaticLong == 9L);
expect(m.volatileMember == 27);
}