[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