[vmkit-commits] [vmkit] r198210 - First version of stack locking algorithm. Inflation is not yet tested.
Gael Thomas
gael.thomas at lip6.fr
Mon Dec 30 03:34:19 PST 2013
Author: gthomas
Date: Mon Dec 30 05:34:18 2013
New Revision: 198210
URL: http://llvm.org/viewvc/llvm-project?rev=198210&view=rev
Log:
First version of stack locking algorithm. Inflation is not yet tested.
Modified:
vmkit/branches/mcjit/include/j3/j3.h
vmkit/branches/mcjit/include/j3/j3codegen.h
vmkit/branches/mcjit/include/j3/j3meta.def
vmkit/branches/mcjit/include/j3/j3monitor.h
vmkit/branches/mcjit/include/j3/j3object.h
vmkit/branches/mcjit/include/j3/j3thread.h
vmkit/branches/mcjit/lib/j3/vm/j3.cc
vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc
vmkit/branches/mcjit/lib/j3/vm/j3object.cc
Modified: vmkit/branches/mcjit/include/j3/j3.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3.h?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3.h (original)
+++ vmkit/branches/mcjit/include/j3/j3.h Mon Dec 30 05:34:18 2013
@@ -92,6 +92,7 @@ namespace j3 {
llvm::Type* typeJ3Object;
llvm::Type* typeJ3ObjectPtr;
llvm::Type* typeJ3ObjectHandlePtr;
+ llvm::Type* typeJ3LockRecord;
llvm::Type* typeGXXException;
J3Options* options() { return &_options; }
Modified: vmkit/branches/mcjit/include/j3/j3codegen.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3codegen.h?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3codegen.h (original)
+++ vmkit/branches/mcjit/include/j3/j3codegen.h Mon Dec 30 05:34:18 2013
@@ -81,6 +81,7 @@ namespace j3 {
uint32_t wideReadU1();
uint32_t wideReadS1();
+ llvm::Value* spToCurrentThread(llvm::Value* sp);
llvm::Value* currentThread();
llvm::Value* nullCheck(llvm::Value* obj);
@@ -100,6 +101,9 @@ namespace j3 {
llvm::Value* vt(llvm::Value* obj);
void initialiseJ3Type(J3Type* cl);
+ void monitorEnter(llvm::Value* obj);
+ void monitorExit(llvm::Value* obj);
+
llvm::Value* isAssignableTo(llvm::Value* obj, J3Type* type);
void instanceof(llvm::Value* obj, J3Type* type);
void checkCast(llvm::Value* obj, J3Type* type);
Modified: vmkit/branches/mcjit/include/j3/j3meta.def
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3meta.def?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3meta.def (original)
+++ vmkit/branches/mcjit/include/j3/j3meta.def Mon Dec 30 05:34:18 2013
@@ -8,6 +8,8 @@ _x(funcJ3ClassStringAt, "j3::J3
_x(funcJ3ObjectTypeJavaClass, "j3::J3ObjectType::javaClass()")
_x(funcJniEnv, "j3::J3::jniEnv()")
_x(funcJ3ObjectAllocate, "j3::J3Object::allocate(j3::J3VirtualTable*, unsigned long)")
+_x(funcJ3ObjectMonitorEnter, "j3::J3Object::monitorEnter(j3::J3Object*)")
+_x(funcJ3ObjectMonitorExit, "j3::J3Object::monitorExit(j3::J3Object*)")
_x(funcThrowException, "vmkit::VMKit::throwException(void*)")
_x(funcClassCastException, "j3::J3::classCastException()")
_x(funcNullPointerException, "j3::J3::nullPointerException()")
Modified: vmkit/branches/mcjit/include/j3/j3monitor.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3monitor.h?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3monitor.h (original)
+++ vmkit/branches/mcjit/include/j3/j3monitor.h Mon Dec 30 05:34:18 2013
@@ -12,6 +12,15 @@ 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 J3Monitor {
friend class J3MonitorManager;
Modified: vmkit/branches/mcjit/include/j3/j3object.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3object.h?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3object.h (original)
+++ vmkit/branches/mcjit/include/j3/j3object.h Mon Dec 30 05:34:18 2013
@@ -92,15 +92,18 @@ namespace j3 {
J3VirtualTable* _vt;
uintptr_t _header;
/*
- * biased (not yet implemented): 0 | epoch | age | 101
- * thread_id | epoch | age | 101
- * not locked: hash-code 24 bits | age 5 bits | 001
- * stack locked: pointer to lock record | 00
- * inflated: pointer to monitor | 01
+ * biasable (not yet implemented): 0 | epoch | age | 101
+ * biased (not yet implemented): thread_id | epoch | age | 101
+ * not locked: hash-code 24 bits | age 5 bits | 001
+ * stack locked: pointer to lock record | 00
+ * inflated: pointer to monitor | 10
*/
J3Object(); /* never directly allocate an object */
+ static void monitorEnter(J3Object* obj);
+ static void monitorExit(J3Object* obj);
+
static J3Object* allocate(J3VirtualTable* vt, size_t n);
static J3Object* doNewNoInit(J3Class* cl);
static J3Object* doNew(J3Class* cl);
Modified: vmkit/branches/mcjit/include/j3/j3thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/include/j3/j3thread.h?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/include/j3/j3thread.h (original)
+++ vmkit/branches/mcjit/include/j3/j3thread.h Mon Dec 30 05:34:18 2013
@@ -15,12 +15,11 @@ namespace j3 {
class J3Thread : public vmkit::Thread {
friend class J3Monitor;
+ friend class J3CodeGen;
- public:
static const uint32_t gepInterfaceMethodIndex = 1;
+ uint32_t _interfaceMethodIndex;
- private:
- uint32_t _interfaceMethodIndex;
vmkit::BumpAllocator* _allocator;
JNIEnv _jniEnv;
J3LocalReferences _localReferences;
Modified: vmkit/branches/mcjit/lib/j3/vm/j3.cc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/mcjit/lib/j3/vm/j3.cc?rev=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3.cc Mon Dec 30 05:34:18 2013
@@ -58,6 +58,7 @@ void J3::introspect() {
typeJ3Object = introspectType("class.j3::J3Object");
typeJ3ObjectPtr = llvm::PointerType::getUnqual(typeJ3Object);
typeJ3ObjectHandlePtr = llvm::PointerType::getUnqual(introspectType("class.j3::J3ObjectHandle"));
+ typeJ3LockRecord = introspectType("class.j3::J3LockRecord");
typeGXXException = llvm::StructType::get(llvm::Type::getInt8Ty(llvmContext())->getPointerTo(),
llvm::Type::getInt32Ty(llvmContext()), NULL);
@@ -229,6 +230,7 @@ void J3::printStackTrace() {
void J3::forceSymbolDefinition() {
J3ArrayObject a; a.length(); /* J3ArrayObject */
+ J3LockRecord* l = new J3LockRecord(); /* J3LockRecord */
try {
throw (void*)0;
} catch(void* e) {
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=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3codegen.cc Mon Dec 30 05:34:18 2013
@@ -158,15 +158,116 @@ llvm::Value* J3CodeGen::unflatten(llvm::
}
}
-llvm::Value* J3CodeGen::currentThread() {
- llvm::Type* type = vm->dataLayout()->getIntPtrType(module()->getContext());
+llvm::Value* J3CodeGen::spToCurrentThread(llvm::Value* sp) {
+ llvm::Type* type = builder->getIntPtrTy(vm->dataLayout());
- return builder->CreateIntToPtr(builder->CreateAnd(builder->CreatePtrToInt(builder->CreateCall(frameAddress, builder->getInt32(0)),
- type),
+ return builder->CreateIntToPtr(builder->CreateAnd(builder->CreatePtrToInt(sp, type),
llvm::ConstantInt::get(type, vmkit::Thread::getThreadMask())),
vm->typeJ3Thread);
}
+llvm::Value* J3CodeGen::currentThread() {
+ return spToCurrentThread(builder->CreateCall(frameAddress, builder->getInt32(0)));
+}
+
+void J3CodeGen::monitorEnter(llvm::Value* obj) {
+ llvm::Type* uintPtrTy = builder->getIntPtrTy(vm->dataLayout());
+ 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* 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* 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);
+
+ /* unable to stack lock, fall back to monitor */
+ builder->SetInsertPoint(stackFail);
+ builder->CreateCall(funcJ3ObjectMonitorEnter, obj);
+ builder->CreateBr(ok);
+}
+
+void J3CodeGen::monitorExit(llvm::Value* obj) {
+ llvm::Type* uintPtrTy = builder->getIntPtrTy(vm->dataLayout());
+ 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::initialiseJ3Type(J3Type* cl) {
if(!cl->isInitialised())
builder->CreateCall(funcJ3TypeInitialise, builder->CreateBitCast(cl->llvmDescriptor(module()), vm->typeJ3TypePtr));
@@ -1320,11 +1421,11 @@ void J3CodeGen::translate() {
break;
case J3Cst::BC_monitorenter: /* 0xc2 */
- stack.pop();
+ monitorEnter(stack.pop());
break;
case J3Cst::BC_monitorexit: /* 0xc3 */
- stack.pop();
+ monitorExit(stack.pop());
break;
case J3Cst::BC_wide: nyi(); /* 0xc4 */
@@ -1386,7 +1487,7 @@ void J3CodeGen::generateJava() {
J3::classFormatError(cl, L"Code attribute of %ls %ls is too large (%d)", method->name()->cStr(), method->sign()->cStr(), length);
nullValue = builder
- ->CreateIntToPtr(llvm::ConstantInt::get(vm->dataLayout()->getIntPtrType(module()->getContext()), (uintptr_t)0),
+ ->CreateIntToPtr(llvm::ConstantInt::get(builder->getIntPtrTy(vm->dataLayout()), (uintptr_t)0),
vm->typeJ3ObjectPtr);
llvm::DIBuilder* dbgBuilder = new llvm::DIBuilder(*module());
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=198210&r1=198209&r2=198210&view=diff
==============================================================================
--- vmkit/branches/mcjit/lib/j3/vm/j3object.cc (original)
+++ vmkit/branches/mcjit/lib/j3/vm/j3object.cc Mon Dec 30 05:34:18 2013
@@ -274,6 +274,7 @@ uintptr_t* J3Object::header() {
J3Object* J3Object::allocate(J3VirtualTable* vt, size_t n) {
J3Object* res = (J3Object*)vmkit::GC::allocate(n);
res->_vt = vt;
+ res->_header = 1;
return res;
}
@@ -286,6 +287,14 @@ J3Object* J3Object::doNew(J3Class* cl) {
return doNewNoInit(cl);
}
+void J3Object::monitorEnter(J3Object* obj) {
+ J3::internalError(L"implement me: monitorenter");
+}
+
+void J3Object::monitorExit(J3Object* obj) {
+ J3::internalError(L"implement me: monitorexit");
+}
+
/*
* --- J3ArrayObject ---
*/
More information about the vmkit-commits
mailing list