src/share/vm/shark/sharkCompiler.cpp

Print this page
rev 3850 : [mq]: shark.patch


  31 #include "code/exceptionHandlerTable.hpp"
  32 #include "code/oopRecorder.hpp"
  33 #include "compiler/abstractCompiler.hpp"
  34 #include "compiler/oopMap.hpp"
  35 #include "shark/llvmHeaders.hpp"
  36 #include "shark/sharkBuilder.hpp"
  37 #include "shark/sharkCodeBuffer.hpp"
  38 #include "shark/sharkCompiler.hpp"
  39 #include "shark/sharkContext.hpp"
  40 #include "shark/sharkEntry.hpp"
  41 #include "shark/sharkFunction.hpp"
  42 #include "shark/sharkMemoryManager.hpp"
  43 #include "shark/sharkNativeWrapper.hpp"
  44 #include "shark/shark_globals.hpp"
  45 #include "utilities/debug.hpp"
  46 
  47 #include <fnmatch.h>
  48 
  49 using namespace llvm;
  50 
  51 #if SHARK_LLVM_VERSION >= 27
  52 namespace {
  53   cl::opt<std::string>
  54   MCPU("mcpu");
  55 
  56   cl::list<std::string>
  57   MAttrs("mattr",
  58          cl::CommaSeparated);
  59 }
  60 #endif
  61 
  62 SharkCompiler::SharkCompiler()
  63   : AbstractCompiler() {
  64   // Create the lock to protect the memory manager and execution engine
  65   _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock");
  66   MutexLocker locker(execution_engine_lock());
  67 
  68   // Make LLVM safe for multithreading
  69   if (!llvm_start_multithreaded())
  70     fatal("llvm_start_multithreaded() failed");
  71 
  72   // Initialize the native target
  73   InitializeNativeTarget();
  74 



  75   // Create the two contexts which we'll use
  76   _normal_context = new SharkContext("normal");
  77   _native_context = new SharkContext("native");
  78 
  79   // Create the memory manager
  80   _memory_manager = new SharkMemoryManager();
  81 
  82 #if SHARK_LLVM_VERSION >= 27
  83   // Finetune LLVM for the current host CPU.
  84   StringMap<bool> Features;
  85   bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features);
  86   std::string cpu("-mcpu=" + llvm::sys::getHostCPUName());
  87 
  88   std::vector<const char*> args;
  89   args.push_back(""); // program name
  90   args.push_back(cpu.c_str());
  91 
  92   std::string mattr("-mattr=");
  93   if(gotCpuFeatures){
  94     for(StringMap<bool>::iterator I = Features.begin(),
  95       E = Features.end(); I != E; ++I){
  96       if(I->second){
  97         std::string attr(I->first());
  98         mattr+="+"+attr+",";
  99       }
 100     }
 101     args.push_back(mattr.c_str());
 102   }
 103 
 104   args.push_back(0);  // terminator
 105   cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
 106 
 107   // Create the JIT
 108   std::string ErrorMsg;
 109 
 110   EngineBuilder builder(_normal_context->module());
 111   builder.setMCPU(MCPU);
 112   builder.setMAttrs(MAttrs);
 113   builder.setJITMemoryManager(memory_manager());
 114   builder.setEngineKind(EngineKind::JIT);
 115   builder.setErrorStr(&ErrorMsg);










 116   _execution_engine = builder.create();
 117 
 118   if (!execution_engine()) {
 119     if (!ErrorMsg.empty())
 120       printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str());
 121     else
 122       printf("Unknown error while creating Shark JIT\n");
 123     exit(1);
 124   }
 125 
 126   execution_engine()->addModule(
 127     _native_context->module());
 128 #else
 129   _execution_engine = ExecutionEngine::createJIT(
 130     _normal_context->module_provider(),
 131     NULL, memory_manager(), CodeGenOpt::Default);
 132   execution_engine()->addModuleProvider(
 133     _native_context->module_provider());
 134 #endif
 135 
 136   // All done
 137   mark_initialized();
 138 }
 139 
 140 void SharkCompiler::initialize() {
 141   ShouldNotCallThis();
 142 }
 143 
 144 void SharkCompiler::compile_method(ciEnv*    env,
 145                                    ciMethod* target,
 146                                    int       entry_bci) {
 147   assert(is_initialized(), "should be");
 148   ResourceMark rm;
 149   const char *name = methodname(
 150     target->holder()->name()->as_utf8(), target->name()->as_utf8());
 151 
 152   // Do the typeflow analysis
 153   ciTypeFlow *flow;
 154   if (entry_bci == InvocationEntryBci)


 244   return nmethod::new_native_nmethod(target,
 245                                      compile_id,
 246                                      masm->code(),
 247                                      0,
 248                                      0,
 249                                      wrapper->frame_size(),
 250                                      wrapper->receiver_offset(),
 251                                      wrapper->lock_offset(),
 252                                      wrapper->oop_maps());
 253 }
 254 
 255 void SharkCompiler::generate_native_code(SharkEntry* entry,
 256                                          Function*   function,
 257                                          const char* name) {
 258   // Print the LLVM bitcode, if requested
 259   if (SharkPrintBitcodeOf != NULL) {
 260     if (!fnmatch(SharkPrintBitcodeOf, name, 0))
 261       function->dump();
 262   }
 263 






 264   // Compile to native code
 265   address code = NULL;
 266   context()->add_function(function);
 267   {
 268     MutexLocker locker(execution_engine_lock());
 269     free_queued_methods();
 270 
 271     if (SharkPrintAsmOf != NULL) {
 272 #if SHARK_LLVM_VERSION >= 27
 273 #ifndef NDEBUG




 274       if (!fnmatch(SharkPrintAsmOf, name, 0)) {
 275         llvm::SetCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
 276         llvm::DebugFlag = true;
 277       }
 278       else {
 279         llvm::SetCurrentDebugType("");
 280         llvm::DebugFlag = false;
 281       }
 282 #endif // !NDEBUG
 283 #else
 284       // NB you need to patch LLVM with http://tinyurl.com/yf3baln for this
 285       std::vector<const char*> args;
 286       args.push_back(""); // program name
 287       if (!fnmatch(SharkPrintAsmOf, name, 0))
 288         args.push_back("-debug-only=x86-emitter");
 289       else
 290         args.push_back("-debug-only=none");
 291       args.push_back(0);  // terminator
 292       cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
 293 #endif // SHARK_LLVM_VERSION
 294     }




 295     memory_manager()->set_entry_for_function(function, entry);
 296     code = (address) execution_engine()->getPointerToFunction(function);
 297   }

 298   entry->set_entry_point(code);
 299   entry->set_function(function);
 300   entry->set_context(context());
 301   address code_start = entry->code_start();
 302   address code_limit = entry->code_limit();
 303 
 304   // Register generated code for profiling, etc
 305   if (JvmtiExport::should_post_dynamic_code_generated())
 306     JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit);
 307 
 308   // Print debug information, if requested
 309   if (SharkTraceInstalls) {
 310     tty->print_cr(
 311       " [%p-%p): %s (%d bytes code)",
 312       code_start, code_limit, name, code_limit - code_start);
 313   }
 314 }
 315 
 316 void SharkCompiler::free_compiled_method(address code) {
 317   // This method may only be called when the VM is at a safepoint.
 318   // All _thread_in_vm threads will be waiting for the safepoint to
 319   // finish with the exception of the VM thread, so we can consider
 320   // ourself the owner of the execution engine lock even though we
 321   // can't actually acquire it at this time.
 322   assert(Thread::current()->is_VM_thread(), "must be called by VM thread");
 323   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 324 
 325   SharkEntry *entry = (SharkEntry *) code;
 326   entry->context()->push_to_free_queue(entry->function());
 327 }
 328 
 329 void SharkCompiler::free_queued_methods() {
 330   // The free queue is protected by the execution engine lock
 331   assert(execution_engine_lock()->owned_by_self(), "should be");
 332 
 333   while (true) {
 334     Function *function = context()->pop_from_free_queue();
 335     if (function == NULL)
 336       break;
 337 
 338     execution_engine()->freeMachineCodeForFunction(function);
 339     function->eraseFromParent();
 340   }
 341 }
 342 
 343 const char* SharkCompiler::methodname(const char* klass, const char* method) {


  31 #include "code/exceptionHandlerTable.hpp"
  32 #include "code/oopRecorder.hpp"
  33 #include "compiler/abstractCompiler.hpp"
  34 #include "compiler/oopMap.hpp"
  35 #include "shark/llvmHeaders.hpp"
  36 #include "shark/sharkBuilder.hpp"
  37 #include "shark/sharkCodeBuffer.hpp"
  38 #include "shark/sharkCompiler.hpp"
  39 #include "shark/sharkContext.hpp"
  40 #include "shark/sharkEntry.hpp"
  41 #include "shark/sharkFunction.hpp"
  42 #include "shark/sharkMemoryManager.hpp"
  43 #include "shark/sharkNativeWrapper.hpp"
  44 #include "shark/shark_globals.hpp"
  45 #include "utilities/debug.hpp"
  46 
  47 #include <fnmatch.h>
  48 
  49 using namespace llvm;
  50 

  51 namespace {
  52   cl::opt<std::string>
  53   MCPU("mcpu");
  54 
  55   cl::list<std::string>
  56   MAttrs("mattr",
  57          cl::CommaSeparated);
  58 }

  59 
  60 SharkCompiler::SharkCompiler()
  61   : AbstractCompiler() {
  62   // Create the lock to protect the memory manager and execution engine
  63   _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock");
  64   MutexLocker locker(execution_engine_lock());
  65 
  66   // Make LLVM safe for multithreading
  67   if (!llvm_start_multithreaded())
  68     fatal("llvm_start_multithreaded() failed");
  69 
  70   // Initialize the native target
  71   InitializeNativeTarget();
  72 
  73   // MCJIT require a native AsmPrinter
  74   InitializeNativeTargetAsmPrinter();
  75 
  76   // Create the two contexts which we'll use
  77   _normal_context = new SharkContext("normal");
  78   _native_context = new SharkContext("native");
  79 
  80   // Create the memory manager
  81   _memory_manager = new SharkMemoryManager();
  82 

  83   // Finetune LLVM for the current host CPU.
  84   StringMap<bool> Features;
  85   bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features);
  86   std::string cpu("-mcpu=" + llvm::sys::getHostCPUName());
  87 
  88   std::vector<const char*> args;
  89   args.push_back(""); // program name
  90   args.push_back(cpu.c_str());
  91 
  92   std::string mattr("-mattr=");
  93   if(gotCpuFeatures){
  94     for(StringMap<bool>::iterator I = Features.begin(),
  95       E = Features.end(); I != E; ++I){
  96       if(I->second){
  97         std::string attr(I->first());
  98         mattr+="+"+attr+",";
  99       }
 100     }
 101     args.push_back(mattr.c_str());
 102   }
 103 
 104   args.push_back(0);  // terminator
 105   cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
 106 
 107   // Create the JIT
 108   std::string ErrorMsg;
 109 
 110   EngineBuilder builder(_normal_context->module());
 111   builder.setMCPU(MCPU);
 112   builder.setMAttrs(MAttrs);
 113   builder.setJITMemoryManager(memory_manager());
 114   builder.setEngineKind(EngineKind::JIT);
 115   builder.setErrorStr(&ErrorMsg);
 116   if (! fnmatch(SharkOptimizationLevel, "None", 0)) {
 117     tty->print_cr("Shark optimization level set to: None");
 118     builder.setOptLevel(llvm::CodeGenOpt::None);
 119   } else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) {
 120     tty->print_cr("Shark optimization level set to: Less");
 121     builder.setOptLevel(llvm::CodeGenOpt::Less);
 122   } else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) {
 123     tty->print_cr("Shark optimization level set to: Aggressive");
 124     builder.setOptLevel(llvm::CodeGenOpt::Aggressive);
 125   } // else Default is selected by, well, default :-)
 126   _execution_engine = builder.create();
 127 
 128   if (!execution_engine()) {
 129     if (!ErrorMsg.empty())
 130       printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str());
 131     else
 132       printf("Unknown error while creating Shark JIT\n");
 133     exit(1);
 134   }
 135 
 136   execution_engine()->addModule(
 137     _native_context->module());







 138 
 139   // All done
 140   mark_initialized();
 141 }
 142 
 143 void SharkCompiler::initialize() {
 144   ShouldNotCallThis();
 145 }
 146 
 147 void SharkCompiler::compile_method(ciEnv*    env,
 148                                    ciMethod* target,
 149                                    int       entry_bci) {
 150   assert(is_initialized(), "should be");
 151   ResourceMark rm;
 152   const char *name = methodname(
 153     target->holder()->name()->as_utf8(), target->name()->as_utf8());
 154 
 155   // Do the typeflow analysis
 156   ciTypeFlow *flow;
 157   if (entry_bci == InvocationEntryBci)


 247   return nmethod::new_native_nmethod(target,
 248                                      compile_id,
 249                                      masm->code(),
 250                                      0,
 251                                      0,
 252                                      wrapper->frame_size(),
 253                                      wrapper->receiver_offset(),
 254                                      wrapper->lock_offset(),
 255                                      wrapper->oop_maps());
 256 }
 257 
 258 void SharkCompiler::generate_native_code(SharkEntry* entry,
 259                                          Function*   function,
 260                                          const char* name) {
 261   // Print the LLVM bitcode, if requested
 262   if (SharkPrintBitcodeOf != NULL) {
 263     if (!fnmatch(SharkPrintBitcodeOf, name, 0))
 264       function->dump();
 265   }
 266 
 267   if (SharkVerifyFunction != NULL) {
 268     if (!fnmatch(SharkVerifyFunction, name, 0)) {
 269       verifyFunction(*function);
 270     }
 271   }
 272 
 273   // Compile to native code
 274   address code = NULL;
 275   context()->add_function(function);
 276   {
 277     MutexLocker locker(execution_engine_lock());
 278     free_queued_methods();
 279 


 280 #ifndef NDEBUG
 281 #if SHARK_LLVM_VERSION <= 31
 282 #define setCurrentDebugType SetCurrentDebugType
 283 #endif
 284     if (SharkPrintAsmOf != NULL) {
 285       if (!fnmatch(SharkPrintAsmOf, name, 0)) {
 286         llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
 287         llvm::DebugFlag = true;
 288       }
 289       else {
 290         llvm::setCurrentDebugType("");
 291         llvm::DebugFlag = false;
 292       }












 293     }
 294 #ifdef setCurrentDebugType
 295 #undef setCurrentDebugType
 296 #endif
 297 #endif // !NDEBUG
 298     memory_manager()->set_entry_for_function(function, entry);
 299     code = (address) execution_engine()->getPointerToFunction(function);
 300   }
 301   assert(code != NULL, "code must be != NULL");
 302   entry->set_entry_point(code);
 303   entry->set_function(function);
 304   entry->set_context(context());
 305   address code_start = entry->code_start();
 306   address code_limit = entry->code_limit();
 307 
 308   // Register generated code for profiling, etc
 309   if (JvmtiExport::should_post_dynamic_code_generated())
 310     JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit);
 311 
 312   // Print debug information, if requested
 313   if (SharkTraceInstalls) {
 314     tty->print_cr(
 315       " [%p-%p): %s (%d bytes code)",
 316       code_start, code_limit, name, code_limit - code_start);
 317   }
 318 }
 319 
 320 void SharkCompiler::free_compiled_method(address code) {
 321   // This method may only be called when the VM is at a safepoint.
 322   // All _thread_in_vm threads will be waiting for the safepoint to
 323   // finish with the exception of the VM thread, so we can consider
 324   // ourself the owner of the execution engine lock even though we
 325   // can't actually acquire it at this time.
 326   assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");
 327   assert_locked_or_safepoint(CodeCache_lock);
 328 
 329   SharkEntry *entry = (SharkEntry *) code;
 330   entry->context()->push_to_free_queue(entry->function());
 331 }
 332 
 333 void SharkCompiler::free_queued_methods() {
 334   // The free queue is protected by the execution engine lock
 335   assert(execution_engine_lock()->owned_by_self(), "should be");
 336 
 337   while (true) {
 338     Function *function = context()->pop_from_free_queue();
 339     if (function == NULL)
 340       break;
 341 
 342     execution_engine()->freeMachineCodeForFunction(function);
 343     function->eraseFromParent();
 344   }
 345 }
 346 
 347 const char* SharkCompiler::methodname(const char* klass, const char* method) {