[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