Shark: Update to LLVM 4.2, add debugging

Andrew Haley aph at redhat.com
Thu Jan 22 09:31:26 PST 2009


This bumps Shark to use LLVM 4.2.  A few changes were needed, in
particular a workaround for a heinous LLVM bug, but the result is
much improved: it will run various benchmarks and it will also
run Eclipse, at least until the JIT runs out of memory.  I've
also added debugging facilities, of which Shark was rather lacking.

While this still isn't ready for prime time, it's an indication of
progress.  Do I need to say that Gary did most of the work?  Thought
not.

Although we're talking about possibly stabilizing for a release, no
one should be using Shark in production so this patch should be safe
to commit now.

Andrew.


2009-01-22  Andrew Haley  <aph at redhat.com>

	* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp (class
	ZeroFrame::FrameType): Set ENTRY_FRAME = 0xCAFEBABE.

	* ports/hotspot/src/share/vm/shark/shark_globals.hpp (SHARK_FLAGS):
	Add SharkPrintAsmOf.

	* ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Add comment.

	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp
	(SharkFunction::initialize): Set builder()->sharkEntry.
	Use fnmatch() instead of strcmp().
	Generate debugging dumps.
	* ports/hotspot/src/share/vm/shark/sharkEntry.hpp
	(SharkEntry::code_start, code_limit): Rewrite.
	(SharkEntry::setBounds): New.

	* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
	(SharkBuilder::pointer_constant): New function.
	* ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp
	(SharkBytecodeTracer::decode_one_word):
	use SharkBuilder::pointer_constant.
	* ports/hotspot/src/share/vm/shark/sharkBuilder.cpp
	(SharkBuilder::sharkEntry): New.
	(SharkBuilder::CreateUnimplemented): use SharkBuilder::pointer_constant.
	(SharkBuilder::CreateShouldNotReachHere): Likewise.
	(MyJITMemoryManager::endFunctionBody): New method.
	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
	(SharkBlock::check_zero): use SharkBuilder::pointer_constant.
	(SharkBlock::check_bounds): Likewise.
	(SharkBlock::add_safepoint): Likewise.
	(SharkBlock::do_new): Likewise.
	(SharkBlock::do_monitorexit): Don't check for null monitor.

	* ports/hotspot/src/share/vm/shark/llvmHeaders.hpp: Add
	llvm/ExecutionEngine/JITMemoryManager.h,
	llvm/Support/CommandLine.h.
	* ports/hotspot/src/share/vm/includeDB_shark (sharkBuilder.hpp):
	add sharkEntry.hpp.

diff -r 62c52213166e ports/hotspot/src/cpu/zero/vm/stack_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -142,7 +142,7 @@
   };

   enum FrameType {
-    ENTRY_FRAME = 1,
+    ENTRY_FRAME = 0xCAFEBABE,
     INTERPRETER_FRAME,
     SHARK_FRAME,
     DEOPTIMIZER_FRAME
diff -r 62c52213166e ports/hotspot/src/share/vm/includeDB_shark
--- a/ports/hotspot/src/share/vm/includeDB_shark	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/includeDB_shark	Thu Jan 22 17:19:30 2009 +0000
@@ -112,6 +112,7 @@
 sharkBuilder.hpp                        sizes.hpp
 sharkBuilder.hpp                        sharkType.hpp
 sharkBuilder.hpp                        sharkValue.inline.hpp
+sharkBuilder.hpp                        sharkEntry.hpp

 sharkBytecodeTracer.cpp                 sharkBytecodeTracer.hpp
 sharkBytecodeTracer.cpp                 sharkState.inline.hpp
@@ -269,3 +270,4 @@
 sharkValue.inline.hpp                   ciType.hpp
 sharkValue.inline.hpp                   llvmHeaders.hpp
 sharkValue.inline.hpp                   sharkValue.hpp
+
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/llvmHeaders.hpp
--- a/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/llvmHeaders.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -36,6 +36,10 @@
 #include <llvm/ModuleProvider.h>
 #include <llvm/Support/IRBuilder.h>
 #include <llvm/Type.h>
+#include <llvm/ExecutionEngine/JITMemoryManager.h>
+#include <llvm/Support/CommandLine.h>
+
+#include <map>

 #ifdef assert
   #undef assert
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkBlock.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Thu Jan 22 17:19:30 2009 +0000
@@ -992,7 +992,7 @@
   if (value->is_jobject()) {
     call_vm_nocheck(
       SharkRuntime::throw_NullPointerException(),
-      LLVMValue::intptr_constant((intptr_t) __FILE__),
+      builder()->pointer_constant(__FILE__),
       LLVMValue::jint_constant(__LINE__));
   }
   else {
@@ -1021,7 +1021,7 @@
   SharkTrackingState *saved_state = current_state()->copy();
   call_vm_nocheck(
     SharkRuntime::throw_ArrayIndexOutOfBoundsException(),
-    LLVMValue::intptr_constant((intptr_t) __FILE__),
+    builder()->pointer_constant(__FILE__),
     LLVMValue::jint_constant(__LINE__),
     index->jint_value());
   handle_exception(function()->CreateGetPendingException());
@@ -1141,8 +1141,7 @@

   Value *state = builder()->CreateLoad(
     builder()->CreateIntToPtr(
-      LLVMValue::intptr_constant(
-        (intptr_t) SafepointSynchronize::address_of_state()),
+      builder()->pointer_constant(SafepointSynchronize::address_of_state()),
       PointerType::getUnqual(SharkType::jint_type())),
     "state");

@@ -2238,13 +2237,13 @@
     builder()->SetInsertPoint(heap_alloc);

     Value *top_addr = builder()->CreateIntToPtr(
-      LLVMValue::intptr_constant((intptr_t) Universe::heap()->top_addr()),
+	builder()->pointer_constant(Universe::heap()->top_addr()),
       PointerType::getUnqual(SharkType::intptr_type()),
       "top_addr");

     Value *end = builder()->CreateLoad(
       builder()->CreateIntToPtr(
-        LLVMValue::intptr_constant((intptr_t) Universe::heap()->end_addr()),
+        builder()->pointer_constant(Universe::heap()->end_addr()),
         PointerType::getUnqual(SharkType::intptr_type())),
       "end");

@@ -2473,7 +2472,10 @@
 void SharkBlock::do_monitorexit()
 {
   SharkValue *lockee = pop();
-  check_null(lockee);
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_null(lockee);
   Value *object = lockee->jobject_value();

   // Find the monitor associated with this object
@@ -2513,5 +2515,8 @@
   // Release the lock
   builder()->SetInsertPoint(got_monitor);
   monitor->release(this);
-  check_pending_exception();
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_pending_exception();
 }
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkBuilder.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.cpp	Thu Jan 22 17:19:30 2009 +0000
@@ -28,12 +28,15 @@

 using namespace llvm;

+std::map<const llvm::Function*, SharkEntry*> SharkBuilder::sharkEntry;
+
 SharkBuilder::SharkBuilder()
   : IRBuilder<>(),
       _module("shark"),
       _module_provider(module()),
-      _execution_engine(ExecutionEngine::create(&_module_provider))
-{
+      _execution_engine(ExecutionEngine::createJIT
+			(&_module_provider, NULL, new MyJITMemoryManager(),
+			 /* Fast */ false)) {
   init_external_functions();
 }

@@ -152,7 +155,7 @@
 {
   return CreateCall2(
     SharkRuntime::unimplemented(),
-    LLVMValue::intptr_constant((intptr_t) file),
+    pointer_constant(file),
     LLVMValue::jint_constant(line));
 }

@@ -160,7 +163,7 @@
 {
   return CreateCall2(
     SharkRuntime::should_not_reach_here(),
-    LLVMValue::intptr_constant((intptr_t) file),
+    pointer_constant(file),
     LLVMValue::jint_constant(line));
 }

@@ -174,3 +177,16 @@
     ConstantInt::get(Type::Int1Ty, 0)};
   return CreateCall(llvm_memory_barrier_fn(), args, args + 5);
 }
+
+void SharkBuilder::MyJITMemoryManager::endFunctionBody
+  (const llvm::Function *F, unsigned char *FunctionStart,
+   unsigned char *FunctionEnd)
+{
+  mm->endFunctionBody(F, FunctionStart, FunctionEnd);
+#ifndef PRODUCT
+  SharkEntry *e = sharkEntry[F];
+  if (e)
+    e->setBounds(FunctionStart, FunctionEnd);
+#endif // !PRODUCT
+}
+
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -27,11 +27,76 @@
  public:
   SharkBuilder();

+  static std::map<const llvm::Function*, SharkEntry*> sharkEntry;
+
  private:
   llvm::Module                 _module;
   llvm::ExistingModuleProvider _module_provider;
   llvm::ExecutionEngine*       _execution_engine;

+  // MyJITMemoryManager wraps the JIT Memory Manager: this allows us
+  // to run our own memory allocation policies, but the purpose here
+  // is to allow us to intercept JITMemoryManager::endFunctionBody.
+  class MyJITMemoryManager : public llvm::JITMemoryManager {
+
+    llvm::JITMemoryManager *mm;
+
+  public:
+
+    MyJITMemoryManager()
+    {
+      mm = llvm::JITMemoryManager::CreateDefaultMemManager();
+    }
+
+    virtual void AllocateGOT() {
+      mm->AllocateGOT();
+    }
+
+    virtual unsigned char *getGOTBase() const {
+      return mm->getGOTBase();
+    }
+
+    virtual unsigned char *startFunctionBody(const llvm::Function *F,
+					     uintptr_t &ActualSize) {
+      return mm->startFunctionBody(F, ActualSize);
+    }
+
+    virtual unsigned char *allocateStub(const llvm::GlobalValue* F,
+					unsigned StubSize,
+					unsigned Alignment) {
+      return mm->allocateStub(F, StubSize, Alignment);
+    }
+
+    void endFunctionBody(const llvm::Function *F, unsigned char *FunctionStart,
+			 unsigned char *FunctionEnd);
+
+    virtual void deallocateMemForFunction(const llvm::Function *F) {
+      return mm->deallocateMemForFunction(F);
+    }
+
+    virtual unsigned char* startExceptionTable(const llvm::Function* F,
+					       uintptr_t &ActualSize) {
+      return mm->startExceptionTable(F, ActualSize);
+    }
+
+    virtual void endExceptionTable(const llvm::Function *F,
+				   unsigned char *TableStart,
+				   unsigned char *TableEnd,
+				   unsigned char* FrameRegister) {
+      mm->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
+    }
+
+    virtual void setMemoryWritable() {
+      mm->setMemoryWritable();
+    }
+
+    virtual void setMemoryExecutable() {
+      mm->setMemoryExecutable();
+    }
+  };
+
+  MyJITMemoryManager *MemMgr;
+
  public:
   llvm::Module* module()
   {
@@ -125,9 +190,37 @@
                                 const llvm::FunctionType* sig,
                                 const char*               name);

+  llvm::Constant* pointer_constant(const void *ptr)
+  {
+    // Create a pointer constant that points at PTR.  We do this by
+    // creating a GlobalVariable mapped at PTR.  This is a workaround
+    // for http://www.llvm.org/bugs/show_bug.cgi?id=2920
+
+    using namespace llvm;
+
+    // This might be useful but it returns a const pointer that can't
+    // be used for anything.  Go figure...
+//     {
+//       const GlobalValue *value
+// 	= execution_engine()->getGlobalValueAtAddress(const_cast<void*>(ptr));
+//       if (value)
+// 	return ConstantExpr::getPtrToInt(value, SharkType::intptr_type());
+//     }
+
+    char name[128];
+    snprintf(name, sizeof name - 1, "pointer_constant_%p", ptr);
+
+    GlobalVariable *value = new GlobalVariable(SharkType::intptr_type(),
+      false, GlobalValue::ExternalLinkage,
+      NULL, name, module());
+    execution_engine()->addGlobalMapping(value, const_cast<void*>(ptr));
+
+    return ConstantExpr::getPtrToInt(value, SharkType::intptr_type());
+  }
+
   // Helper for making pointers
  public:
-  llvm::Constant* make_pointer(intptr_t addr, const llvm::Type* type) const
+  llvm::Constant* make_pointer(intptr_t addr, const llvm::Type* type)
   {
     return llvm::ConstantExpr::getIntToPtr(
       LLVMValue::intptr_constant(addr),
@@ -193,8 +286,7 @@
       LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
       CreateIntToPtr(
         CreateAdd(
-          LLVMValue::intptr_constant(
-            (intptr_t) ((CardTableModRefBS *) bs)->byte_map_base),
+          pointer_constant(((CardTableModRefBS *) bs)->byte_map_base),
           CreateLShr(
             CreatePtrToInt(field, SharkType::intptr_type()),
             LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkBytecodeTracer.cpp	Thu Jan 22 17:19:30 2009 +0000
@@ -89,7 +89,7 @@
     break;

   case T_ADDRESS:
-    *dst = LLVMValue::intptr_constant(value->returnAddress_value());
+    *dst = builder->pointer_constant((const void*)value->returnAddress_value());
     break;

   default:
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkEntry.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkEntry.cpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkEntry.cpp	Thu Jan 22 17:19:30 2009 +0000
@@ -41,30 +41,6 @@
 // Lots of the stuff down here is machine- and LLVM-specific.
 // It's only debug stuff though, and none of it's critical.

-address SharkEntry::code_start() const
-{
-  return (address) entry_point();
-}
-
-address SharkEntry::code_limit() const
-{
-#ifdef PPC
-  // LLVM seems to insert three junk instructions and a null after
-  // every function.  Only the first junk instruction seems to be
-  // kept after the next function is generated, however, so this
-  // method will only work before you generate another function.
-  // I wish there was a nicer way to do this, but that's life...
-  uint32_t *limit = (uint32_t *) code_start();
-  while (*limit)
-    limit++;
-  assert(limit[-1] == 0xd143cfec && limit[-2] == 0xd143cfec, "should be");
-  limit -= 3;
-  return (address) limit;
-#else
-  Unimplemented();
-#endif // PPC
-}
-
 void SharkEntry::print_pd_statistics(address start, address limit) const
 {
 #ifdef PPC
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkEntry.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkEntry.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkEntry.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -48,8 +48,24 @@

 #ifndef PRODUCT
  private:
-  address code_start() const;
-  address code_limit() const;
+  address code_start() const
+  {
+    return start;
+  }
+  address code_limit() const
+  {
+    return limit;
+  }
   void print_pd_statistics(address start, address limit) const;
+
+  address start, limit;
+
+public:
+  void setBounds(unsigned char *FunctionStart, unsigned char *FunctionEnd)
+  {
+    start = (address)FunctionStart;
+    limit = (address)FunctionEnd;
+  }
+
 #endif // !PRODUCT
 };
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkFunction.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Thu Jan 22 17:19:30 2009 +0000
@@ -26,6 +26,8 @@
 #include "incls/_precompiled.incl"
 #include "incls/_sharkFunction.cpp.incl"

+#include <fnmatch.h>
+
 using namespace llvm;

 void SharkFunction::initialize()
@@ -37,6 +39,11 @@
   // Create the function
   _function = builder()->CreateFunction();
   entry->set_llvm_function(function());
+#ifndef PRODUCT
+  // FIXME: there should be a mutex when updating sharkEntry in case
+  // there are multiple compilation threads.
+  builder()->sharkEntry[function()] = entry;
+#endif // !PRODUCT

   // Create the list of blocks
   set_block_insertion_point(NULL);
@@ -122,10 +129,25 @@

   // Dump the bitcode, if requested
   if (SharkPrintBitcodeOf != NULL) {
-    if (!strcmp(SharkPrintBitcodeOf, name()))
+    if (!fnmatch(SharkPrintBitcodeOf, name(), 0))
       function()->dump();
   }

+  if (SharkPrintAsmOf != NULL) {
+#if defined (__x86_64) || defined (__i386)
+      std::vector<const char*> Args;
+      Args.push_back(""); // program name
+      if (!fnmatch(SharkPrintAsmOf, name(), 0))
+	// Oh, yuck.  The LLVM name for this debugging dump is
+	// target-specific.
+	Args.push_back("-debug-only=" "x86-emitter");
+      else
+	Args.push_back("-debug-only=");
+      Args.push_back(0);  // Null terminator.
+      cl::ParseCommandLineOptions(Args.size()-1, (char**)&Args[0]);
+#endif
+  }
+
   // Compile to native code
   void *code = builder()->execution_engine()->getPointerToFunction(function());
   entry->set_entry_point((ZeroEntry::method_entry_t) code);
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/sharkFunction.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -232,6 +232,8 @@

   // OopMap support
  public:
+  // Every time a new, distinct pc is required, an extra byte is
+  // emitted into the codebuffer
   int code_offset() const
   {
     int offset = masm()->offset();
diff -r 62c52213166e ports/hotspot/src/share/vm/shark/shark_globals.hpp
--- a/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Thu Jan 22 10:21:33 2009 -0500
+++ b/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Thu Jan 22 17:19:30 2009 +0000
@@ -48,6 +48,9 @@
   develop(ccstr, SharkPrintBitcodeOf, NULL,                                   \
           "Print the LLVM bitcode of the specified method")                   \
                                                                               \
+  develop(ccstr, SharkPrintAsmOf, NULL,                                   \
+          "Print the asm of the specified method")                   \
+                                                                              \
   develop(bool, SharkTraceBytecodes, false,                                   \
           "Trace bytecode compilation")                                       \
                                                                               \



More information about the distro-pkg-dev mailing list