[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