src/share/vm/shark/sharkCompiler.cpp

Fri, 11 Jan 2013 16:47:23 -0800

author
twisti
date
Fri, 11 Jan 2013 16:47:23 -0800
changeset 4443
c095a7f289aa
parent 4314
2cd5e15048e6
child 5919
469216acdb28
permissions
-rw-r--r--

8005818: Shark: fix OSR for non-empty incoming stack
Reviewed-by: twisti
Contributed-by: Roman Kennke <rkennke@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 namespace {
    52   cl::opt<std::string>
    53   MCPU("mcpu");
    55   cl::list<std::string>
    56   MAttrs("mattr",
    57          cl::CommaSeparated);
    58 }
    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());
    66   // Make LLVM safe for multithreading
    67   if (!llvm_start_multithreaded())
    68     fatal("llvm_start_multithreaded() failed");
    70   // Initialize the native target
    71   InitializeNativeTarget();
    73   // MCJIT require a native AsmPrinter
    74   InitializeNativeTargetAsmPrinter();
    76   // Create the two contexts which we'll use
    77   _normal_context = new SharkContext("normal");
    78   _native_context = new SharkContext("native");
    80   // Create the memory manager
    81   _memory_manager = new SharkMemoryManager();
    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   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();
   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   }
   136   execution_engine()->addModule(
   137     _native_context->module());
   139   // All done
   140   mark_initialized();
   141 }
   143 void SharkCompiler::initialize() {
   144   ShouldNotCallThis();
   145 }
   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());
   155   // Do the typeflow analysis
   156   ciTypeFlow *flow;
   157   if (entry_bci == InvocationEntryBci)
   158     flow = target->get_flow_analysis();
   159   else
   160     flow = target->get_osr_flow_analysis(entry_bci);
   161   if (flow->failing())
   162     return;
   163   if (SharkPrintTypeflowOf != NULL) {
   164     if (!fnmatch(SharkPrintTypeflowOf, name, 0))
   165       flow->print_on(tty);
   166   }
   168   // Create the recorders
   169   Arena arena;
   170   env->set_oop_recorder(new OopRecorder(&arena));
   171   OopMapSet oopmaps;
   172   env->set_debug_info(new DebugInformationRecorder(env->oop_recorder()));
   173   env->debug_info()->set_oopmaps(&oopmaps);
   174   env->set_dependencies(new Dependencies(env));
   176   // Create the code buffer and builder
   177   CodeBuffer hscb("Shark", 256 * K, 64 * K);
   178   hscb.initialize_oop_recorder(env->oop_recorder());
   179   MacroAssembler *masm = new MacroAssembler(&hscb);
   180   SharkCodeBuffer cb(masm);
   181   SharkBuilder builder(&cb);
   183   // Emit the entry point
   184   SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
   186   // Build the LLVM IR for the method
   187   Function *function = SharkFunction::build(env, &builder, flow, name);
   188   if (env->failing()) {
   189     return;
   190   }
   192   // Generate native code.  It's unpleasant that we have to drop into
   193   // the VM to do this -- it blocks safepoints -- but I can't see any
   194   // other way to handle the locking.
   195   {
   196     ThreadInVMfromNative tiv(JavaThread::current());
   197     generate_native_code(entry, function, name);
   198   }
   200   // Install the method into the VM
   201   CodeOffsets offsets;
   202   offsets.set_value(CodeOffsets::Deopt, 0);
   203   offsets.set_value(CodeOffsets::Exceptions, 0);
   204   offsets.set_value(CodeOffsets::Verified_Entry,
   205                     target->is_static() ? 0 : wordSize);
   207   ExceptionHandlerTable handler_table;
   208   ImplicitExceptionTable inc_table;
   210   env->register_method(target,
   211                        entry_bci,
   212                        &offsets,
   213                        0,
   214                        &hscb,
   215                        0,
   216                        &oopmaps,
   217                        &handler_table,
   218                        &inc_table,
   219                        this,
   220                        env->comp_level(),
   221                        false,
   222                        false);
   223 }
   225 nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,
   226                                                 methodHandle    target,
   227                                                 int             compile_id,
   228                                                 BasicType*      arg_types,
   229                                                 BasicType       return_type) {
   230   assert(is_initialized(), "should be");
   231   ResourceMark rm;
   232   const char *name = methodname(
   233     target->klass_name()->as_utf8(), target->name()->as_utf8());
   235   // Create the code buffer and builder
   236   SharkCodeBuffer cb(masm);
   237   SharkBuilder builder(&cb);
   239   // Emit the entry point
   240   SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));
   242   // Build the LLVM IR for the method
   243   SharkNativeWrapper *wrapper = SharkNativeWrapper::build(
   244     &builder, target, name, arg_types, return_type);
   246   // Generate native code
   247   generate_native_code(entry, wrapper->function(), name);
   249   // Return the nmethod for installation in the VM
   250   return nmethod::new_native_nmethod(target,
   251                                      compile_id,
   252                                      masm->code(),
   253                                      0,
   254                                      0,
   255                                      wrapper->frame_size(),
   256                                      wrapper->receiver_offset(),
   257                                      wrapper->lock_offset(),
   258                                      wrapper->oop_maps());
   259 }
   261 void SharkCompiler::generate_native_code(SharkEntry* entry,
   262                                          Function*   function,
   263                                          const char* name) {
   264   // Print the LLVM bitcode, if requested
   265   if (SharkPrintBitcodeOf != NULL) {
   266     if (!fnmatch(SharkPrintBitcodeOf, name, 0))
   267       function->dump();
   268   }
   270   if (SharkVerifyFunction != NULL) {
   271     if (!fnmatch(SharkVerifyFunction, name, 0)) {
   272       verifyFunction(*function);
   273     }
   274   }
   276   // Compile to native code
   277   address code = NULL;
   278   context()->add_function(function);
   279   {
   280     MutexLocker locker(execution_engine_lock());
   281     free_queued_methods();
   283 #ifndef NDEBUG
   284 #if SHARK_LLVM_VERSION <= 31
   285 #define setCurrentDebugType SetCurrentDebugType
   286 #endif
   287     if (SharkPrintAsmOf != NULL) {
   288       if (!fnmatch(SharkPrintAsmOf, name, 0)) {
   289         llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
   290         llvm::DebugFlag = true;
   291       }
   292       else {
   293         llvm::setCurrentDebugType("");
   294         llvm::DebugFlag = false;
   295       }
   296     }
   297 #ifdef setCurrentDebugType
   298 #undef setCurrentDebugType
   299 #endif
   300 #endif // !NDEBUG
   301     memory_manager()->set_entry_for_function(function, entry);
   302     code = (address) execution_engine()->getPointerToFunction(function);
   303   }
   304   assert(code != NULL, "code must be != NULL");
   305   entry->set_entry_point(code);
   306   entry->set_function(function);
   307   entry->set_context(context());
   308   address code_start = entry->code_start();
   309   address code_limit = entry->code_limit();
   311   // Register generated code for profiling, etc
   312   if (JvmtiExport::should_post_dynamic_code_generated())
   313     JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit);
   315   // Print debug information, if requested
   316   if (SharkTraceInstalls) {
   317     tty->print_cr(
   318       " [%p-%p): %s (%d bytes code)",
   319       code_start, code_limit, name, code_limit - code_start);
   320   }
   321 }
   323 void SharkCompiler::free_compiled_method(address code) {
   324   // This method may only be called when the VM is at a safepoint.
   325   // All _thread_in_vm threads will be waiting for the safepoint to
   326   // finish with the exception of the VM thread, so we can consider
   327   // ourself the owner of the execution engine lock even though we
   328   // can't actually acquire it at this time.
   329   assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");
   330   assert_locked_or_safepoint(CodeCache_lock);
   332   SharkEntry *entry = (SharkEntry *) code;
   333   entry->context()->push_to_free_queue(entry->function());
   334 }
   336 void SharkCompiler::free_queued_methods() {
   337   // The free queue is protected by the execution engine lock
   338   assert(execution_engine_lock()->owned_by_self(), "should be");
   340   while (true) {
   341     Function *function = context()->pop_from_free_queue();
   342     if (function == NULL)
   343       break;
   345     execution_engine()->freeMachineCodeForFunction(function);
   346     function->eraseFromParent();
   347   }
   348 }
   350 const char* SharkCompiler::methodname(const char* klass, const char* method) {
   351   char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1);
   353   char *dst = buf;
   354   for (const char *c = klass; *c; c++) {
   355     if (*c == '/')
   356       *(dst++) = '.';
   357     else
   358       *(dst++) = *c;
   359   }
   360   *(dst++) = ':';
   361   *(dst++) = ':';
   362   for (const char *c = method; *c; c++) {
   363     *(dst++) = *c;
   364   }
   365   *(dst++) = '\0';
   366   return buf;
   367 }

mercurial