Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/shark/sharkBuilder.cpp
32285 views
/*1* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.2* Copyright 2008, 2009, 2010 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/ciMethod.hpp"27#include "memory/resourceArea.hpp"28#include "oops/method.hpp"29#include "runtime/os.hpp"30#include "runtime/synchronizer.hpp"31#include "runtime/thread.hpp"32#include "shark/llvmHeaders.hpp"33#include "shark/llvmValue.hpp"34#include "shark/sharkBuilder.hpp"35#include "shark/sharkContext.hpp"36#include "shark/sharkRuntime.hpp"37#include "utilities/debug.hpp"3839using namespace llvm;4041SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer)42: IRBuilder<>(SharkContext::current()),43_code_buffer(code_buffer) {44}4546// Helpers for accessing structures47Value* SharkBuilder::CreateAddressOfStructEntry(Value* base,48ByteSize offset,49Type* type,50const char* name) {51return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name);52}5354LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base,55ByteSize offset,56Type* type,57const char* name) {58return CreateLoad(59CreateAddressOfStructEntry(60base, offset, PointerType::getUnqual(type)),61name);62}6364// Helpers for accessing arrays6566LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) {67return CreateValueOfStructEntry(68arrayoop, in_ByteSize(arrayOopDesc::length_offset_in_bytes()),69SharkType::jint_type(), "length");70}7172Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,73Type* element_type,74int element_bytes,75ByteSize base_offset,76Value* index,77const char* name) {78Value* offset = CreateIntCast(index, SharkType::intptr_type(), false);79if (element_bytes != 1)80offset = CreateShl(81offset,82LLVMValue::intptr_constant(exact_log2(element_bytes)));83offset = CreateAdd(84LLVMValue::intptr_constant(in_bytes(base_offset)), offset);8586return CreateIntToPtr(87CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset),88PointerType::getUnqual(element_type),89name);90}9192Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,93BasicType basic_type,94ByteSize base_offset,95Value* index,96const char* name) {97return CreateArrayAddress(98arrayoop,99SharkType::to_arrayType(basic_type),100type2aelembytes(basic_type),101base_offset, index, name);102}103104Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,105BasicType basic_type,106Value* index,107const char* name) {108return CreateArrayAddress(109arrayoop, basic_type,110in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)),111index, name);112}113114// Helpers for creating intrinsics and external functions.115116Type* SharkBuilder::make_type(char type, bool void_ok) {117switch (type) {118// Primitive types119case 'c':120return SharkType::jbyte_type();121case 'i':122return SharkType::jint_type();123case 'l':124return SharkType::jlong_type();125case 'x':126return SharkType::intptr_type();127case 'f':128return SharkType::jfloat_type();129case 'd':130return SharkType::jdouble_type();131132// Pointers to primitive types133case 'C':134case 'I':135case 'L':136case 'X':137case 'F':138case 'D':139return PointerType::getUnqual(make_type(tolower(type), false));140141// VM objects142case 'T':143return SharkType::thread_type();144case 'M':145return PointerType::getUnqual(SharkType::monitor_type());146case 'O':147return SharkType::oop_type();148case 'K':149return SharkType::klass_type();150151// Miscellaneous152case 'v':153assert(void_ok, "should be");154return SharkType::void_type();155case '1':156return SharkType::bit_type();157158default:159ShouldNotReachHere();160}161}162163FunctionType* SharkBuilder::make_ftype(const char* params,164const char* ret) {165std::vector<Type*> param_types;166for (const char* c = params; *c; c++)167param_types.push_back(make_type(*c, false));168169assert(strlen(ret) == 1, "should be");170Type *return_type = make_type(*ret, true);171172return FunctionType::get(return_type, param_types, false);173}174175// Create an object representing an intrinsic or external function by176// referencing the symbol by name. This is the LLVM-style approach,177// but it cannot be used on functions within libjvm.so its symbols178// are not exported. Note that you cannot make this work simply by179// exporting the symbols, as some symbols have the same names as180// symbols in the standard libraries (eg, atan2, fabs) and would181// obscure them were they visible.182Value* SharkBuilder::make_function(const char* name,183const char* params,184const char* ret) {185return SharkContext::current().get_external(name, make_ftype(params, ret));186}187188// Create an object representing an external function by inlining a189// function pointer in the code. This is not the LLVM way, but it's190// the only way to access functions in libjvm.so and functions like191// __kernel_dmb on ARM which is accessed via an absolute address.192Value* SharkBuilder::make_function(address func,193const char* params,194const char* ret) {195return CreateIntToPtr(196LLVMValue::intptr_constant((intptr_t) func),197PointerType::getUnqual(make_ftype(params, ret)));198}199200// VM calls201202Value* SharkBuilder::find_exception_handler() {203return make_function(204(address) SharkRuntime::find_exception_handler, "TIi", "i");205}206207Value* SharkBuilder::monitorenter() {208return make_function((address) SharkRuntime::monitorenter, "TM", "v");209}210211Value* SharkBuilder::monitorexit() {212return make_function((address) SharkRuntime::monitorexit, "TM", "v");213}214215Value* SharkBuilder::new_instance() {216return make_function((address) SharkRuntime::new_instance, "Ti", "v");217}218219Value* SharkBuilder::newarray() {220return make_function((address) SharkRuntime::newarray, "Tii", "v");221}222223Value* SharkBuilder::anewarray() {224return make_function((address) SharkRuntime::anewarray, "Tii", "v");225}226227Value* SharkBuilder::multianewarray() {228return make_function((address) SharkRuntime::multianewarray, "TiiI", "v");229}230231Value* SharkBuilder::register_finalizer() {232return make_function((address) SharkRuntime::register_finalizer, "TO", "v");233}234235Value* SharkBuilder::safepoint() {236return make_function((address) SafepointSynchronize::block, "T", "v");237}238239Value* SharkBuilder::throw_ArithmeticException() {240return make_function(241(address) SharkRuntime::throw_ArithmeticException, "TCi", "v");242}243244Value* SharkBuilder::throw_ArrayIndexOutOfBoundsException() {245return make_function(246(address) SharkRuntime::throw_ArrayIndexOutOfBoundsException, "TCii", "v");247}248249Value* SharkBuilder::throw_ClassCastException() {250return make_function(251(address) SharkRuntime::throw_ClassCastException, "TCi", "v");252}253254Value* SharkBuilder::throw_NullPointerException() {255return make_function(256(address) SharkRuntime::throw_NullPointerException, "TCi", "v");257}258259// High-level non-VM calls260261Value* SharkBuilder::f2i() {262return make_function((address) SharedRuntime::f2i, "f", "i");263}264265Value* SharkBuilder::f2l() {266return make_function((address) SharedRuntime::f2l, "f", "l");267}268269Value* SharkBuilder::d2i() {270return make_function((address) SharedRuntime::d2i, "d", "i");271}272273Value* SharkBuilder::d2l() {274return make_function((address) SharedRuntime::d2l, "d", "l");275}276277Value* SharkBuilder::is_subtype_of() {278return make_function((address) SharkRuntime::is_subtype_of, "KK", "c");279}280281Value* SharkBuilder::current_time_millis() {282return make_function((address) os::javaTimeMillis, "", "l");283}284285Value* SharkBuilder::sin() {286return make_function("llvm.sin.f64", "d", "d");287}288289Value* SharkBuilder::cos() {290return make_function("llvm.cos.f64", "d", "d");291}292293Value* SharkBuilder::tan() {294return make_function((address) ::tan, "d", "d");295}296297Value* SharkBuilder::atan2() {298return make_function((address) ::atan2, "dd", "d");299}300301Value* SharkBuilder::sqrt() {302return make_function("llvm.sqrt.f64", "d", "d");303}304305Value* SharkBuilder::log() {306return make_function("llvm.log.f64", "d", "d");307}308309Value* SharkBuilder::log10() {310return make_function("llvm.log10.f64", "d", "d");311}312313Value* SharkBuilder::pow() {314return make_function("llvm.pow.f64", "dd", "d");315}316317Value* SharkBuilder::exp() {318return make_function("llvm.exp.f64", "d", "d");319}320321Value* SharkBuilder::fabs() {322return make_function((address) ::fabs, "d", "d");323}324325Value* SharkBuilder::unsafe_field_offset_to_byte_offset() {326extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset);327return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l");328}329330Value* SharkBuilder::osr_migration_end() {331return make_function((address) SharedRuntime::OSR_migration_end, "C", "v");332}333334// Semi-VM calls335336Value* SharkBuilder::throw_StackOverflowError() {337return make_function((address) ZeroStack::handle_overflow, "T", "v");338}339340Value* SharkBuilder::uncommon_trap() {341return make_function((address) SharkRuntime::uncommon_trap, "Ti", "i");342}343344Value* SharkBuilder::deoptimized_entry_point() {345return make_function((address) CppInterpreter::main_loop, "iT", "v");346}347348// Native-Java transition349350Value* SharkBuilder::check_special_condition_for_native_trans() {351return make_function(352(address) JavaThread::check_special_condition_for_native_trans,353"T", "v");354}355356Value* SharkBuilder::frame_address() {357return make_function("llvm.frameaddress", "i", "C");358}359360Value* SharkBuilder::memset() {361// LLVM 2.8 added a fifth isVolatile field for memset362// introduced with LLVM r100304363return make_function("llvm.memset.p0i8.i32", "Cciii", "v");364}365366Value* SharkBuilder::unimplemented() {367return make_function((address) report_unimplemented, "Ci", "v");368}369370Value* SharkBuilder::should_not_reach_here() {371return make_function((address) report_should_not_reach_here, "Ci", "v");372}373374Value* SharkBuilder::dump() {375return make_function((address) SharkRuntime::dump, "Cx", "v");376}377378// Public interface to low-level non-VM calls379380CallInst* SharkBuilder::CreateGetFrameAddress() {381return CreateCall(frame_address(), LLVMValue::jint_constant(0));382}383384CallInst* SharkBuilder::CreateMemset(Value* dst,385Value* value,386Value* len,387Value* align) {388return CreateCall5(memset(), dst, value, len, align,389LLVMValue::jint_constant(0));390}391392CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) {393return CreateCall2(394unimplemented(),395CreateIntToPtr(396LLVMValue::intptr_constant((intptr_t) file),397PointerType::getUnqual(SharkType::jbyte_type())),398LLVMValue::jint_constant(line));399}400401CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) {402return CreateCall2(403should_not_reach_here(),404CreateIntToPtr(405LLVMValue::intptr_constant((intptr_t) file),406PointerType::getUnqual(SharkType::jbyte_type())),407LLVMValue::jint_constant(line));408}409410#ifndef PRODUCT411CallInst* SharkBuilder::CreateDump(Value* value) {412const char *name;413if (value->hasName())414// XXX this leaks, but it's only debug code415name = strdup(value->getName().str().c_str());416else417name = "unnamed_value";418419if (isa<PointerType>(value->getType()))420value = CreatePtrToInt(value, SharkType::intptr_type());421else if (value->getType()->422isIntegerTy()423)424value = CreateIntCast(value, SharkType::intptr_type(), false);425else426Unimplemented();427428return CreateCall2(429dump(),430CreateIntToPtr(431LLVMValue::intptr_constant((intptr_t) name),432PointerType::getUnqual(SharkType::jbyte_type())),433value);434}435#endif // PRODUCT436437// HotSpot memory barriers438439void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {440if (bs->kind() != BarrierSet::CardTableModRef)441Unimplemented();442443CreateStore(444LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),445CreateIntToPtr(446CreateAdd(447LLVMValue::intptr_constant(448(intptr_t) ((CardTableModRefBS *) bs)->byte_map_base),449CreateLShr(450CreatePtrToInt(field, SharkType::intptr_type()),451LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),452PointerType::getUnqual(SharkType::jbyte_type())));453}454455// Helpers for accessing the code buffer456457Value* SharkBuilder::code_buffer_address(int offset) {458return CreateAdd(459code_buffer()->base_pc(),460LLVMValue::intptr_constant(offset));461}462463Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) {464return CreateLoad(465CreateIntToPtr(466code_buffer_address(code_buffer()->inline_oop(object)),467PointerType::getUnqual(SharkType::oop_type())),468name);469}470471Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) {472assert(metadata != NULL, "inlined metadata must not be NULL");473assert(metadata->is_metaspace_object(), "sanity check");474return CreateLoad(475CreateIntToPtr(476code_buffer_address(code_buffer()->inline_Metadata(metadata)),477PointerType::getUnqual(type)),478name);479}480481Value* SharkBuilder::CreateInlineData(void* data,482size_t size,483Type* type,484const char* name) {485return CreateIntToPtr(486code_buffer_address(code_buffer()->inline_data(data, size)),487type,488name);489}490491// Helpers for creating basic blocks.492493BasicBlock* SharkBuilder::GetBlockInsertionPoint() const {494BasicBlock *cur = GetInsertBlock();495496// BasicBlock::Create takes an insertBefore argument, so497// we need to find the block _after_ the current block498Function::iterator iter = cur->getParent()->begin();499Function::iterator end = cur->getParent()->end();500while (iter != end) {501iter++;502if (&*iter == cur) {503iter++;504break;505}506}507508if (iter == end)509return NULL;510else511return iter;512}513514BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const {515return BasicBlock::Create(516SharkContext::current(), name, GetInsertBlock()->getParent(), ip);517}518519LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {520return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name);521}522523StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {524return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name);525}526527528