implement support for volatile fields

This commit is contained in:
Joel Dice 2009-03-02 20:18:15 -07:00
parent 8c9d625f8f
commit 2ca8132d97
12 changed files with 159 additions and 23 deletions

View File

@ -17,10 +17,13 @@
namespace vm {
enum Operation {
Return
Return,
LoadBarrier,
StoreStoreBarrier,
StoreLoadBarrier
};
const unsigned OperationCount = Return + 1;
const unsigned OperationCount = StoreLoadBarrier + 1;
enum UnaryOperation {
Call,

View File

@ -2603,7 +2603,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (throwIfVolatileField(t, field)) return;
Compiler::Operand* table;
@ -2675,6 +2674,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
default:
abort(t);
}
if (fieldFlags(t, field) & ACC_VOLATILE) {
c->loadBarrier();
}
} break;
case goto_: {
@ -3505,7 +3508,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
if (throwIfVolatileField(t, field)) return;
object staticTable = 0;
@ -3563,6 +3565,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
table = frame->popObject();
}
if (fieldFlags(t, field) & ACC_VOLATILE) {
c->storeStoreBarrier();
}
switch (fieldCode(t, field)) {
case ByteField:
case BooleanField:
@ -3605,6 +3611,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
default: abort(t);
}
if (fieldFlags(t, field) & ACC_VOLATILE) {
c->storeLoadBarrier();
}
} break;
case ret:
@ -3613,6 +3623,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
return;
case return_:
if ((methodFlags(t, context->method) & ConstructorFlag)
and (classFlags(t, methodClass(t, context->method))
& HasFinalMemberFlag))
{
c->storeStoreBarrier();
}
handleExit(t, frame);
c->return_(0, 0);
return;

View File

@ -3320,6 +3320,29 @@ appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
SiteMask(resultTypeMask, resultRegisterMask >> 32, AnyFrameIndex)));
}
class BarrierEvent: public Event {
public:
BarrierEvent(Context* c, Operation op):
Event(c), op(op)
{ }
virtual const char* name() {
return "BarrierEvent";
}
virtual void compile(Context* c) {
c->assembler->apply(op);
}
Operation op;
};
void
appendBarrier(Context* c, Operation op)
{
append(c, new (c->zone->allocate(sizeof(BarrierEvent))) BarrierEvent(c, op));
}
class MemoryEvent: public Event {
public:
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
@ -5175,6 +5198,18 @@ class MyCompiler: public Compiler {
return result;
}
virtual void loadBarrier() {
appendBarrier(&c, LoadBarrier);
}
virtual void storeStoreBarrier() {
appendBarrier(&c, StoreStoreBarrier);
}
virtual void storeLoadBarrier() {
appendBarrier(&c, StoreLoadBarrier);
}
virtual unsigned compile() {
return c.machineCodeSize = ::compile(&c);
}

View File

@ -124,6 +124,10 @@ class Compiler {
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
virtual Operand* neg(unsigned size, Operand* a) = 0;
virtual void loadBarrier() = 0;
virtual void storeStoreBarrier() = 0;
virtual void storeLoadBarrier() = 0;
virtual unsigned compile() = 0;
virtual unsigned poolSize() = 0;
virtual void writeTo(uint8_t* dst) = 0;

View File

@ -14,6 +14,7 @@
#include "machine.h"
#include "processor.h"
#include "process.h"
#include "arch.h"
using namespace vm;
@ -1452,11 +1453,14 @@ interpret(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (throwIfVolatileField(t, field)) goto throw_;
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
pushField(t, popObject(t), field);
if (fieldFlags(t, field) & ACC_VOLATILE) {
loadMemoryBarrier();
}
} else {
exception = makeNullPointerException(t);
goto throw_;
@ -1468,7 +1472,6 @@ interpret(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (throwIfVolatileField(t, field)) goto throw_;
assert(t, fieldFlags(t, field) & ACC_STATIC);
@ -1477,6 +1480,10 @@ interpret(Thread* t)
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
pushField(t, classStaticTable(t, fieldClass(t, field)), field);
if (fieldFlags(t, field) & ACC_VOLATILE) {
loadMemoryBarrier();
}
} goto loop;
case goto_: {
@ -2403,7 +2410,10 @@ interpret(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (throwIfVolatileField(t, field)) goto throw_;
if (fieldFlags(t, field) & ACC_VOLATILE) {
storeStoreMemoryBarrier();
}
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
@ -2464,6 +2474,10 @@ interpret(Thread* t)
default: abort(t);
}
if (fieldFlags(t, field) & ACC_VOLATILE) {
storeLoadMemoryBarrier();
}
} goto loop;
case putstatic: {
@ -2471,7 +2485,10 @@ interpret(Thread* t)
object field = resolveField(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
if (throwIfVolatileField(t, field)) goto throw_;
if (fieldFlags(t, field) & ACC_VOLATILE) {
storeStoreMemoryBarrier();
}
assert(t, fieldFlags(t, field) & ACC_STATIC);
@ -2518,6 +2535,10 @@ interpret(Thread* t)
default: abort(t);
}
if (fieldFlags(t, field) & ACC_VOLATILE) {
storeLoadMemoryBarrier();
}
} goto loop;
case ret: {
@ -2525,6 +2546,13 @@ interpret(Thread* t)
} goto loop;
case return_: {
object method = frameMethod(t, frame);
if ((methodFlags(t, method) & ConstructorFlag)
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
{
storeStoreMemoryBarrier();
}
if (frame > base) {
popFrame(t);
goto loop;

View File

@ -835,6 +835,10 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
staticTypes[staticCount++] = code;
} else {
if (flags & ACC_FINAL) {
classFlags(t, class_) |= HasFinalMemberFlag;
}
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
if (excess) {
memberOffset += BytesPerWord - excess;
@ -1160,6 +1164,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
{
methodVmFlags(t, method) |= ClassInitFlag;
classVmFlags(t, class_) |= NeedInitFlag;
} else if (strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0)) == 0)
{
methodVmFlags(t, method) |= ConstructorFlag;
}
}

View File

@ -82,10 +82,12 @@ const unsigned InitFlag = 1 << 3;
const unsigned PrimitiveFlag = 1 << 4;
const unsigned SingletonFlag = 1 << 5;
const unsigned BootstrapFlag = 1 << 6;
const unsigned HasFinalMemberFlag = 1 << 7;
// method flags:
const unsigned ClassInitFlag = 1 << 0;
const unsigned CompiledFlag = 1 << 1;
const unsigned ConstructorFlag = 1 << 2;
typedef Machine JavaVM;
typedef Thread JNIEnv;

View File

@ -114,6 +114,7 @@ inline int cmp(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 0, 0); }
inline int cmpl(int bf, int ra, int rb) { return X(31, bf << 2, ra, rb, 32, 0); }
inline int cmpi(int bf, int ra, int i) { return D(11, bf << 2, ra, i); }
inline int cmpli(int bf, int ra, int i) { return D(10, bf << 2, ra, i); }
inline int sync(int L) { return X(31, L, 0, 0, 598, 0); }
// PSEUDO-INSTRUCTIONS
inline int li(int rt, int i) { return addi(rt, 0, i); }
inline int lis(int rt, int i) { return addis(rt, 0, i); }
@ -1470,6 +1471,12 @@ return_(Context* c)
issue(c, blr());
}
void
memoryBarrier(Context* c)
{
issue(c, sync(0));
}
// END OPERATION COMPILERS
@ -1487,6 +1494,9 @@ populateTables(ArchitectureContext* c)
TernaryOperationType* to = c->ternaryOperations;
zo[Return] = return_;
zo[LoadBarrier] = memoryBarrier;
zo[StoreStoreBarrier] = memoryBarrier;
zo[StoreLoadBarrier] = memoryBarrier;
uo[index(LongCall, C)] = CAST1(longCallC);

View File

@ -49,6 +49,24 @@ memoryBarrier()
__asm__ __volatile__("sync": : :"memory");
}
inline void
storeStoreMemoryBarrier()
{
memoryBarrier();
}
inline void
storeLoadMemoryBarrier()
{
memoryBarrier();
}
inline void
loadMemoryBarrier()
{
memoryBarrier();
}
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned argumentsSize,

View File

@ -188,21 +188,6 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
int
findLineNumber(Thread* t, object method, unsigned ip);
inline bool
throwIfVolatileField(Thread* t, object field)
{
if (fieldFlags(t, field) & ACC_VOLATILE) {
object message = makeString
(t, "volatile fields are not yet supported: %s.%s",
&byteArrayBody(t, className(t, fieldClass(t, field)), 0),
&byteArrayBody(t, fieldName(t, field), 0));
t->exception = makeNoSuchFieldError(t, message);
return true;
} else {
return false;
}
}
} // namespace vm
#endif//PROCESS_H

View File

@ -470,6 +470,10 @@ return_(Context* c)
c->code.append(0xc3);
}
void
ignore(Context*)
{ }
void
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
{
@ -1897,6 +1901,9 @@ populateTables(ArchitectureContext* c)
BinaryOperationType* bo = c->binaryOperations;
zo[Return] = return_;
zo[LoadBarrier] = ignore;
zo[StoreStoreBarrier] = ignore;
zo[StoreLoadBarrier] = ignore;
uo[index(Call, C)] = CAST1(callC);
uo[index(Call, R)] = CAST1(callR);

View File

@ -53,6 +53,25 @@ memoryBarrier()
__asm__ __volatile__("": : :"memory");
}
inline void
storeStoreMemoryBarrier()
{
memoryBarrier();
}
inline void
storeLoadMemoryBarrier()
{
memoryBarrier();
}
inline void
loadMemoryBarrier()
{
memoryBarrier();
}
inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
unsigned, unsigned argumentsSize, unsigned returnType)