提交 4df65638 编写于 作者: T twisti

8003868: fix shark for latest HotSpot and LLVM

Reviewed-by: twisti
Contributed-by: NRoman Kennke <rkennke@redhat.com>
上级 147bbce4
......@@ -80,6 +80,11 @@ void MacroAssembler::store_oop(jobject obj) {
emit_address((address) obj);
}
void MacroAssembler::store_Metadata(Metadata* md) {
code_section()->relocate(pc(), metadata_Relocation::spec_for_immediate());
emit_address((address) md);
}
static void should_not_call() {
report_should_not_call(__FILE__, __LINE__);
}
......
......@@ -55,6 +55,7 @@ class MacroAssembler : public Assembler {
public:
void advance(int bytes);
void store_oop(jobject obj);
void store_Metadata(Metadata* obj);
};
#ifdef ASSERT
......
......@@ -1015,11 +1015,7 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) {
// Helper for figuring out if frames are interpreter frames
bool CppInterpreter::contains(address pc) {
#ifdef PRODUCT
ShouldNotCallThis();
#else
return false; // make frame::print_value_on work
#endif // !PRODUCT
}
// Result handlers and convertors
......
......@@ -52,11 +52,7 @@ define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
#ifdef _ALLBSD_SOURCE
define_pd_global(bool, UseMembar, true);
#else
define_pd_global(bool, UseMembar, false);
#endif
// GC Ergo Flags
define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
......
......@@ -3667,7 +3667,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
}
// initialize compiler(s)
#if defined(COMPILER1) || defined(COMPILER2)
#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK)
CompileBroker::compilation_init();
#endif
......
......@@ -35,6 +35,7 @@
#undef DEBUG
#endif
#include <llvm/Analysis/Verifier.h>
#include <llvm/Argument.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
......@@ -42,29 +43,21 @@
#include <llvm/Instructions.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
#if SHARK_LLVM_VERSION < 27
#include <llvm/ModuleProvider.h>
#endif
#if SHARK_LLVM_VERSION <= 31
#include <llvm/Support/IRBuilder.h>
#if SHARK_LLVM_VERSION >= 29
#include <llvm/Support/Threading.h>
#else
#include <llvm/System/Threading.h>
#include <llvm/IRBuilder.h>
#endif
#include <llvm/Target/TargetSelect.h>
#include <llvm/Support/Threading.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Type.h>
#include <llvm/ExecutionEngine/JITMemoryManager.h>
#include <llvm/Support/CommandLine.h>
#if SHARK_LLVM_VERSION >= 27
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ADT/StringMap.h>
#include <llvm/Support/Debug.h>
#if SHARK_LLVM_VERSION >= 29
#include <llvm/Support/Host.h>
#else
#include <llvm/System/Host.h>
#endif
#endif
#include <map>
......
......@@ -56,6 +56,10 @@ class LLVMValue : public AllStatic {
{
return llvm::ConstantPointerNull::get(SharkType::oop_type());
}
static llvm::ConstantPointerNull* nullKlass()
{
return llvm::ConstantPointerNull::get(SharkType::klass_type());
}
public:
static llvm::ConstantInt* bit_constant(int value)
......
......@@ -170,10 +170,12 @@ void SharkBlock::parse_bytecode(int start, int limit) {
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
push(SharkConstant::for_ldc(iter())->value(builder()));
case Bytecodes::_ldc2_w: {
SharkConstant* constant = SharkConstant::for_ldc(iter());
assert(constant->is_loaded(), "trap should handle unloaded classes");
push(constant->value(builder()));
break;
}
case Bytecodes::_iload_0:
case Bytecodes::_lload_0:
case Bytecodes::_fload_0:
......@@ -1000,9 +1002,9 @@ void SharkBlock::do_div_or_rem(bool is_long, bool is_rem) {
builder()->SetInsertPoint(done);
PHINode *result;
if (is_long)
result = builder()->CreatePHI(SharkType::jlong_type(), "result");
result = builder()->CreatePHI(SharkType::jlong_type(), 0, "result");
else
result = builder()->CreatePHI(SharkType::jint_type(), "result");
result = builder()->CreatePHI(SharkType::jint_type(), 0, "result");
result->addIncoming(special_result, special_case);
result->addIncoming(general_result, general_case);
......@@ -1036,12 +1038,12 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) {
value = constant->value(builder());
}
if (!is_get || value == NULL) {
if (!is_field)
object = builder()->CreateInlineOop(field->holder());
if (!is_field) {
object = builder()->CreateInlineOop(field->holder()->java_mirror());
}
BasicType basic_type = field->type()->basic_type();
const Type *stack_type = SharkType::to_stackType(basic_type);
const Type *field_type = SharkType::to_arrayType(basic_type);
Type *stack_type = SharkType::to_stackType(basic_type);
Type *field_type = SharkType::to_arrayType(basic_type);
Value *addr = builder()->CreateAddressOfStructEntry(
object, in_ByteSize(field->offset_in_bytes()),
......@@ -1050,8 +1052,12 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) {
// Do the access
if (is_get) {
Value *field_value = builder()->CreateLoad(addr);
Value* field_value;
if (field->is_volatile()) {
field_value = builder()->CreateAtomicLoad(addr);
} else {
field_value = builder()->CreateLoad(addr);
}
if (field_type != stack_type) {
field_value = builder()->CreateIntCast(
field_value, stack_type, basic_type != T_CHAR);
......@@ -1067,13 +1073,15 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) {
field_value, field_type, basic_type != T_CHAR);
}
builder()->CreateStore(field_value, addr);
if (field->is_volatile()) {
builder()->CreateAtomicStore(field_value, addr);
} else {
builder()->CreateStore(field_value, addr);
}
if (!field->type()->is_primitive_type())
if (!field->type()->is_primitive_type()) {
builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
if (field->is_volatile())
builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
}
}
}
......@@ -1105,7 +1113,7 @@ void SharkBlock::do_lcmp() {
builder()->CreateBr(done);
builder()->SetInsertPoint(done);
PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result");
result->addIncoming(LLVMValue::jint_constant(-1), lt);
result->addIncoming(LLVMValue::jint_constant(0), eq);
result->addIncoming(LLVMValue::jint_constant(1), gt);
......@@ -1152,7 +1160,7 @@ void SharkBlock::do_fcmp(bool is_double, bool unordered_is_greater) {
builder()->CreateBr(done);
builder()->SetInsertPoint(done);
PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result");
result->addIncoming(LLVMValue::jint_constant(-1), lt);
result->addIncoming(LLVMValue::jint_constant(0), eq);
result->addIncoming(LLVMValue::jint_constant(1), gt);
......
......@@ -47,14 +47,14 @@ SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer)
// Helpers for accessing structures
Value* SharkBuilder::CreateAddressOfStructEntry(Value* base,
ByteSize offset,
const Type* type,
Type* type,
const char* name) {
return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name);
}
LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base,
ByteSize offset,
const Type* type,
Type* type,
const char* name) {
return CreateLoad(
CreateAddressOfStructEntry(
......@@ -71,7 +71,7 @@ LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) {
}
Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,
const Type* element_type,
Type* element_type,
int element_bytes,
ByteSize base_offset,
Value* index,
......@@ -114,7 +114,7 @@ Value* SharkBuilder::CreateArrayAddress(Value* arrayoop,
// Helpers for creating intrinsics and external functions.
const Type* SharkBuilder::make_type(char type, bool void_ok) {
Type* SharkBuilder::make_type(char type, bool void_ok) {
switch (type) {
// Primitive types
case 'c':
......@@ -146,6 +146,8 @@ const Type* SharkBuilder::make_type(char type, bool void_ok) {
return PointerType::getUnqual(SharkType::monitor_type());
case 'O':
return SharkType::oop_type();
case 'K':
return SharkType::klass_type();
// Miscellaneous
case 'v':
......@@ -159,14 +161,14 @@ const Type* SharkBuilder::make_type(char type, bool void_ok) {
}
}
const FunctionType* SharkBuilder::make_ftype(const char* params,
FunctionType* SharkBuilder::make_ftype(const char* params,
const char* ret) {
std::vector<const Type*> param_types;
std::vector<Type*> param_types;
for (const char* c = params; *c; c++)
param_types.push_back(make_type(*c, false));
assert(strlen(ret) == 1, "should be");
const Type *return_type = make_type(*ret, true);
Type *return_type = make_type(*ret, true);
return FunctionType::get(return_type, param_types, false);
}
......@@ -274,7 +276,7 @@ Value* SharkBuilder::d2l() {
}
Value* SharkBuilder::is_subtype_of() {
return make_function((address) SharkRuntime::is_subtype_of, "OO", "c");
return make_function((address) SharkRuntime::is_subtype_of, "KK", "c");
}
Value* SharkBuilder::current_time_millis() {
......@@ -352,79 +354,14 @@ Value* SharkBuilder::check_special_condition_for_native_trans() {
"T", "v");
}
// Low-level non-VM calls
// The ARM-specific code here is to work around unimplemented
// atomic exchange and memory barrier intrinsics in LLVM.
//
// Delegating to external functions for these would normally
// incur a speed penalty, but Linux on ARM is a special case
// in that atomic operations on that platform are handled by
// external functions anyway. It would be *preferable* for
// the calls to be hidden away in LLVM, but it's not hurting
// performance so having the calls here is acceptable.
//
// If you are building Shark on a platform without atomic
// exchange and/or memory barrier intrinsics then it is only
// acceptable to mimic this approach if your platform cannot
// perform these operations without delegating to a function.
#ifdef ARM
static jint zero_cmpxchg_int(volatile jint *ptr, jint oldval, jint newval) {
return Atomic::cmpxchg(newval, ptr, oldval);
}
#endif // ARM
Value* SharkBuilder::cmpxchg_int() {
return make_function(
#ifdef ARM
(address) zero_cmpxchg_int,
#else
"llvm.atomic.cmp.swap.i32.p0i32",
#endif // ARM
"Iii", "i");
}
#ifdef ARM
static intptr_t zero_cmpxchg_ptr(volatile intptr_t* ptr,
intptr_t oldval,
intptr_t newval) {
return Atomic::cmpxchg_ptr(newval, ptr, oldval);
}
#endif // ARM
Value* SharkBuilder::cmpxchg_ptr() {
return make_function(
#ifdef ARM
(address) zero_cmpxchg_ptr,
#else
"llvm.atomic.cmp.swap.i" LP64_ONLY("64") NOT_LP64("32") ".p0i" LP64_ONLY("64") NOT_LP64("32"),
#endif // ARM
"Xxx", "x");
}
Value* SharkBuilder::frame_address() {
return make_function("llvm.frameaddress", "i", "C");
}
Value* SharkBuilder::memory_barrier() {
return make_function(
#ifdef ARM
(address) 0xffff0fa0, // __kernel_dmb
#else
"llvm.memory.barrier",
#endif // ARM
"11111", "v");
}
Value* SharkBuilder::memset() {
#if SHARK_LLVM_VERSION >= 28
// LLVM 2.8 added a fifth isVolatile field for memset
// introduced with LLVM r100304
return make_function("llvm.memset.i32", "Cciii", "v");
#else
return make_function("llvm.memset.i32", "Ccii", "v");
#endif
return make_function("llvm.memset.p0i8.i32", "Cciii", "v");
}
Value* SharkBuilder::unimplemented() {
......@@ -441,43 +378,16 @@ Value* SharkBuilder::dump() {
// Public interface to low-level non-VM calls
CallInst* SharkBuilder::CreateCmpxchgInt(Value* exchange_value,
Value* dst,
Value* compare_value) {
return CreateCall3(cmpxchg_int(), dst, compare_value, exchange_value);
}
CallInst* SharkBuilder::CreateCmpxchgPtr(Value* exchange_value,
Value* dst,
Value* compare_value) {
return CreateCall3(cmpxchg_ptr(), dst, compare_value, exchange_value);
}
CallInst* SharkBuilder::CreateGetFrameAddress() {
return CreateCall(frame_address(), LLVMValue::jint_constant(0));
}
CallInst *SharkBuilder::CreateMemoryBarrier(int flags) {
Value *args[] = {
LLVMValue::bit_constant((flags & BARRIER_LOADLOAD) ? 1 : 0),
LLVMValue::bit_constant((flags & BARRIER_LOADSTORE) ? 1 : 0),
LLVMValue::bit_constant((flags & BARRIER_STORELOAD) ? 1 : 0),
LLVMValue::bit_constant((flags & BARRIER_STORESTORE) ? 1 : 0),
LLVMValue::bit_constant(1)};
return CreateCall(memory_barrier(), args, args + 5);
}
CallInst* SharkBuilder::CreateMemset(Value* dst,
Value* value,
Value* len,
Value* align) {
#if SHARK_LLVM_VERSION >= 28
return CreateCall5(memset(), dst, value, len, align,
LLVMValue::jint_constant(0));
#else
return CreateCall4(memset(), dst, value, len, align);
#endif
}
CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) {
......@@ -510,11 +420,7 @@ CallInst* SharkBuilder::CreateDump(Value* value) {
if (isa<PointerType>(value->getType()))
value = CreatePtrToInt(value, SharkType::intptr_type());
else if (value->getType()->
#if SHARK_LLVM_VERSION >= 27
isIntegerTy()
#else
isInteger()
#endif
)
value = CreateIntCast(value, SharkType::intptr_type(), false);
else
......@@ -563,9 +469,19 @@ Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) {
name);
}
Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) {
assert(metadata != NULL, "inlined metadata must not be NULL");
assert(metadata->is_metadata(), "sanity check");
return CreateLoad(
CreateIntToPtr(
code_buffer_address(code_buffer()->inline_Metadata(metadata)),
PointerType::getUnqual(type)),
name);
}
Value* SharkBuilder::CreateInlineData(void* data,
size_t size,
const Type* type,
Type* type,
const char* name) {
return CreateIntToPtr(
code_buffer_address(code_buffer()->inline_data(data, size)),
......@@ -600,3 +516,11 @@ BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const {
return BasicBlock::Create(
SharkContext::current(), name, GetInsertBlock()->getParent(), ip);
}
LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name);
}
StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name);
}
......@@ -53,22 +53,37 @@ class SharkBuilder : public llvm::IRBuilder<> {
return _code_buffer;
}
public:
llvm::LoadInst* CreateAtomicLoad(llvm::Value* ptr,
unsigned align = HeapWordSize,
llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent,
llvm::SynchronizationScope synchScope = llvm::CrossThread,
bool isVolatile = true,
const char *name = "");
llvm::StoreInst* CreateAtomicStore(llvm::Value *val,
llvm::Value *ptr,
unsigned align = HeapWordSize,
llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent,
llvm::SynchronizationScope SynchScope = llvm::CrossThread,
bool isVolatile = true,
const char *name = "");
// Helpers for accessing structures.
public:
llvm::Value* CreateAddressOfStructEntry(llvm::Value* base,
ByteSize offset,
const llvm::Type* type,
llvm::Type* type,
const char *name = "");
llvm::LoadInst* CreateValueOfStructEntry(llvm::Value* base,
ByteSize offset,
const llvm::Type* type,
llvm::Type* type,
const char *name = "");
// Helpers for accessing arrays.
public:
llvm::LoadInst* CreateArrayLength(llvm::Value* arrayoop);
llvm::Value* CreateArrayAddress(llvm::Value* arrayoop,
const llvm::Type* element_type,
llvm::Type* element_type,
int element_bytes,
ByteSize base_offset,
llvm::Value* index,
......@@ -85,8 +100,8 @@ class SharkBuilder : public llvm::IRBuilder<> {
// Helpers for creating intrinsics and external functions.
private:
static const llvm::Type* make_type(char type, bool void_ok);
static const llvm::FunctionType* make_ftype(const char* params,
static llvm::Type* make_type(char type, bool void_ok);
static llvm::FunctionType* make_ftype(const char* params,
const char* ret);
llvm::Value* make_function(const char* name,
const char* params,
......@@ -165,7 +180,6 @@ class SharkBuilder : public llvm::IRBuilder<> {
llvm::Value* cmpxchg_int();
llvm::Value* cmpxchg_ptr();
llvm::Value* frame_address();
llvm::Value* memory_barrier();
llvm::Value* memset();
llvm::Value* unimplemented();
llvm::Value* should_not_reach_here();
......@@ -173,14 +187,7 @@ class SharkBuilder : public llvm::IRBuilder<> {
// Public interface to low-level non-VM calls.
public:
llvm::CallInst* CreateCmpxchgInt(llvm::Value* exchange_value,
llvm::Value* dst,
llvm::Value* compare_value);
llvm::CallInst* CreateCmpxchgPtr(llvm::Value* exchange_value,
llvm::Value* dst,
llvm::Value* compare_value);
llvm::CallInst* CreateGetFrameAddress();
llvm::CallInst* CreateMemoryBarrier(int flags);
llvm::CallInst* CreateMemset(llvm::Value* dst,
llvm::Value* value,
llvm::Value* len,
......@@ -189,15 +196,6 @@ class SharkBuilder : public llvm::IRBuilder<> {
llvm::CallInst* CreateShouldNotReachHere(const char* file, int line);
NOT_PRODUCT(llvm::CallInst* CreateDump(llvm::Value* value));
// Flags for CreateMemoryBarrier.
public:
enum BarrierFlags {
BARRIER_LOADLOAD = 1,
BARRIER_LOADSTORE = 2,
BARRIER_STORELOAD = 4,
BARRIER_STORESTORE = 8
};
// HotSpot memory barriers
public:
void CreateUpdateBarrierSet(BarrierSet* bs, llvm::Value* field);
......@@ -209,9 +207,14 @@ class SharkBuilder : public llvm::IRBuilder<> {
llvm::Value* CreateInlineOop(ciObject* object, const char* name = "") {
return CreateInlineOop(object->constant_encoding(), name);
}
llvm::Value* CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name = "");
llvm::Value* CreateInlineMetadata(ciMetadata* metadata, llvm::PointerType* type, const char* name = "") {
return CreateInlineMetadata(metadata->constant_encoding(), type, name);
}
llvm::Value* CreateInlineData(void* data,
size_t size,
const llvm::Type* type,
llvm::Type* type,
const char* name = "");
// Helpers for creating basic blocks.
......@@ -222,5 +225,4 @@ class SharkBuilder : public llvm::IRBuilder<> {
llvm::BasicBlock* CreateBlock(llvm::BasicBlock* ip,
const char* name="") const;
};
#endif // SHARE_VM_SHARK_SHARKBUILDER_HPP
#endif // SHARE_VM_SHARK_SHARKBUILDER_HPP
......@@ -107,11 +107,10 @@ void SharkDecacher::process_oop_tmp_slot(Value** value, int offset) {
void SharkDecacher::process_method_slot(Value** value, int offset) {
// Decache the method pointer
write_value_to_frame(
SharkType::Method*_type(),
SharkType::Method_type(),
*value,
offset);
oopmap()->set_oop(slot2reg(offset));
}
void SharkDecacher::process_pc_slot(int offset) {
......@@ -205,7 +204,7 @@ void SharkCacher::process_oop_tmp_slot(Value** value, int offset) {
void SharkCacher::process_method_slot(Value** value, int offset) {
// Cache the method pointer
*value = read_value_from_frame(SharkType::Method*_type(), offset);
*value = read_value_from_frame(SharkType::Method_type(), offset);
}
void SharkFunctionEntryCacher::process_method_slot(Value** value, int offset) {
......@@ -230,7 +229,7 @@ void SharkCacher::process_local_slot(int index,
}
Value* SharkOSREntryCacher::CreateAddressOfOSRBufEntry(int offset,
const Type* type) {
Type* type) {
Value *result = builder()->CreateStructGEP(osr_buf(), offset);
if (type != SharkType::intptr_type())
result = builder()->CreateBitCast(result, PointerType::getUnqual(type));
......@@ -254,12 +253,12 @@ void SharkOSREntryCacher::process_local_slot(int index,
}
}
void SharkDecacher::write_value_to_frame(const Type* type,
void SharkDecacher::write_value_to_frame(Type* type,
Value* value,
int offset) {
builder()->CreateStore(value, stack()->slot_addr(offset, type));
}
Value* SharkCacher::read_value_from_frame(const Type* type, int offset) {
Value* SharkCacher::read_value_from_frame(Type* type, int offset) {
return builder()->CreateLoad(stack()->slot_addr(offset, type));
}
......@@ -192,7 +192,7 @@ class SharkDecacher : public SharkCacherDecacher {
// Writer helper
protected:
void write_value_to_frame(const llvm::Type* type,
void write_value_to_frame(llvm::Type* type,
llvm::Value* value,
int offset);
};
......@@ -321,7 +321,7 @@ class SharkCacher : public SharkCacherDecacher {
// Writer helper
protected:
llvm::Value* read_value_from_frame(const llvm::Type* type, int offset);
llvm::Value* read_value_from_frame(llvm::Type* type, int offset);
};
class SharkJavaCallCacher : public SharkCacher {
......@@ -422,7 +422,7 @@ class SharkOSREntryCacher : public SharkFunctionEntryCacher {
// Helper
private:
llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type);
llvm::Value* CreateAddressOfOSRBufEntry(int offset, llvm::Type* type);
};
#endif // SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
......@@ -81,6 +81,13 @@ class SharkCodeBuffer : public StackObj {
return offset;
}
int inline_Metadata(Metadata* metadata) const {
masm()->align(BytesPerWord);
int offset = masm()->offset();
masm()->store_Metadata(metadata);
return offset;
}
// Inline a block of non-oop data into the buffer and return its offset.
public:
int inline_data(void *src, size_t size) const {
......
......@@ -48,7 +48,6 @@
using namespace llvm;
#if SHARK_LLVM_VERSION >= 27
namespace {
cl::opt<std::string>
MCPU("mcpu");
......@@ -57,7 +56,6 @@ namespace {
MAttrs("mattr",
cl::CommaSeparated);
}
#endif
SharkCompiler::SharkCompiler()
: AbstractCompiler() {
......@@ -72,6 +70,9 @@ SharkCompiler::SharkCompiler()
// Initialize the native target
InitializeNativeTarget();
// MCJIT require a native AsmPrinter
InitializeNativeTargetAsmPrinter();
// Create the two contexts which we'll use
_normal_context = new SharkContext("normal");
_native_context = new SharkContext("native");
......@@ -79,7 +80,6 @@ SharkCompiler::SharkCompiler()
// Create the memory manager
_memory_manager = new SharkMemoryManager();
#if SHARK_LLVM_VERSION >= 27
// Finetune LLVM for the current host CPU.
StringMap<bool> Features;
bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features);
......@@ -113,6 +113,16 @@ SharkCompiler::SharkCompiler()
builder.setJITMemoryManager(memory_manager());
builder.setEngineKind(EngineKind::JIT);
builder.setErrorStr(&ErrorMsg);
if (! fnmatch(SharkOptimizationLevel, "None", 0)) {
tty->print_cr("Shark optimization level set to: None");
builder.setOptLevel(llvm::CodeGenOpt::None);
} else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) {
tty->print_cr("Shark optimization level set to: Less");
builder.setOptLevel(llvm::CodeGenOpt::Less);
} else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) {
tty->print_cr("Shark optimization level set to: Aggressive");
builder.setOptLevel(llvm::CodeGenOpt::Aggressive);
} // else Default is selected by, well, default :-)
_execution_engine = builder.create();
if (!execution_engine()) {
......@@ -125,13 +135,6 @@ SharkCompiler::SharkCompiler()
execution_engine()->addModule(
_native_context->module());
#else
_execution_engine = ExecutionEngine::createJIT(
_normal_context->module_provider(),
NULL, memory_manager(), CodeGenOpt::Default);
execution_engine()->addModuleProvider(
_native_context->module_provider());
#endif
// All done
mark_initialized();
......@@ -261,6 +264,12 @@ void SharkCompiler::generate_native_code(SharkEntry* entry,
function->dump();
}
if (SharkVerifyFunction != NULL) {
if (!fnmatch(SharkVerifyFunction, name, 0)) {
verifyFunction(*function);
}
}
// Compile to native code
address code = NULL;
context()->add_function(function);
......@@ -268,33 +277,28 @@ void SharkCompiler::generate_native_code(SharkEntry* entry,
MutexLocker locker(execution_engine_lock());
free_queued_methods();
if (SharkPrintAsmOf != NULL) {
#if SHARK_LLVM_VERSION >= 27
#ifndef NDEBUG
#if SHARK_LLVM_VERSION <= 31
#define setCurrentDebugType SetCurrentDebugType
#endif
if (SharkPrintAsmOf != NULL) {
if (!fnmatch(SharkPrintAsmOf, name, 0)) {
llvm::SetCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
llvm::DebugFlag = true;
}
else {
llvm::SetCurrentDebugType("");
llvm::setCurrentDebugType("");
llvm::DebugFlag = false;
}
#endif // !NDEBUG
#else
// NB you need to patch LLVM with http://tinyurl.com/yf3baln for this
std::vector<const char*> args;
args.push_back(""); // program name
if (!fnmatch(SharkPrintAsmOf, name, 0))
args.push_back("-debug-only=x86-emitter");
else
args.push_back("-debug-only=none");
args.push_back(0); // terminator
cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]);
#endif // SHARK_LLVM_VERSION
}
#ifdef setCurrentDebugType
#undef setCurrentDebugType
#endif
#endif // !NDEBUG
memory_manager()->set_entry_for_function(function, entry);
code = (address) execution_engine()->getPointerToFunction(function);
}
assert(code != NULL, "code must be != NULL");
entry->set_entry_point(code);
entry->set_function(function);
entry->set_context(context());
......@@ -319,8 +323,8 @@ void SharkCompiler::free_compiled_method(address code) {
// finish with the exception of the VM thread, so we can consider
// ourself the owner of the execution engine lock even though we
// can't actually acquire it at this time.
assert(Thread::current()->is_VM_thread(), "must be called by VM thread");
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");
assert_locked_or_safepoint(CodeCache_lock);
SharkEntry *entry = (SharkEntry *) code;
entry->context()->push_to_free_queue(entry->function());
......
......@@ -37,10 +37,8 @@ SharkConstant* SharkConstant::for_ldc(ciBytecodeStream *iter) {
ciType *type = NULL;
if (constant.basic_type() == T_OBJECT) {
ciEnv *env = ciEnv::current();
if (constant.as_object()->is_klass())
type = env->Class_klass();
else
type = env->String_klass();
assert(constant.as_object()->klass() == env->String_klass() || constant.as_object()->klass() == env->Class_klass(), "should be");
type = constant.as_object()->klass();
}
return new SharkConstant(constant, type);
}
......@@ -108,17 +106,16 @@ SharkConstant::SharkConstant(ciConstant constant, ciType *type) {
// objects (which differ between ldc* and get*, thanks!)
ciObject *object = constant.as_object();
assert(type != NULL, "shouldn't be");
if (object->is_klass()) {
// The constant returned for a klass is the ciKlass
// for the entry, but we want the java_mirror.
ciKlass *klass = object->as_klass();
if (!klass->is_loaded()) {
if ((! object->is_null_object()) && object->klass() == ciEnv::current()->Class_klass()) {
ciKlass *klass = object->klass();
if (! klass->is_loaded()) {
_is_loaded = false;
return;
}
object = klass->java_mirror();
}
if (object->is_null_object() || !object->can_be_constant()) {
if (object->is_null_object() || ! object->can_be_constant() || ! object->is_loaded()) {
_is_loaded = false;
return;
}
......
......@@ -29,6 +29,7 @@
#include "shark/llvmHeaders.hpp"
#include "shark/sharkContext.hpp"
#include "utilities/globalDefinitions.hpp"
#include "memory/allocation.hpp"
using namespace llvm;
......@@ -52,6 +53,9 @@ SharkContext::SharkContext(const char* name)
_itableOffsetEntry_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), itableOffsetEntry::size() * wordSize));
_Metadata_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), sizeof(Metadata)));
_klass_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), sizeof(Klass)));
......@@ -61,7 +65,7 @@ SharkContext::SharkContext(const char* name)
_jniHandleBlock_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), sizeof(JNIHandleBlock)));
_Method*_type = PointerType::getUnqual(
_Method_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), sizeof(Method)));
_monitor_type = ArrayType::get(
......@@ -76,14 +80,14 @@ SharkContext::SharkContext(const char* name)
_zeroStack_type = PointerType::getUnqual(
ArrayType::get(jbyte_type(), sizeof(ZeroStack)));
std::vector<const Type*> params;
params.push_back(Method*_type());
std::vector<Type*> params;
params.push_back(Method_type());
params.push_back(intptr_type());
params.push_back(thread_type());
_entry_point_type = FunctionType::get(jint_type(), params, false);
params.clear();
params.push_back(Method*_type());
params.push_back(Method_type());
params.push_back(PointerType::getUnqual(jbyte_type()));
params.push_back(intptr_type());
params.push_back(thread_type());
......@@ -150,7 +154,7 @@ SharkContext::SharkContext(const char* name)
}
}
class SharkFreeQueueItem : public CHeapObj {
class SharkFreeQueueItem : public CHeapObj<mtNone> {
public:
SharkFreeQueueItem(llvm::Function* function, SharkFreeQueueItem *next)
: _function(function), _next(next) {}
......
......@@ -42,11 +42,7 @@ class SharkContext : public llvm::LLVMContext {
private:
llvm::Module* _module;
#if SHARK_LLVM_VERSION >= 27
public:
#else
private:
#endif
llvm::Module* module() const {
return _module;
}
......@@ -59,127 +55,126 @@ class SharkContext : public llvm::LLVMContext {
// Module accessors
public:
#if SHARK_LLVM_VERSION < 27
llvm::ModuleProvider* module_provider() const {
return new llvm::ExistingModuleProvider(module());
}
#endif
void add_function(llvm::Function* function) const {
module()->getFunctionList().push_back(function);
}
llvm::Constant* get_external(const char* name,
const llvm::FunctionType* sig) {
llvm::FunctionType* sig) {
return module()->getOrInsertFunction(name, sig);
}
// Basic types
private:
const llvm::Type* _void_type;
const llvm::IntegerType* _bit_type;
const llvm::IntegerType* _jbyte_type;
const llvm::IntegerType* _jshort_type;
const llvm::IntegerType* _jint_type;
const llvm::IntegerType* _jlong_type;
const llvm::Type* _jfloat_type;
const llvm::Type* _jdouble_type;
llvm::Type* _void_type;
llvm::IntegerType* _bit_type;
llvm::IntegerType* _jbyte_type;
llvm::IntegerType* _jshort_type;
llvm::IntegerType* _jint_type;
llvm::IntegerType* _jlong_type;
llvm::Type* _jfloat_type;
llvm::Type* _jdouble_type;
public:
const llvm::Type* void_type() const {
llvm::Type* void_type() const {
return _void_type;
}
const llvm::IntegerType* bit_type() const {
llvm::IntegerType* bit_type() const {
return _bit_type;
}
const llvm::IntegerType* jbyte_type() const {
llvm::IntegerType* jbyte_type() const {
return _jbyte_type;
}
const llvm::IntegerType* jshort_type() const {
llvm::IntegerType* jshort_type() const {
return _jshort_type;
}
const llvm::IntegerType* jint_type() const {
llvm::IntegerType* jint_type() const {
return _jint_type;
}
const llvm::IntegerType* jlong_type() const {
llvm::IntegerType* jlong_type() const {
return _jlong_type;
}
const llvm::Type* jfloat_type() const {
llvm::Type* jfloat_type() const {
return _jfloat_type;
}
const llvm::Type* jdouble_type() const {
llvm::Type* jdouble_type() const {
return _jdouble_type;
}
const llvm::IntegerType* intptr_type() const {
llvm::IntegerType* intptr_type() const {
return LP64_ONLY(jlong_type()) NOT_LP64(jint_type());
}
// Compound types
private:
const llvm::PointerType* _itableOffsetEntry_type;
const llvm::PointerType* _jniEnv_type;
const llvm::PointerType* _jniHandleBlock_type;
const llvm::PointerType* _klass_type;
const llvm::PointerType* _Method*_type;
const llvm::ArrayType* _monitor_type;
const llvm::PointerType* _oop_type;
const llvm::PointerType* _thread_type;
const llvm::PointerType* _zeroStack_type;
const llvm::FunctionType* _entry_point_type;
const llvm::FunctionType* _osr_entry_point_type;
llvm::PointerType* _itableOffsetEntry_type;
llvm::PointerType* _jniEnv_type;
llvm::PointerType* _jniHandleBlock_type;
llvm::PointerType* _Metadata_type;
llvm::PointerType* _klass_type;
llvm::PointerType* _Method_type;
llvm::ArrayType* _monitor_type;
llvm::PointerType* _oop_type;
llvm::PointerType* _thread_type;
llvm::PointerType* _zeroStack_type;
llvm::FunctionType* _entry_point_type;
llvm::FunctionType* _osr_entry_point_type;
public:
const llvm::PointerType* itableOffsetEntry_type() const {
llvm::PointerType* itableOffsetEntry_type() const {
return _itableOffsetEntry_type;
}
const llvm::PointerType* jniEnv_type() const {
llvm::PointerType* jniEnv_type() const {
return _jniEnv_type;
}
const llvm::PointerType* jniHandleBlock_type() const {
llvm::PointerType* jniHandleBlock_type() const {
return _jniHandleBlock_type;
}
const llvm::PointerType* klass_type() const {
llvm::PointerType* Metadata_type() const {
return _Metadata_type;
}
llvm::PointerType* klass_type() const {
return _klass_type;
}
const llvm::PointerType* Method*_type() const {
return _Method*_type;
llvm::PointerType* Method_type() const {
return _Method_type;
}
const llvm::ArrayType* monitor_type() const {
llvm::ArrayType* monitor_type() const {
return _monitor_type;
}
const llvm::PointerType* oop_type() const {
llvm::PointerType* oop_type() const {
return _oop_type;
}
const llvm::PointerType* thread_type() const {
llvm::PointerType* thread_type() const {
return _thread_type;
}
const llvm::PointerType* zeroStack_type() const {
llvm::PointerType* zeroStack_type() const {
return _zeroStack_type;
}
const llvm::FunctionType* entry_point_type() const {
llvm::FunctionType* entry_point_type() const {
return _entry_point_type;
}
const llvm::FunctionType* osr_entry_point_type() const {
llvm::FunctionType* osr_entry_point_type() const {
return _osr_entry_point_type;
}
// Mappings
private:
const llvm::Type* _to_stackType[T_CONFLICT];
const llvm::Type* _to_arrayType[T_CONFLICT];
llvm::Type* _to_stackType[T_CONFLICT];
llvm::Type* _to_arrayType[T_CONFLICT];
private:
const llvm::Type* map_type(const llvm::Type* const* table,
llvm::Type* map_type(llvm::Type* const* table,
BasicType type) const {
assert(type >= 0 && type < T_CONFLICT, "unhandled type");
const llvm::Type* result = table[type];
llvm::Type* result = table[type];
assert(result != NULL, "unhandled type");
return result;
}
public:
const llvm::Type* to_stackType(BasicType type) const {
llvm::Type* to_stackType(BasicType type) const {
return map_type(_to_stackType, type);
}
const llvm::Type* to_arrayType(BasicType type) const {
llvm::Type* to_arrayType(BasicType type) const {
return map_type(_to_arrayType, type);
}
......
......@@ -91,7 +91,7 @@ class SharkFunction : public SharkTargetInvariants {
bool is_osr() const {
return flow()->is_osr_flow();
}
const llvm::FunctionType* entry_point_type() const {
llvm::FunctionType* entry_point_type() const {
if (is_osr())
return SharkType::osr_entry_point_type();
else
......
......@@ -171,7 +171,7 @@ void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) {
builder()->CreateBr(done);
builder()->SetInsertPoint(done);
PHINode *phi = builder()->CreatePHI(a->getType(), "result");
PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result");
phi->addIncoming(a, return_a);
phi->addIncoming(b, return_b);
......@@ -210,7 +210,7 @@ void SharkIntrinsics::do_Object_getClass() {
Value *klass = builder()->CreateValueOfStructEntry(
state()->pop()->jobject_value(),
in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
SharkType::klass_type(),
"klass");
state()->push(
......@@ -265,8 +265,7 @@ void SharkIntrinsics::do_Unsafe_compareAndSwapInt() {
"addr");
// Perform the operation
Value *result = builder()->CreateCmpxchgInt(x, addr, e);
Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent);
// Push the result
state()->push(
SharkValue::create_jint(
......
......@@ -79,7 +79,6 @@ void SharkMemoryManager::setMemoryExecutable() {
mm()->setMemoryExecutable();
}
#if SHARK_LLVM_VERSION >= 27
void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
mm()->deallocateExceptionTable(ptr);
}
......@@ -87,26 +86,23 @@ void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
void SharkMemoryManager::deallocateFunctionBody(void *ptr) {
mm()->deallocateFunctionBody(ptr);
}
#else
void SharkMemoryManager::deallocateMemForFunction(const Function* F) {
return mm()->deallocateMemForFunction(F);
}
#endif
uint8_t* SharkMemoryManager::allocateGlobal(uintptr_t Size,
unsigned int Alignment) {
return mm()->allocateGlobal(Size, Alignment);
}
#if SHARK_LLVM_VERSION < 27
void* SharkMemoryManager::getDlsymTable() const {
return mm()->getDlsymTable();
void* SharkMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
return mm()->getPointerToNamedFunction(Name, AbortOnFailure);
}
uint8_t* SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
return mm()->allocateCodeSection(Size, Alignment, SectionID);
}
void SharkMemoryManager::SetDlsymTable(void *ptr) {
mm()->SetDlsymTable(ptr);
uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
return mm()->allocateDataSection(Size, Alignment, SectionID);
}
#endif
void SharkMemoryManager::setPoisonMemory(bool poison) {
mm()->setPoisonMemory(poison);
......
......@@ -75,20 +75,15 @@ class SharkMemoryManager : public llvm::JITMemoryManager {
unsigned char* TableStart,
unsigned char* TableEnd,
unsigned char* FrameRegister);
#if SHARK_LLVM_VERSION < 27
void* getDlsymTable() const;
void SetDlsymTable(void *ptr);
#endif
void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true);
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
void setPoisonMemory(bool);
uint8_t* allocateGlobal(uintptr_t, unsigned int);
void setMemoryWritable();
void setMemoryExecutable();
#if SHARK_LLVM_VERSION >= 27
void deallocateExceptionTable(void *ptr);
void deallocateFunctionBody(void *ptr);
#else
void deallocateMemForFunction(const llvm::Function* F);
#endif
unsigned char *allocateSpace(intptr_t Size,
unsigned int Alignment);
};
......
......@@ -59,7 +59,6 @@ void SharkNativeWrapper::initialize(const char *name) {
OopMap *oopmap = new OopMap(
SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
SharkStack::oopmap_slot_munge(arg_size()));
oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset()));
// Set up the oop_tmp slot if required:
// - For static methods we use it to handlize the class argument
......@@ -83,9 +82,9 @@ void SharkNativeWrapper::initialize(const char *name) {
}
// Start building the argument list
std::vector<const Type*> param_types;
std::vector<Type*> param_types;
std::vector<Value*> param_values;
const PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
// First argument is the JNIEnv
param_types.push_back(SharkType::jniEnv_type());
......@@ -149,7 +148,7 @@ void SharkNativeWrapper::initialize(const char *name) {
builder()->CreateBr(merge);
builder()->SetInsertPoint(merge);
phi = builder()->CreatePHI(box_type, "boxed_object");
phi = builder()->CreatePHI(box_type, 0, "boxed_object");
phi->addIncoming(ConstantPointerNull::get(box_type), null);
phi->addIncoming(box, not_null);
box = phi;
......@@ -170,7 +169,7 @@ void SharkNativeWrapper::initialize(const char *name) {
// fall through
default:
const Type *param_type = SharkType::to_stackType(arg_type(i));
Type *param_type = SharkType::to_stackType(arg_type(i));
param_types.push_back(param_type);
param_values.push_back(
......@@ -201,7 +200,7 @@ void SharkNativeWrapper::initialize(const char *name) {
// Make the call
BasicType result_type = target()->result_type();
const Type* return_type;
Type* return_type;
if (result_type == T_VOID)
return_type = SharkType::void_type();
else if (is_returning_oop())
......@@ -213,7 +212,7 @@ void SharkNativeWrapper::initialize(const char *name) {
PointerType::getUnqual(
FunctionType::get(return_type, param_types, false)));
Value *result = builder()->CreateCall(
native_function, param_values.begin(), param_values.end());
native_function, llvm::makeArrayRef(param_values));
// Start the transition back to _thread_in_Java
CreateSetThreadState(_thread_in_native_trans);
......@@ -221,7 +220,7 @@ void SharkNativeWrapper::initialize(const char *name) {
// Make sure new state is visible in the GC thread
if (os::is_MP()) {
if (UseMembar)
builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread);
else
CreateWriteMemorySerializePage();
}
......@@ -305,7 +304,7 @@ void SharkNativeWrapper::initialize(const char *name) {
builder()->CreateBr(merge);
builder()->SetInsertPoint(merge);
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "result");
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result");
phi->addIncoming(LLVMValue::null(), null);
phi->addIncoming(unboxed_result, not_null);
result = phi;
......
......@@ -75,7 +75,7 @@ void SharkStack::initialize(Value* method) {
_method_slot_offset = offset++;
if (setup_sp_and_method) {
builder()->CreateStore(
method, slot_addr(method_slot_offset(), SharkType::Method*_type()));
method, slot_addr(method_slot_offset(), SharkType::Method_type()));
}
// Unextended SP
......@@ -163,7 +163,7 @@ Value* SharkStack::CreatePopFrame(int result_slots) {
}
Value* SharkStack::slot_addr(int offset,
const Type* type,
Type* type,
const char* name) const {
bool needs_cast = type && type != SharkType::intptr_type();
......
......@@ -204,7 +204,7 @@ class SharkStack : public SharkCompileInvariants {
// Addresses of things in the frame
public:
llvm::Value* slot_addr(int offset,
const llvm::Type* type = NULL,
llvm::Type* type = NULL,
const char* name = "") const;
llvm::Value* monitor_addr(int index) const {
......
......@@ -131,7 +131,7 @@ void SharkState::merge(SharkState* other,
Value *this_method = this->method();
Value *other_method = other->method();
if (this_method != other_method) {
PHINode *phi = builder()->CreatePHI(SharkType::Method*_type(), "method");
PHINode *phi = builder()->CreatePHI(SharkType::Method_type(), 0, "method");
phi->addIncoming(this_method, this_block);
phi->addIncoming(other_method, other_block);
set_method(phi);
......@@ -142,7 +142,7 @@ void SharkState::merge(SharkState* other,
Value *other_oop_tmp = other->oop_tmp();
if (this_oop_tmp != other_oop_tmp) {
assert(this_oop_tmp && other_oop_tmp, "can't merge NULL with non-NULL");
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "oop_tmp");
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "oop_tmp");
phi->addIncoming(this_oop_tmp, this_block);
phi->addIncoming(other_oop_tmp, other_block);
set_oop_tmp(phi);
......@@ -243,7 +243,7 @@ SharkOSREntryState::SharkOSREntryState(SharkTopLevelBlock* block,
Value* method,
Value* osr_buf)
: SharkState(block) {
assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
assert(block->stack_depth_at_entry() == 0, "entry block shouldn't have stack");
set_num_monitors(block->ciblock()->monitor_count());
// Local variables
......@@ -287,7 +287,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
char name[18];
// Method
set_method(builder()->CreatePHI(SharkType::Method*_type(), "method"));
set_method(builder()->CreatePHI(SharkType::Method_type(), 0, "method"));
// Local variables
for (int i = 0; i < max_locals(); i++) {
......@@ -307,7 +307,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
case T_ARRAY:
snprintf(name, sizeof(name), "local_%d_", i);
value = SharkValue::create_phi(
type, builder()->CreatePHI(SharkType::to_stackType(type), name));
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
break;
case T_ADDRESS:
......@@ -345,7 +345,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
case T_ARRAY:
snprintf(name, sizeof(name), "stack_%d_", i);
value = SharkValue::create_phi(
type, builder()->CreatePHI(SharkType::to_stackType(type), name));
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
break;
case T_ADDRESS:
......
......@@ -65,6 +65,7 @@ void SharkTopLevelBlock::scan_for_traps() {
switch (bc()) {
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
if (!SharkConstant::for_ldc(iter())->is_loaded()) {
set_trap(
Deoptimization::make_trap_request(
......@@ -109,7 +110,8 @@ void SharkTopLevelBlock::scan_for_traps() {
case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
method = iter()->get_method(will_link);
ciSignature* sig;
method = iter()->get_method(will_link, &sig);
assert(will_link, "typeflow responsibility");
if (!method->holder()->is_linked()) {
......@@ -562,12 +564,12 @@ void SharkTopLevelBlock::marshal_exception_fast(int num_options) {
Value *exception_klass = builder()->CreateValueOfStructEntry(
xstack(0)->jobject_value(),
in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
SharkType::klass_type(),
"exception_klass");
for (int i = 0; i < num_options; i++) {
Value *check_klass =
builder()->CreateInlineOop(exc_handler(i)->catch_klass());
builder()->CreateInlineMetadata(exc_handler(i)->catch_klass(), SharkType::klass_type());
BasicBlock *not_exact = function()->CreateBlock("not_exact");
BasicBlock *not_subtype = function()->CreateBlock("not_subtype");
......@@ -823,7 +825,7 @@ void SharkTopLevelBlock::do_aload(BasicType basic_type) {
builder()->CreateArrayAddress(
array->jarray_value(), basic_type, index->jint_value()));
const Type *stack_type = SharkType::to_stackType(basic_type);
Type *stack_type = SharkType::to_stackType(basic_type);
if (value->getType() != stack_type)
value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR);
......@@ -910,7 +912,7 @@ void SharkTopLevelBlock::do_astore(BasicType basic_type) {
ShouldNotReachHere();
}
const Type *array_type = SharkType::to_arrayType(basic_type);
Type *array_type = SharkType::to_arrayType(basic_type);
if (value->getType() != array_type)
value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR);
......@@ -1102,9 +1104,9 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller,
Value *SharkTopLevelBlock::get_direct_callee(ciMethod* method) {
return builder()->CreateBitCast(
builder()->CreateInlineOop(method),
SharkType::Method*_type(),
"callee");
builder()->CreateInlineMetadata(method, SharkType::Method_type()),
SharkType::Method_type(),
"callee");
}
Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver,
......@@ -1118,7 +1120,7 @@ Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver,
return builder()->CreateLoad(
builder()->CreateArrayAddress(
klass,
SharkType::Method*_type(),
SharkType::Method_type(),
vtableEntry::size() * wordSize,
in_ByteSize(InstanceKlass::vtable_start_offset() * wordSize),
LLVMValue::intptr_constant(vtable_index)),
......@@ -1136,7 +1138,7 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver,
// Locate the receiver's itable
Value *object_klass = builder()->CreateValueOfStructEntry(
receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
SharkType::klass_type(),
"object_klass");
Value *vtable_start = builder()->CreateAdd(
......@@ -1169,12 +1171,12 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver,
}
// Locate this interface's entry in the table
Value *iklass = builder()->CreateInlineOop(method->holder());
Value *iklass = builder()->CreateInlineMetadata(method->holder(), SharkType::klass_type());
BasicBlock *loop_entry = builder()->GetInsertBlock();
builder()->CreateBr(loop);
builder()->SetInsertPoint(loop);
PHINode *itable_entry_addr = builder()->CreatePHI(
SharkType::intptr_type(), "itable_entry_addr");
SharkType::intptr_type(), 0, "itable_entry_addr");
itable_entry_addr->addIncoming(itable_start, loop_entry);
Value *itable_entry = builder()->CreateIntToPtr(
......@@ -1183,11 +1185,11 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver,
Value *itable_iklass = builder()->CreateValueOfStructEntry(
itable_entry,
in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()),
SharkType::oop_type(),
SharkType::klass_type(),
"itable_iklass");
builder()->CreateCondBr(
builder()->CreateICmpEQ(itable_iklass, LLVMValue::null()),
builder()->CreateICmpEQ(itable_iklass, LLVMValue::nullKlass()),
got_null, not_null);
// A null entry means that the class doesn't implement the
......@@ -1231,7 +1233,7 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver,
method->itable_index() * itableMethodEntry::size() * wordSize)),
LLVMValue::intptr_constant(
itableMethodEntry::method_offset_in_bytes())),
PointerType::getUnqual(SharkType::Method*_type())),
PointerType::getUnqual(SharkType::Method_type())),
"callee");
}
......@@ -1243,7 +1245,9 @@ void SharkTopLevelBlock::do_call() {
// Find the method being called
bool will_link;
ciMethod *dest_method = iter()->get_method(will_link);
ciSignature* sig;
ciMethod *dest_method = iter()->get_method(will_link, &sig);
assert(will_link, "typeflow responsibility");
assert(dest_method->is_static() == is_static, "must match bc");
......@@ -1259,10 +1263,17 @@ void SharkTopLevelBlock::do_call() {
assert(holder_klass->is_interface() ||
holder_klass->super() == NULL ||
!is_interface, "must match bc");
bool is_forced_virtual = is_interface && holder_klass == java_lang_Object_klass();
ciKlass *holder = iter()->get_declared_method_holder();
ciInstanceKlass *klass =
ciEnv::get_instance_klass_for_declared_method_holder(holder);
if (is_forced_virtual) {
klass = java_lang_Object_klass();
}
// Find the receiver in the stack. We do this before
// trying to inline because the inliner can only use
// zero-checked values, not being able to perform the
......@@ -1294,7 +1305,7 @@ void SharkTopLevelBlock::do_call() {
// Find the method we are calling
Value *callee;
if (call_is_virtual) {
if (is_virtual) {
if (is_virtual || is_forced_virtual) {
assert(klass->is_linked(), "scan_for_traps responsibility");
int vtable_index = call_method->resolve_vtable_index(
target()->holder(), klass);
......@@ -1490,12 +1501,12 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) {
// Get the class we're checking against
builder()->SetInsertPoint(not_null);
Value *check_klass = builder()->CreateInlineOop(klass);
Value *check_klass = builder()->CreateInlineMetadata(klass, SharkType::klass_type());
// Get the class of the object being tested
Value *object_klass = builder()->CreateValueOfStructEntry(
object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
SharkType::klass_type(),
"object_klass");
// Perform the check
......@@ -1520,7 +1531,7 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) {
// First merge
builder()->SetInsertPoint(merge1);
PHINode *nonnull_result = builder()->CreatePHI(
SharkType::jint_type(), "nonnull_result");
SharkType::jint_type(), 0, "nonnull_result");
nonnull_result->addIncoming(
LLVMValue::jint_constant(IC_IS_INSTANCE), is_instance);
nonnull_result->addIncoming(
......@@ -1531,7 +1542,7 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) {
// Second merge
builder()->SetInsertPoint(merge2);
PHINode *result = builder()->CreatePHI(
SharkType::jint_type(), "result");
SharkType::jint_type(), 0, "result");
result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block);
result->addIncoming(nonnull_result, nonnull_block);
......@@ -1698,7 +1709,7 @@ void SharkTopLevelBlock::do_new() {
heap_object = builder()->CreateIntToPtr(
old_top, SharkType::oop_type(), "heap_object");
Value *check = builder()->CreateCmpxchgPtr(new_top, top_addr, old_top);
Value *check = builder()->CreateAtomicCmpXchg(top_addr, old_top, new_top, llvm::SequentiallyConsistent);
builder()->CreateCondBr(
builder()->CreateICmpEQ(old_top, check),
initialize, retry);
......@@ -1707,7 +1718,7 @@ void SharkTopLevelBlock::do_new() {
builder()->SetInsertPoint(initialize);
if (tlab_object) {
PHINode *phi = builder()->CreatePHI(
SharkType::oop_type(), "fast_object");
SharkType::oop_type(), 0, "fast_object");
phi->addIncoming(tlab_object, got_tlab);
phi->addIncoming(heap_object, got_heap);
fast_object = phi;
......@@ -1730,7 +1741,7 @@ void SharkTopLevelBlock::do_new() {
Value *klass_addr = builder()->CreateAddressOfStructEntry(
fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
PointerType::getUnqual(SharkType::oop_type()),
PointerType::getUnqual(SharkType::klass_type()),
"klass_addr");
// Set the mark
......@@ -1744,7 +1755,7 @@ void SharkTopLevelBlock::do_new() {
builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr);
// Set the class
Value *rtklass = builder()->CreateInlineOop(klass);
Value *rtklass = builder()->CreateInlineMetadata(klass, SharkType::klass_type());
builder()->CreateStore(rtklass, klass_addr);
got_fast = builder()->GetInsertBlock();
......@@ -1767,7 +1778,7 @@ void SharkTopLevelBlock::do_new() {
builder()->SetInsertPoint(push_object);
}
if (fast_object) {
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "object");
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "object");
phi->addIncoming(fast_object, got_fast);
phi->addIncoming(slow_object, got_slow);
object = phi;
......@@ -1849,8 +1860,9 @@ void SharkTopLevelBlock::do_multianewarray() {
void SharkTopLevelBlock::acquire_method_lock() {
Value *lockee;
if (target()->is_static())
if (target()->is_static()) {
lockee = builder()->CreateInlineOop(target()->holder()->java_mirror());
}
else
lockee = local(0)->jobject_value();
......@@ -1898,7 +1910,7 @@ void SharkTopLevelBlock::acquire_lock(Value *lockee, int exception_action) {
Value *lock = builder()->CreatePtrToInt(
monitor_header_addr, SharkType::intptr_type());
Value *check = builder()->CreateCmpxchgPtr(lock, mark_addr, disp);
Value *check = builder()->CreateAtomicCmpXchg(mark_addr, disp, lock, llvm::Acquire);
builder()->CreateCondBr(
builder()->CreateICmpEQ(disp, check),
acquired_fast, try_recursive);
......@@ -1983,7 +1995,7 @@ void SharkTopLevelBlock::release_lock(int exception_action) {
PointerType::getUnqual(SharkType::intptr_type()),
"mark_addr");
Value *check = builder()->CreateCmpxchgPtr(disp, mark_addr, lock);
Value *check = builder()->CreateAtomicCmpXchg(mark_addr, lock, disp, llvm::Release);
builder()->CreateCondBr(
builder()->CreateICmpEQ(lock, check),
released_fast, slow_path);
......
......@@ -290,7 +290,7 @@ class SharkTopLevelBlock : public SharkBlock {
int exception_action) {
decache_for_VM_call();
stack()->CreateSetLastJavaFrame();
llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end);
llvm::CallInst *res = builder()->CreateCall(callee, llvm::makeArrayRef(args_start, args_end));
stack()->CreateResetLastJavaFrame();
cache_after_VM_call();
if (exception_action & EAM_CHECK) {
......
......@@ -40,82 +40,85 @@ class SharkType : public AllStatic {
// Basic types
public:
static const llvm::Type* void_type() {
static llvm::Type* void_type() {
return context().void_type();
}
static const llvm::IntegerType* bit_type() {
static llvm::IntegerType* bit_type() {
return context().bit_type();
}
static const llvm::IntegerType* jbyte_type() {
static llvm::IntegerType* jbyte_type() {
return context().jbyte_type();
}
static const llvm::IntegerType* jshort_type() {
static llvm::IntegerType* jshort_type() {
return context().jshort_type();
}
static const llvm::IntegerType* jint_type() {
static llvm::IntegerType* jint_type() {
return context().jint_type();
}
static const llvm::IntegerType* jlong_type() {
static llvm::IntegerType* jlong_type() {
return context().jlong_type();
}
static const llvm::Type* jfloat_type() {
static llvm::Type* jfloat_type() {
return context().jfloat_type();
}
static const llvm::Type* jdouble_type() {
static llvm::Type* jdouble_type() {
return context().jdouble_type();
}
static const llvm::IntegerType* intptr_type() {
static llvm::IntegerType* intptr_type() {
return context().intptr_type();
}
// Compound types
public:
static const llvm::PointerType* itableOffsetEntry_type() {
static llvm::PointerType* itableOffsetEntry_type() {
return context().itableOffsetEntry_type();
}
static const llvm::PointerType* jniEnv_type() {
static llvm::PointerType* jniEnv_type() {
return context().jniEnv_type();
}
static const llvm::PointerType* jniHandleBlock_type() {
static llvm::PointerType* jniHandleBlock_type() {
return context().jniHandleBlock_type();
}
static const llvm::PointerType* klass_type() {
static llvm::PointerType* Metadata_type() {
return context().Metadata_type();
}
static llvm::PointerType* klass_type() {
return context().klass_type();
}
static const llvm::PointerType* Method*_type() {
return context().Method*_type();
static llvm::PointerType* Method_type() {
return context().Method_type();
}
static const llvm::ArrayType* monitor_type() {
static llvm::ArrayType* monitor_type() {
return context().monitor_type();
}
static const llvm::PointerType* oop_type() {
static llvm::PointerType* oop_type() {
return context().oop_type();
}
static const llvm::PointerType* thread_type() {
static llvm::PointerType* thread_type() {
return context().thread_type();
}
static const llvm::PointerType* zeroStack_type() {
static llvm::PointerType* zeroStack_type() {
return context().zeroStack_type();
}
static const llvm::FunctionType* entry_point_type() {
static llvm::FunctionType* entry_point_type() {
return context().entry_point_type();
}
static const llvm::FunctionType* osr_entry_point_type() {
static llvm::FunctionType* osr_entry_point_type() {
return context().osr_entry_point_type();
}
// Mappings
public:
static const llvm::Type* to_stackType(BasicType type) {
static llvm::Type* to_stackType(BasicType type) {
return context().to_stackType(type);
}
static const llvm::Type* to_stackType(ciType* type) {
static llvm::Type* to_stackType(ciType* type) {
return to_stackType(type->basic_type());
}
static const llvm::Type* to_arrayType(BasicType type) {
static llvm::Type* to_arrayType(BasicType type) {
return context().to_arrayType(type);
}
static const llvm::Type* to_arrayType(ciType* type) {
static llvm::Type* to_arrayType(ciType* type) {
return to_arrayType(type->basic_type());
}
};
......
......@@ -233,7 +233,7 @@ SharkValue* SharkNormalValue::merge(SharkBuilder* builder,
assert(type() == other->type(), "should be");
assert(zero_checked() == other->zero_checked(), "should be");
PHINode *phi = builder->CreatePHI(SharkType::to_stackType(type()), name);
PHINode *phi = builder->CreatePHI(SharkType::to_stackType(type()), 0, name);
phi->addIncoming(this->generic_value(), this_block);
phi->addIncoming(other->generic_value(), other_block);
return SharkValue::create_generic(type(), phi, zero_checked());
......
......@@ -40,6 +40,12 @@
product(intx, SharkMaxInlineSize, 32, \
"Maximum bytecode size of methods to inline when using Shark") \
\
product(bool, EliminateNestedLocks, true, \
"Eliminate nested locks of the same object when possible") \
\
product(ccstr, SharkOptimizationLevel, "Default", \
"The optimization level passed to LLVM, possible values: None, Less, Default and Agressive") \
\
/* compiler debugging */ \
develop(ccstr, SharkPrintTypeflowOf, NULL, \
"Print the typeflow of the specified method") \
......@@ -58,6 +64,10 @@
\
diagnostic(bool, SharkPerformanceWarnings, false, \
"Warn about things that could be made faster") \
\
develop(ccstr, SharkVerifyFunction, NULL, \
"Runs LLVM verify over LLVM IR") \
SHARK_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册