diff --git a/src/assembler.h b/src/assembler.h index b7248dd583..6aa6242072 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -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, diff --git a/src/compile.cpp b/src/compile.cpp index 437bb70790..1e3a18e49d 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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; diff --git a/src/compiler.cpp b/src/compiler.cpp index 820a1ee339..5dea180685 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -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); } diff --git a/src/compiler.h b/src/compiler.h index fe4e427ade..bfcd5842c1 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -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; diff --git a/src/interpret.cpp b/src/interpret.cpp index d3919f7117..74ae8f55bf 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -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; diff --git a/src/machine.cpp b/src/machine.cpp index fa7cae8707..335e9cf9d6 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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(""), + &byteArrayBody(t, methodName(t, method), 0)) == 0) + { + methodVmFlags(t, method) |= ConstructorFlag; } } diff --git a/src/machine.h b/src/machine.h index 06e3298fea..63806421f8 100644 --- a/src/machine.h +++ b/src/machine.h @@ -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; diff --git a/src/powerpc.cpp b/src/powerpc.cpp index edfcf07e4b..2db705efaf 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -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); diff --git a/src/powerpc.h b/src/powerpc.h index feb6c7b285..cd90bdc484 100644 --- a/src/powerpc.h +++ b/src/powerpc.h @@ -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, diff --git a/src/process.h b/src/process.h index 8be25c0bd0..78c231b307 100644 --- a/src/process.h +++ b/src/process.h @@ -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 diff --git a/src/x86.cpp b/src/x86.cpp index 77c91367cd..c63ba57365 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -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); diff --git a/src/x86.h b/src/x86.h index 71d84e140c..578d27690b 100644 --- a/src/x86.h +++ b/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)