[vmkit-commits] [vmkit] r119377 - in /vmkit/branches/precise: include/mvm/Threads/ObjectLocks.h lib/J3/Classpath/ClasspathVMSystem.inc lib/J3/Classpath/ClasspathVMThread.inc lib/J3/Compiler/JavaAOTCompiler.cpp lib/J3/Compiler/JavaJIT.cpp lib/J3/Compiler/JavaJIT.h lib/J3/Compiler/JavaJITCompiler.cpp lib/J3/VMCore/JavaClass.cpp lib/J3/VMCore/JavaRuntimeJIT.cpp lib/J3/VMCore/ReferenceQueue.cpp lib/J3/VMCore/ReferenceQueue.h lib/Mvm/CommonThread/ObjectLocks.cpp lib/Mvm/CommonThread/Sigsegv.cpp lib/Mvm/CommonThread/ctthread.cpp

Nicolas Geoffray nicolas.geoffray at lip6.fr
Tue Nov 16 12:23:44 PST 2010


Author: geoffray
Date: Tue Nov 16 14:23:43 2010
New Revision: 119377

URL: http://llvm.org/viewvc/llvm-project?rev=119377&view=rev
Log:
Fix interface calls, class resolution, thread initialisation, and object locking.
Multi-threading with a copying collector now works!


Modified:
    vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h
    vmkit/branches/precise/lib/J3/Classpath/ClasspathVMSystem.inc
    vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc
    vmkit/branches/precise/lib/J3/Compiler/JavaAOTCompiler.cpp
    vmkit/branches/precise/lib/J3/Compiler/JavaJIT.cpp
    vmkit/branches/precise/lib/J3/Compiler/JavaJIT.h
    vmkit/branches/precise/lib/J3/Compiler/JavaJITCompiler.cpp
    vmkit/branches/precise/lib/J3/VMCore/JavaClass.cpp
    vmkit/branches/precise/lib/J3/VMCore/JavaRuntimeJIT.cpp
    vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.cpp
    vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.h
    vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp
    vmkit/branches/precise/lib/Mvm/CommonThread/Sigsegv.cpp
    vmkit/branches/precise/lib/Mvm/CommonThread/ctthread.cpp

Modified: vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h (original)
+++ vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h Tue Nov 16 14:23:43 2010
@@ -89,6 +89,7 @@
 
   friend class LockSystem;
   friend class LockingThread;
+  friend class ThinLock;
 };
 
 
@@ -154,7 +155,7 @@
 
   /// initialise - Initialise the value of the lock.
   ///
-  static void initialise(gc* object, LockSystem& table);
+  static void removeFatLock(FatLock* fatLock, LockSystem& table);
 
   /// overflowThinlock - Change the lock of this object to a fat lock because
   /// we have reached 0xFF locks.

Modified: vmkit/branches/precise/lib/J3/Classpath/ClasspathVMSystem.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Classpath/ClasspathVMSystem.inc?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Classpath/ClasspathVMSystem.inc (original)
+++ vmkit/branches/precise/lib/J3/Classpath/ClasspathVMSystem.inc Tue Nov 16 14:23:43 2010
@@ -35,6 +35,8 @@
   llvm_gcroot(src, 0);
   llvm_gcroot(dst, 0);
   llvm_gcroot(cur, 0);
+  assert(src->getVirtualTable());
+  assert(dst->getVirtualTable());
 
   JavaThread* th = JavaThread::get();
   Jnjvm *vm = th->getJVM();

Modified: vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc (original)
+++ vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc Tue Nov 16 14:23:43 2010
@@ -40,6 +40,10 @@
   llvm_gcroot(javaThread, 0);
 
   Jnjvm* vm = thread->getJVM();
+  // Wait some time to let the creator initialise these fields.
+  while ((thread->javaThread == NULL) || (thread->vmThread == NULL)) {
+    mvm::Thread::yield();
+  }
 
   // Ok, now that the thread is created we can set the the value of vmdata,
   // which is the JavaThread object.
@@ -90,9 +94,10 @@
   assert(javaThread && "VMThread with no Java equivalent");
  
   JavaThread* th = new JavaThread(vm);
-  th->initialise(javaThread, vmThread);
   if (!th) vm->outOfMemoryError();
   th->start((void (*)(mvm::Thread*))start);
+  // Now that the thread has been created, initialise its object fields.
+  th->initialise(javaThread, vmThread);
 
   END_NATIVE_EXCEPTION
 }

Modified: vmkit/branches/precise/lib/J3/Compiler/JavaAOTCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Compiler/JavaAOTCompiler.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Compiler/JavaAOTCompiler.cpp (original)
+++ vmkit/branches/precise/lib/J3/Compiler/JavaAOTCompiler.cpp Tue Nov 16 14:23:43 2010
@@ -1484,6 +1484,7 @@
   if (!VT->IMT) {
     Elemts.push_back(Constant::getNullValue(PTy));
   } else {
+    // TODO: add a null element at the end to diagnose errors.
     Class* cl = classDef->asClass();
     assert(cl && "Not a class");
     std::set<JavaMethod*> contents[InterfaceMethodTable::NumIndexes];

Modified: vmkit/branches/precise/lib/J3/Compiler/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Compiler/JavaJIT.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Compiler/JavaJIT.cpp (original)
+++ vmkit/branches/precise/lib/J3/Compiler/JavaJIT.cpp Tue Nov 16 14:23:43 2010
@@ -2189,7 +2189,7 @@
 }
 
 
-void JavaJIT::invokeInterface(uint16 index, bool buggyVirtual) {
+void JavaJIT::invokeInterface(uint16 index) {
   
   // Do the usual
   JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
@@ -2221,7 +2221,8 @@
   targetObject = new LoadInst(
           targetObject, "", TheCompiler->useCooperativeGC(), currentBlock);
   JITVerifyNull(targetObject);
-#if 1
+  // TODO: The following code needs more testing.
+#if 0
   BasicBlock* endBlock = createBasicBlock("end interface invoke");
   PHINode * node = PHINode::Create(virtualPtrType, "", endBlock);
 
@@ -2317,9 +2318,12 @@
       
   currentBlock = endBlock;
 #else
-  Value* Args[3] = { targetObject, Meth, Index };
-  Value* node = CallInst::Create(
-      intrinsics->ResolveInterfaceFunction, Args, Args + 3, "", currentBlock);
+  std::vector<Value*> Args;
+  Args.push_back(targetObject);
+  Args.push_back(Meth);
+  Args.push_back(Index);
+  Value* node =
+      invoke(intrinsics->ResolveInterfaceFunction, Args, "", currentBlock);
   node = new BitCastInst(node, virtualPtrType, "", currentBlock);
 #endif
 

Modified: vmkit/branches/precise/lib/J3/Compiler/JavaJIT.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Compiler/JavaJIT.h?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Compiler/JavaJIT.h (original)
+++ vmkit/branches/precise/lib/J3/Compiler/JavaJIT.h Tue Nov 16 14:23:43 2010
@@ -448,10 +448,8 @@
   /// invokeVirtual - Invoke a Java virtual method.
   void invokeVirtual(uint16 index);
 
-  /// invokeInterface - Invoke a Java interface method. The buggyVirtual
-  /// argument is for buggy java to bytecode compilers which emit a virtual
-  /// call instead of an interface call in some occasions.
-  void invokeInterface(uint16 index, bool buggyVirtual = false);
+  /// invokeInterface - Invoke a Java interface method.
+  void invokeInterface(uint16 index);
 
   /// invokeSpecial - Invoke an instance Java method directly.
   void invokeSpecial(uint16 index);

Modified: vmkit/branches/precise/lib/J3/Compiler/JavaJITCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Compiler/JavaJITCompiler.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Compiler/JavaJITCompiler.cpp (original)
+++ vmkit/branches/precise/lib/J3/Compiler/JavaJITCompiler.cpp Tue Nov 16 14:23:43 2010
@@ -272,6 +272,7 @@
  
   std::set<JavaMethod*> contents[InterfaceMethodTable::NumIndexes];
   cl->fillIMT(contents);
+
   
   for (uint32_t i = 0; i < InterfaceMethodTable::NumIndexes; ++i) {
     std::set<JavaMethod*>& atIndex = contents[i];
@@ -300,7 +301,7 @@
         if (OldMethod && OldMethod != Cmeth) SameMethod = false;
         else OldMethod = Cmeth;
        
-        if (Cmeth) methods.push_back(Cmeth);
+        methods.push_back(Cmeth);
       }
 
       if (SameMethod) {
@@ -312,7 +313,8 @@
         }
       } else {
 
-        uint32_t length = 2 * size * sizeof(uintptr_t);
+        // Add one to have a NULL-terminated table.
+        uint32_t length = (2 * size + 1) * sizeof(uintptr_t);
       
         uintptr_t* table = (uintptr_t*)
           cl->classLoader->allocator.Allocate(length, "IMT");
@@ -325,14 +327,16 @@
              et = methods.end(); it != et; ++it, j += 2, ++Interf) {
           JavaMethod* Imeth = *Interf;
           JavaMethod* Cmeth = *it;
+          assert(Imeth != NULL);
           assert(j < 2 * size - 1);
           table[j] = (uintptr_t)Imeth;
           if (Cmeth) {
-             table[j + 1] = getPointerOrStub(*Cmeth, JavaMethod::Interface);
+            table[j + 1] = getPointerOrStub(*Cmeth, JavaMethod::Interface);
           } else {
             table[j + 1] = (uintptr_t)ThrowUnfoundInterface;
           }
         }
+        assert(Interf == atIndex.end());
       }
     }
   }

Modified: vmkit/branches/precise/lib/J3/VMCore/JavaClass.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaClass.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaClass.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaClass.cpp Tue Nov 16 14:23:43 2010
@@ -765,14 +765,16 @@
     interfaces[i]->fillIMT(meths);
   }
 
-  if (super) super->fillIMT(meths);
+  if (super != NULL) {
+    super->fillIMT(meths);
+  }
 
-  if (isInterface()) {
+  // Specification says that an invokeinterface also looks at j.l.Object.
+  if (isInterface() || (super == NULL)) {
     for (uint32 i = 0; i < nbVirtualMethods; ++i) {
       JavaMethod& meth = virtualMethods[i];
       uint32_t index = InterfaceMethodTable::getIndex(meth.name, meth.type);
-      if (meths[index].find(&meth) == meths[index].end())
-        meths[index].insert(&meth);
+      meths[index].insert(&meth);
     }
   }
 }
@@ -924,12 +926,21 @@
 
 
 #ifndef ISOLATE_SHARING
+#ifdef ISOLATE
+void Class::resolveClass() {
+  UNIMPLEMENTED();
+}
+#else
 void Class::resolveClass() {
   if (isResolved() || isErroneous()) return;
   resolveParents();
   loadExceptions();
-  setResolved();
+  // Do a compare and swap in case another thread initialized the class.
+  __sync_val_compare_and_swap(
+      &(getCurrentTaskClassMirror().status), loaded, resolved);
+  assert(isResolved() || isErroneous());
 }
+#endif
 #else
 void Class::resolveClass() {
   assert(status >= resolved && 

Modified: vmkit/branches/precise/lib/J3/VMCore/JavaRuntimeJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaRuntimeJIT.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaRuntimeJIT.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaRuntimeJIT.cpp Tue Nov 16 14:23:43 2010
@@ -16,6 +16,7 @@
 #include "JavaString.h"
 #include "JavaThread.h"
 #include "JavaTypes.h"
+#include "JavaUpcalls.h"
 #include "Jnjvm.h"
 
 #include "j3/OpcodeNames.def"
@@ -750,12 +751,16 @@
   uintptr_t result = NULL;
   InterfaceMethodTable* IMT = JavaObject::getClass(obj)->virtualVT->IMT;
   assert(JavaObject::instanceOf(obj, meth->classDef));
+  assert(meth->classDef->isInterface() ||
+      (meth->classDef == meth->classDef->classLoader->bootstrapLoader->upcalls->OfObject));
+  assert(index == InterfaceMethodTable::getIndex(meth->name, meth->type));
   if ((IMT->contents[index] & 1) == 0) {
     result = IMT->contents[index];
-  } else { 
+  } else {
     uintptr_t* table = (uintptr_t*)(IMT->contents[index] & ~1);
     uint32 i = 0;
-    while (table[i] != (uintptr_t)meth) { i += 2; }
+    while (table[i] != (uintptr_t)meth && table[i] != 0) { i += 2; }
+    assert(table[i] != 0);
     result = table[i + 1];
   }
   assert((result != 0) && "Bad IMT");

Modified: vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.cpp Tue Nov 16 14:23:43 2010
@@ -71,6 +71,7 @@
 
 
 void ReferenceThread::addToEnqueue(gc* obj) {
+  llvm_gcroot(obj, 0);
   if (ToEnqueueIndex >= ToEnqueueLength) {
     uint32 newLength = ToEnqueueLength * GROW_FACTOR;
     gc** newQueue = new gc*[newLength];

Modified: vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.h?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.h (original)
+++ vmkit/branches/precise/lib/J3/VMCore/ReferenceQueue.h Tue Nov 16 14:23:43 2010
@@ -41,6 +41,7 @@
 
   ReferenceQueue(uint8_t s) {
     References = new gc*[INITIAL_QUEUE_SIZE];
+    memset(References, 0, INITIAL_QUEUE_SIZE * sizeof(gc*));
     QueueLength = INITIAL_QUEUE_SIZE;
     CurrentIndex = 0;
     semantics = s;
@@ -56,6 +57,7 @@
     if (CurrentIndex >= QueueLength) {
       uint32 newLength = QueueLength * GROW_FACTOR;
       gc** newQueue = new gc*[newLength];
+      memset(newQueue, 0, newLength * sizeof(gc*));
       if (!newQueue) {
         fprintf(stderr, "I don't know how to handle reference overflow yet!\n");
         abort();

Modified: vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp (original)
+++ vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp Tue Nov 16 14:23:43 2010
@@ -26,6 +26,7 @@
 void ThinLock::overflowThinLock(gc* object, LockSystem& table) {
   llvm_gcroot(object, 0);
   FatLock* obj = table.allocate(object);
+  uintptr_t ID = obj->getID();
   obj->acquireAll(object, (ThinCountMask >> ThinCountShift) + 1);
   uintptr_t oldValue = 0;
   uintptr_t newValue = 0;
@@ -33,14 +34,18 @@
   do {
     oldValue = object->header;
     newValue = obj->getID() | (oldValue & NonLockBitsMask);
+    assert(obj->associatedObject == object);
     yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
-  } while (yieldedValue != oldValue);
+  } while (((object->header) & ~NonLockBitsMask) != ID);
+  assert(obj->associatedObject == object);
 }
  
 /// initialise - Initialise the value of the lock.
 ///
-void ThinLock::initialise(gc* object, LockSystem& table) {
+void ThinLock::removeFatLock(FatLock* fatLock, LockSystem& table) {
+  gc* object = fatLock->associatedObject;
   llvm_gcroot(object, 0);
+  uintptr_t ID = fatLock->getID();
   uintptr_t oldValue = 0;
   uintptr_t newValue = 0;
   uintptr_t yieldedValue = 0;
@@ -48,7 +53,9 @@
     oldValue = object->header;
     newValue = oldValue & NonLockBitsMask;
     yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
-  } while (yieldedValue != oldValue);
+  } while (oldValue != yieldedValue);
+  assert((oldValue & NonLockBitsMask) != ID);
+  fatLock->associatedObject = NULL;
 }
   
 FatLock* ThinLock::changeToFatlock(gc* object, LockSystem& table) {
@@ -60,61 +67,91 @@
     uintptr_t oldValue = 0;
     uintptr_t newValue = 0;
     uintptr_t yieldedValue = 0;
+    uintptr_t ID = obj->getID();
     do {
       oldValue = object->header;
-      newValue = obj->getID() | (oldValue & NonLockBitsMask);
+      newValue = ID | (oldValue & NonLockBitsMask);
+      assert(obj->associatedObject == object);
       yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
-    } while (yieldedValue != oldValue);
+    } while (((object->header) & ~NonLockBitsMask) != ID);
     return obj;
   } else {
     FatLock* res = table.getFatLockFromID(object->header);
     assert(res && "Lock deallocated while held.");
+    assert(res->associatedObject == object);
     return res;
   }
 }
 
+void printDebugMessage(gc* object, LockSystem& table) {
+  llvm_gcroot(object, 0);
+  fprintf(stderr,
+      "WARNING: [%p] has been waiting really long for %p (header = %x)\n",
+      (void*)mvm::Thread::get(),
+      (void*)object,
+      object->header);
+  FatLock* obj = table.getFatLockFromID(object->header);
+  if (obj != NULL) {
+    fprintf(stderr,
+        "WARNING: [%p] is waiting on fatlock %p. "
+        "Its associated object is %p. The owner is %p\n",
+        (void*)mvm::Thread::get(),
+        (void*)obj,
+        (void*)obj->getAssociatedObject(),
+        (void*)obj->owner());
+  }
+}
+
 void ThinLock::acquire(gc* object, LockSystem& table) {
   llvm_gcroot(object, 0);
   uint64_t id = mvm::Thread::get()->getThreadID();
   uintptr_t oldValue = 0;
   uintptr_t newValue = 0;
   uintptr_t yieldedValue = 0;
-  do {
-    oldValue = object->header & NonLockBitsMask;
-    newValue = oldValue | id;
-    yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
-  } while ((object->header & ~NonLockBitsMask) == 0);
 
-  if (yieldedValue == oldValue) {
-    assert(owner(object, table) && "Not owner after quitting acquire!");
-    return;
-  }
-  
-  if ((yieldedValue & Thread::IDMask) == id) {
+  if ((object->header & Thread::IDMask) == id) {
     assert(owner(object, table) && "Inconsistent lock");
-    if ((yieldedValue & ThinCountMask) != ThinCountMask) {
+    if ((object->header & ThinCountMask) != ThinCountMask) {
+      uint32 count = object->header & ThinCountMask;
       do {
         oldValue = object->header;
         newValue = oldValue + ThinCountAdd;
         yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
-      } while (oldValue != yieldedValue);
+      } while ((object->header & ThinCountMask) == count);
     } else {
       overflowThinLock(object, table);
     }
     assert(owner(object, table) && "Not owner after quitting acquire!");
     return;
   }
-      
+
+  do {
+    oldValue = object->header & NonLockBitsMask;
+    newValue = oldValue | id;
+    yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+  } while ((object->header & ~NonLockBitsMask) == 0);
+
+  if (((object->header) & ~NonLockBitsMask) == id) {
+    assert(owner(object, table) && "Not owner after quitting acquire!");
+    return;
+  }
+
+  // Simple counter to lively diagnose possible dead locks in this code.
+  int counter = 0;  
   while (true) {
     if (object->header & FatMask) {
       FatLock* obj = table.getFatLockFromID(object->header);
       if (obj != NULL) {
         if (obj->acquire(object)) {
+          assert(owner(object, table) && "Not owner after acquring fat lock!");
           break;
         }
       }
     }
-    
+   
+    counter++;
+    if (counter == 1000) printDebugMessage(object, table);
+
     while (object->header & ~NonLockBitsMask) {
       if (object->header & FatMask) {
         break;
@@ -125,19 +162,22 @@
     
     if ((object->header & ~NonLockBitsMask) == 0) {
       FatLock* obj = table.allocate(object);
+      obj->acquire(object);
       do {
         oldValue = object->header & NonLockBitsMask;
         newValue = oldValue | obj->getID();
+        assert(obj->associatedObject == object);
         yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
       } while ((object->header & ~NonLockBitsMask) == 0);
 
-      if (oldValue != yieldedValue) {
-        assert((getFatLock(object, table) != obj) && "Inconsistent lock");
+      if ((getFatLock(object, table) != obj)) {
+        assert((object->header & ~NonLockBitsMask) != obj->getID());
+        obj->internalLock.unlock();
         table.deallocate(obj);
       } else {
-        assert((getFatLock(object, table) == obj) && "Inconsistent lock");
+        assert(owner(object, table) && "Inconsistent lock");
+        break;
       }
-      assert(!owner(object, table) && "Inconsistent lock");
     }
   }
 
@@ -157,18 +197,19 @@
       oldValue = object->header;
       newValue = oldValue & NonLockBitsMask;
       yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
-    } while (yieldedValue != oldValue);
+    } while ((object->header & ~NonLockBitsMask) == id);
   } else if (object->header & FatMask) {
     FatLock* obj = table.getFatLockFromID(object->header);
     assert(obj && "Lock deallocated while held.");
     obj->release(object, table);
   } else {
     assert(((object->header & ThinCountMask) > 0) && "Inconsistent state");    
+    uint32 count = (object->header & ThinCountMask);
     do {
       oldValue = object->header;
       newValue = oldValue - ThinCountAdd;
       yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
-    } while (yieldedValue != oldValue);
+    } while ((object->header & ThinCountMask) == count);
   }
 }
 
@@ -196,7 +237,9 @@
   }
 }
 
-void FatLock::acquireAll(gc* obj, uint32 nb) {
+void FatLock::acquireAll(gc* object, uint32 nb) {
+  assert(associatedObject == object);
+  llvm_gcroot(object, 0);
   internalLock.lockAll(nb);
 }
 
@@ -210,6 +253,7 @@
   
 FatLock::FatLock(uint32_t i, gc* a) {
   llvm_gcroot(a, 0);
+  assert(a != NULL);
   firstThread = NULL;
   index = i;
   associatedObject = a;
@@ -228,7 +272,7 @@
   assert(associatedObject == obj && "Mismatch object in lock");
   if (!waitingThreads && !lockingThreads &&
       internalLock.recursionCount() == 1) {
-    mvm::ThinLock::initialise(associatedObject, table);
+    mvm::ThinLock::removeFatLock(this, table);
     table.deallocate(this);
   }
   internalLock.unlock();
@@ -312,6 +356,7 @@
     tab[internalIndex] = res;
   }
    
+  assert(res->associatedObject == obj);
   // Return the lock.
   return res;
 }

Modified: vmkit/branches/precise/lib/Mvm/CommonThread/Sigsegv.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/Mvm/CommonThread/Sigsegv.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/Mvm/CommonThread/Sigsegv.cpp (original)
+++ vmkit/branches/precise/lib/Mvm/CommonThread/Sigsegv.cpp Tue Nov 16 14:23:43 2010
@@ -55,7 +55,7 @@
                     "\nthe VM.\n");
   } else {
     fprintf(stderr, "Thread %p received a SIGSEGV: either the VM code or an external\n"
-                    "native method is bogus. Aborting...\n", th);
+                    "native method is bogus. Aborting...\n", (void*)th);
   }
   th->printBacktrace();
   abort();

Modified: vmkit/branches/precise/lib/Mvm/CommonThread/ctthread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/Mvm/CommonThread/ctthread.cpp?rev=119377&r1=119376&r2=119377&view=diff
==============================================================================
--- vmkit/branches/precise/lib/Mvm/CommonThread/ctthread.cpp (original)
+++ vmkit/branches/precise/lib/Mvm/CommonThread/ctthread.cpp Tue Nov 16 14:23:43 2010
@@ -209,6 +209,94 @@
   assert(addr && "No address to start with");
 }
 
+
+#ifdef WITH_LLVM_GCC
+void Thread::scanStack(uintptr_t closure) {
+  StackWalker Walker(this);
+  while (MethodInfo* MI = Walker.get()) {
+    MI->scan(closure, Walker.ip, Walker.addr);
+    ++Walker;
+  }
+}
+
+#else
+
+void Thread::scanStack(uintptr_t closure) {
+  register unsigned int  **max = (unsigned int**)(void*)this->baseSP;
+  if (mvm::Thread::get() != this) {
+    register unsigned int  **cur = (unsigned int**)this->waitOnSP();
+    for(; cur<max; cur++) Collector::scanObject((void**)cur, closure);
+  } else {
+    jmp_buf buf;
+    setjmp(buf);
+    register unsigned int  **cur = (unsigned int**)&buf;
+    for(; cur<max; cur++) Collector::scanObject((void**)cur, closure);
+  }
+}
+#endif
+
+void Thread::enterUncooperativeCode(unsigned level) {
+  if (isMvmThread()) {
+    if (!inRV) {
+      assert(!lastSP && "SP already set when entering uncooperative code");
+      // Get the caller.
+      void* temp = FRAME_PTR();
+      // Make sure to at least get the caller of the caller.
+      ++level;
+      while (level--) temp = ((void**)temp)[0];
+      // The cas is not necessary, but it does a memory barrier.
+      __sync_bool_compare_and_swap(&lastSP, 0, temp);
+      if (doYield) joinRVBeforeEnter();
+      assert(lastSP && "No last SP when entering uncooperative code");
+    }
+  }
+}
+
+void Thread::enterUncooperativeCode(void* SP) {
+  if (isMvmThread()) {
+    if (!inRV) {
+      assert(!lastSP && "SP already set when entering uncooperative code");
+      // The cas is not necessary, but it does a memory barrier.
+      __sync_bool_compare_and_swap(&lastSP, 0, SP);
+      if (doYield) joinRVBeforeEnter();
+      assert(lastSP && "No last SP when entering uncooperative code");
+    }
+  }
+}
+
+void Thread::leaveUncooperativeCode() {
+  if (isMvmThread()) {
+    if (!inRV) {
+      assert(lastSP && "No last SP when leaving uncooperative code");
+      void* savedSP = lastSP;
+      // The cas is not necessary, but it does a memory barrier.
+      __sync_bool_compare_and_swap(&lastSP, lastSP, 0);
+      // A rendezvous has just been initiated, join it.
+      if (doYield) joinRVAfterLeave(savedSP);
+      assert(!lastSP && "SP has a value after leaving uncooperative code");
+    }
+  }
+}
+
+void* Thread::waitOnSP() {
+  // First see if we can get lastSP directly.
+  void* sp = lastSP;
+  if (sp) return sp;
+  
+  // Then loop a fixed number of iterations to get lastSP.
+  for (uint32 count = 0; count < 1000; ++count) {
+    sp = lastSP;
+    if (sp) return sp;
+  }
+  
+  // Finally, yield until lastSP is not set.
+  while ((sp = lastSP) == NULL) mvm::Thread::yield();
+
+  assert(sp != NULL && "Still no sp");
+  return sp;
+}
+
+
 uintptr_t Thread::baseAddr = 0;
 
 // These could be set at runtime.
@@ -321,12 +409,12 @@
   sa.sa_sigaction = sigsegvHandler;
   sigaction(SIGSEGV, &sa, NULL);
 
-  th->MyVM->rendezvous.addThread(th);
 
   assert(th->MyVM && "VM not set in a thread");
 #ifdef ISOLATE
   th->IsolateID = th->MyVM->IsolateID;
 #endif
+  th->MyVM->rendezvous.addThread(th);
   th->routine(th);
   th->MyVM->removeThread(th);
   delete th;
@@ -342,6 +430,8 @@
   pthread_attr_init(&attributs);
   pthread_attr_setstack(&attributs, this, STACK_SIZE);
   routine = fct;
+  // Make sure to add it in the list of threads before leaving this function:
+  // the garbage collector wants to trace this thread.
   MyVM->addThread(this);
   int res = pthread_create((pthread_t*)(void*)(&internalThreadID), &attributs,
                            (void* (*)(void *))internalThreadStart, this);
@@ -376,89 +466,3 @@
   index = (index & ~TheStackManager.baseAddr) >> 20;
   TheStackManager.used[index] = 0;
 }
-
-#ifdef WITH_LLVM_GCC
-void Thread::scanStack(uintptr_t closure) {
-  StackWalker Walker(this);
-  while (MethodInfo* MI = Walker.get()) {
-    MI->scan(closure, Walker.ip, Walker.addr);
-    ++Walker;
-  }
-}
-
-#else
-
-void Thread::scanStack(uintptr_t closure) {
-  register unsigned int  **max = (unsigned int**)(void*)this->baseSP;
-  if (mvm::Thread::get() != this) {
-    register unsigned int  **cur = (unsigned int**)this->waitOnSP();
-    for(; cur<max; cur++) Collector::scanObject((void**)cur, closure);
-  } else {
-    jmp_buf buf;
-    setjmp(buf);
-    register unsigned int  **cur = (unsigned int**)&buf;
-    for(; cur<max; cur++) Collector::scanObject((void**)cur, closure);
-  }
-}
-#endif
-
-void Thread::enterUncooperativeCode(unsigned level) {
-  if (isMvmThread()) {
-    if (!inRV) {
-      assert(!lastSP && "SP already set when entering uncooperative code");
-      // Get the caller.
-      void* temp = FRAME_PTR();
-      // Make sure to at least get the caller of the caller.
-      ++level;
-      while (level--) temp = ((void**)temp)[0];
-      // The cas is not necessary, but it does a memory barrier.
-      __sync_bool_compare_and_swap(&lastSP, 0, temp);
-      if (doYield) joinRVBeforeEnter();
-      assert(lastSP && "No last SP when entering uncooperative code");
-    }
-  }
-}
-
-void Thread::enterUncooperativeCode(void* SP) {
-  if (isMvmThread()) {
-    if (!inRV) {
-      assert(!lastSP && "SP already set when entering uncooperative code");
-      // The cas is not necessary, but it does a memory barrier.
-      __sync_bool_compare_and_swap(&lastSP, 0, SP);
-      if (doYield) joinRVBeforeEnter();
-      assert(lastSP && "No last SP when entering uncooperative code");
-    }
-  }
-}
-
-void Thread::leaveUncooperativeCode() {
-  if (isMvmThread()) {
-    if (!inRV) {
-      assert(lastSP && "No last SP when leaving uncooperative code");
-      void* savedSP = lastSP;
-      // The cas is not necessary, but it does a memory barrier.
-      __sync_bool_compare_and_swap(&lastSP, lastSP, 0);
-      // A rendezvous has just been initiated, join it.
-      if (doYield) joinRVAfterLeave(savedSP);
-      assert(!lastSP && "SP has a value after leaving uncooperative code");
-    }
-  }
-}
-
-void* Thread::waitOnSP() {
-  // First see if we can get lastSP directly.
-  void* sp = lastSP;
-  if (sp) return sp;
-  
-  // Then loop a fixed number of iterations to get lastSP.
-  for (uint32 count = 0; count < 1000; ++count) {
-    sp = lastSP;
-    if (sp) return sp;
-  }
-  
-  // Finally, yield until lastSP is not set.
-  while ((sp = lastSP) == NULL) mvm::Thread::yield();
-
-  assert(sp != NULL && "Still no sp");
-  return sp;
-}





More information about the vmkit-commits mailing list