[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