1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/shark/sharkCompiler.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,366 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc. 1.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 + * 1.9 + * This code is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License version 2 only, as 1.11 + * published by the Free Software Foundation. 1.12 + * 1.13 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.16 + * version 2 for more details (a copy is included in the LICENSE file that 1.17 + * accompanied this code). 1.18 + * 1.19 + * You should have received a copy of the GNU General Public License version 1.20 + * 2 along with this work; if not, write to the Free Software Foundation, 1.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.22 + * 1.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.24 + * or visit www.oracle.com if you need additional information or have any 1.25 + * questions. 1.26 + * 1.27 + */ 1.28 + 1.29 +#include "precompiled.hpp" 1.30 +#include "ci/ciEnv.hpp" 1.31 +#include "ci/ciMethod.hpp" 1.32 +#include "code/debugInfoRec.hpp" 1.33 +#include "code/dependencies.hpp" 1.34 +#include "code/exceptionHandlerTable.hpp" 1.35 +#include "code/oopRecorder.hpp" 1.36 +#include "compiler/abstractCompiler.hpp" 1.37 +#include "compiler/oopMap.hpp" 1.38 +#include "shark/llvmHeaders.hpp" 1.39 +#include "shark/sharkBuilder.hpp" 1.40 +#include "shark/sharkCodeBuffer.hpp" 1.41 +#include "shark/sharkCompiler.hpp" 1.42 +#include "shark/sharkContext.hpp" 1.43 +#include "shark/sharkEntry.hpp" 1.44 +#include "shark/sharkFunction.hpp" 1.45 +#include "shark/sharkMemoryManager.hpp" 1.46 +#include "shark/sharkNativeWrapper.hpp" 1.47 +#include "shark/shark_globals.hpp" 1.48 +#include "utilities/debug.hpp" 1.49 + 1.50 +#include <fnmatch.h> 1.51 + 1.52 +using namespace llvm; 1.53 + 1.54 +namespace { 1.55 + cl::opt<std::string> 1.56 + MCPU("mcpu"); 1.57 + 1.58 + cl::list<std::string> 1.59 + MAttrs("mattr", 1.60 + cl::CommaSeparated); 1.61 +} 1.62 + 1.63 +SharkCompiler::SharkCompiler() 1.64 + : AbstractCompiler() { 1.65 + // Create the lock to protect the memory manager and execution engine 1.66 + _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock"); 1.67 + MutexLocker locker(execution_engine_lock()); 1.68 + 1.69 + // Make LLVM safe for multithreading 1.70 + if (!llvm_start_multithreaded()) 1.71 + fatal("llvm_start_multithreaded() failed"); 1.72 + 1.73 + // Initialize the native target 1.74 + InitializeNativeTarget(); 1.75 + 1.76 + // MCJIT require a native AsmPrinter 1.77 + InitializeNativeTargetAsmPrinter(); 1.78 + 1.79 + // Create the two contexts which we'll use 1.80 + _normal_context = new SharkContext("normal"); 1.81 + _native_context = new SharkContext("native"); 1.82 + 1.83 + // Create the memory manager 1.84 + _memory_manager = new SharkMemoryManager(); 1.85 + 1.86 + // Finetune LLVM for the current host CPU. 1.87 + StringMap<bool> Features; 1.88 + bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features); 1.89 + std::string cpu("-mcpu=" + llvm::sys::getHostCPUName()); 1.90 + 1.91 + std::vector<const char*> args; 1.92 + args.push_back(""); // program name 1.93 + args.push_back(cpu.c_str()); 1.94 + 1.95 + std::string mattr("-mattr="); 1.96 + if(gotCpuFeatures){ 1.97 + for(StringMap<bool>::iterator I = Features.begin(), 1.98 + E = Features.end(); I != E; ++I){ 1.99 + if(I->second){ 1.100 + std::string attr(I->first()); 1.101 + mattr+="+"+attr+","; 1.102 + } 1.103 + } 1.104 + args.push_back(mattr.c_str()); 1.105 + } 1.106 + 1.107 + args.push_back(0); // terminator 1.108 + cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]); 1.109 + 1.110 + // Create the JIT 1.111 + std::string ErrorMsg; 1.112 + 1.113 + EngineBuilder builder(_normal_context->module()); 1.114 + builder.setMCPU(MCPU); 1.115 + builder.setMAttrs(MAttrs); 1.116 + builder.setJITMemoryManager(memory_manager()); 1.117 + builder.setEngineKind(EngineKind::JIT); 1.118 + builder.setErrorStr(&ErrorMsg); 1.119 + if (! fnmatch(SharkOptimizationLevel, "None", 0)) { 1.120 + tty->print_cr("Shark optimization level set to: None"); 1.121 + builder.setOptLevel(llvm::CodeGenOpt::None); 1.122 + } else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) { 1.123 + tty->print_cr("Shark optimization level set to: Less"); 1.124 + builder.setOptLevel(llvm::CodeGenOpt::Less); 1.125 + } else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) { 1.126 + tty->print_cr("Shark optimization level set to: Aggressive"); 1.127 + builder.setOptLevel(llvm::CodeGenOpt::Aggressive); 1.128 + } // else Default is selected by, well, default :-) 1.129 + _execution_engine = builder.create(); 1.130 + 1.131 + if (!execution_engine()) { 1.132 + if (!ErrorMsg.empty()) 1.133 + printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str()); 1.134 + else 1.135 + printf("Unknown error while creating Shark JIT\n"); 1.136 + exit(1); 1.137 + } 1.138 + 1.139 + execution_engine()->addModule(_native_context->module()); 1.140 + 1.141 + // All done 1.142 + set_state(initialized); 1.143 +} 1.144 + 1.145 +void SharkCompiler::initialize() { 1.146 + ShouldNotCallThis(); 1.147 +} 1.148 + 1.149 +void SharkCompiler::compile_method(ciEnv* env, 1.150 + ciMethod* target, 1.151 + int entry_bci) { 1.152 + assert(is_initialized(), "should be"); 1.153 + ResourceMark rm; 1.154 + const char *name = methodname( 1.155 + target->holder()->name()->as_utf8(), target->name()->as_utf8()); 1.156 + 1.157 + // Do the typeflow analysis 1.158 + ciTypeFlow *flow; 1.159 + if (entry_bci == InvocationEntryBci) 1.160 + flow = target->get_flow_analysis(); 1.161 + else 1.162 + flow = target->get_osr_flow_analysis(entry_bci); 1.163 + if (flow->failing()) 1.164 + return; 1.165 + if (SharkPrintTypeflowOf != NULL) { 1.166 + if (!fnmatch(SharkPrintTypeflowOf, name, 0)) 1.167 + flow->print_on(tty); 1.168 + } 1.169 + 1.170 + // Create the recorders 1.171 + Arena arena; 1.172 + env->set_oop_recorder(new OopRecorder(&arena)); 1.173 + OopMapSet oopmaps; 1.174 + env->set_debug_info(new DebugInformationRecorder(env->oop_recorder())); 1.175 + env->debug_info()->set_oopmaps(&oopmaps); 1.176 + env->set_dependencies(new Dependencies(env)); 1.177 + 1.178 + // Create the code buffer and builder 1.179 + CodeBuffer hscb("Shark", 256 * K, 64 * K); 1.180 + hscb.initialize_oop_recorder(env->oop_recorder()); 1.181 + MacroAssembler *masm = new MacroAssembler(&hscb); 1.182 + SharkCodeBuffer cb(masm); 1.183 + SharkBuilder builder(&cb); 1.184 + 1.185 + // Emit the entry point 1.186 + SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); 1.187 + 1.188 + // Build the LLVM IR for the method 1.189 + Function *function = SharkFunction::build(env, &builder, flow, name); 1.190 + if (env->failing()) { 1.191 + return; 1.192 + } 1.193 + 1.194 + // Generate native code. It's unpleasant that we have to drop into 1.195 + // the VM to do this -- it blocks safepoints -- but I can't see any 1.196 + // other way to handle the locking. 1.197 + { 1.198 + ThreadInVMfromNative tiv(JavaThread::current()); 1.199 + generate_native_code(entry, function, name); 1.200 + } 1.201 + 1.202 + // Install the method into the VM 1.203 + CodeOffsets offsets; 1.204 + offsets.set_value(CodeOffsets::Deopt, 0); 1.205 + offsets.set_value(CodeOffsets::Exceptions, 0); 1.206 + offsets.set_value(CodeOffsets::Verified_Entry, 1.207 + target->is_static() ? 0 : wordSize); 1.208 + 1.209 + ExceptionHandlerTable handler_table; 1.210 + ImplicitExceptionTable inc_table; 1.211 + 1.212 + env->register_method(target, 1.213 + entry_bci, 1.214 + &offsets, 1.215 + 0, 1.216 + &hscb, 1.217 + 0, 1.218 + &oopmaps, 1.219 + &handler_table, 1.220 + &inc_table, 1.221 + this, 1.222 + env->comp_level(), 1.223 + false, 1.224 + false); 1.225 +} 1.226 + 1.227 +nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm, 1.228 + methodHandle target, 1.229 + int compile_id, 1.230 + BasicType* arg_types, 1.231 + BasicType return_type) { 1.232 + assert(is_initialized(), "should be"); 1.233 + ResourceMark rm; 1.234 + const char *name = methodname( 1.235 + target->klass_name()->as_utf8(), target->name()->as_utf8()); 1.236 + 1.237 + // Create the code buffer and builder 1.238 + SharkCodeBuffer cb(masm); 1.239 + SharkBuilder builder(&cb); 1.240 + 1.241 + // Emit the entry point 1.242 + SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); 1.243 + 1.244 + // Build the LLVM IR for the method 1.245 + SharkNativeWrapper *wrapper = SharkNativeWrapper::build( 1.246 + &builder, target, name, arg_types, return_type); 1.247 + 1.248 + // Generate native code 1.249 + generate_native_code(entry, wrapper->function(), name); 1.250 + 1.251 + // Return the nmethod for installation in the VM 1.252 + return nmethod::new_native_nmethod(target, 1.253 + compile_id, 1.254 + masm->code(), 1.255 + 0, 1.256 + 0, 1.257 + wrapper->frame_size(), 1.258 + wrapper->receiver_offset(), 1.259 + wrapper->lock_offset(), 1.260 + wrapper->oop_maps()); 1.261 +} 1.262 + 1.263 +void SharkCompiler::generate_native_code(SharkEntry* entry, 1.264 + Function* function, 1.265 + const char* name) { 1.266 + // Print the LLVM bitcode, if requested 1.267 + if (SharkPrintBitcodeOf != NULL) { 1.268 + if (!fnmatch(SharkPrintBitcodeOf, name, 0)) 1.269 + function->dump(); 1.270 + } 1.271 + 1.272 + if (SharkVerifyFunction != NULL) { 1.273 + if (!fnmatch(SharkVerifyFunction, name, 0)) { 1.274 + verifyFunction(*function); 1.275 + } 1.276 + } 1.277 + 1.278 + // Compile to native code 1.279 + address code = NULL; 1.280 + context()->add_function(function); 1.281 + { 1.282 + MutexLocker locker(execution_engine_lock()); 1.283 + free_queued_methods(); 1.284 + 1.285 +#ifndef NDEBUG 1.286 +#if SHARK_LLVM_VERSION <= 31 1.287 +#define setCurrentDebugType SetCurrentDebugType 1.288 +#endif 1.289 + if (SharkPrintAsmOf != NULL) { 1.290 + if (!fnmatch(SharkPrintAsmOf, name, 0)) { 1.291 + llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit")); 1.292 + llvm::DebugFlag = true; 1.293 + } 1.294 + else { 1.295 + llvm::setCurrentDebugType(""); 1.296 + llvm::DebugFlag = false; 1.297 + } 1.298 + } 1.299 +#ifdef setCurrentDebugType 1.300 +#undef setCurrentDebugType 1.301 +#endif 1.302 +#endif // !NDEBUG 1.303 + memory_manager()->set_entry_for_function(function, entry); 1.304 + code = (address) execution_engine()->getPointerToFunction(function); 1.305 + } 1.306 + assert(code != NULL, "code must be != NULL"); 1.307 + entry->set_entry_point(code); 1.308 + entry->set_function(function); 1.309 + entry->set_context(context()); 1.310 + address code_start = entry->code_start(); 1.311 + address code_limit = entry->code_limit(); 1.312 + 1.313 + // Register generated code for profiling, etc 1.314 + if (JvmtiExport::should_post_dynamic_code_generated()) 1.315 + JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit); 1.316 + 1.317 + // Print debug information, if requested 1.318 + if (SharkTraceInstalls) { 1.319 + tty->print_cr( 1.320 + " [%p-%p): %s (%d bytes code)", 1.321 + code_start, code_limit, name, code_limit - code_start); 1.322 + } 1.323 +} 1.324 + 1.325 +void SharkCompiler::free_compiled_method(address code) { 1.326 + // This method may only be called when the VM is at a safepoint. 1.327 + // All _thread_in_vm threads will be waiting for the safepoint to 1.328 + // finish with the exception of the VM thread, so we can consider 1.329 + // ourself the owner of the execution engine lock even though we 1.330 + // can't actually acquire it at this time. 1.331 + assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread"); 1.332 + assert_locked_or_safepoint(CodeCache_lock); 1.333 + 1.334 + SharkEntry *entry = (SharkEntry *) code; 1.335 + entry->context()->push_to_free_queue(entry->function()); 1.336 +} 1.337 + 1.338 +void SharkCompiler::free_queued_methods() { 1.339 + // The free queue is protected by the execution engine lock 1.340 + assert(execution_engine_lock()->owned_by_self(), "should be"); 1.341 + 1.342 + while (true) { 1.343 + Function *function = context()->pop_from_free_queue(); 1.344 + if (function == NULL) 1.345 + break; 1.346 + 1.347 + execution_engine()->freeMachineCodeForFunction(function); 1.348 + function->eraseFromParent(); 1.349 + } 1.350 +} 1.351 + 1.352 +const char* SharkCompiler::methodname(const char* klass, const char* method) { 1.353 + char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1); 1.354 + 1.355 + char *dst = buf; 1.356 + for (const char *c = klass; *c; c++) { 1.357 + if (*c == '/') 1.358 + *(dst++) = '.'; 1.359 + else 1.360 + *(dst++) = *c; 1.361 + } 1.362 + *(dst++) = ':'; 1.363 + *(dst++) = ':'; 1.364 + for (const char *c = method; *c; c++) { 1.365 + *(dst++) = *c; 1.366 + } 1.367 + *(dst++) = '\0'; 1.368 + return buf; 1.369 +}