[vmkit-commits] [vmkit] r144401 - in /vmkit/trunk: include/mvm/System.h include/mvm/VirtualMachine.h lib/J3/Compiler/JavaJIT.cpp lib/J3/VMCore/Jnjvm.h lib/Mvm/CommonThread/Sigsegv.cpp lib/Mvm/CommonThread/ctthread.cpp lib/Mvm/Compiler/JIT.cpp lib/Mvm/Compiler/VmkitGC.cpp lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp

Nicolas Geoffray nicolas.geoffray at lip6.fr
Fri Nov 11 10:38:38 PST 2011


Author: geoffray
Date: Fri Nov 11 12:38:37 2011
New Revision: 144401

URL: http://llvm.org/viewvc/llvm-project?rev=144401&view=rev
Log:
Make use of the new LLVM GCStrategy::findCustomSafepoint method and hardware null trap to remove explicit null checks in methods without a try/catch.


Modified:
    vmkit/trunk/include/mvm/System.h
    vmkit/trunk/include/mvm/VirtualMachine.h
    vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp
    vmkit/trunk/lib/J3/VMCore/Jnjvm.h
    vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp
    vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
    vmkit/trunk/lib/Mvm/Compiler/JIT.cpp
    vmkit/trunk/lib/Mvm/Compiler/VmkitGC.cpp
    vmkit/trunk/lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp

Modified: vmkit/trunk/include/mvm/System.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/System.h?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/System.h (original)
+++ vmkit/trunk/include/mvm/System.h Fri Nov 11 12:38:37 2011
@@ -214,6 +214,14 @@
   static void Exit(int value) {
     _exit(value);
   }
+
+  static bool SupportsHardwareNullCheck() {
+#if LINUX_OS && ARCH_X64
+    return true;
+#else
+    return false;
+#endif
+  }
 };
 
 }

Modified: vmkit/trunk/include/mvm/VirtualMachine.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/VirtualMachine.h?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/VirtualMachine.h (original)
+++ vmkit/trunk/include/mvm/VirtualMachine.h Fri Nov 11 12:38:37 2011
@@ -224,6 +224,12 @@
   /// runApplication - Run an application. The application name is in
   /// the arguments, hence it is the virtual machine's job to parse them.
   virtual void runApplication(int argc, char** argv) = 0;
+
+//===----------------------------------------------------------------------===//
+// (5) Exception-related methods.
+//===----------------------------------------------------------------------===//
+
+  virtual void nullPointerException() = 0;
 };
 
 } // end namespace mvm

Modified: vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp (original)
+++ vmkit/trunk/lib/J3/Compiler/JavaJIT.cpp Fri Nov 11 12:38:37 2011
@@ -1333,16 +1333,23 @@
 
 void JavaJIT::JITVerifyNull(Value* obj) {
   if (TheCompiler->hasExceptionsEnabled()) {
-    Constant* zero = intrinsics->JavaObjectNullConstant;
-    Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, zero, "");
+    if (nbHandlers == 0 && mvm::System::SupportsHardwareNullCheck()) {
+      Value* indexes[2] = { intrinsics->constantZero, intrinsics->constantZero };
+      Value* VTPtr = GetElementPtrInst::Create(obj, indexes, "", currentBlock);
+      Instruction* VT = new LoadInst(VTPtr, "", true, currentBlock);
+      VT->setDebugLoc(DebugLoc::get(currentBytecodeIndex, 1, DbgSubprogram));
+    } else {
+      Constant* zero = intrinsics->JavaObjectNullConstant;
+      Value* test = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, obj, zero, "");
 
-    BasicBlock* exit = createBasicBlock("verifyNullExit");
-    BasicBlock* cont = createBasicBlock("verifyNullCont");
+      BasicBlock* exit = createBasicBlock("verifyNullExit");
+      BasicBlock* cont = createBasicBlock("verifyNullCont");
 
-    BranchInst::Create(exit, cont, test, currentBlock);
-    currentBlock = exit;
-    throwRuntimeException(intrinsics->NullPointerExceptionFunction, 0, 0);
-    currentBlock = cont;
+      BranchInst::Create(exit, cont, test, currentBlock);
+      currentBlock = exit;
+      throwRuntimeException(intrinsics->NullPointerExceptionFunction, 0, 0);
+      currentBlock = cont;
+    }
   } 
 }
 

Modified: vmkit/trunk/lib/J3/VMCore/Jnjvm.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/VMCore/Jnjvm.h?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/J3/VMCore/Jnjvm.h (original)
+++ vmkit/trunk/lib/J3/VMCore/Jnjvm.h Fri Nov 11 12:38:37 2011
@@ -268,7 +268,6 @@
   void arrayStoreException();
   void indexOutOfBounds(const JavaObject* obj, sint32 entry);
   void negativeArraySizeException(int size);
-  void nullPointerException();
   void illegalAccessException(const char* msg);
   void illegalMonitorStateException(const JavaObject* obj);
   void interruptedException(const JavaObject* obj);
@@ -287,6 +286,7 @@
   void classNotFoundException(JavaString* str);
   void noClassDefFoundError(UserClass* cl, const UTF8* name);
   void classFormatError(const char* str);
+  virtual void nullPointerException();
   
   /// asciizToStr - Constructs a java/lang/String object from the given asciiz.
   ///

Modified: vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/Sigsegv.cpp Fri Nov 11 12:38:37 2011
@@ -1,4 +1,4 @@
-//===----------- Sigsegv.cc - Sigsegv default handling --------------------===//
+//===----------- Sigsegv.cpp - Sigsegv default handling -------------------===//
 //
 //                     The VMKit project
 //
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 
+#include "mvm/MethodInfo.h"
+#include "mvm/System.h"
 #include "mvm/VirtualMachine.h"
 #include "mvm/Threads/Thread.h"
 
@@ -16,51 +18,54 @@
 
 using namespace mvm;
 
-#if defined(__MACH__) && defined(__i386__)
-#include "ucontext.h"
-#endif
+#if defined(ARCH_X64) && defined(LINUX_OS)
+extern "C" {
+  void NativeHandleSignal(void);
+  asm(
+    ".text\n"
+    ".align 8\n"
+    ".globl NativeHandleSignal\n"
+  "NativeHandleSignal:\n"
+    // Save The faulting address to fake a reall method call
+    "pushq %rdi\n"
+    "jmp   ThrowNullPointerException\n"
+    );
+}
+
+#define UPDATE_REGS() \
+    ((ucontext_t*)context)->uc_mcontext.gregs[REG_RDI] = ((ucontext_t*)context)->uc_mcontext.gregs[REG_RIP] + 1; \
+    ((ucontext_t*)context)->uc_mcontext.gregs[REG_RIP] = (word_t)NativeHandleSignal;
 
-void sigsegvHandler(int n, siginfo_t *_info, void *context) {
-  word_t addr = (word_t)_info->si_addr;
-#if defined(__i386__)
-  struct frame {
-    struct frame *caller;
-    void         *ip;
-  };
-  
-  /* my frame */
-  struct frame *fp;
-  /* get it */
-  asm ("mov %%ebp, %0" : "=&r"(fp));
-  /* my caller */
-  struct frame *caller = fp->caller; 
-  /* preserve my caller if I return from the handler */
-  void *caller_ip = caller->ip; 
-
-#if defined(__MACH__)
-  //.gregs[REG_EIP]; /* just like it's on the stack.. */
-  caller->ip = (void *)((ucontext_t*)context)->uc_mcontext->__ss.__eip;
 #else
-  /* just like it's on the stack... */
-  caller->ip = (void *)((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP]; 
-#endif
+#define UPDATE_REGS() UNIMPLEMENTED();
 #endif
 
+
+extern "C" void ThrowNullPointerException(word_t ip) {
+  mvm::Thread* th = mvm::Thread::get();
+  mvm::FrameInfo* FI = th->MyVM->IPToFrameInfo(ip);
+  if (FI->Metadata == NULL) {
+    fprintf(stderr, "Thread %p received a SIGSEGV: either the VM code or an external\n"
+                    "native method is bogus. Aborting...\n", (void*)th);
+    abort();
+  }
+  mvm::Thread::get()->MyVM->nullPointerException();
+  UNREACHABLE();
+}
+
+void sigsegvHandler(int n, siginfo_t *_info, void *context) {
   mvm::Thread* th = mvm::Thread::get();
+  word_t addr = (word_t)_info->si_addr;
   if (addr > (word_t)th->getThreadID() && addr < (word_t)th->baseSP) {
     fprintf(stderr, "Stack overflow in VM code or in JNI code. If it is from\n"
                     "the VM, it is either from the JIT, the GC or the runtime."
                     "\nThis has to be fixed in the VM: VMKit makes sure that\n"
                     "the bottom of the stack is always available when entering"
                     "\nthe VM.\n");
+    abort();
+  } else if (mvm::System::SupportsHardwareNullCheck()) {
+    UPDATE_REGS();
   } else {
-    fprintf(stderr, "Thread %p received a SIGSEGV: either the VM code or an external\n"
-                    "native method is bogus. Aborting...\n", (void*)th);
+    abort();
   }
-  th->printBacktrace();
-  abort();
-  
-#if defined(__i386__)
-  caller->ip = caller_ip; /* restore the caller ip */
-#endif
 }

Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Fri Nov 11 12:38:37 2011
@@ -318,6 +318,8 @@
 /// machine specific.
 StackThreadManager TheStackManager;
 
+extern void sigsegvHandler(int, siginfo_t*, void*);
+
 /// internalThreadStart - The initial function called by a thread. Sets some
 /// thread specific data, registers the thread to the GC and calls the
 /// given routine of th.
@@ -325,6 +327,15 @@
 void Thread::internalThreadStart(mvm::Thread* th) {
   th->baseSP  = System::GetCallerAddress();
 
+  // Set the SIGSEGV handler to diagnose errors.
+  struct sigaction sa;
+  sigset_t mask;
+  sigfillset(&mask);
+  sa.sa_flags = SA_SIGINFO;
+  sa.sa_mask = mask;
+  sa.sa_sigaction = sigsegvHandler;
+  sigaction(SIGSEGV, &sa, NULL);
+
   assert(th->MyVM && "VM not set in a thread");
   th->MyVM->rendezvous.addThread(th);
   th->routine(th);

Modified: vmkit/trunk/lib/Mvm/Compiler/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/JIT.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/Compiler/JIT.cpp (original)
+++ vmkit/trunk/lib/Mvm/Compiler/JIT.cpp Fri Nov 11 12:38:37 2011
@@ -407,6 +407,9 @@
     frame->Metadata = meta;
     frame->SourceIndex = I->Loc.getLine();
     frame->ReturnAddress = JCE->getLabelAddress(I->Label);
+    // If the safe point is fro an NPE, increment the return address to
+    // not clash with post calls.
+    if (I->Loc.getCol() == 1) frame->ReturnAddress += 1;
     int i = 0;
     for (llvm::GCFunctionInfo::live_iterator KI = FI->live_begin(I),
          KE = FI->live_end(I); KI != KE; ++KI) {

Modified: vmkit/trunk/lib/Mvm/Compiler/VmkitGC.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Compiler/VmkitGC.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/Compiler/VmkitGC.cpp (original)
+++ vmkit/trunk/lib/Mvm/Compiler/VmkitGC.cpp Fri Nov 11 12:38:37 2011
@@ -10,7 +10,11 @@
 
 #include "llvm/CodeGen/GCs.h"
 #include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Target/TargetInstrInfo.h"
 
 #include "mvm/JIT.h"
 
@@ -20,6 +24,7 @@
   class VmkitGC : public GCStrategy {
   public:
     VmkitGC();
+    bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction &MF);
   };
 }
 
@@ -31,5 +36,33 @@
 X("vmkit", "VMKit GC for JIT-generated functions");
 
 VmkitGC::VmkitGC() {
-  NeededSafePoints = 1 << GC::PostCall;
+  CustomSafePoints = true;
+}
+
+static MCSymbol *InsertLabel(MachineBasicBlock &MBB, 
+                             MachineBasicBlock::iterator MI,
+                             DebugLoc DL) {
+  const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
+  MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol();
+  BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
+  return Label;
+}
+
+
+bool VmkitGC::findCustomSafePoints(GCFunctionInfo& FI, MachineFunction &MF) {
+  for (MachineFunction::iterator BBI = MF.begin(),
+                                 BBE = MF.end(); BBI != BBE; ++BBI) {
+    for (MachineBasicBlock::iterator MI = BBI->begin(),
+                                     ME = BBI->end(); MI != ME; ++MI) {
+      if (MI->getDesc().isCall()) {
+        MachineBasicBlock::iterator RAI = MI; ++RAI;                                
+        MCSymbol* Label = InsertLabel(*MI->getParent(), RAI, MI->getDebugLoc());
+        FI.addSafePoint(GC::PostCall, Label, MI->getDebugLoc());
+      } else if (MI->getDebugLoc().getCol() == 1) {
+        MCSymbol* Label = InsertLabel(*MI->getParent(), MI, MI->getDebugLoc());
+        FI.addSafePoint(GC::Loop, Label, MI->getDebugLoc());
+      }
+    }
+  }
+  return false;
 }

Modified: vmkit/trunk/lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp?rev=144401&r1=144400&r2=144401&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp (original)
+++ vmkit/trunk/lib/Mvm/StaticGCPrinter/VmkitGCPrinter.cpp Fri Nov 11 12:38:37 2011
@@ -14,13 +14,17 @@
 #include "llvm/CodeGen/GCStrategy.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/Module.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/Target/Mangler.h"
 #include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/ADT/SmallString.h"
@@ -37,6 +41,7 @@
   class VmkitAOTGC : public GCStrategy {
   public:
     VmkitAOTGC();
+    virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF);
   };
 }
 
@@ -44,10 +49,40 @@
 X("vmkit", "Vmkit GC for AOT-generated functions");
 
 VmkitAOTGC::VmkitAOTGC() {
-  NeededSafePoints = 1 << GC::PostCall;
+  CustomSafePoints = true;
   UsesMetadata = true;
 }
 
+
+static MCSymbol *InsertLabel(MachineBasicBlock &MBB, 
+                             MachineBasicBlock::iterator MI,
+                             DebugLoc DL) {
+  const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
+  MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol();
+  BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
+  return Label;
+}
+
+
+bool VmkitAOTGC::findCustomSafePoints(GCFunctionInfo& FI, MachineFunction &MF) {
+  for (MachineFunction::iterator BBI = MF.begin(),
+                                 BBE = MF.end(); BBI != BBE; ++BBI) {
+    for (MachineBasicBlock::iterator MI = BBI->begin(),
+                                     ME = BBI->end(); MI != ME; ++MI) {
+      if (MI->getDesc().isCall()) {
+        MachineBasicBlock::iterator RAI = MI; ++RAI;                                
+        MCSymbol* Label = InsertLabel(*MI->getParent(), RAI, MI->getDebugLoc());
+        FI.addSafePoint(GC::PostCall, Label, MI->getDebugLoc());
+      } else if (MI->getDebugLoc().getCol() == 1) {
+        MCSymbol* Label = InsertLabel(*MI->getParent(), MI, MI->getDebugLoc());
+        FI.addSafePoint(GC::Loop, Label, MI->getDebugLoc());
+      }
+    }
+  }
+  return false;
+}
+
+
 namespace {
 
   class VmkitAOTGCMetadataPrinter : public GCMetadataPrinter {
@@ -317,7 +352,13 @@
       }
 
       // Return address
-      AP.OutStreamer.EmitSymbolValue(J->Label, IntPtrSize, 0);
+      const MCExpr* address = MCSymbolRefExpr::Create(J->Label, AP.OutStreamer.getContext());
+      if (DL.getCol() == 1) {
+        const MCExpr* one = MCConstantExpr::Create(1, AP.OutStreamer.getContext());
+        address = MCBinaryExpr::CreateAdd(address, one, AP.OutStreamer.getContext());
+      }
+
+      AP.OutStreamer.EmitValue(address, IntPtrSize, 0);
       AP.EmitInt16(sourceIndex);
       AP.EmitInt16(FrameSize);
       AP.EmitInt16(LiveCount);





More information about the vmkit-commits mailing list