src/share/vm/shark/sharkCompiler.cpp

Mon, 04 Apr 2011 03:02:00 -0700

author
twisti
date
Mon, 04 Apr 2011 03:02:00 -0700
changeset 2729
e863062e521d
parent 2314
f95d63e2154a
child 4314
2cd5e15048e6
permissions
-rw-r--r--

7032458: Zero and Shark fixes
Reviewed-by: twisti
Contributed-by: Gary Benson <gbenson@redhat.com>

     1 /*
     2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  *
    24  */
    26 #include "precompiled.hpp"
    27 #include "ci/ciEnv.hpp"
    28 #include "ci/ciMethod.hpp"
    29 #include "code/debugInfoRec.hpp"
    30 #include "code/dependencies.hpp"
    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"
    47 #include <fnmatch.h>
    49 using namespace llvm;
    51 #if SHARK_LLVM_VERSION >= 27
    52 namespace {
    53   cl::opt<std::string>
    54   MCPU("mcpu");
    56   cl::list<std::string>
    57   MAttrs("mattr",
    58          cl::CommaSeparated);
    59 }
    60 #endif
    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());
    68   // Make LLVM safe for multithreading
    69   if (!llvm_start_multithreaded())
    70     fatal("llvm_start_multithreaded() failed");
    72   // Initialize the native target
    73   InitializeNativeTarget();
    75   // Create the two contexts which we'll use
    76   _normal_context = new SharkContext("normal");
    77   _native_context = new SharkContext("native");
    79   // Create the memory manager
    80   _memory_manager = new SharkMemoryManager();
    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());
    88   std::vector<const char*> args;
    89   args.push_back(""); // program name
    90   args.push_back(cpu.c_str());
    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   }
   104   args.push_back(0);  // terminator
   105   cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
   107   // Create the JIT
   108   std::string ErrorMsg;
   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();
   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   }
   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
   136   // All done
   137   mark_initialized();
   138 }
   140 void SharkCompiler::initialize() {
   141   ShouldNotCallThis();
   142 }
   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());
   152   // Do the typeflow analysis
   153   ciTypeFlow *flow;
   154   if (entry_bci == InvocationEntryBci)
   155     flow = target->get_flow_analysis();
   156   else
   157     flow = target->get_osr_flow_analysis(entry_bci);
   158   if (flow->failing())
   159     return;
   160   if (SharkPrintTypeflowOf != NULL) {
   161     if (!fnmatch(SharkPrintTypeflowOf, name, 0))
   162       flow->print_on(tty);
   163   }
   165   // Create the recorders
   166   Arena arena;
   167   env->set_oop_recorder(new OopRecorder(&arena));
   168   OopMapSet oopmaps;
   169   env->set_debug_info(new DebugInformationRecorder(env->oop_recorder()));
   170   env->debug_info()->set_oopmaps(&oopmaps);
   171   env->set_dependencies(new Dependencies(env));
   173   // Create the code buffer and builder
   174   CodeBuffer hscb("Shark", 256 * K, 64 * K);
   175   hscb.initialize_oop_recorder(env->oop_recorder());
   176   MacroAssembler *masm = new MacroAssembler(&hscb);
   177   SharkCodeBuffer cb(masm);
   178   SharkBuilder builder(&cb);
   180   // Emit the entry point
   181   SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
   183   // Build the LLVM IR for the method
   184   Function *function = SharkFunction::build(env, &builder, flow, name);
   186   // Generate native code.  It's unpleasant that we have to drop into
   187   // the VM to do this -- it blocks safepoints -- but I can't see any
   188   // other way to handle the locking.
   189   {
   190     ThreadInVMfromNative tiv(JavaThread::current());
   191     generate_native_code(entry, function, name);
   192   }
   194   // Install the method into the VM
   195   CodeOffsets offsets;
   196   offsets.set_value(CodeOffsets::Deopt, 0);
   197   offsets.set_value(CodeOffsets::Exceptions, 0);
   198   offsets.set_value(CodeOffsets::Verified_Entry,
   199                     target->is_static() ? 0 : wordSize);
   201   ExceptionHandlerTable handler_table;
   202   ImplicitExceptionTable inc_table;
   204   env->register_method(target,
   205                        entry_bci,
   206                        &offsets,
   207                        0,
   208                        &hscb,
   209                        0,
   210                        &oopmaps,
   211                        &handler_table,
   212                        &inc_table,
   213                        this,
   214                        env->comp_level(),
   215                        false,
   216                        false);
   217 }
   219 nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,
   220                                                 methodHandle    target,
   221                                                 int             compile_id,
   222                                                 BasicType*      arg_types,
   223                                                 BasicType       return_type) {
   224   assert(is_initialized(), "should be");
   225   ResourceMark rm;
   226   const char *name = methodname(
   227     target->klass_name()->as_utf8(), target->name()->as_utf8());
   229   // Create the code buffer and builder
   230   SharkCodeBuffer cb(masm);
   231   SharkBuilder builder(&cb);
   233   // Emit the entry point
   234   SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
   236   // Build the LLVM IR for the method
   237   SharkNativeWrapper *wrapper = SharkNativeWrapper::build(
   238     &builder, target, name, arg_types, return_type);
   240   // Generate native code
   241   generate_native_code(entry, wrapper->function(), name);
   243   // Return the nmethod for installation in the VM
   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 }
   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   }
   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();
   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();
   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);
   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 }
   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");
   325   SharkEntry *entry = (SharkEntry *) code;
   326   entry->context()->push_to_free_queue(entry->function());
   327 }
   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");
   333   while (true) {
   334     Function *function = context()->pop_from_free_queue();
   335     if (function == NULL)
   336       break;
   338     execution_engine()->freeMachineCodeForFunction(function);
   339     function->eraseFromParent();
   340   }
   341 }
   343 const char* SharkCompiler::methodname(const char* klass, const char* method) {
   344   char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1);
   346   char *dst = buf;
   347   for (const char *c = klass; *c; c++) {
   348     if (*c == '/')
   349       *(dst++) = '.';
   350     else
   351       *(dst++) = *c;
   352   }
   353   *(dst++) = ':';
   354   *(dst++) = ':';
   355   for (const char *c = method; *c; c++) {
   356     *(dst++) = *c;
   357   }
   358   *(dst++) = '\0';
   359   return buf;
   360 }

mercurial