[vmkit-commits] [vmkit] r198211 - hashCode and wait are working with my stack locking/thin lock algorithm.

Gael Thomas gael.thomas at lip6.fr
Mon Dec 30 07:35:03 PST 2013


Author: gthomas
Date: Mon Dec 30 09:35:02 2013
New Revision: 198211

URL: http://llvm.org/viewvc/llvm-project?rev=198211&view=rev
Log:
hashCode and wait are working with my stack locking/thin lock algorithm.

Modified:
    vmkit/branches/mcjit/include/j3/j3monitor.h
    vmkit/branches/mcjit/include/j3/j3object.h
    vmkit/branches/mcjit/include/j3/j3thread.h
    vmkit/branches/mcjit/include/vmkit/thread.h
    vmkit/branches/mcjit/lib/j3/openjdk/j3openjdk.cc
    vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc
    vmkit/branches/mcjit/lib/j3/vm/j3monitor.cc
    vmkit/branches/mcjit/lib/j3/vm/j3object.cc
    vmkit/branches/mcjit/lib/j3/vm/j3thread.cc
    vmkit/branches/mcjit/lib/vmkit/thread.cc

Modified: vmkit/branches/mcjit/include/j3/j3monitor.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3monitor.h?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3monitor.h (original)
+++ vmkit/branches/mcjit/include/j3/j3monitor.h Mon Dec 30 09:35:02 2013
@@ -23,20 +23,24 @@ namespace j3 {
 
 	class J3Monitor {
 		friend class J3MonitorManager;
+		friend class J3Object;
 
 		J3Monitor*      _next;
 
 		J3Thread*       owner;
-		uint32_t        recursiveCount;
+		uint32_t        lockCount;
 		pthread_mutex_t mutex;
 		pthread_cond_t  cond;
 		uintptr_t       header;
 		J3Object*       object;
+		J3LockRecord*   record;
+
+		void checkRecord();
 
 		void init(J3Monitor* next); /* acquire the lock for the next inflate */		
 	public:
 		bool isDeflatable(); /* acquire the lock for the next inflate */
-		void prepare(J3Object* _object, J3Thread* _owner, uint32_t _recursiveCount, uintptr_t _header);
+		void prepare(J3Object* _object, uintptr_t header, J3LockRecord* _record);
 
 		void lock();
 		void unlock();

Modified: vmkit/branches/mcjit/include/j3/j3object.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3object.h?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3object.h (original)
+++ vmkit/branches/mcjit/include/j3/j3object.h Mon Dec 30 09:35:02 2013
@@ -22,6 +22,7 @@ namespace j3 {
 	class J3VirtualTable;
 	class J3FixedPoint;
 	class J3Method;
+	class J3Monitor;
 
 	// see: Cliff Click and John Rose. 2002. Fast subtype checking in the HotSpot JVM. 
 	// In Proceedings of the 2002 joint ACM-ISCOPE conference on Java Grande (JGI '02). ACM, New York, NY, USA, 96-107. 
@@ -89,8 +90,8 @@ namespace j3 {
 		static const uint32_t gepHeader = 1;
 
 	private:
-		J3VirtualTable* _vt;
-		uintptr_t       _header;
+		J3VirtualTable*     _vt;
+		volatile uintptr_t  _header;
 		/* 
 		 *     biasable (not yet implemented):  0         | epoch | age        | 101
 		 *     biased (not yet implemented):    thread_id | epoch | age        | 101
@@ -101,6 +102,9 @@ namespace j3 {
 
 		J3Object(); /* never directly allocate an object */
 
+		J3Monitor* monitor();
+		uint32_t   hashCode();
+
 		static void monitorEnter(J3Object* obj);
 		static void monitorExit(J3Object* obj);
 
@@ -109,8 +113,8 @@ namespace j3 {
 		static J3Object* doNew(J3Class* cl);
 	public:
 
-		J3VirtualTable* vt();
-		uintptr_t*      header();
+		J3VirtualTable*     vt();
+		volatile uintptr_t* header();
 	};
 
 	class J3ArrayObject : public J3Object {
@@ -151,6 +155,8 @@ namespace j3 {
 		static J3ObjectHandle* doNewObject(J3Class* cl);
 		static J3ObjectHandle* doNewArray(J3ArrayClass* cl, uint32_t length);
 
+		void            wait();
+
 		bool            isSame(J3ObjectHandle* handle) { return obj() == handle->obj(); }
 
 		void            harakiri() { _obj = 0; }

Modified: vmkit/branches/mcjit/include/j3/j3thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3thread.h?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3thread.h (original)
+++ vmkit/branches/mcjit/include/j3/j3thread.h Mon Dec 30 09:35:02 2013
@@ -25,7 +25,6 @@ namespace j3 {
 		J3LocalReferences          _localReferences;
 		J3ObjectHandle*            _pendingException;
 		J3ObjectHandle*            _javaThread;
-		J3Thread*                  _nextLocked;
 
 		virtual void run();
 		static void doRun();
@@ -57,6 +56,7 @@ namespace j3 {
 		JNIEnv* jniEnv() { return &_jniEnv; }
 
 		static J3Thread* get();
+		static J3Thread* get(void* ptr);
 
 		static void start(J3ObjectHandle* handle);
 	};

Modified: vmkit/branches/mcjit/include/vmkit/thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/vmkit/thread.h?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/vmkit/thread.h (original)
+++ vmkit/branches/mcjit/include/vmkit/thread.h Mon Dec 30 09:35:02 2013
@@ -26,12 +26,13 @@ namespace vmkit {
 
 		VMKit* vm() { return _vm; }
 
+		static uintptr_t getThreadMask();
+		static Thread* get(void* ptr);
 		static Thread* get();
 
 		void start();
 		void join();
 
-		static uintptr_t getThreadMask();
 	};
 
 	class StackWalker {

Modified: vmkit/branches/mcjit/lib/j3/openjdk/j3openjdk.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/openjdk/j3openjdk.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/openjdk/j3openjdk.cc (original)
+++ vmkit/branches/mcjit/lib/j3/openjdk/j3openjdk.cc Mon Dec 30 09:35:02 2013
@@ -33,7 +33,12 @@ jint JNICALL JVM_IHashCode(JNIEnv* env,
 	return res;
 }
 
-void JNICALL JVM_MonitorWait(JNIEnv* env, jobject obj, jlong ms) { enterJVM(); NYI(); leaveJVM(); }
+void JNICALL JVM_MonitorWait(JNIEnv* env, jobject obj, jlong ms) { 
+	enterJVM(); 
+	obj->wait();
+	leaveJVM(); 
+}
+
 void JNICALL JVM_MonitorNotify(JNIEnv* env, jobject obj) { enterJVM(); NYI(); leaveJVM(); }
 void JNICALL JVM_MonitorNotifyAll(JNIEnv* env, jobject obj) { enterJVM(); NYI(); leaveJVM(); }
 jobject JNICALL JVM_Clone(JNIEnv* env, jobject obj) { enterJVM(); NYI(); leaveJVM(); }

Modified: vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc Mon Dec 30 09:35:02 2013
@@ -197,6 +197,8 @@ void J3CodeGen::monitorEnter(llvm::Value
 	builder->CreateStore(record, recordPtr);
 	llvm::Value* gepR[] = { builder->getInt32(0), builder->getInt32(J3LockRecord::gepHeader) };
 	builder->CreateStore(header, builder->CreateGEP(record, gepR));
+	llvm::Value* gepC[] = { builder->getInt32(0), builder->getInt32(J3LockRecord::gepLockCount) };
+	builder->CreateStore(builder->getInt32(0), builder->CreateGEP(record, gepC));
 	llvm::Value* orig = builder->CreateOr(builder->CreateAnd(header, llvm::ConstantInt::get(uintPtrTy, ~6)), 
 																				llvm::ConstantInt::get(uintPtrTy, 1)); /* ...001 */
 	llvm::Value* res = builder->CreateAtomicCmpXchg(headerPtr, 
@@ -208,7 +210,6 @@ void J3CodeGen::monitorEnter(llvm::Value
 
 	/* stack locked, increment the counter */
 	builder->SetInsertPoint(stackLocked);
-	llvm::Value* gepC[] = { builder->getInt32(0), builder->getInt32(J3LockRecord::gepLockCount) };
 	llvm::Value* countPtr = builder->CreateGEP(builder->CreateLoad(recordPtr), gepC);
 	builder->CreateStore(builder->CreateAdd(builder->CreateLoad(countPtr), builder->getInt32(1)), countPtr);
 	builder->CreateBr(ok);

Modified: vmkit/branches/mcjit/lib/j3/vm/j3monitor.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3monitor.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3monitor.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3monitor.cc Mon Dec 30 09:35:02 2013
@@ -16,29 +16,39 @@ bool J3Monitor::isDeflatable() {
 	return pthread_mutex_trylock(&mutex) == 0;
 }
 
-void J3Monitor::prepare(J3Object* _object, J3Thread* _owner, uint32_t _recursiveCount, uintptr_t _header) {
+void J3Monitor::prepare(J3Object* _object, uintptr_t _header, J3LockRecord* _record) {
 	object = _object;
-	owner = _owner;
-	recursiveCount = _recursiveCount;
+	record = _record;
 	header = _header;
+	owner  = _record ? J3Thread::get(_record) : 0;
+}
+
+void J3Monitor::checkRecord() {
+	if(record) {
+		lockCount = record->lockCount;
+		record    = 0;
+	}
 }
 
 void J3Monitor::lock() {
 	J3Thread* self = J3Thread::get();
-	if(owner == self) {
-		recursiveCount++;
-	} else {
+
+	if(owner == self)
+		checkRecord();
+	else {
 		pthread_mutex_lock(&mutex);
-		recursiveCount++;
 		owner = self;
 	}
+	lockCount++;
 }
 
 void J3Monitor::unlock() {
 	J3Thread* self = J3Thread::get();
 	if(owner != self)
 		J3::illegalMonitorStateException();
-	if(!--recursiveCount) {
+
+	checkRecord();
+	if(!--lockCount) {
 		owner = 0;
 		pthread_mutex_unlock(&mutex);
 	} else
@@ -55,7 +65,9 @@ void J3Monitor::timed_wait(uint64_t ms,
 	if(owner != self)
 		J3::illegalMonitorStateException();
 
-	uint32_t r = recursiveCount;
+	checkRecord();
+
+	uint32_t r = lockCount;
 	owner = 0;
 
 	if(ms || ns) {
@@ -69,11 +81,12 @@ void J3Monitor::timed_wait(uint64_t ms,
 			ts.tv_nsec -= 1e9;
 		}
 		pthread_cond_timedwait(&cond, &mutex, &ts);
+		
 	} else
 		pthread_cond_wait(&cond, &mutex);
 
 	owner = self;
-	recursiveCount = r;
+	lockCount = r;
 }
 
 void J3Monitor::notify() {

Modified: vmkit/branches/mcjit/lib/j3/vm/j3object.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3object.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3object.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3object.cc Mon Dec 30 09:35:02 2013
@@ -13,6 +13,7 @@
 #include "j3/j3.h"
 #include "j3/j3constants.h"
 #include "j3/j3thread.h"
+#include "j3/j3monitor.h"
 
 using namespace j3;
 
@@ -267,7 +268,7 @@ J3VirtualTable* J3Object::vt() {
 	return _vt; 
 }
 
-uintptr_t* J3Object::header() { 
+volatile uintptr_t* J3Object::header() { 
 	return &_header; 
 }
 
@@ -295,6 +296,73 @@ void J3Object::monitorExit(J3Object* obj
 	J3::internalError(L"implement me: monitorexit");
 }
 
+uint32_t J3Object::hashCode() {
+	static uint32_t curHashCode = 0;
+
+	while(1) {
+		uintptr_t header = _header;
+		if((header & 0x7) == 1) { /* not locked, not inflated */
+			uint32_t res = header >> 8;
+			if(res)
+				return res;
+			do {
+				res = __sync_add_and_fetch(&curHashCode, 1) & 0xffffff;
+			} while(!res);
+			
+			if(__sync_val_compare_and_swap(&_header, header, res<<8 | (header & 0xff)) == header)
+				return res;
+		} else {
+			/* if stack locked, force the inflation because I can not modify the stack of the owner */
+			J3Monitor* m = monitor();
+
+			header = m->header;
+
+			uint32_t res = header >> 8;
+			if(res)
+				return res;
+			do {
+				res = __sync_add_and_fetch(&curHashCode, 1) & 0xffffff;
+			} while(!res);
+			
+			if(__sync_val_compare_and_swap(&m->header, header, res<<8 | (header & 0xff)) == header)
+				return res;
+		}
+	}
+}
+
+J3Monitor* J3Object::monitor() {
+	uintptr_t header = _header;
+
+	while(1) {
+		uintptr_t header = _header;
+
+		if((header & 0x3) == 2) { /* already inflated */ 
+			J3Monitor* res = (J3Monitor*)(header & -2);
+			if(res)
+				return res;
+			else
+				sched_yield(); /* another guy is trying to inflate this monitor */
+		} else if(__sync_val_compare_and_swap(&_header, header, 2) == header) {
+			/* ok, I'm the boss */
+			J3Monitor* monitor = J3Thread::get()->vm()->monitorManager.allocate();
+
+			if(!(header & 3)) { /* stack locked */
+				J3LockRecord* record = (J3LockRecord*)header;
+				fprintf(stderr, " preparing monitor with %p\n", record);
+				/* I can read record->header because, in the worst case, the owner is blocked in the sched_yield loop */
+				monitor->prepare(this, record->header, record); 
+			} else {            /* not locked at all */
+				if((header & 7) != 1)
+					J3::internalError(L"should not happen");
+				monitor->prepare(this, header, 0);
+			}
+			_header = (uintptr_t)monitor | 2;
+
+			return monitor;
+		}
+	}
+}
+
 /*
  *    ---   J3ArrayObject ---
  */
@@ -313,15 +381,12 @@ J3Object* J3ArrayObject::doNew(J3ArrayCl
 /*
  *    J3ObjectHandle
  */
+void J3ObjectHandle::wait() {
+	obj()->monitor()->wait();
+}
+
 uint32_t J3ObjectHandle::hashCode() {
-	do {
-		uintptr_t oh = *obj()->header();
-		uintptr_t res = oh;
-		if(res)
-			return res;
-		uintptr_t nh = oh + 256;
-		__sync_val_compare_and_swap(obj()->header(), oh, nh);
-	} while(1);
+	return obj()->hashCode();
 }
 
 J3ObjectHandle* J3ObjectHandle::allocate(J3VirtualTable* vt, size_t n) {

Modified: vmkit/branches/mcjit/lib/j3/vm/j3thread.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3thread.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3thread.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3thread.cc Mon Dec 30 09:35:02 2013
@@ -87,6 +87,10 @@ void J3Thread::restore(J3ObjectHandle* p
 	_localReferences.restore(ptr); 
 }
 
+J3Thread* J3Thread::get(void* ptr) { 
+	return (J3Thread*)Thread::get(ptr); 
+}
+
 J3Thread* J3Thread::get() { 
 	return (J3Thread*)Thread::get(); 
 }

Modified: vmkit/branches/mcjit/lib/vmkit/thread.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/vmkit/thread.cc?rev=198211&r1=198210&r2=198211&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/vmkit/thread.cc (original)
+++ vmkit/branches/mcjit/lib/vmkit/thread.cc Mon Dec 30 09:35:02 2013
@@ -17,7 +17,11 @@ void Thread::operator delete(void* p) {
 }
 
 Thread* Thread::get() {
-	return (Thread*)((uintptr_t)__builtin_frame_address(0) & getThreadMask());
+	return get(__builtin_frame_address(0));
+}
+
+Thread* Thread::get(void* ptr) {
+	return (Thread*)((uintptr_t)ptr & getThreadMask());
 }
 
 uintptr_t Thread::getThreadMask() {





More information about the vmkit-commits mailing list