[vmkit-commits] [vmkit] r64140 - in /vmkit/trunk/lib: JnJVM/LLVMRuntime/runtime-default.ll JnJVM/VMCore/ExceptionsCheck.inc JnJVM/VMCore/ExceptionsDwarf.inc JnJVM/VMCore/JavaJIT.cpp JnJVM/VMCore/JavaJIT.h JnJVM/VMCore/JavaJITOpcodes.cpp JnJVM/VMCore/JavaMetaJIT.cpp JnJVM/VMCore/JavaObject.cpp JnJVM/VMCore/JavaRuntimeJIT.cpp JnJVM/VMCore/JavaThread.h Mvm/Runtime/JIT.cpp
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Mon Feb 9 05:33:31 PST 2009
Author: geoffray
Date: Mon Feb 9 07:33:30 2009
New Revision: 64140
URL: http://llvm.org/viewvc/llvm-project?rev=64140&view=rev
Log:
New exception model, where exceptions are checked after each function call.
This has a little cost for applications without exceptions, but is a big
win for application with a lot of exceptions. Since exceptions are usual
in Java, we chose not to continue with dwarf.
Added:
vmkit/trunk/lib/JnJVM/VMCore/ExceptionsCheck.inc
vmkit/trunk/lib/JnJVM/VMCore/ExceptionsDwarf.inc
Modified:
vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll
vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp
vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.h
vmkit/trunk/lib/JnJVM/VMCore/JavaJITOpcodes.cpp
vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp
vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp
vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp
vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h
vmkit/trunk/lib/Mvm/Runtime/JIT.cpp
Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original)
+++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Mon Feb 9 07:33:30 2009
@@ -194,11 +194,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Exception methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-declare void @jnjvmNullPointerException()
-declare void @jnjvmClassCastException(%JavaObject*, %JavaCommonClass*)
-declare void @indexOutOfBoundsException(%JavaObject*, i32)
-declare void @negativeArraySizeException(i32)
-declare void @outOfMemoryError(i32)
+declare %JavaObject* @jnjvmNullPointerException()
+declare %JavaObject* @jnjvmClassCastException(%JavaObject*, %JavaCommonClass*)
+declare %JavaObject* @indexOutOfBoundsException(%JavaObject*, i32)
+declare %JavaObject* @negativeArraySizeException(i32)
+declare %JavaObject* @outOfMemoryError(i32)
declare void @JavaThreadThrowException(%JavaObject*)
declare void @jniProceedPendingException()
Added: vmkit/trunk/lib/JnJVM/VMCore/ExceptionsCheck.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/ExceptionsCheck.inc?rev=64140&view=auto
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/ExceptionsCheck.inc (added)
+++ vmkit/trunk/lib/JnJVM/VMCore/ExceptionsCheck.inc Mon Feb 9 07:33:30 2009
@@ -0,0 +1,518 @@
+Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
+ const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ Instruction* res = CallInst::Create(F, args.begin(), args.end(), Name,
+ InsertAtEnd);
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+
+ Constant* zero = module->JavaObjectNullConstant;
+ Value* test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "",
+ currentBlock);
+
+ BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock);
+
+
+ if (!currentExceptionBlock->empty()) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ }
+
+ currentBlock = ifNormal;
+
+ return res;
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ Instruction* res = CallInst::Create(F, arg1, Name, InsertAtEnd);
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+
+ Constant* zero = module->JavaObjectNullConstant;
+ Value* test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "",
+ currentBlock);
+
+ BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock);
+
+ if (!currentExceptionBlock->empty()) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ }
+
+ currentBlock = ifNormal;
+
+ return res;
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
+ const char* Name, BasicBlock *InsertAtEnd) {
+
+ Value* args[2] = { arg1, arg2 };
+
+ Instruction* res = CallInst::Create(F, args, args + 2, Name, InsertAtEnd);
+
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+
+ Constant* zero = module->JavaObjectNullConstant;
+ Value* test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "",
+ currentBlock);
+
+ BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock);
+
+ if (!currentExceptionBlock->empty()) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ }
+
+ currentBlock = ifNormal;
+
+ return res;
+}
+
+Instruction* JavaJIT::invoke(Value *F, const char* Name,
+ BasicBlock *InsertAtEnd) {
+ Instruction* res = llvm::CallInst::Create(F, Name, InsertAtEnd);
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+
+ Constant* zero = module->JavaObjectNullConstant;
+ Value* test = new ICmpInst(ICmpInst::ICMP_NE, obj, zero, "",
+ currentBlock);
+
+ BranchInst::Create(currentExceptionBlock, ifNormal, test, currentBlock);
+
+ if (!currentExceptionBlock->empty()) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ }
+
+ currentBlock = ifNormal;
+
+ return res;
+}
+
+void JavaJIT::throwException(llvm::Function* F, Value* arg1) {
+ Value* obj = CallInst::Create(F, arg1, "", currentBlock);
+ if (currentExceptionBlock != endExceptionBlock) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ BranchInst::Create(currentExceptionBlock, currentBlock);
+ } else {
+ if (endNode) {
+ const FunctionType *funcType = llvmFunction->getFunctionType();
+ const Type* returnType = funcType->getReturnType();
+ endNode->addIncoming(Constant::getNullValue(returnType), currentBlock);
+ }
+ BranchInst::Create(endBlock, currentBlock);
+ }
+}
+
+void JavaJIT::throwException(Value* obj) {
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+ new StoreInst(obj, javaExceptionPtr, currentBlock);
+ if (currentExceptionBlock != endExceptionBlock) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ BranchInst::Create(currentExceptionBlock, currentBlock);
+ } else {
+ if (endNode) {
+ const FunctionType *funcType = llvmFunction->getFunctionType();
+ const Type* returnType = funcType->getReturnType();
+ endNode->addIncoming(Constant::getNullValue(returnType), currentBlock);
+ }
+ BranchInst::Create(endBlock, currentBlock);
+ }
+}
+
+void JavaJIT::throwException(llvm::Function* F, Value** args,
+ uint32 nbArgs) {
+ Value* obj = CallInst::Create(F, args, args + nbArgs, "", currentBlock);
+ if (currentExceptionBlock != endExceptionBlock) {
+ Instruction* insn = currentExceptionBlock->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) node->addIncoming(obj, currentBlock);
+ BranchInst::Create(currentExceptionBlock, currentBlock);
+ } else {
+ if (endNode) {
+ const FunctionType *funcType = llvmFunction->getFunctionType();
+ const Type* returnType = funcType->getReturnType();
+ endNode->addIncoming(Constant::getNullValue(returnType), currentBlock);
+ }
+ BranchInst::Create(endBlock, currentBlock);
+ }
+}
+
+/// Handler - This class represents an exception handler. It is only needed
+/// when parsing the .class file in the JIT, therefore it is only defined
+/// here. The readExceptionTable function is the only function that makes
+/// use of this class.
+struct Handler {
+
+ /// startpc - The bytecode number that begins the try clause.
+ uint32 startpc;
+
+ /// endpc - The bytecode number that ends the try clause.
+ uint32 endpc;
+
+ /// handlerpc - The bytecode number where the handler code starts.
+ uint32 handlerpc;
+
+ /// catche - Index in the constant pool of the exception class.
+ uint16 catche;
+
+ /// catchClass - The class of the exception: it must always be loaded before
+ /// reading the exception table so that we do not throw an exception
+ /// when compiling.
+ UserClass* catchClass;
+
+ /// tester - The basic block that tests if the exception is handled by this
+ /// handler. If the handler is not the first of a list of handlers with the
+ /// same range, than this block is the catcher block. Otherwise, it is the
+ /// destination of the catcher block and of the handlers that do not handler
+ /// the exception.
+ llvm::BasicBlock* tester;
+
+ /// javaHandler - The Java code that handles the exception. At this point, we
+ /// know we have caught and are handling the exception. The Java exception
+ /// object is the PHI node that begins this block.
+ llvm::BasicBlock* javaHandler;
+
+};
+
+unsigned JavaJIT::readExceptionTable(Reader& reader, uint32 codeLen) {
+
+ // This function uses currentBlock to simplify things. We save the current
+ // value of currentBlock to restore it at the end of the function
+ BasicBlock* temp = currentBlock;
+
+ sint16 nbe = reader.readU2();
+ sint16 sync = isSynchro(compilingMethod->access) ? 1 : 0;
+ nbe += sync;
+
+ // Loop over all handlers in the bytecode to initialize their values.
+ Handler* handlers = (Handler*)alloca(sizeof(Handler) * (nbe - sync));
+ for (uint16 i = 0; i < nbe - sync; ++i) {
+ Handler* ex = &handlers[i];
+ ex->startpc = reader.readU2();
+ ex->endpc = reader.readU2();
+ ex->handlerpc = reader.readU2();
+
+ ex->catche = reader.readU2();
+
+#ifndef ISOLATE_SHARING
+ if (ex->catche) {
+ UserClass* cl =
+ (UserClass*)(compilingClass->ctpInfo->isClassLoaded(ex->catche));
+ // When loading the class, we made sure that all exception classes
+ // were loaded, so cl must have a value.
+ assert(cl && "exception class has not been loaded");
+ ex->catchClass = cl;
+ } else {
+ ex->catchClass = Classpath::newThrowable;
+ }
+#endif
+
+ ex->tester = createBasicBlock("testException");
+
+ // PHI Node for the exception object
+ PHINode::Create(JnjvmModule::JavaObjectType, "", ex->tester);
+
+ // Set the unwind destination of the instructions in the range of this
+ // handler to the test block of the handler. If an instruction already has
+ // a handler and thus is not the synchronize or regular end handler block,
+ // leave it as-is.
+ for (uint16 i = ex->startpc; i < ex->endpc; ++i) {
+ if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
+ opcodeInfos[i].exceptionBlock = ex->tester;
+ }
+ }
+
+ // If the handler pc does not already have a block, create a new one.
+ if (!(opcodeInfos[ex->handlerpc].newBlock)) {
+ opcodeInfos[ex->handlerpc].newBlock = createBasicBlock("javaHandler");
+ }
+
+ // Set the Java handler for this exception.
+ ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock;
+
+ if (ex->javaHandler->empty()) {
+ PHINode::Create(JnjvmModule::JavaObjectType, "", ex->javaHandler);
+ }
+
+ }
+
+ // Loop over all handlers to implement their tester.
+ for (sint16 i = 0; i < nbe - sync; ++i) {
+ Handler* cur = &handlers[i];
+ BasicBlock* bbNext = 0;
+ PHINode* javaNode = 0;
+ currentExceptionBlock = opcodeInfos[cur->handlerpc].exceptionBlock;
+
+ // Look out where we go if we're not the handler for the exception.
+ if (i + 1 != nbe - sync) {
+ Handler* next = &handlers[i + 1];
+ if (!(cur->startpc >= next->startpc && cur->endpc <= next->endpc)) {
+ // If there is no handler to go to (either one that has the same range
+ // or one that contains the range), then we jump to the end handler.
+ bbNext = endExceptionBlock;
+ } else {
+ // If there's a handler to goto, we jump to its tester block and record
+ // the exception PHI node to give our exception to the tester.
+ bbNext = next->tester;
+ javaNode = dyn_cast<PHINode>(bbNext->begin());
+ assert(javaNode);
+ }
+ } else {
+ // If there's no handler after us, we jump to the end handler.
+ bbNext = endExceptionBlock;
+ }
+
+ currentBlock = cur->tester;
+
+ Value* clVar = 0;
+#ifdef ISOLATE_SHARING
+ // We're dealing with exceptions, don't catch the exception if the class can
+ // not be found.
+ if (cur->catche) clVar = getResolvedClass(cur->catche, false, false, 0);
+ else clVar = CallInst::Create(module->GetJnjvmExceptionClassFunction,
+ isolateLocal, "", currentBlock);
+#else
+ // We know catchClass exists because we have loaded all exceptions catched
+ // by the method when we loaded the class that defined this method.
+ clVar = module->getNativeClass(cur->catchClass);
+#endif
+ if (clVar->getType() != module->JavaCommonClassType)
+ clVar = new BitCastInst(clVar, module->JavaCommonClassType, "",
+ currentBlock);
+
+
+#ifdef SERVICE
+ // Verifies that the current isolate is not stopped. If it is, we don't
+ // catch the exception but resume unwinding.
+ JnjvmClassLoader* loader = compilingClass->classLoader;;
+ if (loader != loader->bootstrapLoader) {
+ Value* threadId = getCurrentThread();
+ Value* Isolate = GetElementPtrInst::Create(threadId,
+ module->constantFour, "",
+ currentBlock);
+
+ Isolate = new LoadInst(Isolate, "", currentBlock);
+ Isolate = new BitCastInst(Isolate, module->ptrPtrType, "", currentBlock);
+ Value* Status = GetElementPtrInst::Create(Isolate, module->constantOne, "",
+ currentBlock);
+ Status = new LoadInst(Status, "", currentBlock);
+ Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock);
+
+ Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status,
+ module->constantOne, "", currentBlock);
+
+ BasicBlock* raiseBlock = createBasicBlock("raiseBlock");
+ BasicBlock* continueBlock = createBasicBlock("continueBlock");
+ BranchInst::Create(raiseBlock, continueBlock, stopping, currentBlock);
+ currentBlock = raiseBlock;
+ BranchInst::Create(endExceptionBlock, currentBlock);
+
+ currentBlock = continueBlock;
+ }
+#endif
+
+ // Get the Java exception.
+ Value* obj = currentBlock->begin();
+
+ Value* objCl = CallInst::Create(module->GetClassFunction, obj, "",
+ currentBlock);
+
+ Value* depthCl = ConstantInt::get(Type::Int32Ty, cur->catchClass->depth);
+ Value* depthClObj = CallInst::Create(module->GetDepthFunction, objCl, "",
+ currentBlock);
+
+ // Compare the exception with the exception class we catch.
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_ULE, depthCl, depthClObj, "",
+ currentBlock);
+
+ BasicBlock* supDepth = createBasicBlock("superior depth");
+
+ // Add the Java exception in the phi node of the next block.
+ if (javaNode)
+ javaNode->addIncoming(obj, currentBlock);
+
+ BranchInst::Create(supDepth, bbNext, cmp, currentBlock);
+
+ currentBlock = supDepth;
+ Value* inDisplay = CallInst::Create(module->GetDisplayFunction,
+ objCl, "", currentBlock);
+
+ Value* displayArgs[2] = { inDisplay, depthCl };
+ Value* clInDisplay = CallInst::Create(module->GetClassInDisplayFunction,
+ displayArgs, displayArgs + 2, "",
+ currentBlock);
+
+ cmp = new ICmpInst(ICmpInst::ICMP_EQ, clInDisplay, clVar, "",
+ currentBlock);
+
+ // Add the Java exception in the phi node of the handler.
+ Instruction* insn = cur->javaHandler->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ assert(node && "malformed exceptions");
+ node->addIncoming(obj, currentBlock);
+
+ // Add the Java exception in the phi node of the next block.
+ if (javaNode)
+ javaNode->addIncoming(obj, currentBlock);
+
+ // If we are catching this exception, then jump to the Java Handler,
+ // otherwise jump to our next handler.
+ BranchInst::Create(cur->javaHandler, bbNext, cmp, currentBlock);
+
+ currentBlock = cur->javaHandler;
+
+ // First thing in the handler: clear the exception.
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+ Value* threadId = getCurrentThread();
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Clear exceptions.
+ new StoreInst(module->JavaObjectNullConstant, javaExceptionPtr,
+ currentBlock);
+
+#if defined(SERVICE)
+
+ // Change the isolate we are currently running, now that we have catched
+ // the exception: the exception may have been thrown by another isolate.
+ Value* threadId = 0;
+ Value* OldIsolateID = 0;
+ Value* IsolateIDPtr = 0;
+ Value* OldIsolate = 0;
+ Value* NewIsolate = 0;
+ Value* IsolatePtr = 0;
+ currentBlock = cur->javaHandler;
+ if (loader != loader->bootstrapLoader) {
+ threadId = getCurrentThread();
+
+ IsolateIDPtr = GetElementPtrInst::Create(threadId, module->constantThree,
+ "", cur->javaHandler);
+ const Type* realType = PointerType::getUnqual(module->pointerSizeType);
+ IsolateIDPtr = new BitCastInst(IsolateIDPtr, realType, "",
+ cur->javaHandler);
+ OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler);
+
+ Value* MyID = ConstantInt::get(module->pointerSizeType,
+ loader->getIsolate()->IsolateID);
+
+ new StoreInst(MyID, IsolateIDPtr, cur->javaHandler);
+ IsolatePtr = GetElementPtrInst::Create(threadId, module->constantFour, "",
+ cur->javaHandler);
+
+ OldIsolate = new LoadInst(IsolatePtr, "", cur->javaHandler);
+ NewIsolate = module->getIsolate(loader->getIsolate(), currentBlock);
+ new StoreInst(NewIsolate, IsolatePtr, cur->javaHandler);
+
+ }
+#endif
+
+ }
+
+ // Restore currentBlock.
+ currentBlock = temp;
+ return nbe;
+
+}
+
+void JavaJIT::finishExceptions() {
+ pred_iterator PI = pred_begin(endExceptionBlock);
+ pred_iterator PE = pred_end(endExceptionBlock);
+ if (PI == PE) {
+ endExceptionBlock->eraseFromParent();
+ } else {
+ if (endNode) {
+ const FunctionType *funcType = llvmFunction->getFunctionType();
+ const Type* returnType = funcType->getReturnType();
+ endNode->addIncoming(Constant::getNullValue(returnType),
+ endExceptionBlock);
+ }
+ BranchInst::Create(endBlock, endExceptionBlock);
+ }
+
+
+ PI = pred_begin(unifiedUnreachable);
+ PE = pred_end(unifiedUnreachable);
+ if (PI == PE) {
+ unifiedUnreachable->eraseFromParent();
+ } else {
+ new UnreachableInst(unifiedUnreachable);
+ }
+
+ for (Function::iterator BI = llvmFunction->begin(), BE = llvmFunction->end();
+ BI != BE; BI++) {
+ PI = pred_begin(BI);
+ PE = pred_end(BI);
+ if (PI == PE) {
+ Instruction* insn = BI->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ if (node) {
+ node->replaceAllUsesWith(Constant::getNullValue(node->getType()));
+ node->eraseFromParent();
+ }
+ }
+ }
+
+}
Added: vmkit/trunk/lib/JnJVM/VMCore/ExceptionsDwarf.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/ExceptionsDwarf.inc?rev=64140&view=auto
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/ExceptionsDwarf.inc (added)
+++ vmkit/trunk/lib/JnJVM/VMCore/ExceptionsDwarf.inc Mon Feb 9 07:33:30 2009
@@ -0,0 +1,581 @@
+Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
+ const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ return llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
+ args.begin(),
+ args.end(), Name, InsertAtEnd);
+ } else {
+ return llvm::CallInst::Create(F, args.begin(), args.end(), Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ Value* arg[1] = { arg1 };
+ return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
+ arg, arg + 1, Name, InsertAtEnd);
+ } else {
+ return CallInst::Create(F, arg1, Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
+ const char* Name, BasicBlock *InsertAtEnd) {
+
+ Value* args[2] = { arg1, arg2 };
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
+ args, args + 2, Name, InsertAtEnd);
+ } else {
+ return CallInst::Create(F, args, args + 2, Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, const char* Name,
+ BasicBlock *InsertAtEnd) {
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ Value* args[1];
+ return llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
+ args, args, Name,
+ InsertAtEnd);
+ } else {
+ return llvm::CallInst::Create(F, Name, InsertAtEnd);
+ }
+}
+
+void JavaJIT::throwException(llvm::Function* F, Value* arg1) {
+ if (currentExceptionBlock != endExceptionBlock) {
+ Value* exArgs[1] = { arg1 };
+ InvokeInst::Create(F, unifiedUnreachable,
+ currentExceptionBlock, exArgs, exArgs + 1,
+ "", currentBlock);
+ } else {
+ CallInst::Create(F, arg1, "", currentBlock);
+ new UnreachableInst(currentBlock);
+ }
+}
+
+void JavaJIT::throwException(Value* obj) {
+ Function* F = module->ThrowExceptionFunction;
+ if (currentExceptionBlock != endExceptionBlock) {
+ Value* exArgs[1] = { obj };
+ InvokeInst::Create(F, unifiedUnreachable,
+ currentExceptionBlock, exArgs, exArgs + 1,
+ "", currentBlock);
+ } else {
+ CallInst::Create(F, obj, "", currentBlock);
+ new UnreachableInst(currentBlock);
+ }
+}
+
+void JavaJIT::throwException(llvm::Function* F, Value** args,
+ uint32 nbArgs) {
+ if (currentExceptionBlock != endExceptionBlock) {
+ InvokeInst::Create(F, unifiedUnreachable,
+ currentExceptionBlock, args, args + nbArgs,
+ "", currentBlock);
+ } else {
+ CallInst::Create(F, args, args + nbArgs, "", currentBlock);
+ new UnreachableInst(currentBlock);
+ }
+}
+
+/// Handler - This class represents an exception handler. It is only needed
+/// when parsing the .class file in the JIT, therefore it is only defined
+/// here. The readExceptionTable function is the only function that makes
+/// use of this class.
+struct Handler {
+
+ /// startpc - The bytecode number that begins the try clause.
+ uint32 startpc;
+
+ /// endpc - The bytecode number that ends the try clause.
+ uint32 endpc;
+
+ /// handlerpc - The bytecode number where the handler code starts.
+ uint32 handlerpc;
+
+ /// catche - Index in the constant pool of the exception class.
+ uint16 catche;
+
+ /// catchClass - The class of the exception: it must always be loaded before
+ /// reading the exception table so that we do not throw an exception
+ /// when compiling.
+ UserClass* catchClass;
+
+ /// catcher - The basic block that catches the exception. The catcher deals
+ /// with LLVM codegen and declares the llvm.select method. This block is the
+ /// destination of invoke instructions that are in the try clause.
+ llvm::BasicBlock* catcher;
+
+ /// tester - The basic block that tests if the exception is handled by this
+ /// handler. If the handler is not the first of a list of handlers with the
+ /// same range, than this block is the catcher block. Otherwise, it is the
+ /// destination of the catcher block and of the handlers that do not handler
+ /// the exception.
+ llvm::BasicBlock* tester;
+
+ /// javaHandler - The Java code that handles the exception. At this point, we
+ /// know we have caught and are handling the exception. The Java exception
+ /// object is the PHI node that begins this block.
+ llvm::BasicBlock* javaHandler;
+
+ /// nativeHandler - The CXX exception-related code that handles the exception.
+ /// The block clears the exception from the execution environment, calls
+ /// the CXX begin and end catch methods and jumps to the Java handler.
+ llvm::BasicBlock* nativeHandler;
+
+ /// exceptionPHI - The CXX exception object for the tester block. The
+ /// tester has incoming blocks, either from the catcher or from other
+ /// handlers that don't handle the exception. Therefore each incoming block
+ /// specifies the CXX exception object that was caught.
+ llvm::PHINode* exceptionPHI;
+};
+
+unsigned JavaJIT::readExceptionTable(Reader& reader, uint32 codeLen) {
+
+ // This function uses currentBlock to simplify things. We save the current
+ // value of currentBlock to restore it at the end of the function
+ BasicBlock* temp = currentBlock;
+
+ sint16 nbe = reader.readU2();
+ sint16 sync = isSynchro(compilingMethod->access) ? 1 : 0;
+ nbe += sync;
+
+ // realEndExceptionBlock is the block where handlers will resume if
+ // they don't treat the exception. realEndExceptionBlock does not
+ // have to catch the exception.
+ BasicBlock* realEndExceptionBlock = endExceptionBlock;
+
+ // endExceptionBlockCatcher is the block where every instruction will
+ // unwind.
+ BasicBlock* endExceptionBlockCatcher = endExceptionBlock;
+
+ if (sync) {
+ // synchronizeExceptionBlock is the the block which will release the lock
+ // on the object. trySynchronizeExceptionBlock is the block which will
+ // catch the exception if one is thrown.
+ BasicBlock* synchronizeExceptionBlock =
+ createBasicBlock("synchronizeExceptionBlock");
+ BasicBlock* trySynchronizeExceptionBlock =
+ createBasicBlock("trySynchronizeExceptionBlock");
+
+ // So synchronizeExceptionBlock becomes the block where every instructions
+ // will unwind.
+ realEndExceptionBlock = synchronizeExceptionBlock;
+ endExceptionBlockCatcher = trySynchronizeExceptionBlock;
+ Value* argsSync = 0;
+ if (isVirtual(compilingMethod->access)) {
+ argsSync = llvmFunction->arg_begin();
+ } else {
+ Value* cl = module->getJavaClass(compilingClass);
+ argsSync = cl;
+ }
+
+ // In the synchronizeExceptionBlock: release the object and go to
+ // endExceptionBlock, which will unwind the function.
+
+ CallInst::Create(module->ReleaseObjectFunction, argsSync, "",
+ synchronizeExceptionBlock);
+
+ BranchInst::Create(endExceptionBlock, synchronizeExceptionBlock);
+
+
+ // In the trySynchronizeExceptionBlock: catch the exception and move
+ // to synchronizeExceptionBlock.
+
+ const PointerType* PointerTy_0 = module->ptrType;
+ Instruction* ptr_eh_ptr = CallInst::Create(module->llvmGetException,
+ "eh_ptr",
+ trySynchronizeExceptionBlock);
+ Constant* C = ConstantExpr::getCast(Instruction::BitCast,
+ module->personality, PointerTy_0);
+ Value* int32_eh_select_params[3] =
+ { ptr_eh_ptr, C, module->constantPtrNull };
+ CallInst::Create(module->exceptionSelector, int32_eh_select_params,
+ int32_eh_select_params + 3, "eh_select",
+ trySynchronizeExceptionBlock);
+
+ BranchInst::Create(synchronizeExceptionBlock,
+ trySynchronizeExceptionBlock);
+
+ // Now we can set the unwind destination of all instructions to
+ // the exception catcher.
+ for (uint16 i = 0; i < codeLen; ++i) {
+ if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
+ opcodeInfos[i].exceptionBlock = trySynchronizeExceptionBlock;
+ }
+ }
+ }
+
+ // Loop over all handlers in the bytecode to initialize their values.
+ Handler* handlers = (Handler*)alloca(sizeof(Handler) * (nbe - sync));
+ for (uint16 i = 0; i < nbe - sync; ++i) {
+ Handler* ex = &handlers[i];
+ ex->startpc = reader.readU2();
+ ex->endpc = reader.readU2();
+ ex->handlerpc = reader.readU2();
+
+ ex->catche = reader.readU2();
+
+#ifndef ISOLATE_SHARING
+ if (ex->catche) {
+ UserClass* cl =
+ (UserClass*)(compilingClass->ctpInfo->isClassLoaded(ex->catche));
+ // When loading the class, we made sure that all exception classes
+ // were loaded, so cl must have a value.
+ assert(cl && "exception class has not been loaded");
+ ex->catchClass = cl;
+ } else {
+ ex->catchClass = Classpath::newThrowable;
+ }
+#endif
+
+ ex->catcher = createBasicBlock("testException");
+
+ // Set the unwind destination of the instructions in the range of this
+ // handler to the test block of the handler. If an instruction already has
+ // a handler and thus is not the synchronize or regular end handler block,
+ // leave it as-is.
+ for (uint16 i = ex->startpc; i < ex->endpc; ++i) {
+ if (opcodeInfos[i].exceptionBlock == endExceptionBlockCatcher) {
+ opcodeInfos[i].exceptionBlock = ex->catcher;
+ }
+ }
+
+ // If the handler pc does not already have a block, create a new one.
+ if (!(opcodeInfos[ex->handlerpc].newBlock)) {
+ opcodeInfos[ex->handlerpc].newBlock = createBasicBlock("javaHandler");
+ }
+
+ // Set the Java handler for this exception.
+ ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock;
+
+ // Set the native handler of this exception, which will catch the exception
+ // object.
+ ex->nativeHandler = createBasicBlock("nativeHandler");
+ }
+
+ // Loop over all handlers to know which ones have the same range. Handlers
+ // with a same range all verify the exception's class, but only one catches
+ // the exception. This is the reason why we have a tester block
+ // and a catcher block: the first one tests the exception's class, and the
+ // second one catches the exception.
+ bool first = true;
+ for (sint16 i = 0; i < nbe - sync; ++i) {
+ Handler* cur = &handlers[i];
+
+ // If we are the first handler, we must have one block for catching
+ // the exception, and one block for comparing the exception. The former
+ // is catcher and the latter is tester. Handlers that live in
+ // the range of this handler will jump to tester because they
+ // have already catched the exception. The other instructions in the range
+ // of this handler will jump to catcher because the
+ // exception still has to be catched.
+ if (first) {
+ cur->tester = createBasicBlock("realTestException");
+ } else {
+ cur->tester = cur->catcher;
+ }
+
+ // Set the exception as a phi node. This PHI has two types of incoming
+ // nodes:
+ // - Handlers within the range: they have already catched the exception
+ // and verified its type. They are not the right handler for the
+ // exception, so they jump to this handler
+ // - The testException block of this handler (which is unique). It has
+ // catched the exception and is now jumping to perform the test.
+ cur->exceptionPHI = PHINode::Create(module->ptrType, "", cur->tester);
+
+ // Look if the next handler has the same range or has a different range.
+ // If it's in the same range, then no need to catch the exception.
+ // Otherwise, it's a new range and we need to catch the exception.
+ if (i + 1 != nbe - sync) {
+ Handler* next = &handlers[i + 1];
+
+ if (cur->startpc == next->startpc && cur->endpc == next->endpc) {
+ first = false;
+ } else {
+ first = true;
+ }
+ }
+ }
+
+
+ // Loop over all handlers to implement their catcher and tester.
+ for (sint16 i = 0; i < nbe - sync; ++i) {
+ Handler* cur = &handlers[i];
+ BasicBlock* bbNext = 0;
+ PHINode* nodeNext = 0;
+ currentExceptionBlock = opcodeInfos[cur->handlerpc].exceptionBlock;
+
+ // Look out where we go if we're not the handler for the exception.
+ if (i + 1 != nbe - sync) {
+ Handler* next = &handlers[i + 1];
+ if (!(cur->startpc >= next->startpc && cur->endpc <= next->endpc)) {
+ // If there is no handler to go to (either one that has the same range
+ // or one that contains the range), then we jump to the end handler.
+ bbNext = realEndExceptionBlock;
+ } else {
+ // If there's a handler to goto, we jump to its tester block and record
+ // the exception PHI node to give our exception to the tester.
+ bbNext = next->tester;
+ nodeNext = next->exceptionPHI;
+ }
+ } else {
+ // If there's no handler after us, we jump to the end handler.
+ bbNext = realEndExceptionBlock;
+ }
+
+ // If the tester and the catcher is not the same, then we must implement
+ // the catcher. The catcher catches the exception, jumps to the tester
+ // and gives the exception as an incoming node the the exceptionPHI.
+ if (cur->tester != cur->catcher) {
+ const PointerType* PointerTy_0 = module->ptrType;
+ Instruction* ptr_eh_ptr =
+ CallInst::Create(module->llvmGetException, "eh_ptr", cur->catcher);
+ Constant* C = ConstantExpr::getCast(Instruction::BitCast,
+ module->personality, PointerTy_0);
+ Value* int32_eh_select_params[3] =
+ { ptr_eh_ptr, C, module->constantPtrNull };
+ llvm::CallInst::Create(module->exceptionSelector,
+ int32_eh_select_params,
+ int32_eh_select_params + 3, "eh_select",
+ cur->catcher);
+ llvm::BranchInst::Create(cur->tester, cur->catcher);
+ cur->exceptionPHI->addIncoming(ptr_eh_ptr, cur->catcher);
+ }
+
+ currentBlock = cur->tester;
+
+ Value* clVar = 0;
+#ifdef ISOLATE_SHARING
+ // We're dealing with exceptions, don't catch the exception if the class can
+ // not be found.
+ if (cur->catche) clVar = getResolvedClass(cur->catche, false, false, 0);
+ else clVar = CallInst::Create(module->GetJnjvmExceptionClassFunction,
+ isolateLocal, "", currentBlock);
+#else
+ // We know catchClass exists because we have loaded all exceptions catched
+ // by the method when we loaded the class that defined this method.
+ clVar = module->getNativeClass(cur->catchClass);
+#endif
+ if (clVar->getType() != module->JavaCommonClassType)
+ clVar = new BitCastInst(clVar, module->JavaCommonClassType, "",
+ currentBlock);
+
+
+#ifdef SERVICE
+ // Verifies that the current isolate is not stopped. If it is, we don't
+ // catch the exception but resume unwinding.
+ JnjvmClassLoader* loader = compilingClass->classLoader;;
+ if (loader != loader->bootstrapLoader) {
+ Value* threadId = getCurrentThread();
+ Value* Isolate = GetElementPtrInst::Create(threadId,
+ module->constantFour, "",
+ currentBlock);
+
+ Isolate = new LoadInst(Isolate, "", currentBlock);
+ Isolate = new BitCastInst(Isolate, module->ptrPtrType, "", currentBlock);
+ Value* Status = GetElementPtrInst::Create(Isolate, module->constantOne, "",
+ currentBlock);
+ Status = new LoadInst(Status, "", currentBlock);
+ Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock);
+
+ Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status,
+ module->constantOne, "", currentBlock);
+
+ BasicBlock* raiseBlock = createBasicBlock("raiseBlock");
+ BasicBlock* continueBlock = createBasicBlock("continueBlock");
+ BranchInst::Create(raiseBlock, continueBlock, stopping, currentBlock);
+ currentBlock = raiseBlock;
+ BranchInst::Create(endExceptionBlock, currentBlock);
+
+ currentBlock = continueBlock;
+ }
+#endif
+
+ Value* threadId = getCurrentThread();
+ Value* geps[2] = { module->constantZero,
+ module->OffsetJavaExceptionInThreadConstant };
+
+ Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
+ geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ Value* objCl = CallInst::Create(module->GetClassFunction, obj, "",
+ currentBlock);
+
+ Value* depthCl = ConstantInt::get(Type::Int32Ty, cur->catchClass->depth);
+ Value* depthClObj = CallInst::Create(module->GetDepthFunction, objCl, "",
+ currentBlock);
+
+ // Compare the exception with the exception class we catch.
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_ULE, depthCl, depthClObj, "",
+ currentBlock);
+
+ BasicBlock* supDepth = createBasicBlock("superior depth");
+
+ BranchInst::Create(supDepth, bbNext, cmp, currentBlock);
+
+ if (nodeNext)
+ nodeNext->addIncoming(cur->exceptionPHI, currentBlock);
+
+ currentBlock = supDepth;
+ Value* inDisplay = CallInst::Create(module->GetDisplayFunction,
+ objCl, "", currentBlock);
+
+ Value* displayArgs[2] = { inDisplay, depthCl };
+ Value* clInDisplay = CallInst::Create(module->GetClassInDisplayFunction,
+ displayArgs, displayArgs + 2, "",
+ currentBlock);
+
+ cmp = new ICmpInst(ICmpInst::ICMP_EQ, clInDisplay, clVar, "",
+ currentBlock);
+
+ // If we are catching this exception, then jump to the nativeHandler,
+ // otherwise jump to our next handler.
+ BranchInst::Create(cur->nativeHandler, bbNext, cmp, currentBlock);
+
+ // Add the incoming value to the next handler, which is the exception we
+ // just catched.
+ if (nodeNext)
+ nodeNext->addIncoming(cur->exceptionPHI, currentBlock);
+
+ currentBlock = cur->nativeHandler;
+
+ threadId = getCurrentThread();
+ javaExceptionPtr = GetElementPtrInst::Create(threadId, geps, geps + 2, "",
+ currentBlock);
+
+ // Get the Java exception.
+ Value* exc = new LoadInst(javaExceptionPtr, "", currentBlock);
+
+ Value* geps2[2] = { module->constantZero,
+ module->OffsetCXXExceptionInThreadConstant };
+
+ Value* cxxExceptionPtr = GetElementPtrInst::Create(threadId, geps2,
+ geps2 + 2, "",
+ currentBlock);
+
+ // Clear exceptions.
+ new StoreInst(module->constantPtrNull, cxxExceptionPtr, currentBlock);
+ new StoreInst(module->JavaObjectNullConstant, javaExceptionPtr,
+ currentBlock);
+
+ // Call the CXX begin and end catcher.
+ CallInst::Create(module->exceptionBeginCatch, cur->exceptionPHI,
+ "tmp8", cur->nativeHandler);
+ CallInst::Create(module->exceptionEndCatch, "", cur->nativeHandler);
+
+ // We can now jump to the Java handler!
+ BranchInst::Create(cur->javaHandler, cur->nativeHandler);
+
+ // If the Java handler is empty, create a PHI node that will contain the
+ // exception and give our own.
+ if (cur->javaHandler->empty()) {
+ PHINode* node = PHINode::Create(JnjvmModule::JavaObjectType, "",
+ cur->javaHandler);
+ node->addIncoming(exc, cur->nativeHandler);
+
+ } else {
+ // If the Java handler is not empty, then the first instruction is the
+ // PHI node. Give it our own.
+ Instruction* insn = cur->javaHandler->begin();
+ PHINode* node = dyn_cast<PHINode>(insn);
+ assert(node && "malformed exceptions");
+ node->addIncoming(exc, cur->nativeHandler);
+ }
+
+
+#if defined(SERVICE)
+
+ // Change the isolate we are currently running, now that we have catched
+ // the exception: the exception may have been thrown by another isolate.
+ Value* threadId = 0;
+ Value* OldIsolateID = 0;
+ Value* IsolateIDPtr = 0;
+ Value* OldIsolate = 0;
+ Value* NewIsolate = 0;
+ Value* IsolatePtr = 0;
+ currentBlock = cur->javaHandler;
+ if (loader != loader->bootstrapLoader) {
+ threadId = getCurrentThread();
+
+ IsolateIDPtr = GetElementPtrInst::Create(threadId, module->constantThree,
+ "", cur->javaHandler);
+ const Type* realType = PointerType::getUnqual(module->pointerSizeType);
+ IsolateIDPtr = new BitCastInst(IsolateIDPtr, realType, "",
+ cur->javaHandler);
+ OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler);
+
+ Value* MyID = ConstantInt::get(module->pointerSizeType,
+ loader->getIsolate()->IsolateID);
+
+ new StoreInst(MyID, IsolateIDPtr, cur->javaHandler);
+ IsolatePtr = GetElementPtrInst::Create(threadId, module->constantFour, "",
+ cur->javaHandler);
+
+ OldIsolate = new LoadInst(IsolatePtr, "", cur->javaHandler);
+ NewIsolate = module->getIsolate(loader->getIsolate(), currentBlock);
+ new StoreInst(NewIsolate, IsolatePtr, cur->javaHandler);
+
+ }
+#endif
+
+ }
+
+ // Restore currentBlock.
+ currentBlock = temp;
+ return nbe;
+
+}
+
+void JavaJIT::finishExceptions() {
+ pred_iterator PI = pred_begin(endExceptionBlock);
+ pred_iterator PE = pred_end(endExceptionBlock);
+ if (PI == PE) {
+ endExceptionBlock->eraseFromParent();
+ } else {
+ Value* threadId = getCurrentThread();
+ Value* geps2[2] = { module->constantZero,
+ module->OffsetCXXExceptionInThreadConstant };
+
+ Value* cxxExceptionPtr = GetElementPtrInst::Create(threadId, geps2,
+ geps2 + 2, "",
+ currentBlock);
+ cxxExceptionPtr = new LoadInst(cxxExceptionPtr, "", currentBlock);
+ llvm::CallInst::Create(module->unwindResume, cxxExceptionPtr, "",
+ currentBlock);
+ new UnreachableInst(currentBlock);
+ }
+
+ PI = pred_begin(unifiedUnreachable);
+ PE = pred_end(unifiedUnreachable);
+ if (PI == PE) {
+ unifiedUnreachable->eraseFromParent();
+ } else {
+ new UnreachableInst(unifiedUnreachable);
+ }
+
+}
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Mon Feb 9 07:33:30 2009
@@ -778,18 +778,17 @@
if (PI == PE && returnType != Type::VoidTy) {
Instruction* I = currentBlock->getTerminator();
- assert((isa<UnreachableInst>(I) || isa<InvokeInst>(I)) &&
- "Malformed end Java block");
-
if (isa<UnreachableInst>(I)) {
I->eraseFromParent();
BranchInst::Create(endBlock, currentBlock);
+ endNode->addIncoming(Constant::getNullValue(returnType),
+ currentBlock);
} else if (InvokeInst* II = dyn_cast<InvokeInst>(I)) {
II->setNormalDest(endBlock);
+ endNode->addIncoming(Constant::getNullValue(returnType),
+ currentBlock);
}
- endNode->addIncoming(Constant::getNullValue(returnType),
- currentBlock);
}
currentBlock = endBlock;
@@ -837,31 +836,8 @@
}
currentBlock = endExceptionBlock;
- PI = pred_begin(endExceptionBlock);
- PE = pred_end(endExceptionBlock);
- if (PI == PE) {
- endExceptionBlock->eraseFromParent();
- } else {
- Value* threadId = getCurrentThread();
- Value* geps2[2] = { module->constantZero,
- module->OffsetCXXExceptionInThreadConstant };
-
- Value* cxxExceptionPtr = GetElementPtrInst::Create(threadId, geps2,
- geps2 + 2, "",
- currentBlock);
- cxxExceptionPtr = new LoadInst(cxxExceptionPtr, "", currentBlock);
- llvm::CallInst::Create(module->unwindResume, cxxExceptionPtr, "",
- currentBlock);
- new UnreachableInst(currentBlock);
- }
-
- PI = pred_begin(unifiedUnreachable);
- PE = pred_end(unifiedUnreachable);
- if (PI == PE) {
- unifiedUnreachable->eraseFromParent();
- } else {
- new UnreachableInst(unifiedUnreachable);
- }
+
+ finishExceptions();
func->setLinkage(GlobalValue::ExternalLinkage);
@@ -874,460 +850,6 @@
return llvmFunction;
}
-/// Handler - This class represents an exception handler. It is only needed
-/// when parsing the .class file in the JIT, therefore it is only defined
-/// here. The readExceptionTable function is the only function that makes
-/// use of this class.
-struct Handler {
-
- /// startpc - The bytecode number that begins the try clause.
- uint32 startpc;
-
- /// endpc - The bytecode number that ends the try clause.
- uint32 endpc;
-
- /// handlerpc - The bytecode number where the handler code starts.
- uint32 handlerpc;
-
- /// catche - Index in the constant pool of the exception class.
- uint16 catche;
-
- /// catchClass - The class of the exception: it must always be loaded before
- /// reading the exception table so that we do not throw an exception
- /// when compiling.
- UserClass* catchClass;
-
- /// catcher - The basic block that catches the exception. The catcher deals
- /// with LLVM codegen and declares the llvm.select method. This block is the
- /// destination of invoke instructions that are in the try clause.
- llvm::BasicBlock* catcher;
-
- /// tester - The basic block that tests if the exception is handled by this
- /// handler. If the handler is not the first of a list of handlers with the
- /// same range, than this block is the catcher block. Otherwise, it is the
- /// destination of the catcher block and of the handlers that do not handler
- /// the exception.
- llvm::BasicBlock* tester;
-
- /// javaHandler - The Java code that handles the exception. At this point, we
- /// know we have caught and are handling the exception. The Java exception
- /// object is the PHI node that begins this block.
- llvm::BasicBlock* javaHandler;
-
- /// nativeHandler - The CXX exception-related code that handles the exception.
- /// The block clears the exception from the execution environment, calls
- /// the CXX begin and end catch methods and jumps to the Java handler.
- llvm::BasicBlock* nativeHandler;
-
- /// exceptionPHI - The CXX exception object for the tester block. The
- /// tester has incoming blocks, either from the catcher or from other
- /// handlers that don't handle the exception. Therefore each incoming block
- /// specifies the CXX exception object that was caught.
- llvm::PHINode* exceptionPHI;
-};
-
-unsigned JavaJIT::readExceptionTable(Reader& reader, uint32 codeLen) {
-
- // This function uses currentBlock to simplify things. We save the current
- // value of currentBlock to restore it at the end of the function
- BasicBlock* temp = currentBlock;
-
- sint16 nbe = reader.readU2();
- sint16 sync = isSynchro(compilingMethod->access) ? 1 : 0;
- nbe += sync;
-
- // realEndExceptionBlock is the block where handlers will resume if
- // they don't treat the exception. realEndExceptionBlock does not
- // have to catch the exception.
- BasicBlock* realEndExceptionBlock = endExceptionBlock;
-
- // endExceptionBlockCatcher is the block where every instruction will
- // unwind.
- BasicBlock* endExceptionBlockCatcher = endExceptionBlock;
-
- if (sync) {
- // synchronizeExceptionBlock is the the block which will release the lock
- // on the object. trySynchronizeExceptionBlock is the block which will
- // catch the exception if one is thrown.
- BasicBlock* synchronizeExceptionBlock =
- createBasicBlock("synchronizeExceptionBlock");
- BasicBlock* trySynchronizeExceptionBlock =
- createBasicBlock("trySynchronizeExceptionBlock");
-
- // So synchronizeExceptionBlock becomes the block where every instructions
- // will unwind.
- realEndExceptionBlock = synchronizeExceptionBlock;
- endExceptionBlockCatcher = trySynchronizeExceptionBlock;
- Value* argsSync = 0;
- if (isVirtual(compilingMethod->access)) {
- argsSync = llvmFunction->arg_begin();
- } else {
- Value* cl = module->getJavaClass(compilingClass);
- argsSync = cl;
- }
-
- // In the synchronizeExceptionBlock: release the object and go to
- // endExceptionBlock, which will unwind the function.
-
- CallInst::Create(module->ReleaseObjectFunction, argsSync, "",
- synchronizeExceptionBlock);
-
- BranchInst::Create(endExceptionBlock, synchronizeExceptionBlock);
-
-
- // In the trySynchronizeExceptionBlock: catch the exception and move
- // to synchronizeExceptionBlock.
-
- const PointerType* PointerTy_0 = module->ptrType;
- Instruction* ptr_eh_ptr = CallInst::Create(module->llvmGetException,
- "eh_ptr",
- trySynchronizeExceptionBlock);
- Constant* C = ConstantExpr::getCast(Instruction::BitCast,
- module->personality, PointerTy_0);
- Value* int32_eh_select_params[3] =
- { ptr_eh_ptr, C, module->constantPtrNull };
- CallInst::Create(module->exceptionSelector, int32_eh_select_params,
- int32_eh_select_params + 3, "eh_select",
- trySynchronizeExceptionBlock);
-
- BranchInst::Create(synchronizeExceptionBlock,
- trySynchronizeExceptionBlock);
-
- // Now we can set the unwind destination of all instructions to
- // the exception catcher.
- for (uint16 i = 0; i < codeLen; ++i) {
- if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
- opcodeInfos[i].exceptionBlock = trySynchronizeExceptionBlock;
- }
- }
- }
-
- // Loop over all handlers in the bytecode to initialize their values.
- Handler* handlers = (Handler*)alloca(sizeof(Handler) * (nbe - sync));
- for (uint16 i = 0; i < nbe - sync; ++i) {
- Handler* ex = &handlers[i];
- ex->startpc = reader.readU2();
- ex->endpc = reader.readU2();
- ex->handlerpc = reader.readU2();
-
- ex->catche = reader.readU2();
-
-#ifndef ISOLATE_SHARING
- if (ex->catche) {
- UserClass* cl =
- (UserClass*)(compilingClass->ctpInfo->isClassLoaded(ex->catche));
- // When loading the class, we made sure that all exception classes
- // were loaded, so cl must have a value.
- assert(cl && "exception class has not been loaded");
- ex->catchClass = cl;
- } else {
- ex->catchClass = Classpath::newThrowable;
- }
-#endif
-
- ex->catcher = createBasicBlock("testException");
-
- // Set the unwind destination of the instructions in the range of this
- // handler to the test block of the handler. If an instruction already has
- // a handler and thus is not the synchronize or regular end handler block,
- // leave it as-is.
- for (uint16 i = ex->startpc; i < ex->endpc; ++i) {
- if (opcodeInfos[i].exceptionBlock == endExceptionBlockCatcher) {
- opcodeInfos[i].exceptionBlock = ex->catcher;
- }
- }
-
- // If the handler pc does not already have a block, create a new one.
- if (!(opcodeInfos[ex->handlerpc].newBlock)) {
- opcodeInfos[ex->handlerpc].newBlock = createBasicBlock("javaHandler");
- }
-
- // Set the Java handler for this exception.
- ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock;
-
- // Set the native handler of this exception, which will catch the exception
- // object.
- ex->nativeHandler = createBasicBlock("nativeHandler");
- }
-
- // Loop over all handlers to know which ones have the same range. Handlers
- // with a same range all verify the exception's class, but only one catches
- // the exception. This is the reason why we have a tester block
- // and a catcher block: the first one tests the exception's class, and the
- // second one catches the exception.
- bool first = true;
- for (sint16 i = 0; i < nbe - sync; ++i) {
- Handler* cur = &handlers[i];
-
- // If we are the first handler, we must have one block for catching
- // the exception, and one block for comparing the exception. The former
- // is catcher and the latter is tester. Handlers that live in
- // the range of this handler will jump to tester because they
- // have already catched the exception. The other instructions in the range
- // of this handler will jump to catcher because the
- // exception still has to be catched.
- if (first) {
- cur->tester = createBasicBlock("realTestException");
- } else {
- cur->tester = cur->catcher;
- }
-
- // Set the exception as a phi node. This PHI has two types of incoming
- // nodes:
- // - Handlers within the range: they have already catched the exception
- // and verified its type. They are not the right handler for the
- // exception, so they jump to this handler
- // - The testException block of this handler (which is unique). It has
- // catched the exception and is now jumping to perform the test.
- cur->exceptionPHI = PHINode::Create(module->ptrType, "", cur->tester);
-
- // Look if the next handler has the same range or has a different range.
- // If it's in the same range, then no need to catch the exception.
- // Otherwise, it's a new range and we need to catch the exception.
- if (i + 1 != nbe - sync) {
- Handler* next = &handlers[i + 1];
-
- if (cur->startpc == next->startpc && cur->endpc == next->endpc) {
- first = false;
- } else {
- first = true;
- }
- }
- }
-
-
- // Loop over all handlers to implement their catcher and tester.
- for (sint16 i = 0; i < nbe - sync; ++i) {
- Handler* cur = &handlers[i];
- BasicBlock* bbNext = 0;
- PHINode* nodeNext = 0;
- currentExceptionBlock = opcodeInfos[cur->handlerpc].exceptionBlock;
-
- // Look out where we go if we're not the handler for the exception.
- if (i + 1 != nbe - sync) {
- Handler* next = &handlers[i + 1];
- if (!(cur->startpc >= next->startpc && cur->endpc <= next->endpc)) {
- // If there is no handler to go to (either one that has the same range
- // or one that contains the range), then we jump to the end handler.
- bbNext = realEndExceptionBlock;
- } else {
- // If there's a handler to goto, we jump to its tester block and record
- // the exception PHI node to give our exception to the tester.
- bbNext = next->tester;
- nodeNext = next->exceptionPHI;
- }
- } else {
- // If there's no handler after us, we jump to the end handler.
- bbNext = realEndExceptionBlock;
- }
-
- // If the tester and the catcher is not the same, then we must implement
- // the catcher. The catcher catches the exception, jumps to the tester
- // and gives the exception as an incoming node the the exceptionPHI.
- if (cur->tester != cur->catcher) {
- const PointerType* PointerTy_0 = module->ptrType;
- Instruction* ptr_eh_ptr =
- CallInst::Create(module->llvmGetException, "eh_ptr", cur->catcher);
- Constant* C = ConstantExpr::getCast(Instruction::BitCast,
- module->personality, PointerTy_0);
- Value* int32_eh_select_params[3] =
- { ptr_eh_ptr, C, module->constantPtrNull };
- llvm::CallInst::Create(module->exceptionSelector,
- int32_eh_select_params,
- int32_eh_select_params + 3, "eh_select",
- cur->catcher);
- llvm::BranchInst::Create(cur->tester, cur->catcher);
- cur->exceptionPHI->addIncoming(ptr_eh_ptr, cur->catcher);
- }
-
- currentBlock = cur->tester;
-
- Value* clVar = 0;
-#ifdef ISOLATE_SHARING
- // We're dealing with exceptions, don't catch the exception if the class can
- // not be found.
- if (cur->catche) clVar = getResolvedClass(cur->catche, false, false, 0);
- else clVar = CallInst::Create(module->GetJnjvmExceptionClassFunction,
- isolateLocal, "", currentBlock);
-#else
- // We know catchClass exists because we have loaded all exceptions catched
- // by the method when we loaded the class that defined this method.
- clVar = module->getNativeClass(cur->catchClass);
-#endif
- if (clVar->getType() != module->JavaCommonClassType)
- clVar = new BitCastInst(clVar, module->JavaCommonClassType, "",
- currentBlock);
-
-
-#ifdef SERVICE
- // Verifies that the current isolate is not stopped. If it is, we don't
- // catch the exception but resume unwinding.
- JnjvmClassLoader* loader = compilingClass->classLoader;;
- if (loader != loader->bootstrapLoader) {
- Value* threadId = getCurrentThread();
- Value* Isolate = GetElementPtrInst::Create(threadId,
- module->constantFour, "",
- currentBlock);
-
- Isolate = new LoadInst(Isolate, "", currentBlock);
- Isolate = new BitCastInst(Isolate, module->ptrPtrType, "", currentBlock);
- Value* Status = GetElementPtrInst::Create(Isolate, module->constantOne, "",
- currentBlock);
- Status = new LoadInst(Status, "", currentBlock);
- Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock);
-
- Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status,
- module->constantOne, "", currentBlock);
-
- BasicBlock* raiseBlock = createBasicBlock("raiseBlock");
- BasicBlock* continueBlock = createBasicBlock("continueBlock");
- BranchInst::Create(raiseBlock, continueBlock, stopping, currentBlock);
- currentBlock = raiseBlock;
- BranchInst::Create(endExceptionBlock, currentBlock);
-
- currentBlock = continueBlock;
- }
-#endif
-
- Value* threadId = getCurrentThread();
- Value* geps[2] = { module->constantZero,
- module->OffsetJavaExceptionInThreadConstant };
-
- Value* javaExceptionPtr = GetElementPtrInst::Create(threadId, geps,
- geps + 2, "",
- currentBlock);
-
- // Get the Java exception.
- Value* obj = new LoadInst(javaExceptionPtr, "", currentBlock);
-
- Value* objCl = CallInst::Create(module->GetClassFunction, obj, "",
- currentBlock);
-
- Value* depthCl = ConstantInt::get(Type::Int32Ty, cur->catchClass->depth);
- Value* depthClObj = CallInst::Create(module->GetDepthFunction, objCl, "",
- currentBlock);
-
- // Compare the exception with the exception class we catch.
- Value* cmp = new ICmpInst(ICmpInst::ICMP_ULE, depthCl, depthClObj, "",
- currentBlock);
-
- BasicBlock* supDepth = createBasicBlock("superior depth");
-
- BranchInst::Create(supDepth, bbNext, cmp, currentBlock);
-
- if (nodeNext)
- nodeNext->addIncoming(cur->exceptionPHI, currentBlock);
-
- currentBlock = supDepth;
- Value* inDisplay = CallInst::Create(module->GetDisplayFunction,
- objCl, "", currentBlock);
-
- Value* displayArgs[2] = { inDisplay, depthCl };
- Value* clInDisplay = CallInst::Create(module->GetClassInDisplayFunction,
- displayArgs, displayArgs + 2, "",
- currentBlock);
-
- cmp = new ICmpInst(ICmpInst::ICMP_EQ, clInDisplay, clVar, "",
- currentBlock);
-
- // If we are catching this exception, then jump to the nativeHandler,
- // otherwise jump to our next handler.
- BranchInst::Create(cur->nativeHandler, bbNext, cmp, currentBlock);
-
- // Add the incoming value to the next handler, which is the exception we
- // just catched.
- if (nodeNext)
- nodeNext->addIncoming(cur->exceptionPHI, currentBlock);
-
- currentBlock = cur->nativeHandler;
-
- threadId = getCurrentThread();
- javaExceptionPtr = GetElementPtrInst::Create(threadId, geps, geps + 2, "",
- currentBlock);
-
- // Get the Java exception.
- Value* exc = new LoadInst(javaExceptionPtr, "", currentBlock);
-
- Value* geps2[2] = { module->constantZero,
- module->OffsetCXXExceptionInThreadConstant };
-
- Value* cxxExceptionPtr = GetElementPtrInst::Create(threadId, geps2,
- geps2 + 2, "",
- currentBlock);
-
- // Clear exceptions.
- new StoreInst(module->constantPtrNull, cxxExceptionPtr, currentBlock);
- new StoreInst(module->JavaObjectNullConstant, javaExceptionPtr,
- currentBlock);
-
- // Call the CXX begin and end catcher.
- CallInst::Create(module->exceptionBeginCatch, cur->exceptionPHI,
- "tmp8", cur->nativeHandler);
- CallInst::Create(module->exceptionEndCatch, "", cur->nativeHandler);
-
- // We can now jump to the Java handler!
- BranchInst::Create(cur->javaHandler, cur->nativeHandler);
-
- // If the Java handler is empty, create a PHI node that will contain the
- // exception and give our own.
- if (cur->javaHandler->empty()) {
- PHINode* node = PHINode::Create(JnjvmModule::JavaObjectType, "",
- cur->javaHandler);
- node->addIncoming(exc, cur->nativeHandler);
-
- } else {
- // If the Java handler is not empty, then the first instruction is the
- // PHI node. Give it our own.
- Instruction* insn = cur->javaHandler->begin();
- PHINode* node = dyn_cast<PHINode>(insn);
- assert(node && "malformed exceptions");
- node->addIncoming(exc, cur->nativeHandler);
- }
-
-
-#if defined(SERVICE)
-
- // Change the isolate we are currently running, now that we have catched
- // the exception: the exception may have been thrown by another isolate.
- Value* threadId = 0;
- Value* OldIsolateID = 0;
- Value* IsolateIDPtr = 0;
- Value* OldIsolate = 0;
- Value* NewIsolate = 0;
- Value* IsolatePtr = 0;
- currentBlock = cur->javaHandler;
- if (loader != loader->bootstrapLoader) {
- threadId = getCurrentThread();
-
- IsolateIDPtr = GetElementPtrInst::Create(threadId, module->constantThree,
- "", cur->javaHandler);
- const Type* realType = PointerType::getUnqual(module->pointerSizeType);
- IsolateIDPtr = new BitCastInst(IsolateIDPtr, realType, "",
- cur->javaHandler);
- OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler);
-
- Value* MyID = ConstantInt::get(module->pointerSizeType,
- loader->getIsolate()->IsolateID);
-
- new StoreInst(MyID, IsolateIDPtr, cur->javaHandler);
- IsolatePtr = GetElementPtrInst::Create(threadId, module->constantFour, "",
- cur->javaHandler);
-
- OldIsolate = new LoadInst(IsolatePtr, "", cur->javaHandler);
- NewIsolate = module->getIsolate(loader->getIsolate(), currentBlock);
- new StoreInst(NewIsolate, IsolatePtr, cur->javaHandler);
-
- }
-#endif
-
- }
-
- // Restore currentBlock.
- currentBlock = temp;
- return nbe;
-
-}
-
void JavaJIT::compareFP(Value* val1, Value* val2, const Type* ty, bool l) {
Value* one = module->constantOne;
Value* zero = module->constantZero;
@@ -2101,69 +1623,6 @@
}
-Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
- const char* Name,
- BasicBlock *InsertAtEnd) {
-
- // means: is there a handler for me?
- if (currentExceptionBlock != endExceptionBlock) {
- BasicBlock* ifNormal = createBasicBlock("no exception block");
- currentBlock = ifNormal;
- return llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
- args.begin(),
- args.end(), Name, InsertAtEnd);
- } else {
- return llvm::CallInst::Create(F, args.begin(), args.end(), Name, InsertAtEnd);
- }
-}
-
-Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
- BasicBlock *InsertAtEnd) {
-
- // means: is there a handler for me?
- if (currentExceptionBlock != endExceptionBlock) {
- BasicBlock* ifNormal = createBasicBlock("no exception block");
- currentBlock = ifNormal;
- Value* arg[1] = { arg1 };
- return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
- arg, arg + 1, Name, InsertAtEnd);
- } else {
- return CallInst::Create(F, arg1, Name, InsertAtEnd);
- }
-}
-
-Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
- const char* Name, BasicBlock *InsertAtEnd) {
-
- Value* args[2] = { arg1, arg2 };
-
- // means: is there a handler for me?
- if (currentExceptionBlock != endExceptionBlock) {
- BasicBlock* ifNormal = createBasicBlock("no exception block");
- currentBlock = ifNormal;
- return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
- args, args + 2, Name, InsertAtEnd);
- } else {
- return CallInst::Create(F, args, args + 2, Name, InsertAtEnd);
- }
-}
-
-Instruction* JavaJIT::invoke(Value *F, const char* Name,
- BasicBlock *InsertAtEnd) {
- // means: is there a handler for me?
- if (currentExceptionBlock != endExceptionBlock) {
- BasicBlock* ifNormal = createBasicBlock("no exception block");
- currentBlock = ifNormal;
- Value* args[1];
- return llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
- args, args, Name,
- InsertAtEnd);
- } else {
- return llvm::CallInst::Create(F, Name, InsertAtEnd);
- }
-}
-
-
void JavaJIT::invokeInterface(uint16 index, bool buggyVirtual) {
// Do the usual
@@ -2273,26 +1732,9 @@
}
}
-void JavaJIT::throwException(llvm::Function* F, Value* arg1) {
- if (currentExceptionBlock != endExceptionBlock) {
- Value* exArgs[1] = { arg1 };
- InvokeInst::Create(F, unifiedUnreachable,
- currentExceptionBlock, exArgs, exArgs + 1,
- "", currentBlock);
- } else {
- CallInst::Create(F, arg1, "", currentBlock);
- new UnreachableInst(currentBlock);
- }
-}
-void JavaJIT::throwException(llvm::Function* F, Value** args,
- uint32 nbArgs) {
- if (currentExceptionBlock != endExceptionBlock) {
- InvokeInst::Create(F, unifiedUnreachable,
- currentExceptionBlock, args, args + nbArgs,
- "", currentBlock);
- } else {
- CallInst::Create(F, args, args + nbArgs, "", currentBlock);
- new UnreachableInst(currentBlock);
- }
-}
+#ifdef DWARF_EXCEPTIONS
+#include "ExceptionsDwarf.inc"
+#else
+#include "ExceptionsCheck.inc"
+#endif
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.h?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.h (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.h Mon Feb 9 07:33:30 2009
@@ -61,6 +61,7 @@
llvmFunction = func;
inlining = false;
callsStackWalker = false;
+ endNode = 0;
}
/// javaCompile - Compile the Java method.
@@ -259,7 +260,11 @@
void throwException(llvm::Function* F, llvm::Value** args,
uint32 nbArgs);
void throwException(llvm::Function* F, llvm::Value* arg1);
+ void throwException(llvm::Value* obj);
+ /// finishExceptions - Emit code to unwind the current function if an
+ /// exception is thrown.
+ void finishExceptions();
//===--------------------------- Control flow ----------------------------===//
/// opcodeInfos - The informations for each instruction.
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJITOpcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJITOpcodes.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaJITOpcodes.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaJITOpcodes.cpp Mon Feb 9 07:33:30 2009
@@ -1968,7 +1968,7 @@
case ATHROW : {
llvm::Value* arg = pop();
- throwException(module->ThrowExceptionFunction, arg);
+ throwException(arg);
break;
}
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Mon Feb 9 07:33:30 2009
@@ -52,6 +52,8 @@
}\
+#if defined(DWARF_EXCEPTIONS)
+
#if 1//defined(__PPC__) && !defined(__MACH__)
#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
\
@@ -366,6 +368,311 @@
#endif
+#else // DWARF_EXCEPTIONS
+
+#if 1//defined(__PPC__) && !defined(__MACH__)
+#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) { \
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ verifyNull(obj); \
+ Signdef* sign = getSignature(); \
+ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, sign, ap); \
+ void* func = (((void***)obj)[0])[offset];\
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, _buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ Signdef* sign = getSignature(); \
+ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, sign, ap); \
+ void* func = this->compiledPtr();\
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, _buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ Signdef* sign = getSignature(); \
+ uintptr_t buf = (uintptr_t)alloca(sign->nbArguments * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, sign, ap); \
+ void* func = this->compiledPtr();\
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_STATIC_BUF)sign->getStaticCallBuf())(cl->getConstantPool(), func, _buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(Jnjvm* vm, UserClass* cl, JavaObject* obj, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ \
+ Signdef* sign = getSignature(); \
+ void* func = (((void***)obj)[0])[offset];\
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(Jnjvm* vm, UserClass* cl, JavaObject* obj, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(Jnjvm* vm, UserClass* cl, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_STATIC_BUF)sign->getStaticCallBuf())(cl->getConstantPool(), func, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Virtual(Jnjvm* vm, UserClass* cl, JavaObject* obj, ...) { \
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##VirtualAP(vm, cl, obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Special(Jnjvm* vm, UserClass* cl, JavaObject* obj, ...) {\
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##SpecialAP(vm, cl, obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Static(Jnjvm* vm, UserClass* cl, ...) {\
+ va_list ap;\
+ va_start(ap, cl);\
+ TYPE res = invoke##TYPE_NAME##StaticAP(vm, cl, ap);\
+ va_end(ap); \
+ return res; \
+}\
+
+#else
+
+#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) { \
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj); \
+ void* func = (((void***)obj)[0])[offset];\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_AP)sign->getVirtualCallAP())(cl->getConstantPool(), func, obj, ap);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(Jnjvm* vm, UserClass* cl, JavaObject* obj, va_list ap) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_AP)sign->getVirtualCallAP())(cl->getConstantPool(), func, obj, ap);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(Jnjvm* vm, UserClass* cl, va_list ap) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_STATIC_AP)sign->getStaticCallAP())(cl->getConstantPool(), func, ap);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(Jnjvm* vm, UserClass* cl, JavaObject* obj, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ void* func = (((void***)obj)[0])[offset];\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(Jnjvm* vm, UserClass* cl, JavaObject* obj, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_VIRTUAL_BUF)sign->getVirtualCallBuf())(cl->getConstantPool(), func, obj, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(Jnjvm* vm, UserClass* cl, void* buf) {\
+ if (!cl->isReady()) { \
+ cl->classLoader->loadName(cl->getName(), true, true); \
+ cl->initialiseClass(vm); \
+ } \
+ \
+ void* func = this->compiledPtr();\
+ Signdef* sign = getSignature(); \
+ JavaThread* th = JavaThread::get(); \
+ th->startJava(); \
+ TYPE res = 0; \
+ res = ((FUNC_TYPE_STATIC_BUF)sign->getStaticCallBuf())(cl->getConstantPool(), func, buf);\
+ if (th->pendingException) { \
+ th->throwFromJava(); \
+ } \
+ th->endJava(); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Virtual(Jnjvm* vm, UserClass* cl, JavaObject* obj, ...) { \
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##VirtualAP(vm, cl, obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Special(Jnjvm* vm, UserClass* cl, JavaObject* obj, ...) {\
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##SpecialAP(vm, cl, obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Static(Jnjvm* vm, UserClass* cl, ...) {\
+ va_list ap;\
+ va_start(ap, cl);\
+ TYPE res = invoke##TYPE_NAME##StaticAP(vm, cl, ap);\
+ va_end(ap); \
+ return res; \
+}\
+
+#endif
+#endif
+
typedef uint32 (*uint32_virtual_ap)(UserConstantPool*, void*, JavaObject*, va_list);
typedef sint64 (*sint64_virtual_ap)(UserConstantPool*, void*, JavaObject*, va_list);
typedef float (*float_virtual_ap)(UserConstantPool*, void*, JavaObject*, va_list);
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Mon Feb 9 07:33:30 2009
@@ -78,7 +78,6 @@
extern "C" void printJavaObject(const JavaObject* obj, mvm::PrintBuffer* buf) {
buf->write("JavaObject<");
CommonClass::printClassName(obj->getClass()->getName(), buf);
- fprintf(stderr, "%p\n", ((void**)obj->getVirtualTable())[9]);
buf->write(">");
}
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Mon Feb 9 07:33:30 2009
@@ -338,10 +338,12 @@
mvm::Allocator& allocator = th->getJVM()->gcAllocator;
allocator.freeTemporaryMemory(buf);
+#ifdef DWARF_EXCEPTIONS
// If there's an exception, throw it now.
if (JavaThread::get()->pendingException) {
th->throwPendingException();
}
+#endif
}
// Never throws.
@@ -401,7 +403,7 @@
}
// Creates a Java object and then throws it.
-extern "C" void jnjvmNullPointerException() {
+extern "C" JavaObject* jnjvmNullPointerException() {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
@@ -412,11 +414,17 @@
END_NATIVE_EXCEPTION
+#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
+#else
+ th->pendingException = exc;
+#endif
+
+ return exc;
}
// Creates a Java object and then throws it.
-extern "C" void negativeArraySizeException(sint32 val) {
+extern "C" JavaObject* negativeArraySizeException(sint32 val) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
@@ -426,11 +434,17 @@
END_NATIVE_EXCEPTION
+#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
+#else
+ th->pendingException = exc;
+#endif
+
+ return exc;
}
// Creates a Java object and then throws it.
-extern "C" void outOfMemoryError(sint32 val) {
+extern "C" JavaObject* outOfMemoryError(sint32 val) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
@@ -440,11 +454,18 @@
END_NATIVE_EXCEPTION
+#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
+#else
+ th->pendingException = exc;
+#endif
+
+ return exc;
}
// Creates a Java object and then throws it.
-extern "C" void jnjvmClassCastException(JavaObject* obj, UserCommonClass* cl) {
+extern "C" JavaObject* jnjvmClassCastException(JavaObject* obj,
+ UserCommonClass* cl) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
@@ -454,11 +475,18 @@
END_NATIVE_EXCEPTION
+#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
+#else
+ th->pendingException = exc;
+#endif
+
+ return exc;
}
// Creates a Java object and then throws it.
-extern "C" void indexOutOfBoundsException(JavaObject* obj, sint32 index) {
+extern "C" JavaObject* indexOutOfBoundsException(JavaObject* obj,
+ sint32 index) {
JavaObject *exc = 0;
JavaThread *th = JavaThread::get();
@@ -468,7 +496,13 @@
END_NATIVE_EXCEPTION
+#ifdef DWARF_EXCEPTIONS
th->throwException(exc);
+#else
+ th->pendingException = exc;
+#endif
+
+ return exc;
}
extern "C" void printMethodStart(JavaMethod* meth) {
Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Mon Feb 9 07:33:30 2009
@@ -179,8 +179,10 @@
/// throwFromNative - Throw an exception after executing Native code.
///
void throwFromNative() {
+#ifdef DWARF_EXCEPTIONS
addresses.pop_back();
throwPendingException();
+#endif
}
/// throwFromJava - Throw an exception after executing Java code.
Modified: vmkit/trunk/lib/Mvm/Runtime/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Runtime/JIT.cpp?rev=64140&r1=64139&r2=64140&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/Runtime/JIT.cpp (original)
+++ vmkit/trunk/lib/Mvm/Runtime/JIT.cpp Mon Feb 9 07:33:30 2009
@@ -42,7 +42,11 @@
void MvmModule::initialise(bool Fast, Module* M, TargetMachine* T) {
llvm::NoFramePointerElim = true;
+#if DWARF_EXCEPTIONS
llvm::ExceptionHandling = true;
+#else
+ llvm::ExceptionHandling = false;
+#endif
if (!M) {
globalModule = new llvm::Module("bootstrap module");
globalModuleProvider = new ExistingModuleProvider (globalModule);
More information about the vmkit-commits
mailing list