Mercurial > hg > release > icedtea-1.9
view ports/hotspot/src/share/vm/shark/sharkFunction.cpp @ 1732:5caf65dd9bd3
2009-03-11 Gary Benson <gbenson@redhat.com>
* ports/hotspot/src/share/vm/shark/sharkIntrinsics.hpp: New file.
* ports/hotspot/src/share/vm/shark/sharkIntrinsics.cpp: Likewise.
* ports/hotspot/src/share/vm/shark/shark_globals.hpp
(SharkPerformanceWarnings): New flag.
* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
(SharkBuilder::_llvm_cmpxchg_int_fn): New field.
(SharkBuilder::_llvm_sin_fn): Likewise.
(SharkBuilder::_llvm_cos_fn): Likewise.
(SharkBuilder::_llvm_sqrt_fn): Likewise.
(SharkBuilder::_llvm_log_fn): Likewise.
(SharkBuilder::_llvm_log10_fn): Likewise.
(SharkBuilder::_llvm_pow_fn): Likewise.
(SharkBuilder::_llvm_exp_fn): Likewise.
(SharkBuilder::set_llvm_cmpxchg_int_fn): New method.
(SharkBuilder::set_llvm_sin_fn): Likewise.
(SharkBuilder::set_llvm_cos_fn): Likewise.
(SharkBuilder::set_llvm_sqrt_fn): Likewise.
(SharkBuilder::set_llvm_log_fn): Likewise.
(SharkBuilder::set_llvm_log10_fn): Likewise.
(SharkBuilder::set_llvm_pow_fn): Likewise.
(SharkBuilder::set_llvm_exp_fn): Likewise.
(SharkBuilder::llvm_cmpxchg_int_fn): Likewise.
(SharkBuilder::llvm_sin_fn): Likewise.
(SharkBuilder::llvm_cos_fn): Likewise.
(SharkBuilder::llvm_sqrt_fn): Likewise.
(SharkBuilder::llvm_log_fn): Likewise.
(SharkBuilder::llvm_log10_fn): Likewise.
(SharkBuilder::llvm_pow_fn): Likewise.
(SharkBuilder::llvm_exp_fn): Likewise.
(SharkBuilder::CreateCmpxchgInt): Likewise.
* ports/hotspot/src/share/vm/shark/sharkBuilder.cpp
(SharkBuilder::init_external_functions): Initialize new fields.
(SharkBuilder::CreateCmpxchgInt): New method.
* ports/hotspot/src/share/vm/shark/sharkRuntime.hpp
(SharkRuntime::_current_time_millis): New field.
(SharkRuntime::_fabs): Likewise.
(SharkRuntime::_tan): Likewise.
(SharkRuntime::_atan2): Likewise.
(SharkRuntime::_unsafe_field_offset_to_byte_offset): Likewise.
(SharkRuntime::current_time_millis): New method.
(SharkRuntime::fabs): Likewise.
(SharkRuntime::tan): Likewise.
(SharkRuntime::atan2): Likewise.
(SharkRuntime::unsafe_field_offset_to_byte_offset): Likewise.
* ports/hotspot/src/share/vm/shark/sharkRuntime.cpp
(SharkRuntime::_current_time_millis): New field.
(SharkRuntime::_fabs): Likewise.
(SharkRuntime::_tan): Likewise.
(SharkRuntime::_atan2): Likewise.
(SharkRuntime::_unsafe_field_offset_to_byte_offset): Likewise.
(SharkRuntime::initialize): Initialize the above.
* ports/hotspot/src/share/vm/shark/sharkBlock.hpp
(SharkBlock::SharkBlock): New thread argument.
(SharkBlock::_thread): New field.
(SharkBlock::thread): New method.
* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
(SharkTopLevelBlock::SharkTopLevelBlock): Pass thread to super.
(SharkTopLevelBlock::thread): Removed method.
* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
(SharkTopLevelBlock::do_call): Pass thread to inliner.
* ports/hotspot/src/share/vm/shark/sharkFunction.cpp
(SharkFunction::initialize): Do the arguments before creating blocks.
* ports/hotspot/src/share/vm/shark/sharkInliner.hpp
(SharkInliner::attempt_inline): New thread argument.
* ports/hotspot/src/share/vm/shark/sharkInliner.cpp
(SharkInlineBlock::SharkInlineBlock): Pass thread to super.
(SharkInlinerHelper::SharkInlinerHelper): New thread argument.
(SharkInlinerHelper::_thread): New field.
(SharkInlinerHelper::thread): New method.
(SharkInlinerHelper::do_inline): Pass thread to block constructor.
(SharkInliner::attempt_inline): Attempt to inline intrinsics.
* ports/hotspot/src/share/vm/includeDB_shark: Updated.
(transplanted from 1eeb14582f5a679354df249e23e10b2f61b423e8)
author | Gary Benson <gbenson@redhat.com> |
---|---|
date | Wed, 11 Mar 2009 09:03:27 -0400 |
parents | f7efa3c95c17 |
children | 1b78a216c47e |
line wrap: on
line source
/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ #include "incls/_precompiled.incl" #include "incls/_sharkFunction.cpp.incl" #include <fnmatch.h> using namespace llvm; class SharkEntryState : public SharkState { public: SharkEntryState(SharkTopLevelBlock* block, llvm::Value* method) : SharkState(block, block->function(), method) { char name[18]; // Local variables for (int i = 0; i < max_locals(); i++) { ciType *type = block->local_type_at_entry(i); SharkValue *value = NULL; switch (type->basic_type()) { case T_INT: case T_LONG: case T_FLOAT: case T_DOUBLE: case T_OBJECT: case T_ARRAY: if (i < function()->arg_size()) { snprintf(name, sizeof(name), "local_%d_", i); value = SharkValue::create_generic( type, builder()->CreateLoad( function()->CreateAddressOfFrameEntry( function()->locals_slots_offset() + max_locals() - type->size() - i, SharkType::to_stackType(type)), name)); } else { Unimplemented(); } break; case ciTypeFlow::StateVector::T_BOTTOM: break; case ciTypeFlow::StateVector::T_LONG2: case ciTypeFlow::StateVector::T_DOUBLE2: break; default: ShouldNotReachHere(); } set_local(i, value); } // Non-static methods have a guaranteed non-null receiver if (!function()->target()->is_static()) { assert(local(0)->is_jobject(), "should be"); local(0)->set_zero_checked(true); } // Expression stack assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack"); } }; class SharkEntryState : public SharkState { public: SharkEntryState(SharkTopLevelBlock* block, llvm::Value* method) : SharkState(block, block->function(), method) { char name[18]; // Local variables for (int i = 0; i < max_locals(); i++) { ciType *type = block->local_type_at_entry(i); SharkValue *value = NULL; switch (type->basic_type()) { case T_INT: case T_LONG: case T_FLOAT: case T_DOUBLE: case T_OBJECT: case T_ARRAY: if (i < function()->arg_size()) { snprintf(name, sizeof(name), "local_%d_", i); value = SharkValue::create_generic( type, builder()->CreateLoad( function()->CreateAddressOfFrameEntry( function()->locals_slots_offset() + max_locals() - type->size() - i, SharkType::to_stackType(type)), name)); } else { Unimplemented(); } break; case ciTypeFlow::StateVector::T_BOTTOM: break; case ciTypeFlow::StateVector::T_LONG2: case ciTypeFlow::StateVector::T_DOUBLE2: break; default: ShouldNotReachHere(); } set_local(i, value); } // Non-static methods have a guaranteed non-null receiver if (!function()->target()->is_static()) { assert(local(0)->is_jobject(), "should be"); local(0)->set_zero_checked(true); } // Expression stack assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack"); } }; void SharkFunction::initialize() { // Emit the entry point SharkEntry *entry = (SharkEntry *) masm()->pc(); masm()->advance(sizeof(SharkEntry)); // Create the function _function = builder()->CreateFunction(name()); entry->set_llvm_function(function()); compiler()->memory_manager()->set_entry_for_function(function(), entry); // Get our arguments Function::arg_iterator ai = function()->arg_begin(); Argument *method = ai++; method->setName("method"); _base_pc = ai++; _base_pc->setName("base_pc"); _thread = ai++; _thread->setName("thread"); // Create the list of blocks set_block_insertion_point(NULL); _blocks = NEW_RESOURCE_ARRAY(SharkTopLevelBlock*, flow()->block_count()); for (int i = 0; i < block_count(); i++) { ciTypeFlow::Block *b = flow()->pre_order_at(i); // Work around a bug in pre_order_at() that does not return the // correct pre-ordering. If pre_order_at() were correct this // line could simply be: // _blocks[i] = new SharkTopLevelBlock(this, b); _blocks[b->pre_order()] = new SharkTopLevelBlock(this, b); } // Walk the tree from the start block to determine which // blocks are entered and which blocks require phis SharkTopLevelBlock *start_block = block(0); assert(start_block->start() == 0, "blocks out of order"); start_block->enter(); // Initialize all entered blocks for (int i = 0; i < block_count(); i++) { if (block(i)->entered()) block(i)->initialize(); } // Initialize the monitors _monitor_count = 0; if (target()->is_synchronized() || target()->uses_monitors()) { for (int i = 0; i < block_count(); i++) _monitor_count = MAX2( _monitor_count, block(i)->ciblock()->monitor_count()); } // Create the method preamble set_block_insertion_point(&function()->front()); builder()->SetInsertPoint(CreateBlock()); CreateInitZeroStack(); CreatePushFrame(CreateBuildFrame()); NOT_PRODUCT(builder()->CreateStore( method, CreateAddressOfFrameEntry( method_slot_offset(), SharkType::methodOop_type(), "method_slot"))); // Lock if necessary SharkState *entry_state = new SharkEntryState(start_block, method); if (target()->is_synchronized()) { SharkTopLevelBlock *locker = new SharkTopLevelBlock(this, start_block->ciblock()); locker->add_incoming(entry_state); set_block_insertion_point(start_block->entry_block()); locker->acquire_method_lock(); entry_state = locker->current_state(); } // Transition into the method proper start_block->add_incoming(entry_state); builder()->CreateBr(start_block->entry_block()); // Parse the blocks for (int i = 0; i < block_count(); i++) { if (!block(i)->entered()) continue; if (i + 1 < block_count()) set_block_insertion_point(block(i + 1)->entry_block()); else set_block_insertion_point(NULL); block(i)->emit_IR(); } // Dump the bitcode, if requested if (SharkPrintBitcodeOf != NULL) { if (!fnmatch(SharkPrintBitcodeOf, name(), 0)) function()->dump(); } // Compile to native code entry->set_entry_point(compiler()->compile(name(), function())); // Register generated code for profiling, etc if (JvmtiExport::should_post_dynamic_code_generated()) { JvmtiExport::post_dynamic_code_generated( name(), entry->code_start(), entry->code_limit()); } // Print statistics, if requested if (SharkTraceInstalls) entry->print_statistics(name()); } void SharkFunction::CreateInitZeroStack() { Value *zero_stack = builder()->CreateAddressOfStructEntry( thread(), JavaThread::zero_stack_offset(), SharkType::zeroStack_type(), "zero_stack"); _zero_stack_base = builder()->CreateValueOfStructEntry( zero_stack, ZeroStack::base_offset(), SharkType::intptr_type(), "zero_stack_base"); _zero_stack_pointer_addr = builder()->CreateAddressOfStructEntry( zero_stack, ZeroStack::sp_offset(), PointerType::getUnqual(SharkType::intptr_type()), "zero_stack_pointer_addr"); _zero_frame_pointer_addr = builder()->CreateAddressOfStructEntry( thread(), JavaThread::top_zero_frame_offset(), PointerType::getUnqual(SharkType::intptr_type()), "zero_frame_pointer_addr"); } void SharkFunction::CreateStackOverflowCheck(Value *sp) { BasicBlock *overflow = CreateBlock("stack_overflow"); BasicBlock *no_overflow = CreateBlock("no_overflow"); builder()->CreateCondBr( builder()->CreateICmpULT(sp, zero_stack_base()), overflow, no_overflow); builder()->SetInsertPoint(overflow); builder()->CreateUnimplemented(__FILE__, __LINE__); builder()->CreateUnreachable(); builder()->SetInsertPoint(no_overflow); } void SharkFunction::CreatePushFrame(Value *fp) { builder()->CreateStore(CreateLoadZeroFramePointer(), fp); CreateStoreZeroFramePointer( builder()->CreatePtrToInt(fp, SharkType::intptr_type())); } Value* SharkFunction::CreatePopFrame(int result_slots) { assert(result_slots >= 0 && result_slots <= 2, "should be"); int locals_to_pop = max_locals() - result_slots; Value *fp = CreateLoadZeroFramePointer(); Value *sp = builder()->CreateAdd( fp, LLVMValue::intptr_constant((1 + locals_to_pop) * wordSize)); CreateStoreZeroStackPointer(sp); CreateStoreZeroFramePointer( builder()->CreateLoad( builder()->CreateIntToPtr( fp, PointerType::getUnqual(SharkType::intptr_type())))); return sp; } Value* SharkFunction::CreateBuildFrame() { int locals_words = max_locals(); int extra_locals = locals_words - arg_size(); int header_words = SharkFrame::header_words; int monitor_words = monitor_count()*frame::interpreter_frame_monitor_size(); int stack_words = max_stack(); int frame_words = header_words + monitor_words + stack_words; _oopmap_frame_size = frame_words + extra_locals; // Update the stack pointer Value *zero_stack_pointer = builder()->CreateSub( CreateLoadZeroStackPointer(), LLVMValue::intptr_constant((frame_words + extra_locals) * wordSize)); CreateStackOverflowCheck(zero_stack_pointer); NOT_PRODUCT(CreateStoreZeroStackPointer(zero_stack_pointer)); // Create the frame _frame = builder()->CreateIntToPtr( zero_stack_pointer, PointerType::getUnqual( ArrayType::get(SharkType::intptr_type(), frame_words + locals_words)), "frame"); int offset = 0; // Expression stack _stack_slots_offset = offset; offset += stack_words; // Monitors if (monitor_count()) { _monitors_slots_offset = offset; for (int i = 0; i < monitor_count(); i++) { if (i != 0 || !target()->is_synchronized()) monitor(i)->mark_free(); } } offset += monitor_words; // Exception pointer _exception_slot_offset = offset++; builder()->CreateStore(LLVMValue::null(), exception_slot()); // Method pointer _method_slot_offset = offset++; // Unextended SP builder()->CreateStore( zero_stack_pointer, CreateAddressOfFrameEntry(offset++)); // PC _pc_slot_offset = offset++; // Frame header builder()->CreateStore( LLVMValue::intptr_constant(ZeroFrame::SHARK_FRAME), CreateAddressOfFrameEntry(offset++)); Value *fp = CreateAddressOfFrameEntry(offset++); // Local variables _locals_slots_offset = offset; offset += locals_words; assert(offset == frame_words + locals_words, "should do"); return fp; } Value* SharkFunction::CreateAddressOfFrameEntry(int offset, const llvm::Type* type, const char* name) const { bool needs_cast = type && type != SharkType::intptr_type(); Value* result = builder()->CreateStructGEP( _frame, offset, needs_cast ? "" : name); if (needs_cast) { result = builder()->CreateBitCast( result, PointerType::getUnqual(type), name); } return result; } SharkMonitor* SharkFunction::monitor(Value *index) const { Value *indexes[] = { LLVMValue::jint_constant(0), builder()->CreateSub( LLVMValue::jint_constant(monitor_count() - 1), index), }; return new SharkMonitor( this, builder()->CreateGEP(monitors_slots(), indexes, indexes + 2)); }