mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
implement support for volatile fields
This commit is contained in:
parent
8c9d625f8f
commit
2ca8132d97
@ -17,10 +17,13 @@
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Return
|
Return,
|
||||||
|
LoadBarrier,
|
||||||
|
StoreStoreBarrier,
|
||||||
|
StoreLoadBarrier
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned OperationCount = Return + 1;
|
const unsigned OperationCount = StoreLoadBarrier + 1;
|
||||||
|
|
||||||
enum UnaryOperation {
|
enum UnaryOperation {
|
||||||
Call,
|
Call,
|
||||||
|
@ -2603,7 +2603,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
if (throwIfVolatileField(t, field)) return;
|
|
||||||
|
|
||||||
Compiler::Operand* table;
|
Compiler::Operand* table;
|
||||||
|
|
||||||
@ -2675,6 +2674,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
default:
|
default:
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
c->loadBarrier();
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
@ -3505,7 +3508,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
object field = resolveField(t, codePool(t, code), index - 1);
|
object field = resolveField(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
if (throwIfVolatileField(t, field)) return;
|
|
||||||
|
|
||||||
object staticTable = 0;
|
object staticTable = 0;
|
||||||
|
|
||||||
@ -3563,6 +3565,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
table = frame->popObject();
|
table = frame->popObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
c->storeStoreBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
switch (fieldCode(t, field)) {
|
switch (fieldCode(t, field)) {
|
||||||
case ByteField:
|
case ByteField:
|
||||||
case BooleanField:
|
case BooleanField:
|
||||||
@ -3605,6 +3611,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
c->storeLoadBarrier();
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ret:
|
case ret:
|
||||||
@ -3613,6 +3623,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case return_:
|
case return_:
|
||||||
|
if ((methodFlags(t, context->method) & ConstructorFlag)
|
||||||
|
and (classFlags(t, methodClass(t, context->method))
|
||||||
|
& HasFinalMemberFlag))
|
||||||
|
{
|
||||||
|
c->storeStoreBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
handleExit(t, frame);
|
handleExit(t, frame);
|
||||||
c->return_(0, 0);
|
c->return_(0, 0);
|
||||||
return;
|
return;
|
||||||
|
@ -3320,6 +3320,29 @@ appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
|
|||||||
SiteMask(resultTypeMask, resultRegisterMask >> 32, AnyFrameIndex)));
|
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 {
|
class MemoryEvent: public Event {
|
||||||
public:
|
public:
|
||||||
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
|
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
|
||||||
@ -5175,6 +5198,18 @@ class MyCompiler: public Compiler {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void loadBarrier() {
|
||||||
|
appendBarrier(&c, LoadBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void storeStoreBarrier() {
|
||||||
|
appendBarrier(&c, StoreStoreBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void storeLoadBarrier() {
|
||||||
|
appendBarrier(&c, StoreLoadBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned compile() {
|
virtual unsigned compile() {
|
||||||
return c.machineCodeSize = ::compile(&c);
|
return c.machineCodeSize = ::compile(&c);
|
||||||
}
|
}
|
||||||
|
@ -124,6 +124,10 @@ class Compiler {
|
|||||||
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
virtual Operand* neg(unsigned size, Operand* a) = 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 compile() = 0;
|
||||||
virtual unsigned poolSize() = 0;
|
virtual unsigned poolSize() = 0;
|
||||||
virtual void writeTo(uint8_t* dst) = 0;
|
virtual void writeTo(uint8_t* dst) = 0;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
|
#include "arch.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -1452,11 +1453,14 @@ 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 (throwIfVolatileField(t, field)) goto throw_;
|
|
||||||
|
|
||||||
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
||||||
|
|
||||||
pushField(t, popObject(t), field);
|
pushField(t, popObject(t), field);
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
loadMemoryBarrier();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exception = makeNullPointerException(t);
|
exception = makeNullPointerException(t);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
@ -1468,7 +1472,6 @@ 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 (throwIfVolatileField(t, field)) goto throw_;
|
|
||||||
|
|
||||||
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
||||||
|
|
||||||
@ -1477,6 +1480,10 @@ interpret(Thread* t)
|
|||||||
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
if (UNLIKELY(classInit(t, fieldClass(t, field), 3))) goto invoke;
|
||||||
|
|
||||||
pushField(t, classStaticTable(t, fieldClass(t, field)), field);
|
pushField(t, classStaticTable(t, fieldClass(t, field)), field);
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
loadMemoryBarrier();
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case goto_: {
|
case goto_: {
|
||||||
@ -2403,7 +2410,10 @@ 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 (throwIfVolatileField(t, field)) goto throw_;
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
storeStoreMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
||||||
|
|
||||||
@ -2464,6 +2474,10 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
storeLoadMemoryBarrier();
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case putstatic: {
|
case putstatic: {
|
||||||
@ -2471,7 +2485,10 @@ 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 (throwIfVolatileField(t, field)) goto throw_;
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
storeStoreMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
||||||
|
|
||||||
@ -2518,6 +2535,10 @@ interpret(Thread* t)
|
|||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
||||||
|
storeLoadMemoryBarrier();
|
||||||
|
}
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case ret: {
|
case ret: {
|
||||||
@ -2525,6 +2546,13 @@ interpret(Thread* t)
|
|||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case return_: {
|
case return_: {
|
||||||
|
object method = frameMethod(t, frame);
|
||||||
|
if ((methodFlags(t, method) & ConstructorFlag)
|
||||||
|
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag))
|
||||||
|
{
|
||||||
|
storeStoreMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
if (frame > base) {
|
if (frame > base) {
|
||||||
popFrame(t);
|
popFrame(t);
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -835,6 +835,10 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
|
|
||||||
staticTypes[staticCount++] = code;
|
staticTypes[staticCount++] = code;
|
||||||
} else {
|
} else {
|
||||||
|
if (flags & ACC_FINAL) {
|
||||||
|
classFlags(t, class_) |= HasFinalMemberFlag;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
|
unsigned excess = (memberOffset % fieldSize(t, code)) % BytesPerWord;
|
||||||
if (excess) {
|
if (excess) {
|
||||||
memberOffset += BytesPerWord - excess;
|
memberOffset += BytesPerWord - excess;
|
||||||
@ -1160,6 +1164,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
{
|
{
|
||||||
methodVmFlags(t, method) |= ClassInitFlag;
|
methodVmFlags(t, method) |= ClassInitFlag;
|
||||||
classVmFlags(t, class_) |= NeedInitFlag;
|
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 PrimitiveFlag = 1 << 4;
|
||||||
const unsigned SingletonFlag = 1 << 5;
|
const unsigned SingletonFlag = 1 << 5;
|
||||||
const unsigned BootstrapFlag = 1 << 6;
|
const unsigned BootstrapFlag = 1 << 6;
|
||||||
|
const unsigned HasFinalMemberFlag = 1 << 7;
|
||||||
|
|
||||||
// method flags:
|
// method flags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
const unsigned CompiledFlag = 1 << 1;
|
const unsigned CompiledFlag = 1 << 1;
|
||||||
|
const unsigned ConstructorFlag = 1 << 2;
|
||||||
|
|
||||||
typedef Machine JavaVM;
|
typedef Machine JavaVM;
|
||||||
typedef Thread JNIEnv;
|
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 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 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 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
|
// PSEUDO-INSTRUCTIONS
|
||||||
inline int li(int rt, int i) { return addi(rt, 0, i); }
|
inline int li(int rt, int i) { return addi(rt, 0, i); }
|
||||||
inline int lis(int rt, int i) { return addis(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());
|
issue(c, blr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memoryBarrier(Context* c)
|
||||||
|
{
|
||||||
|
issue(c, sync(0));
|
||||||
|
}
|
||||||
|
|
||||||
// END OPERATION COMPILERS
|
// END OPERATION COMPILERS
|
||||||
|
|
||||||
|
|
||||||
@ -1487,6 +1494,9 @@ populateTables(ArchitectureContext* c)
|
|||||||
TernaryOperationType* to = c->ternaryOperations;
|
TernaryOperationType* to = c->ternaryOperations;
|
||||||
|
|
||||||
zo[Return] = return_;
|
zo[Return] = return_;
|
||||||
|
zo[LoadBarrier] = memoryBarrier;
|
||||||
|
zo[StoreStoreBarrier] = memoryBarrier;
|
||||||
|
zo[StoreLoadBarrier] = memoryBarrier;
|
||||||
|
|
||||||
uo[index(LongCall, C)] = CAST1(longCallC);
|
uo[index(LongCall, C)] = CAST1(longCallC);
|
||||||
|
|
||||||
|
@ -49,6 +49,24 @@ memoryBarrier()
|
|||||||
__asm__ __volatile__("sync": : :"memory");
|
__asm__ __volatile__("sync": : :"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
storeStoreMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
storeLoadMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
loadMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
|
||||||
unsigned argumentCount, unsigned argumentsSize,
|
unsigned argumentCount, unsigned argumentsSize,
|
||||||
|
@ -188,21 +188,6 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
|||||||
int
|
int
|
||||||
findLineNumber(Thread* t, object method, unsigned ip);
|
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
|
} // namespace vm
|
||||||
|
|
||||||
#endif//PROCESS_H
|
#endif//PROCESS_H
|
||||||
|
@ -470,6 +470,10 @@ return_(Context* c)
|
|||||||
c->code.append(0xc3);
|
c->code.append(0xc3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ignore(Context*)
|
||||||
|
{ }
|
||||||
|
|
||||||
void
|
void
|
||||||
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
||||||
{
|
{
|
||||||
@ -1897,6 +1901,9 @@ populateTables(ArchitectureContext* c)
|
|||||||
BinaryOperationType* bo = c->binaryOperations;
|
BinaryOperationType* bo = c->binaryOperations;
|
||||||
|
|
||||||
zo[Return] = return_;
|
zo[Return] = return_;
|
||||||
|
zo[LoadBarrier] = ignore;
|
||||||
|
zo[StoreStoreBarrier] = ignore;
|
||||||
|
zo[StoreLoadBarrier] = ignore;
|
||||||
|
|
||||||
uo[index(Call, C)] = CAST1(callC);
|
uo[index(Call, C)] = CAST1(callC);
|
||||||
uo[index(Call, R)] = CAST1(callR);
|
uo[index(Call, R)] = CAST1(callR);
|
||||||
|
19
src/x86.h
19
src/x86.h
@ -53,6 +53,25 @@ memoryBarrier()
|
|||||||
__asm__ __volatile__("": : :"memory");
|
__asm__ __volatile__("": : :"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
storeStoreMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
storeLoadMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
loadMemoryBarrier()
|
||||||
|
{
|
||||||
|
memoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||||
|
Loading…
Reference in New Issue
Block a user