[vmkit-commits] [vmkit] r68608 - in /vmkit/trunk: include/mvm/JIT.h include/mvm/Threads/Locks.h lib/JnJVM/Compiler/JavaAOTCompiler.cpp lib/JnJVM/Compiler/JavaJIT.cpp lib/JnJVM/Compiler/JavaJITOpcodes.cpp lib/Mvm/Compiler/JIT.cpp
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Wed Apr 8 06:56:39 PDT 2009
Author: geoffray
Date: Wed Apr 8 08:56:36 2009
New Revision: 68608
URL: http://llvm.org/viewvc/llvm-project?rev=68608&view=rev
Log:
Put back thin locks instead of biased locks because we need safe points
for a correct implementation.
Modified:
vmkit/trunk/include/mvm/JIT.h
vmkit/trunk/include/mvm/Threads/Locks.h
vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp
vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp
vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp
vmkit/trunk/lib/Mvm/Compiler/JIT.cpp
Modified: vmkit/trunk/include/mvm/JIT.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/JIT.h?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/JIT.h (original)
+++ vmkit/trunk/include/mvm/JIT.h Wed Apr 8 08:56:36 2009
@@ -109,6 +109,7 @@
llvm::Function* llvm_atomic_lcs_i16;
llvm::Function* llvm_atomic_lcs_i32;
llvm::Function* llvm_atomic_lcs_i64;
+ llvm::Function* llvm_atomic_lcs_ptr;
static llvm::ConstantInt* constantInt8Zero;
@@ -151,9 +152,9 @@
static llvm::Constant* constantPtrNull;
static llvm::ConstantInt* constantPtrSize;
static llvm::ConstantInt* constantThreadIDMask;
- static llvm::ConstantInt* constantLockedMask;
- static llvm::ConstantInt* constantThreadFreeMask;
+ static llvm::ConstantInt* constantFatMask;
static llvm::ConstantInt* constantPtrOne;
+ static llvm::ConstantInt* constantPtrZero;
static const llvm::PointerType* ptrType;
static const llvm::PointerType* ptr32Type;
static const llvm::PointerType* ptrPtrType;
Modified: vmkit/trunk/include/mvm/Threads/Locks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Locks.h?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/Threads/Locks.h (original)
+++ vmkit/trunk/include/mvm/Threads/Locks.h Wed Apr 8 08:56:36 2009
@@ -148,13 +148,10 @@
#endif
static const uint64_t ThinMask = 0x7FFFFF00;
- static const uint64_t ReservedMask = 0X7FFFFFFF;
static const uint64_t ThinCountMask = 0xFF;
-/// ThinLock - This class is an implementation of thin locks with reservation.
-/// The creator of the lock reserves this lock so that a lock only needs
-/// a comparison and not an expensive compare and swap. The template class
+/// ThinLock - This class is an implementation of thin locks. The template class
/// TFatLock is a virtual machine specific fat lock.
///
template <class TFatLock, class Owner>
@@ -166,7 +163,7 @@
/// we have reached 0xFF locks.
void overflowThinLock(Owner* O = 0) {
TFatLock* obj = TFatLock::allocate(O);
- obj->acquireAll(256);
+ obj->acquireAll(257);
lock = ((uintptr_t)obj >> 1) | FatMask;
}
@@ -174,7 +171,7 @@
/// creating this lock.
///
void initialise() {
- lock = (uintptr_t)mvm::Thread::get()->getThreadID();
+ lock = 0;
}
/// ThinLock - Calls initialize.
@@ -188,65 +185,54 @@
TFatLock* changeToFatlock(Owner* O) {
if (!(lock & FatMask)) {
TFatLock* obj = TFatLock::allocate(O);
- uintptr_t val = ((uintptr_t)obj >> 1) | FatMask;
- uint32 count = lock & ThinCountMask;
- obj->acquireAll(count);
+ uint32 val = (((uint32) obj) >> 1) | FatMask;
+ uint32 count = lock & 0xFF;
+ obj->acquireAll(count + 1);
lock = val;
return obj;
} else {
return (TFatLock*)(lock << 1);
}
}
-
/// acquire - Acquire the lock.
void acquire(Owner* O = 0) {
uint64_t id = mvm::Thread::get()->getThreadID();
- if ((lock & ReservedMask) == id) {
- lock |= 1;
- } else if ((lock & ThinMask) == id) {
- if ((lock & ThinCountMask) == ThinCountMask) {
- overflowThinLock(O);
- } else {
- ++lock;
- }
- } else {
- uintptr_t currentLock = lock & ThinMask;
- uintptr_t val =
- (uintptr_t)__sync_val_compare_and_swap((uintptr_t)&lock, currentLock,
- (id + 1));
- if (val != currentLock) {
- if (val & FatMask) {
-end:
- //fat lock!
- TFatLock* obj = (TFatLock*)(lock << 1);
- obj->acquire();
+ uintptr_t val = __sync_val_compare_and_swap((uintptr_t)&lock, 0, id);
+
+ if (val != 0) {
+ //fat!
+ if (!(val & FatMask)) {
+ if ((val & ThinMask) == id) {
+ if ((val & ThinCountMask) != ThinCountMask) {
+ lock++;
+ } else {
+ overflowThinLock(O);
+ }
} else {
TFatLock* obj = TFatLock::allocate(O);
- val = ((uintptr_t)obj >> 1) | FatMask;
- uint32 count = 0;
+ uintptr_t val = ((uintptr_t)obj >> 1) | FatMask;
loop:
- if (lock & FatMask) goto end;
-
- while ((lock & ThinCountMask) != 0) {
+ uint32 count = 0;
+ while (lock) {
if (lock & FatMask) {
#ifdef USE_GC_BOEHM
delete obj;
#endif
goto end;
}
- else {
- mvm::Thread::yield(&count);
- }
+ else mvm::Thread::yield(&count);
}
- currentLock = lock & ThinMask;
- uintptr_t test =
- (uintptr_t)__sync_val_compare_and_swap((uintptr_t)&lock,
- currentLock, val);
- if (test != currentLock) goto loop;
+ uintptr_t test = __sync_val_compare_and_swap((uintptr_t*)&lock, 0, val);
+ if (test) goto loop;
obj->acquire();
}
+ } else {
+
+end:
+ TFatLock* obj = (TFatLock*)(lock << 1);
+ obj->acquire();
}
}
}
@@ -254,12 +240,14 @@
/// release - Release the lock.
void release() {
uint64 id = mvm::Thread::get()->getThreadID();
- if ((lock & ThinMask) == id) {
- --lock;
- } else {
+ if (lock == id) {
+ lock = 0;
+ } else if (lock & FatMask) {
TFatLock* obj = (TFatLock*)(lock << 1);
obj->release();
- }
+ } else {
+ lock--;
+ }
}
/// broadcast - Wakes up all threads waiting for this lock.
@@ -283,7 +271,8 @@
/// lock.
bool owner() {
uint64 id = mvm::Thread::get()->getThreadID();
- if ((lock & ThinMask) == id) return true;
+ if (id == lock) return true;
+ if ((lock & 0x7FFFFF00) == id) return true;
if (lock & FatMask) {
TFatLock* obj = (TFatLock*)(lock << 1);
return obj->owner();
Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp (original)
+++ vmkit/trunk/lib/JnJVM/Compiler/JavaAOTCompiler.cpp Wed Apr 8 08:56:36 2009
@@ -384,8 +384,7 @@
Elmts.push_back(Cl);
// lock
- Constant* L = ConstantInt::get(Type::Int64Ty,
- mvm::Thread::get()->getThreadID());
+ Constant* L = ConstantInt::get(Type::Int64Ty, 0);
Elmts.push_back(ConstantExpr::getIntToPtr(L, JnjvmModule::ptrType));
return ConstantStruct::get(STy, Elmts);
Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp (original)
+++ vmkit/trunk/lib/JnJVM/Compiler/JavaJIT.cpp Wed Apr 8 08:56:36 2009
@@ -386,85 +386,154 @@
return llvmFunction;
}
-
void JavaJIT::monitorEnter(Value* obj) {
-
- Value* gep[2] = { module->constantZero,
- module->JavaObjectLockOffsetConstant };
- Value* lockPtr = GetElementPtrInst::Create(obj, gep, gep + 2, "",
+ std::vector<Value*> gep;
+ gep.push_back(module->constantZero);
+ gep.push_back(module->JavaObjectLockOffsetConstant);
+ Value* lockPtr = GetElementPtrInst::Create(obj, gep.begin(), gep.end(), "",
currentBlock);
- Value* lock = new LoadInst(lockPtr, "", currentBlock);
- lock = new PtrToIntInst(lock, module->pointerSizeType, "", currentBlock);
- Value* lockMask = BinaryOperator::CreateAnd(lock,
- module->constantThreadFreeMask,
- "", currentBlock);
+ lockPtr = new BitCastInst(lockPtr,
+ PointerType::getUnqual(module->pointerSizeType),
+ "", currentBlock);
Value* threadId = getCurrentThread();
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
+
+ std::vector<Value*> atomicArgs;
+ atomicArgs.push_back(lockPtr);
+ atomicArgs.push_back(module->constantPtrZero);
+ atomicArgs.push_back(threadId);
+
+ // Do the atomic compare and swap.
+ Value* atomic = CallInst::Create(module->llvm_atomic_lcs_ptr,
+ atomicArgs.begin(), atomicArgs.end(), "",
+ currentBlock);
- Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lockMask, threadId, "",
- currentBlock);
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, atomic, module->constantPtrZero,
+ "", currentBlock);
- BasicBlock* ThinLockBB = createBasicBlock("thread local");
+ BasicBlock* OK = createBasicBlock("synchronize passed");
+ BasicBlock* NotOK = createBasicBlock("synchronize did not pass");
BasicBlock* FatLockBB = createBasicBlock("fat lock");
- BasicBlock* EndLockBB = createBasicBlock("End lock");
+ BasicBlock* ThinLockBB = createBasicBlock("thin lock");
+
+ BranchInst::Create(OK, NotOK, cmp, currentBlock);
+
+ currentBlock = NotOK;
+
+ // The compare and swap did not pass, look if it's a thin lock
+ Value* isThin = BinaryOperator::CreateAnd(atomic, module->constantFatMask, "",
+ currentBlock);
+ cmp = new ICmpInst(ICmpInst::ICMP_EQ, isThin, module->constantZero, "",
+ currentBlock);
BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock);
+ // It's a thin lock. Look if we're the owner of this lock.
currentBlock = ThinLockBB;
- Value* increment = BinaryOperator::CreateAdd(lock, module->constantPtrOne, "",
- currentBlock);
- increment = new IntToPtrInst(increment, module->ptrType, "", currentBlock);
- new StoreInst(increment, lockPtr, false, currentBlock);
- BranchInst::Create(EndLockBB, currentBlock);
+ Value* idMask = ConstantInt::get(module->pointerSizeType, 0x7FFFFF00);
+ Value* cptMask = ConstantInt::get(module->pointerSizeType, 0xFF);
+ Value* IdInLock = BinaryOperator::CreateAnd(atomic, idMask, "", currentBlock);
+ Value* owner = new ICmpInst(ICmpInst::ICMP_EQ, threadId, IdInLock, "",
+ currentBlock);
+
+ BasicBlock* OwnerBB = createBasicBlock("owner thread");
+
+ BranchInst::Create(OwnerBB, FatLockBB, owner, currentBlock);
+ currentBlock = OwnerBB;
+
+ // OK, we are the owner, now check if the counter will overflow.
+ Value* count = BinaryOperator::CreateAnd(atomic, cptMask, "", currentBlock);
+ cmp = new ICmpInst(ICmpInst::ICMP_ULT, count, cptMask, "", currentBlock);
+
+ BasicBlock* IncCounterBB = createBasicBlock("Increment counter");
+ BasicBlock* OverflowCounterBB = createBasicBlock("Overflow counter");
+
+ BranchInst::Create(IncCounterBB, OverflowCounterBB, cmp, currentBlock);
+ currentBlock = IncCounterBB;
+
+ // The counter will not overflow, increment it.
+ Value* Add = BinaryOperator::CreateAdd(module->constantPtrOne, atomic, "",
+ currentBlock);
+ new StoreInst(Add, lockPtr, false, currentBlock);
+ BranchInst::Create(OK, currentBlock);
+ currentBlock = OverflowCounterBB;
+
+ // The counter will overflow, call this function to create a new lock,
+ // lock it 0x101 times, and pass.
+ CallInst::Create(module->OverflowThinLockFunction, obj, "",
+ currentBlock);
+ BranchInst::Create(OK, currentBlock);
+
currentBlock = FatLockBB;
- // Either it's a fat lock or there is contention or it's not thread local or
- // it's locked at least once.
+ // Either it's a fat lock or there is contention.
CallInst::Create(module->AquireObjectFunction, obj, "", currentBlock);
-
- BranchInst::Create(EndLockBB, currentBlock);
- currentBlock = EndLockBB;
+ BranchInst::Create(OK, currentBlock);
+ currentBlock = OK;
}
void JavaJIT::monitorExit(Value* obj) {
- Value* gep[2] = { module->constantZero,
- module->JavaObjectLockOffsetConstant };
- Value* lockPtr = GetElementPtrInst::Create(obj, gep, gep + 2, "",
+ std::vector<Value*> gep;
+ gep.push_back(module->constantZero);
+ gep.push_back(module->JavaObjectLockOffsetConstant);
+ Value* lockPtr = GetElementPtrInst::Create(obj, gep.begin(), gep.end(), "",
currentBlock);
+ lockPtr = new BitCastInst(lockPtr,
+ PointerType::getUnqual(module->pointerSizeType),
+ "", currentBlock);
Value* lock = new LoadInst(lockPtr, "", currentBlock);
- lock = new PtrToIntInst(lock, module->pointerSizeType, "", currentBlock);
- Value* lockMask = BinaryOperator::CreateAnd(lock, module->constantLockedMask,
- "", currentBlock);
+
Value* threadId = getCurrentThread();
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
- Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lockMask, threadId, "",
+
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lock, threadId, "",
currentBlock);
BasicBlock* EndUnlock = createBasicBlock("end unlock");
- BasicBlock* ThinLockBB = createBasicBlock("desynchronize thin lock");
+ BasicBlock* LockedOnceBB = createBasicBlock("desynchronize thin lock");
+ BasicBlock* NotLockedOnceBB =
+ createBasicBlock("simple desynchronize did not pass");
BasicBlock* FatLockBB = createBasicBlock("fat lock");
+ BasicBlock* ThinLockBB = createBasicBlock("thin lock");
+
+ BranchInst::Create(LockedOnceBB, NotLockedOnceBB, cmp, currentBlock);
+
+ // Locked once, set zero
+ currentBlock = LockedOnceBB;
+ new StoreInst(module->constantPtrZero, lockPtr, false, currentBlock);
+ BranchInst::Create(EndUnlock, currentBlock);
+
+ currentBlock = NotLockedOnceBB;
+ // Look if the lock is thin.
+ Value* isThin = BinaryOperator::CreateAnd(lock, module->constantFatMask, "",
+ currentBlock);
+ cmp = new ICmpInst(ICmpInst::ICMP_EQ, isThin, module->constantPtrZero, "",
+ currentBlock);
BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock);
- // Locked by the thread, decrement.
currentBlock = ThinLockBB;
- Value* decrement = BinaryOperator::CreateSub(lock, module->constantPtrOne, "",
- currentBlock);
- decrement = new IntToPtrInst(decrement, module->ptrType, "", currentBlock);
- new StoreInst(decrement, lockPtr, false, currentBlock);
+
+ // Decrement the counter.
+ Value* Sub = BinaryOperator::CreateSub(lock, module->constantPtrOne, "",
+ currentBlock);
+ new StoreInst(Sub, lockPtr, false, currentBlock);
BranchInst::Create(EndUnlock, currentBlock);
- // Either it's a fat lock or there is contention or it's not thread local.
currentBlock = FatLockBB;
+
+ // Either it's a fat lock or there is contention.
CallInst::Create(module->ReleaseObjectFunction, obj, "", currentBlock);
BranchInst::Create(EndUnlock, currentBlock);
currentBlock = EndUnlock;
}
+
+
#ifdef ISOLATE_SHARING
Value* JavaJIT::getStaticInstanceCtp() {
Value* cl = getClassCtp();
@@ -1517,14 +1586,6 @@
Cl = new BitCastInst(Cl, module->JavaCommonClassType, "", currentBlock);
new StoreInst(Cl, GEP, currentBlock);
- Value* gep2[2] = { module->constantZero,
- module->JavaObjectLockOffsetConstant };
- Value* lockPtr = GetElementPtrInst::Create(val, gep2, gep2 + 2, "",
- currentBlock);
- Value* threadId = getCurrentThread();
- threadId = new BitCastInst(threadId, module->ptrType, "", currentBlock);
- new StoreInst(threadId, lockPtr, currentBlock);
-
push(val, false);
}
Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp (original)
+++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITOpcodes.cpp Wed Apr 8 08:56:36 2009
@@ -1950,16 +1950,6 @@
GEP = GetElementPtrInst::Create(res, gep, gep + 2, "", currentBlock);
new StoreInst(valCl, GEP, currentBlock);
- Value* gep1[2] = { module->constantZero,
- module->JavaObjectLockOffsetConstant };
- Value* lockPtr = GetElementPtrInst::Create(res, gep1, gep1 + 2,
- "", currentBlock);
- Value* threadId = getCurrentThread();
-
- threadId = new BitCastInst(threadId, module->ptrType, "", currentBlock);
-
- new StoreInst(threadId, lockPtr, currentBlock);
-
push(res, false);
break;
Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=68608&r1=68607&r2=68608&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original)
+++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Wed Apr 8 08:56:36 2009
@@ -117,9 +117,10 @@
constantDoubleMinusZero = ConstantFP::get(Type::DoubleTy, -0.0);
constantFloatMinusZero = ConstantFP::get(Type::FloatTy, -0.0f);
constantThreadIDMask = ConstantInt::get(pointerSizeType, mvm::Thread::IDMask);
- constantLockedMask = ConstantInt::get(pointerSizeType, ThinMask);
- constantThreadFreeMask = ConstantInt::get(pointerSizeType, ReservedMask);
+ constantFatMask = ConstantInt::get(pointerSizeType,
+ pointerSizeType == Type::Int32Ty ? 0x80000000 : 0x8000000000000000LL);
constantPtrOne = ConstantInt::get(pointerSizeType, 1);
+ constantPtrZero = ConstantInt::get(pointerSizeType, 0);
constantPtrNull = Constant::getNullValue(ptrType);
constantPtrSize = ConstantInt::get(Type::Int32Ty, sizeof(void*));
@@ -189,6 +190,9 @@
llvm_atomic_lcs_i16 = module->getFunction("llvm.atomic.cmp.swap.i16.p0i16");
llvm_atomic_lcs_i32 = module->getFunction("llvm.atomic.cmp.swap.i32.p0i32");
llvm_atomic_lcs_i64 = module->getFunction("llvm.atomic.cmp.swap.i64.p0i64");
+
+ llvm_atomic_lcs_ptr = pointerSizeType == Type::Int32Ty ? llvm_atomic_lcs_i32 :
+ llvm_atomic_lcs_i64;
}
@@ -232,9 +236,9 @@
llvm::Constant* MvmModule::constantPtrNull;
llvm::ConstantInt* MvmModule::constantPtrSize;
llvm::ConstantInt* MvmModule::constantThreadIDMask;
-llvm::ConstantInt* MvmModule::constantLockedMask;
-llvm::ConstantInt* MvmModule::constantThreadFreeMask;
+llvm::ConstantInt* MvmModule::constantFatMask;
llvm::ConstantInt* MvmModule::constantPtrOne;
+llvm::ConstantInt* MvmModule::constantPtrZero;
const llvm::PointerType* MvmModule::ptrType;
const llvm::PointerType* MvmModule::ptr32Type;
const llvm::PointerType* MvmModule::ptrPtrType;
More information about the vmkit-commits
mailing list