[vmkit-commits] [vmkit] r200846 - monitor enter and monitor exit are now only written in C++ and inlined in JITted code.

Gael Thomas gael.thomas at lip6.fr
Wed Feb 5 07:57:09 PST 2014


Author: gthomas
Date: Wed Feb  5 09:57:09 2014
New Revision: 200846

URL: http://llvm.org/viewvc/llvm-project?rev=200846&view=rev
Log:
monitor enter and monitor exit are now only written in C++ and inlined in JITted code.

Modified:
    vmkit/branches/mcjit/include/j3/j3meta.def
    vmkit/branches/mcjit/include/j3/j3monitor.h
    vmkit/branches/mcjit/include/j3/j3object.h
    vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc
    vmkit/branches/mcjit/lib/j3/vm/j3object.cc

Modified: vmkit/branches/mcjit/include/j3/j3meta.def
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3meta.def?rev=200846&r1=200845&r2=200846&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3meta.def (original)
+++ vmkit/branches/mcjit/include/j3/j3meta.def Wed Feb  5 09:57:09 2014
@@ -4,7 +4,7 @@ _x(funcJ3TypeJavaClass,             "j3:
 _x(funcJniEnv,                      "j3::J3::jniEnv()", 0)
 _x(funcJ3ArrayObjectMultianewArray, "j3::J3ArrayObject::multianewArray(j3::J3ArrayClass*, unsigned int, unsigned int*)", 0)
 _x(funcJ3ObjectAllocate,            "j3::J3Object::allocate(j3::J3VirtualTable*, unsigned long)", 0)
-_x(funcJ3ObjectMonitorEnter,        "j3::J3Object::monitorEnter(j3::J3Object*)", 0)
+_x(funcJ3ObjectMonitorEnter,        "j3::J3Object::monitorEnter(j3::J3Object*, j3::J3LockRecord*)", 0)
 _x(funcJ3ObjectMonitorExit,         "j3::J3Object::monitorExit(j3::J3Object*)", 0)
 _x(funcThrowException,              "vmkit::VMKit::throwException(void*)", 0)
 _x(funcReplayException,             "j3::J3Thread::replayException()", 0)

Modified: vmkit/branches/mcjit/include/j3/j3monitor.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3monitor.h?rev=200846&r1=200845&r2=200846&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3monitor.h (original)
+++ vmkit/branches/mcjit/include/j3/j3monitor.h Wed Feb  5 09:57:09 2014
@@ -11,15 +11,7 @@ namespace vmkit {
 namespace j3 {
 	class J3Thread;
 	class J3Object;
-
-	class J3LockRecord {
-	public:
-		static const uint32_t gepHeader = 0;
-		static const uint32_t gepLockCount = 1;
-
-		uintptr_t header;
-		uint32_t  lockCount;
-	};
+	class J3LockRecord;
 
 	class J3Monitor {
 		friend class J3MonitorManager;
@@ -39,7 +31,7 @@ namespace j3 {
 
 		void init(J3Monitor* next); /* acquire the lock for the next inflate */		
 	public:
-		bool isDeflatable(); /* acquire the lock for the next inflate */
+		bool       isDeflatable(); /* acquire the lock for the next inflate */
 		J3Monitor* prepare(J3Object* _object, uintptr_t header, J3LockRecord* _record);
 		J3Monitor* prepare();
 

Modified: vmkit/branches/mcjit/include/j3/j3object.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3object.h?rev=200846&r1=200845&r2=200846&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3object.h (original)
+++ vmkit/branches/mcjit/include/j3/j3object.h Wed Feb  5 09:57:09 2014
@@ -25,6 +25,15 @@ namespace j3 {
 	class J3Monitor;
 	class J3LockRecord;
 
+	class J3LockRecord {
+	public:
+		static const uint32_t gepHeader = 0;
+		static const uint32_t gepLockCount = 1;
+
+		uintptr_t header;
+		uint32_t  lockCount;
+	};
+
 	// 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. 
 	class J3TypeChecker {
@@ -113,8 +122,8 @@ namespace j3 {
 		static J3LockRecord* asLockRecord(uintptr_t header) { return (J3LockRecord*)header; }
 		static J3Monitor*    asMonitor(uintptr_t header) { return (J3Monitor*)(header & ~3); }
 
-		static void monitorEnter(J3Object* obj);
-		static void monitorExit(J3Object* obj);
+		static void monitorEnter(J3Object* object, J3LockRecord* lockRecord) __attribute__((always_inline));
+		static void monitorExit(J3Object* object) __attribute__((always_inline));
 
 		static J3Object* allocate(J3VirtualTable* vt, uintptr_t n);
 		static J3Object* doNew(J3Class* cl);

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=200846&r1=200845&r2=200846&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc Wed Feb  5 09:57:09 2014
@@ -238,100 +238,11 @@ llvm::Value* J3CodeGen::currentThread()
 }
 
 void J3CodeGen::monitorEnter(llvm::Value* obj) {
-	llvm::Type* recordTy = vm->typeJ3LockRecord;
-	llvm::Type* recordPtrTy = vm->typeJ3LockRecord->getPointerTo();
-
-	llvm::AllocaInst* recordPtr = builder.CreateAlloca(recordPtrTy);
-
-	llvm::BasicBlock* ok = forwardBranch("lock-ok", codeReader->tell(), 0, 0);
-	llvm::BasicBlock* stackLocked = newBB("stack-locked");
-	llvm::BasicBlock* tryStackLock = newBB("try-stack-lock");
-	llvm::BasicBlock* stackFail = newBB("stack-lock-fail");
-
-	/* already stack locked by myself? */
-	llvm::Value* gepH[] = { builder.getInt32(0), builder.getInt32(J3Object::gepHeader) };
-	llvm::Value* headerPtr = builder.CreateGEP(obj, gepH);
-	llvm::Value* header = builder.CreateLoad(headerPtr);
-	
-	builder.CreateStore(builder.CreateIntToPtr(header, recordPtrTy), recordPtr);
-	builder.CreateCondBr(builder.CreateICmpEQ(currentThread(), spToCurrentThread(header)),
-											 stackLocked, tryStackLock);
-
-	/* try to stack lock */
-	builder.SetInsertPoint(tryStackLock);
-	llvm::AllocaInst* record = builder.CreateAlloca(recordTy);
-	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, 
-																									orig, 
-																									builder.CreatePtrToInt(record, uintPtrTy),
-																									llvm::SequentiallyConsistent, 
-																									llvm::CrossThread);
-	builder.CreateCondBr(builder.CreateICmpEQ(res, orig), stackLocked, stackFail);
-
-	/* stack locked, increment the counter */
-	builder.SetInsertPoint(stackLocked);
-	llvm::Value* countPtr = builder.CreateGEP(builder.CreateLoad(recordPtr), gepC);
-	builder.CreateStore(builder.CreateAdd(builder.CreateLoad(countPtr), builder.getInt32(1)), countPtr);
-	builder.CreateBr(ok);
-
-	/* unable to stack lock, fall back to monitor */
-	builder.SetInsertPoint(stackFail);
-	builder.CreateCall(funcJ3ObjectMonitorEnter, obj);
-	builder.CreateBr(ok);
+	builder.CreateCall2(funcJ3ObjectMonitorEnter, obj, builder.CreateAlloca(vm->typeJ3LockRecord));
 }
 
 void J3CodeGen::monitorExit(llvm::Value* obj) {
-	llvm::Type* recordPtrTy = vm->typeJ3LockRecord->getPointerTo();
-
-	llvm::BasicBlock* ok = forwardBranch("unlock-ok", codeReader->tell(), 0, 0);
-	llvm::BasicBlock* stackUnlock = newBB("stack-unlock");
-	//llvm::BasicBlock* tryStackLock = newBB("try-stack-lock");
-	llvm::BasicBlock* monitorUnlock = newBB("monitor-unlock");
-	llvm::BasicBlock* stackRelease = newBB("stack-release");
-	llvm::BasicBlock* stackRec = newBB("stack-rec");
-
-	/* stack locked by myself? */
-	llvm::Value* gepH[] = { builder.getInt32(0), builder.getInt32(J3Object::gepHeader) };
-	llvm::Value* headerPtr = builder.CreateGEP(obj, gepH);
-	llvm::Value* header = builder.CreateLoad(headerPtr);
-	
-	builder.CreateCondBr(builder.CreateICmpEQ(currentThread(), spToCurrentThread(header)),
-											 stackUnlock, monitorUnlock);
-	
-	/* ok, I'm the owner */
-	builder.SetInsertPoint(stackUnlock);
-	llvm::Value* gepC[] = { builder.getInt32(0), builder.getInt32(J3LockRecord::gepLockCount) };
-	llvm::Value* recordPtr = builder.CreateIntToPtr(header, recordPtrTy);
-	llvm::Value* countPtr = builder.CreateGEP(recordPtr, gepC);
-	llvm::Value* count = builder.CreateSub(builder.CreateLoad(countPtr), builder.getInt32(1));
-	builder.CreateCondBr(builder.CreateICmpEQ(count, builder.getInt32(0)), stackRelease, stackRec);
-
-	/* last unlock */
-	builder.SetInsertPoint(stackRelease);
-	llvm::Value* gepR[] = { builder.getInt32(0), builder.getInt32(J3LockRecord::gepHeader) };
-	llvm::Value* orig = builder.CreateLoad(builder.CreateGEP(recordPtr, gepR));
-	llvm::Value* res = builder.CreateAtomicCmpXchg(headerPtr, 
-																									header, 
-																									orig,
-																									llvm::SequentiallyConsistent, 
-																									llvm::CrossThread);
-	builder.CreateCondBr(builder.CreateICmpEQ(res, header), ok, monitorUnlock);
-
-	/* recursive unlock */
-	builder.SetInsertPoint(stackRec);
-	builder.CreateStore(count, countPtr);
-	builder.CreateBr(ok);
-
-	/* monitor unlock */
-	builder.SetInsertPoint(monitorUnlock);
 	builder.CreateCall(funcJ3ObjectMonitorExit, obj);
-	builder.CreateBr(ok);
 }
 
 void J3CodeGen::resolveJ3ObjectType(J3ObjectType* cl) {

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=200846&r1=200845&r2=200846&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3object.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3object.cc Wed Feb  5 09:57:09 2014
@@ -287,12 +287,40 @@ J3Object* J3Object::doNew(J3Class* cl) {
 	return allocate(cl->vt(), cl->structSize());
 }
 
-void J3Object::monitorEnter(J3Object* obj) {
-	J3::internalError("implement me: monitor");
+void J3Object::monitorEnter(J3Object* obj, J3LockRecord* newRecord) {
+	volatile uintptr_t* pheader = &obj->_header;
+	uintptr_t header = *pheader;
+
+	if(isStackLocked(header)) {
+		J3LockRecord* record = asLockRecord(header);
+		if(vmkit::Thread::get(record) == vmkit::Thread::get()) {
+			record->lockCount++;
+			return;
+		} 
+	} else if(isUnlocked(header)) {
+		newRecord->header = header;
+		newRecord->lockCount = 1;
+		if(__sync_val_compare_and_swap(pheader, header, (uintptr_t)newRecord) == header)
+			return;
+	}
+	obj->inflate()->lock();
 }
 
 void J3Object::monitorExit(J3Object* obj) {
-	J3::internalError("implement me: monitor");
+	volatile uintptr_t* pheader = &obj->_header;
+	uintptr_t  header = *pheader;
+
+	if(isStackLocked(header)) {
+		J3LockRecord* record = asLockRecord(header);
+		if(vmkit::Thread::get(record) == vmkit::Thread::get()) {
+			if(!--record->lockCount) {
+				if(__sync_val_compare_and_swap(pheader, header, record->header) == header)
+					return;
+			} else
+				return;
+		}
+	}
+	obj->inflate()->unlock();
 }
 
 uint32_t J3Object::hashCode() {





More information about the vmkit-commits mailing list