1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/shark/sharkCompiler.cpp Wed Aug 11 05:51:21 2010 -0700 1.3 @@ -0,0 +1,340 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright 2008, 2009, 2010 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 "incls/_precompiled.incl" 1.30 +#include "incls/_sharkCompiler.cpp.incl" 1.31 + 1.32 +#include <fnmatch.h> 1.33 + 1.34 +using namespace llvm; 1.35 + 1.36 +#if SHARK_LLVM_VERSION >= 27 1.37 +namespace { 1.38 + cl::opt<std::string> 1.39 + MCPU("mcpu"); 1.40 + 1.41 + cl::list<std::string> 1.42 + MAttrs("mattr", 1.43 + cl::CommaSeparated); 1.44 +} 1.45 +#endif 1.46 + 1.47 +SharkCompiler::SharkCompiler() 1.48 + : AbstractCompiler() { 1.49 + // Create the lock to protect the memory manager and execution engine 1.50 + _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock"); 1.51 + MutexLocker locker(execution_engine_lock()); 1.52 + 1.53 + // Make LLVM safe for multithreading 1.54 + if (!llvm_start_multithreaded()) 1.55 + fatal("llvm_start_multithreaded() failed"); 1.56 + 1.57 + // Initialize the native target 1.58 + InitializeNativeTarget(); 1.59 + 1.60 + // Create the two contexts which we'll use 1.61 + _normal_context = new SharkContext("normal"); 1.62 + _native_context = new SharkContext("native"); 1.63 + 1.64 + // Create the memory manager 1.65 + _memory_manager = new SharkMemoryManager(); 1.66 + 1.67 +#if SHARK_LLVM_VERSION >= 27 1.68 + // Finetune LLVM for the current host CPU. 1.69 + StringMap<bool> Features; 1.70 + bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features); 1.71 + std::string cpu("-mcpu=" + llvm::sys::getHostCPUName()); 1.72 + 1.73 + std::vector<const char*> args; 1.74 + args.push_back(""); // program name 1.75 + args.push_back(cpu.c_str()); 1.76 + 1.77 + std::string mattr("-mattr="); 1.78 + if(gotCpuFeatures){ 1.79 + for(StringMap<bool>::iterator I = Features.begin(), 1.80 + E = Features.end(); I != E; ++I){ 1.81 + if(I->second){ 1.82 + std::string attr(I->first()); 1.83 + mattr+="+"+attr+","; 1.84 + } 1.85 + } 1.86 + args.push_back(mattr.c_str()); 1.87 + } 1.88 + 1.89 + args.push_back(0); // terminator 1.90 + cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]); 1.91 + 1.92 + // Create the JIT 1.93 + std::string ErrorMsg; 1.94 + 1.95 + EngineBuilder builder(_normal_context->module()); 1.96 + builder.setMCPU(MCPU); 1.97 + builder.setMAttrs(MAttrs); 1.98 + builder.setJITMemoryManager(memory_manager()); 1.99 + builder.setEngineKind(EngineKind::JIT); 1.100 + builder.setErrorStr(&ErrorMsg); 1.101 + _execution_engine = builder.create(); 1.102 + 1.103 + if (!execution_engine()) { 1.104 + if (!ErrorMsg.empty()) 1.105 + printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str()); 1.106 + else 1.107 + printf("Unknown error while creating Shark JIT\n"); 1.108 + exit(1); 1.109 + } 1.110 + 1.111 + execution_engine()->addModule( 1.112 + _native_context->module()); 1.113 +#else 1.114 + _execution_engine = ExecutionEngine::createJIT( 1.115 + _normal_context->module_provider(), 1.116 + NULL, memory_manager(), CodeGenOpt::Default); 1.117 + execution_engine()->addModuleProvider( 1.118 + _native_context->module_provider()); 1.119 +#endif 1.120 + 1.121 + // All done 1.122 + mark_initialized(); 1.123 +} 1.124 + 1.125 +void SharkCompiler::initialize() { 1.126 + ShouldNotCallThis(); 1.127 +} 1.128 + 1.129 +void SharkCompiler::compile_method(ciEnv* env, 1.130 + ciMethod* target, 1.131 + int entry_bci) { 1.132 + assert(is_initialized(), "should be"); 1.133 + ResourceMark rm; 1.134 + const char *name = methodname( 1.135 + target->holder()->name()->as_utf8(), target->name()->as_utf8()); 1.136 + 1.137 + // Do the typeflow analysis 1.138 + ciTypeFlow *flow; 1.139 + if (entry_bci == InvocationEntryBci) 1.140 + flow = target->get_flow_analysis(); 1.141 + else 1.142 + flow = target->get_osr_flow_analysis(entry_bci); 1.143 + if (flow->failing()) 1.144 + return; 1.145 + if (SharkPrintTypeflowOf != NULL) { 1.146 + if (!fnmatch(SharkPrintTypeflowOf, name, 0)) 1.147 + flow->print_on(tty); 1.148 + } 1.149 + 1.150 + // Create the recorders 1.151 + Arena arena; 1.152 + env->set_oop_recorder(new OopRecorder(&arena)); 1.153 + OopMapSet oopmaps; 1.154 + env->set_debug_info(new DebugInformationRecorder(env->oop_recorder())); 1.155 + env->debug_info()->set_oopmaps(&oopmaps); 1.156 + env->set_dependencies(new Dependencies(env)); 1.157 + 1.158 + // Create the code buffer and builder 1.159 + CodeBuffer hscb("Shark", 256 * K, 64 * K); 1.160 + hscb.initialize_oop_recorder(env->oop_recorder()); 1.161 + MacroAssembler *masm = new MacroAssembler(&hscb); 1.162 + SharkCodeBuffer cb(masm); 1.163 + SharkBuilder builder(&cb); 1.164 + 1.165 + // Emit the entry point 1.166 + SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); 1.167 + 1.168 + // Build the LLVM IR for the method 1.169 + Function *function = SharkFunction::build(env, &builder, flow, name); 1.170 + 1.171 + // Generate native code. It's unpleasant that we have to drop into 1.172 + // the VM to do this -- it blocks safepoints -- but I can't see any 1.173 + // other way to handle the locking. 1.174 + { 1.175 + ThreadInVMfromNative tiv(JavaThread::current()); 1.176 + generate_native_code(entry, function, name); 1.177 + } 1.178 + 1.179 + // Install the method into the VM 1.180 + CodeOffsets offsets; 1.181 + offsets.set_value(CodeOffsets::Deopt, 0); 1.182 + offsets.set_value(CodeOffsets::Exceptions, 0); 1.183 + offsets.set_value(CodeOffsets::Verified_Entry, 1.184 + target->is_static() ? 0 : wordSize); 1.185 + 1.186 + ExceptionHandlerTable handler_table; 1.187 + ImplicitExceptionTable inc_table; 1.188 + 1.189 + env->register_method(target, 1.190 + entry_bci, 1.191 + &offsets, 1.192 + 0, 1.193 + &hscb, 1.194 + 0, 1.195 + &oopmaps, 1.196 + &handler_table, 1.197 + &inc_table, 1.198 + this, 1.199 + env->comp_level(), 1.200 + false, 1.201 + false); 1.202 +} 1.203 + 1.204 +nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm, 1.205 + methodHandle target, 1.206 + BasicType* arg_types, 1.207 + BasicType return_type) { 1.208 + assert(is_initialized(), "should be"); 1.209 + ResourceMark rm; 1.210 + const char *name = methodname( 1.211 + target->klass_name()->as_utf8(), target->name()->as_utf8()); 1.212 + 1.213 + // Create the code buffer and builder 1.214 + SharkCodeBuffer cb(masm); 1.215 + SharkBuilder builder(&cb); 1.216 + 1.217 + // Emit the entry point 1.218 + SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); 1.219 + 1.220 + // Build the LLVM IR for the method 1.221 + SharkNativeWrapper *wrapper = SharkNativeWrapper::build( 1.222 + &builder, target, name, arg_types, return_type); 1.223 + 1.224 + // Generate native code 1.225 + generate_native_code(entry, wrapper->function(), name); 1.226 + 1.227 + // Return the nmethod for installation in the VM 1.228 + return nmethod::new_native_nmethod(target, 1.229 + masm->code(), 1.230 + 0, 1.231 + 0, 1.232 + wrapper->frame_size(), 1.233 + wrapper->receiver_offset(), 1.234 + wrapper->lock_offset(), 1.235 + wrapper->oop_maps()); 1.236 +} 1.237 + 1.238 +void SharkCompiler::generate_native_code(SharkEntry* entry, 1.239 + Function* function, 1.240 + const char* name) { 1.241 + // Print the LLVM bitcode, if requested 1.242 + if (SharkPrintBitcodeOf != NULL) { 1.243 + if (!fnmatch(SharkPrintBitcodeOf, name, 0)) 1.244 + function->dump(); 1.245 + } 1.246 + 1.247 + // Compile to native code 1.248 + address code = NULL; 1.249 + context()->add_function(function); 1.250 + { 1.251 + MutexLocker locker(execution_engine_lock()); 1.252 + free_queued_methods(); 1.253 + 1.254 + if (SharkPrintAsmOf != NULL) { 1.255 +#if SHARK_LLVM_VERSION >= 27 1.256 +#ifndef NDEBUG 1.257 + if (!fnmatch(SharkPrintAsmOf, name, 0)) { 1.258 + llvm::SetCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit")); 1.259 + llvm::DebugFlag = true; 1.260 + } 1.261 + else { 1.262 + llvm::SetCurrentDebugType(""); 1.263 + llvm::DebugFlag = false; 1.264 + } 1.265 +#endif // !NDEBUG 1.266 +#else 1.267 + // NB you need to patch LLVM with http://tinyurl.com/yf3baln for this 1.268 + std::vector<const char*> args; 1.269 + args.push_back(""); // program name 1.270 + if (!fnmatch(SharkPrintAsmOf, name, 0)) 1.271 + args.push_back("-debug-only=x86-emitter"); 1.272 + else 1.273 + args.push_back("-debug-only=none"); 1.274 + args.push_back(0); // terminator 1.275 + cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]); 1.276 +#endif // SHARK_LLVM_VERSION 1.277 + } 1.278 + memory_manager()->set_entry_for_function(function, entry); 1.279 + code = (address) execution_engine()->getPointerToFunction(function); 1.280 + } 1.281 + entry->set_entry_point(code); 1.282 + entry->set_function(function); 1.283 + entry->set_context(context()); 1.284 + address code_start = entry->code_start(); 1.285 + address code_limit = entry->code_limit(); 1.286 + 1.287 + // Register generated code for profiling, etc 1.288 + if (JvmtiExport::should_post_dynamic_code_generated()) 1.289 + JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit); 1.290 + 1.291 + // Print debug information, if requested 1.292 + if (SharkTraceInstalls) { 1.293 + tty->print_cr( 1.294 + " [%p-%p): %s (%d bytes code)", 1.295 + code_start, code_limit, name, code_limit - code_start); 1.296 + } 1.297 +} 1.298 + 1.299 +void SharkCompiler::free_compiled_method(address code) { 1.300 + // This method may only be called when the VM is at a safepoint. 1.301 + // All _thread_in_vm threads will be waiting for the safepoint to 1.302 + // finish with the exception of the VM thread, so we can consider 1.303 + // ourself the owner of the execution engine lock even though we 1.304 + // can't actually acquire it at this time. 1.305 + assert(Thread::current()->is_VM_thread(), "must be called by VM thread"); 1.306 + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 1.307 + 1.308 + SharkEntry *entry = (SharkEntry *) code; 1.309 + entry->context()->push_to_free_queue(entry->function()); 1.310 +} 1.311 + 1.312 +void SharkCompiler::free_queued_methods() { 1.313 + // The free queue is protected by the execution engine lock 1.314 + assert(execution_engine_lock()->owned_by_self(), "should be"); 1.315 + 1.316 + while (true) { 1.317 + Function *function = context()->pop_from_free_queue(); 1.318 + if (function == NULL) 1.319 + break; 1.320 + 1.321 + execution_engine()->freeMachineCodeForFunction(function); 1.322 + function->eraseFromParent(); 1.323 + } 1.324 +} 1.325 + 1.326 +const char* SharkCompiler::methodname(const char* klass, const char* method) { 1.327 + char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1); 1.328 + 1.329 + char *dst = buf; 1.330 + for (const char *c = klass; *c; c++) { 1.331 + if (*c == '/') 1.332 + *(dst++) = '.'; 1.333 + else 1.334 + *(dst++) = *c; 1.335 + } 1.336 + *(dst++) = ':'; 1.337 + *(dst++) = ':'; 1.338 + for (const char *c = method; *c; c++) { 1.339 + *(dst++) = *c; 1.340 + } 1.341 + *(dst++) = '\0'; 1.342 + return buf; 1.343 +}