mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
implement support for volatile fields
This commit is contained in:
parent
8c9d625f8f
commit
2ca8132d97
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
19
src/x86.h
19
src/x86.h
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user