Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/shark/sharkCompiler.cpp
32285 views
/*1* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.2* Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "ci/ciEnv.hpp"27#include "ci/ciMethod.hpp"28#include "code/debugInfoRec.hpp"29#include "code/dependencies.hpp"30#include "code/exceptionHandlerTable.hpp"31#include "code/oopRecorder.hpp"32#include "compiler/abstractCompiler.hpp"33#include "compiler/oopMap.hpp"34#include "shark/llvmHeaders.hpp"35#include "shark/sharkBuilder.hpp"36#include "shark/sharkCodeBuffer.hpp"37#include "shark/sharkCompiler.hpp"38#include "shark/sharkContext.hpp"39#include "shark/sharkEntry.hpp"40#include "shark/sharkFunction.hpp"41#include "shark/sharkMemoryManager.hpp"42#include "shark/sharkNativeWrapper.hpp"43#include "shark/shark_globals.hpp"44#include "utilities/debug.hpp"4546#include <fnmatch.h>4748using namespace llvm;4950namespace {51cl::opt<std::string>52MCPU("mcpu");5354cl::list<std::string>55MAttrs("mattr",56cl::CommaSeparated);57}5859SharkCompiler::SharkCompiler()60: AbstractCompiler() {61// Create the lock to protect the memory manager and execution engine62_execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock");63MutexLocker locker(execution_engine_lock());6465// Make LLVM safe for multithreading66if (!llvm_start_multithreaded())67fatal("llvm_start_multithreaded() failed");6869// Initialize the native target70InitializeNativeTarget();7172// MCJIT require a native AsmPrinter73InitializeNativeTargetAsmPrinter();7475// Create the two contexts which we'll use76_normal_context = new SharkContext("normal");77_native_context = new SharkContext("native");7879// Create the memory manager80_memory_manager = new SharkMemoryManager();8182// Finetune LLVM for the current host CPU.83StringMap<bool> Features;84bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features);85std::string cpu("-mcpu=" + llvm::sys::getHostCPUName());8687std::vector<const char*> args;88args.push_back(""); // program name89args.push_back(cpu.c_str());9091std::string mattr("-mattr=");92if(gotCpuFeatures){93for(StringMap<bool>::iterator I = Features.begin(),94E = Features.end(); I != E; ++I){95if(I->second){96std::string attr(I->first());97mattr+="+"+attr+",";98}99}100args.push_back(mattr.c_str());101}102103args.push_back(0); // terminator104cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);105106// Create the JIT107std::string ErrorMsg;108109EngineBuilder builder(_normal_context->module());110builder.setMCPU(MCPU);111builder.setMAttrs(MAttrs);112builder.setJITMemoryManager(memory_manager());113builder.setEngineKind(EngineKind::JIT);114builder.setErrorStr(&ErrorMsg);115if (! fnmatch(SharkOptimizationLevel, "None", 0)) {116tty->print_cr("Shark optimization level set to: None");117builder.setOptLevel(llvm::CodeGenOpt::None);118} else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) {119tty->print_cr("Shark optimization level set to: Less");120builder.setOptLevel(llvm::CodeGenOpt::Less);121} else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) {122tty->print_cr("Shark optimization level set to: Aggressive");123builder.setOptLevel(llvm::CodeGenOpt::Aggressive);124} // else Default is selected by, well, default :-)125_execution_engine = builder.create();126127if (!execution_engine()) {128if (!ErrorMsg.empty())129printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str());130else131printf("Unknown error while creating Shark JIT\n");132exit(1);133}134135execution_engine()->addModule(_native_context->module());136137// All done138set_state(initialized);139}140141void SharkCompiler::initialize() {142ShouldNotCallThis();143}144145void SharkCompiler::compile_method(ciEnv* env,146ciMethod* target,147int entry_bci) {148assert(is_initialized(), "should be");149ResourceMark rm;150const char *name = methodname(151target->holder()->name()->as_utf8(), target->name()->as_utf8());152153// Do the typeflow analysis154ciTypeFlow *flow;155if (entry_bci == InvocationEntryBci)156flow = target->get_flow_analysis();157else158flow = target->get_osr_flow_analysis(entry_bci);159if (flow->failing())160return;161if (SharkPrintTypeflowOf != NULL) {162if (!fnmatch(SharkPrintTypeflowOf, name, 0))163flow->print_on(tty);164}165166// Create the recorders167Arena arena;168env->set_oop_recorder(new OopRecorder(&arena));169OopMapSet oopmaps;170env->set_debug_info(new DebugInformationRecorder(env->oop_recorder()));171env->debug_info()->set_oopmaps(&oopmaps);172env->set_dependencies(new Dependencies(env));173174// Create the code buffer and builder175CodeBuffer hscb("Shark", 256 * K, 64 * K);176hscb.initialize_oop_recorder(env->oop_recorder());177MacroAssembler *masm = new MacroAssembler(&hscb);178SharkCodeBuffer cb(masm);179SharkBuilder builder(&cb);180181// Emit the entry point182SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));183184// Build the LLVM IR for the method185Function *function = SharkFunction::build(env, &builder, flow, name);186if (env->failing()) {187return;188}189190// Generate native code. It's unpleasant that we have to drop into191// the VM to do this -- it blocks safepoints -- but I can't see any192// other way to handle the locking.193{194ThreadInVMfromNative tiv(JavaThread::current());195generate_native_code(entry, function, name);196}197198// Install the method into the VM199CodeOffsets offsets;200offsets.set_value(CodeOffsets::Deopt, 0);201offsets.set_value(CodeOffsets::Exceptions, 0);202offsets.set_value(CodeOffsets::Verified_Entry,203target->is_static() ? 0 : wordSize);204205ExceptionHandlerTable handler_table;206ImplicitExceptionTable inc_table;207208env->register_method(target,209entry_bci,210&offsets,2110,212&hscb,2130,214&oopmaps,215&handler_table,216&inc_table,217this,218env->comp_level(),219false,220false);221}222223nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,224methodHandle target,225int compile_id,226BasicType* arg_types,227BasicType return_type) {228assert(is_initialized(), "should be");229ResourceMark rm;230const char *name = methodname(231target->klass_name()->as_utf8(), target->name()->as_utf8());232233// Create the code buffer and builder234SharkCodeBuffer cb(masm);235SharkBuilder builder(&cb);236237// Emit the entry point238SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));239240// Build the LLVM IR for the method241SharkNativeWrapper *wrapper = SharkNativeWrapper::build(242&builder, target, name, arg_types, return_type);243244// Generate native code245generate_native_code(entry, wrapper->function(), name);246247// Return the nmethod for installation in the VM248return nmethod::new_native_nmethod(target,249compile_id,250masm->code(),2510,2520,253wrapper->frame_size(),254wrapper->receiver_offset(),255wrapper->lock_offset(),256wrapper->oop_maps());257}258259void SharkCompiler::generate_native_code(SharkEntry* entry,260Function* function,261const char* name) {262// Print the LLVM bitcode, if requested263if (SharkPrintBitcodeOf != NULL) {264if (!fnmatch(SharkPrintBitcodeOf, name, 0))265function->dump();266}267268if (SharkVerifyFunction != NULL) {269if (!fnmatch(SharkVerifyFunction, name, 0)) {270verifyFunction(*function);271}272}273274// Compile to native code275address code = NULL;276context()->add_function(function);277{278MutexLocker locker(execution_engine_lock());279free_queued_methods();280281#ifndef NDEBUG282#if SHARK_LLVM_VERSION <= 31283#define setCurrentDebugType SetCurrentDebugType284#endif285if (SharkPrintAsmOf != NULL) {286if (!fnmatch(SharkPrintAsmOf, name, 0)) {287llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));288llvm::DebugFlag = true;289}290else {291llvm::setCurrentDebugType("");292llvm::DebugFlag = false;293}294}295#ifdef setCurrentDebugType296#undef setCurrentDebugType297#endif298#endif // !NDEBUG299memory_manager()->set_entry_for_function(function, entry);300code = (address) execution_engine()->getPointerToFunction(function);301}302assert(code != NULL, "code must be != NULL");303entry->set_entry_point(code);304entry->set_function(function);305entry->set_context(context());306address code_start = entry->code_start();307address code_limit = entry->code_limit();308309// Register generated code for profiling, etc310if (JvmtiExport::should_post_dynamic_code_generated())311JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit);312313// Print debug information, if requested314if (SharkTraceInstalls) {315tty->print_cr(316" [%p-%p): %s (%d bytes code)",317code_start, code_limit, name, code_limit - code_start);318}319}320321void SharkCompiler::free_compiled_method(address code) {322// This method may only be called when the VM is at a safepoint.323// All _thread_in_vm threads will be waiting for the safepoint to324// finish with the exception of the VM thread, so we can consider325// ourself the owner of the execution engine lock even though we326// can't actually acquire it at this time.327assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");328assert_locked_or_safepoint(CodeCache_lock);329330SharkEntry *entry = (SharkEntry *) code;331entry->context()->push_to_free_queue(entry->function());332}333334void SharkCompiler::free_queued_methods() {335// The free queue is protected by the execution engine lock336assert(execution_engine_lock()->owned_by_self(), "should be");337338while (true) {339Function *function = context()->pop_from_free_queue();340if (function == NULL)341break;342343execution_engine()->freeMachineCodeForFunction(function);344function->eraseFromParent();345}346}347348const char* SharkCompiler::methodname(const char* klass, const char* method) {349char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1);350351char *dst = buf;352for (const char *c = klass; *c; c++) {353if (*c == '/')354*(dst++) = '.';355else356*(dst++) = *c;357}358*(dst++) = ':';359*(dst++) = ':';360for (const char *c = method; *c; c++) {361*(dst++) = *c;362}363*(dst++) = '\0';364return buf;365}366367368