case Bytecodes::_lload_0:
case Bytecodes::_dload_0:
push_pair_local(0);
break;
case Bytecodes::_iload_1:
case Bytecodes::_fload_1:
case Bytecodes::_aload_1:
push(local(1));
break;
case Bytecodes::_lload_1:
case Bytecodes::_dload_1:
push_pair_local(1);
break;
case Bytecodes::_iload_2:
case Bytecodes::_fload_2:
case Bytecodes::_aload_2:
push(local(2));
break;
case Bytecodes::_lload_2:
case Bytecodes::_dload_2:
push_pair_local(2);
break;
case Bytecodes::_iload_3:
case Bytecodes::_fload_3:
case Bytecodes::_aload_3:
push(local(3));
break;
case Bytecodes::_lload_3:
case Bytecodes::_dload_3:
push_pair_local(3);
break;
case Bytecodes::_iload:
case Bytecodes::_fload:
case Bytecodes::_aload:
push(local(iter()->get_index()));
break;
case Bytecodes::_lload:
case Bytecodes::_dload:
push_pair_local(iter()->get_index());
break;
case Bytecodes::_istore_0:
case Bytecodes::_fstore_0:
case Bytecodes::_astore_0:
set_local(0, pop());
break;
case Bytecodes::_lstore_0:
case Bytecodes::_dstore_0:
pop_pair_local(0);
break;
case Bytecodes::_istore_1:
case Bytecodes::_fstore_1:
case Bytecodes::_astore_1:
set_local(1, pop());
break;
case Bytecodes::_lstore_1:
case Bytecodes::_dstore_1:
pop_pair_local(1);
break;
case Bytecodes::_istore_2:
case Bytecodes::_fstore_2:
case Bytecodes::_astore_2:
set_local(2, pop());
break;
case Bytecodes::_lstore_2:
case Bytecodes::_dstore_2:
pop_pair_local(2);
break;
case Bytecodes::_istore_3:
case Bytecodes::_fstore_3:
case Bytecodes::_astore_3:
set_local(3, pop());
break;
case Bytecodes::_lstore_3:
case Bytecodes::_dstore_3:
pop_pair_local(3);
break;
case Bytecodes::_istore:
case Bytecodes::_fstore:
case Bytecodes::_astore:
set_local(iter()->get_index(), pop());
break;
case Bytecodes::_lstore:
case Bytecodes::_dstore:
pop_pair_local(iter()->get_index());
break;
case Bytecodes::_pop:
pop();
break;
case Bytecodes::_pop2:
pop();
pop();
break;
case Bytecodes::_swap:
a = pop();
b = pop();
push(a);
push(b);
break;
case Bytecodes::_dup:
a = pop();
push(a);
push(a);
break;
case Bytecodes::_dup_x1:
a = pop();
b = pop();
push(a);
push(b);
push(a);
break;
case Bytecodes::_dup_x2:
a = pop();
b = pop();
c = pop();
push(a);
push(c);
push(b);
push(a);
break;
case Bytecodes::_dup2:
a = pop();
b = pop();
push(b);
push(a);
push(b);
push(a);
break;
case Bytecodes::_dup2_x1:
a = pop();
b = pop();
c = pop();
push(b);
push(a);
push(c);
push(b);
push(a);
break;
case Bytecodes::_dup2_x2:
a = pop();
b = pop();
c = pop();
d = pop();
push(b);
push(a);
push(d);
push(c);
push(b);
push(a);
break;
case Bytecodes::_getfield:
if (!do_getfield())
return false;
break;
case Bytecodes::_getstatic:
if (!do_getstatic())
return false;
break;
case Bytecodes::_putfield:
if (!do_putfield())
return false;
break;
case Bytecodes::_iadd:
case Bytecodes::_isub:
case Bytecodes::_imul:
case Bytecodes::_iand:
case Bytecodes::_ixor:
case Bytecodes::_ishl:
case Bytecodes::_ishr:
case Bytecodes::_iushr:
pop();
pop();
push(false);
break;
case Bytecodes::_ior:
a = pop();
b = pop();
push(a && b);
break;
case Bytecodes::_idiv:
case Bytecodes::_irem:
if (!pop())
return false;
pop();
push(false);
break;
case Bytecodes::_ineg:
break;
case Bytecodes::_ladd:
case Bytecodes::_lsub:
case Bytecodes::_lmul:
case Bytecodes::_land:
case Bytecodes::_lxor:
pop();
pop();
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_lor:
a = pop();
b = pop();
push(a && b);
break;
case Bytecodes::_ldiv:
case Bytecodes::_lrem:
pop();
if (!pop())
return false;
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_lneg:
break;
case Bytecodes::_lshl:
case Bytecodes::_lshr:
case Bytecodes::_lushr:
pop();
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_fadd:
case Bytecodes::_fsub:
case Bytecodes::_fmul:
case Bytecodes::_fdiv:
case Bytecodes::_frem:
pop();
pop();
push(false);
break;
case Bytecodes::_fneg:
break;
case Bytecodes::_dadd:
case Bytecodes::_dsub:
case Bytecodes::_dmul:
case Bytecodes::_ddiv:
case Bytecodes::_drem:
pop();
pop();
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_dneg:
break;
case Bytecodes::_iinc:
set_local(iter()->get_index(), false);
break;
case Bytecodes::_lcmp:
pop();
pop();
pop();
pop();
push(false);
break;
case Bytecodes::_fcmpl:
case Bytecodes::_fcmpg:
pop();
pop();
push(false);
break;
case Bytecodes::_dcmpl:
case Bytecodes::_dcmpg:
pop();
pop();
pop();
pop();
push(false);
break;
case Bytecodes::_i2l:
push(false);
break;
case Bytecodes::_i2f:
pop();
push(false);
break;
case Bytecodes::_i2d:
pop();
push(false);
push(false);
break;
case Bytecodes::_l2i:
case Bytecodes::_l2f:
pop();
pop();
push(false);
break;
case Bytecodes::_l2d:
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_f2i:
pop();
push(false);
break;
case Bytecodes::_f2l:
case Bytecodes::_f2d:
pop();
push(false);
push(false);
break;
case Bytecodes::_d2i:
case Bytecodes::_d2f:
pop();
pop();
push(false);
break;
case Bytecodes::_d2l:
pop();
pop();
push(false);
push(false);
break;
case Bytecodes::_i2b:
case Bytecodes::_i2c:
case Bytecodes::_i2s:
pop();
push(false);
break;
case Bytecodes::_return:
case Bytecodes::_ireturn:
case Bytecodes::_lreturn:
case Bytecodes::_freturn:
case Bytecodes::_dreturn:
case Bytecodes::_areturn:
break;
default:
return false;
}
}
return true;
}
void SharkInlinerHelper::initialize_for_check() {
_locals = NEW_RESOURCE_ARRAY(bool, max_locals());
_stack = NEW_RESOURCE_ARRAY(bool, max_stack());
memset(_locals, 0, max_locals() * sizeof(bool));
for (int i = 0; i < target()->arg_size(); i++) {
SharkValue *arg = entry_state()->stack(target()->arg_size() - 1 - i);
if (arg && arg->zero_checked())
set_local(i, true);
}
_sp = _stack;
}
bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field) {
assert(is_get || is_field, "can't inline putstatic");
if (!target()->holder()->is_linked())
return false;
bool will_link;
ciField *field = iter()->get_field(will_link);
if (!will_link)
return false;
if (is_field == field->is_static())
return false;
if (!is_get) {
pop();
if (field->type()->is_two_word())
pop();
}
if (is_field) {
if (!pop())
return false;
}
if (is_get) {
bool result_pushed = false;
if (field->is_constant() && field->is_static()) {
SharkConstant *sc = SharkConstant::for_field(iter());
if (sc->is_loaded()) {
push(sc->is_nonzero());
result_pushed = true;
}
}
if (!result_pushed)
push(false);
if (field->type()->is_two_word())
push(false);
}
return true;
}
bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state) {
if (SharkIntrinsics::is_intrinsic(target)) {
SharkIntrinsics::inline_intrinsic(target, state);
return true;
}
if (may_be_inlinable(target)) {
SharkInlinerHelper inliner(target, state);
if (inliner.is_inlinable()) {
inliner.do_inline();
return true;
}
}
return false;
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkInliner.hpp
#ifndef SHARE_VM_SHARK_SHARKINLINER_HPP
#define SHARE_VM_SHARK_SHARKINLINER_HPP
#include "ci/ciMethod.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkState.hpp"
class SharkInliner : public AllStatic {
public:
static bool attempt_inline(ciMethod* target, SharkState* state);
private:
static bool may_be_inlinable(ciMethod* target);
};
#endif // SHARE_VM_SHARK_SHARKINLINER_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkIntrinsics.cpp
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkIntrinsics.hpp"
#include "shark/sharkState.hpp"
#include "shark/sharkValue.hpp"
#include "shark/shark_globals.hpp"
using namespace llvm;
bool SharkIntrinsics::is_intrinsic(ciMethod *target) {
switch (target->intrinsic_id()) {
case vmIntrinsics::_none:
return false;
case vmIntrinsics::_min:
case vmIntrinsics::_max:
case vmIntrinsics::_dabs:
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
case vmIntrinsics::_datan2:
case vmIntrinsics::_dsqrt:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dpow:
case vmIntrinsics::_dexp:
return true;
case vmIntrinsics::_getClass:
return true;
case vmIntrinsics::_currentTimeMillis:
return true;
case vmIntrinsics::_currentThread:
return true;
case vmIntrinsics::_compareAndSwapInt:
return true;
default:
if (SharkPerformanceWarnings) {
warning(
"unhandled intrinsic vmIntrinsic::%s",
vmIntrinsics::name_at(target->intrinsic_id()));
}
}
return false;
}
void SharkIntrinsics::inline_intrinsic(ciMethod *target, SharkState *state) {
SharkIntrinsics intrinsic(state, target);
intrinsic.do_intrinsic();
}
void SharkIntrinsics::do_intrinsic() {
switch (target()->intrinsic_id()) {
case vmIntrinsics::_min:
do_Math_minmax(llvm::ICmpInst::ICMP_SLE);
break;
case vmIntrinsics::_max:
do_Math_minmax(llvm::ICmpInst::ICMP_SGE);
break;
case vmIntrinsics::_dabs:
do_Math_1to1(builder()->fabs());
break;
case vmIntrinsics::_dsin:
do_Math_1to1(builder()->sin());
break;
case vmIntrinsics::_dcos:
do_Math_1to1(builder()->cos());
break;
case vmIntrinsics::_dtan:
do_Math_1to1(builder()->tan());
break;
case vmIntrinsics::_datan2:
do_Math_2to1(builder()->atan2());
break;
case vmIntrinsics::_dsqrt:
do_Math_1to1(builder()->sqrt());
break;
case vmIntrinsics::_dlog:
do_Math_1to1(builder()->log());
break;
case vmIntrinsics::_dlog10:
do_Math_1to1(builder()->log10());
break;
case vmIntrinsics::_dpow:
do_Math_2to1(builder()->pow());
break;
case vmIntrinsics::_dexp:
do_Math_1to1(builder()->exp());
break;
case vmIntrinsics::_getClass:
do_Object_getClass();
break;
case vmIntrinsics::_currentTimeMillis:
do_System_currentTimeMillis();
break;
case vmIntrinsics::_currentThread:
do_Thread_currentThread();
break;
case vmIntrinsics::_compareAndSwapInt:
do_Unsafe_compareAndSwapInt();
break;
default:
ShouldNotReachHere();
}
}
void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) {
SharkValue *sb = state()->pop();
SharkValue *sa = state()->pop();
Value *a = sa->jint_value();
Value *b = sb->jint_value();
BasicBlock *ip = builder()->GetBlockInsertionPoint();
BasicBlock *return_a = builder()->CreateBlock(ip, "return_a");
BasicBlock *return_b = builder()->CreateBlock(ip, "return_b");
BasicBlock *done = builder()->CreateBlock(ip, "done");
builder()->CreateCondBr(builder()->CreateICmp(p, a, b), return_a, return_b);
builder()->SetInsertPoint(return_a);
builder()->CreateBr(done);
builder()->SetInsertPoint(return_b);
builder()->CreateBr(done);
builder()->SetInsertPoint(done);
PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result");
phi->addIncoming(a, return_a);
phi->addIncoming(b, return_b);
state()->push(
SharkValue::create_jint(
phi,
sa->zero_checked() && sb->zero_checked()));
}
void SharkIntrinsics::do_Math_1to1(Value *function) {
SharkValue *empty = state()->pop();
assert(empty == NULL, "should be");
state()->push(
SharkValue::create_jdouble(
builder()->CreateCall(
function, state()->pop()->jdouble_value())));
state()->push(NULL);
}
void SharkIntrinsics::do_Math_2to1(Value *function) {
SharkValue *empty = state()->pop();
assert(empty == NULL, "should be");
Value *y = state()->pop()->jdouble_value();
empty = state()->pop();
assert(empty == NULL, "should be");
Value *x = state()->pop()->jdouble_value();
state()->push(
SharkValue::create_jdouble(
builder()->CreateCall2(function, x, y)));
state()->push(NULL);
}
void SharkIntrinsics::do_Object_getClass() {
Value *klass = builder()->CreateValueOfStructEntry(
state()->pop()->jobject_value(),
in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::klass_type(),
"klass");
state()->push(
SharkValue::create_jobject(
builder()->CreateValueOfStructEntry(
klass,
Klass::java_mirror_offset(),
SharkType::oop_type(),
"java_mirror"),
true));
}
void SharkIntrinsics::do_System_currentTimeMillis() {
state()->push(
SharkValue::create_jlong(
builder()->CreateCall(builder()->current_time_millis()),
false));
state()->push(NULL);
}
void SharkIntrinsics::do_Thread_currentThread() {
state()->push(
SharkValue::create_jobject(
builder()->CreateValueOfStructEntry(
thread(), JavaThread::threadObj_offset(),
SharkType::oop_type(),
"threadObj"),
true));
}
void SharkIntrinsics::do_Unsafe_compareAndSwapInt() {
Value *x = state()->pop()->jint_value();
Value *e = state()->pop()->jint_value();
SharkValue *empty = state()->pop();
assert(empty == NULL, "should be");
Value *offset = state()->pop()->jlong_value();
Value *object = state()->pop()->jobject_value();
Value *unsafe = state()->pop()->jobject_value();
offset = builder()->CreateCall(
builder()->unsafe_field_offset_to_byte_offset(),
offset);
Value *addr = builder()->CreateIntToPtr(
builder()->CreateAdd(
builder()->CreatePtrToInt(object, SharkType::intptr_type()),
builder()->CreateIntCast(offset, SharkType::intptr_type(), true)),
PointerType::getUnqual(SharkType::jint_type()),
"addr");
Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent);
state()->push(
SharkValue::create_jint(
builder()->CreateIntCast(
builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true),
false));
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkIntrinsics.hpp
#ifndef SHARE_VM_SHARK_SHARKINTRINSICS_HPP
#define SHARE_VM_SHARK_SHARKINTRINSICS_HPP
#include "ci/ciMethod.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkState.hpp"
class SharkIntrinsics : public SharkTargetInvariants {
public:
static bool is_intrinsic(ciMethod* target);
static void inline_intrinsic(ciMethod* target, SharkState* state);
private:
SharkIntrinsics(SharkState* state, ciMethod* target)
: SharkTargetInvariants(state, target), _state(state) {}
private:
SharkState* _state;
private:
SharkState* state() const {
return _state;
}
private:
void do_intrinsic();
private:
void do_Math_minmax(llvm::ICmpInst::Predicate p);
void do_Math_1to1(llvm::Value* function);
void do_Math_2to1(llvm::Value* function);
void do_Object_getClass();
void do_System_currentTimeMillis();
void do_Thread_currentThread();
void do_Unsafe_compareAndSwapInt();
};
#endif // SHARE_VM_SHARK_SHARKINTRINSICS_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkInvariants.cpp
#include "precompiled.hpp"
#include "shark/sharkInvariants.hpp"
int SharkTargetInvariants::count_monitors() {
int result = 0;
if (is_synchronized() || target()->has_monitor_bytecodes()) {
for (int i = 0; i < flow()->block_count(); i++) {
result = MAX2(result, flow()->pre_order_at(i)->monitor_count());
}
}
return result;
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkInvariants.hpp
#ifndef SHARE_VM_SHARK_SHARKINVARIANTS_HPP
#define SHARE_VM_SHARK_SHARKINVARIANTS_HPP
#include "ci/ciEnv.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciTypeFlow.hpp"
#include "code/debugInfoRec.hpp"
#include "code/dependencies.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkBuilder.hpp"
class SharkCompileInvariants : public ResourceObj {
protected:
SharkCompileInvariants(ciEnv* env, SharkBuilder* builder)
: _env(env),
_builder(builder),
_thread(NULL) {}
SharkCompileInvariants(const SharkCompileInvariants* parent)
: _env(parent->_env),
_builder(parent->_builder),
_thread(parent->_thread) {}
private:
ciEnv* _env;
SharkBuilder* _builder;
llvm::Value* _thread;
protected:
ciEnv* env() const {
assert(_env != NULL, "env not available");
return _env;
}
protected:
SharkBuilder* builder() const {
return _builder;
}
protected:
llvm::Value* thread() const {
assert(_thread != NULL, "thread not available");
return _thread;
}
void set_thread(llvm::Value* thread) {
assert(_thread == NULL, "thread already set");
_thread = thread;
}
protected:
DebugInformationRecorder* debug_info() const {
return env()->debug_info();
}
SharkCodeBuffer* code_buffer() const {
return builder()->code_buffer();
}
public:
Dependencies* dependencies() const {
return env()->dependencies();
}
protected:
ciInstanceKlass* java_lang_Object_klass() const {
return env()->Object_klass();
}
ciInstanceKlass* java_lang_Throwable_klass() const {
return env()->Throwable_klass();
}
};
class SharkTargetInvariants : public SharkCompileInvariants {
protected:
SharkTargetInvariants(ciEnv* env, SharkBuilder* builder, ciTypeFlow* flow)
: SharkCompileInvariants(env, builder),
_target(flow->method()),
_flow(flow),
_max_monitors(count_monitors()) {}
SharkTargetInvariants(const SharkCompileInvariants* parent, ciMethod* target)
: SharkCompileInvariants(parent),
_target(target),
_flow(NULL),
_max_monitors(count_monitors()) {}
SharkTargetInvariants(const SharkTargetInvariants* parent)
: SharkCompileInvariants(parent),
_target(parent->_target),
_flow(parent->_flow),
_max_monitors(parent->_max_monitors) {}
private:
int count_monitors();
private:
ciMethod* _target;
ciTypeFlow* _flow;
int _max_monitors;
protected:
ciMethod* target() const {
return _target;
}
protected:
ciTypeFlow* flow() const {
assert(_flow != NULL, "typeflow not available");
return _flow;
}
protected:
int max_locals() const {
return target()->max_locals();
}
int max_stack() const {
return target()->max_stack();
}
int max_monitors() const {
return _max_monitors;
}
int arg_size() const {
return target()->arg_size();
}
bool is_static() const {
return target()->is_static();
}
bool is_synchronized() const {
return target()->is_synchronized();
}
};
#endif // SHARE_VM_SHARK_SHARKINVARIANTS_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkMemoryManager.cpp
#include "precompiled.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkEntry.hpp"
#include "shark/sharkMemoryManager.hpp"
using namespace llvm;
void SharkMemoryManager::AllocateGOT() {
mm()->AllocateGOT();
}
unsigned char* SharkMemoryManager::getGOTBase() const {
return mm()->getGOTBase();
}
unsigned char* SharkMemoryManager::allocateStub(const GlobalValue* F,
unsigned StubSize,
unsigned Alignment) {
return mm()->allocateStub(F, StubSize, Alignment);
}
unsigned char* SharkMemoryManager::startFunctionBody(const Function* F,
uintptr_t& ActualSize) {
return mm()->startFunctionBody(F, ActualSize);
}
void SharkMemoryManager::endFunctionBody(const Function* F,
unsigned char* FunctionStart,
unsigned char* FunctionEnd) {
mm()->endFunctionBody(F, FunctionStart, FunctionEnd);
SharkEntry *entry = get_entry_for_function(F);
if (entry != NULL)
entry->set_code_limit(FunctionEnd);
}
void SharkMemoryManager::setMemoryWritable() {
mm()->setMemoryWritable();
}
void SharkMemoryManager::setMemoryExecutable() {
mm()->setMemoryExecutable();
}
void SharkMemoryManager::deallocateFunctionBody(void *ptr) {
mm()->deallocateFunctionBody(ptr);
}
uint8_t* SharkMemoryManager::allocateGlobal(uintptr_t Size,
unsigned int Alignment) {
return mm()->allocateGlobal(Size, Alignment);
}
void* SharkMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
return mm()->getPointerToNamedFunction(Name, AbortOnFailure);
}
void SharkMemoryManager::setPoisonMemory(bool poison) {
mm()->setPoisonMemory(poison);
}
unsigned char *SharkMemoryManager::allocateSpace(intptr_t Size,
unsigned int Alignment) {
return mm()->allocateSpace(Size, Alignment);
}
#if SHARK_LLVM_VERSION <= 32
uint8_t* SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
return mm()->allocateCodeSection(Size, Alignment, SectionID);
}
uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
return mm()->allocateDataSection(Size, Alignment, SectionID);
}
void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
mm()->deallocateExceptionTable(ptr);
}
unsigned char* SharkMemoryManager::startExceptionTable(const Function* F,
uintptr_t& ActualSize) {
return mm()->startExceptionTable(F, ActualSize);
}
void SharkMemoryManager::endExceptionTable(const Function* F,
unsigned char* TableStart,
unsigned char* TableEnd,
unsigned char* FrameRegister) {
mm()->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
}
#else
uint8_t *SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) {
return mm()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
}
uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) {
return mm()->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
}
bool SharkMemoryManager::finalizeMemory(std::string *ErrMsg) {
return mm()->finalizeMemory(ErrMsg);
}
#endif
C:\hotspot-69087d08d473\src\share\vm/shark/sharkMemoryManager.hpp
#ifndef SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
#define SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
#include "shark/llvmHeaders.hpp"
#include "shark/sharkEntry.hpp"
class SharkMemoryManager : public llvm::JITMemoryManager {
public:
SharkMemoryManager()
: _mm(llvm::JITMemoryManager::CreateDefaultMemManager()) {}
private:
llvm::JITMemoryManager* _mm;
private:
llvm::JITMemoryManager* mm() const {
return _mm;
}
private:
std::map<const llvm::Function*, SharkEntry*> _entry_map;
public:
void set_entry_for_function(const llvm::Function* function,
SharkEntry* entry) {
_entry_map[function] = entry;
}
SharkEntry* get_entry_for_function(const llvm::Function* function) {
return _entry_map[function];
}
public:
void AllocateGOT();
unsigned char* getGOTBase() const;
unsigned char* allocateStub(const llvm::GlobalValue* F,
unsigned StubSize,
unsigned Alignment);
unsigned char* startFunctionBody(const llvm::Function* F,
uintptr_t& ActualSize);
void endFunctionBody(const llvm::Function* F,
unsigned char* FunctionStart,
unsigned char* FunctionEnd);
void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true);
void setPoisonMemory(bool);
uint8_t* allocateGlobal(uintptr_t, unsigned int);
void setMemoryWritable();
void setMemoryExecutable();
void deallocateFunctionBody(void *ptr);
unsigned char *allocateSpace(intptr_t Size,
unsigned int Alignment);
#if SHARK_LLVM_VERSION <= 32
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
unsigned char* startExceptionTable(const llvm::Function* F,
uintptr_t& ActualSize);
void deallocateExceptionTable(void *ptr);
void endExceptionTable(const llvm::Function* F,
unsigned char* TableStart,
unsigned char* TableEnd,
unsigned char* FrameRegister);
#else
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName);
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool IsReadOnly);
bool finalizeMemory(std::string *ErrMsg = 0);
#endif
};
#endif // SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkNativeWrapper.cpp
#include "precompiled.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkNativeWrapper.hpp"
#include "shark/sharkType.hpp"
using namespace llvm;
void SharkNativeWrapper::initialize(const char *name) {
_function = Function::Create(
SharkType::entry_point_type(),
GlobalVariable::InternalLinkage,
name);
Function::arg_iterator ai = function()->arg_begin();
Argument *method = ai++;
method->setName("method");
Argument *base_pc = ai++;
base_pc->setName("base_pc");
code_buffer()->set_base_pc(base_pc);
Argument *thread = ai++;
thread->setName("thread");
set_thread(thread);
builder()->SetInsertPoint(CreateBlock());
#error Needs to be updated for tagged jweak; see JNIHandles.
_stack = SharkStack::CreateBuildAndPushFrame(this, method);
NOT_PRODUCT(method = NULL);
OopMap *oopmap = new OopMap(
SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
SharkStack::oopmap_slot_munge(arg_size()));
if (is_static() || is_returning_oop()) {
_oop_tmp_slot = stack()->slot_addr(
stack()->oop_tmp_slot_offset(),
SharkType::oop_type(),
"oop_tmp_slot");
oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
}
if (is_synchronized()) {
Unimplemented();
_lock_slot_offset = 23;
}
std::vector<Type*> param_types;
std::vector<Value*> param_values;
PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
param_types.push_back(SharkType::jniEnv_type());
param_values.push_back(
builder()->CreateAddressOfStructEntry(
thread,
JavaThread::jni_environment_offset(),
SharkType::jniEnv_type(),
"jni_environment"));
if (is_static()) {
builder()->CreateStore(
builder()->CreateInlineOop(
JNIHandles::make_local(
target()->method_holder()->java_mirror())),
oop_tmp_slot());
param_types.push_back(box_type);
param_values.push_back(oop_tmp_slot());
_receiver_slot_offset = stack()->oop_tmp_slot_offset();
}
else if (is_returning_oop()) {
builder()->CreateStore(LLVMValue::null(), oop_tmp_slot());
}
for (int i = 0; i < arg_size(); i++) {
int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i;
int adjusted_offset = slot_offset;
BasicBlock *null, *not_null, *merge;
Value *box;
PHINode *phi;
switch (arg_type(i)) {
case T_VOID:
break;
case T_OBJECT:
case T_ARRAY:
null = CreateBlock("null");
not_null = CreateBlock("not_null");
merge = CreateBlock("merge");
box = stack()->slot_addr(slot_offset, SharkType::oop_type());
builder()->CreateCondBr(
builder()->CreateICmp(
ICmpInst::ICMP_EQ,
builder()->CreateLoad(box),
LLVMValue::null()),
null, not_null);
builder()->SetInsertPoint(null);
builder()->CreateBr(merge);
builder()->SetInsertPoint(not_null);
builder()->CreateBr(merge);
builder()->SetInsertPoint(merge);
phi = builder()->CreatePHI(box_type, 0, "boxed_object");
phi->addIncoming(ConstantPointerNull::get(box_type), null);
phi->addIncoming(box, not_null);
box = phi;
param_types.push_back(box_type);
param_values.push_back(box);
oopmap->set_oop(SharkStack::slot2reg(slot_offset));
if (i == 0 && !is_static())
_receiver_slot_offset = slot_offset;
break;
case T_LONG:
case T_DOUBLE:
adjusted_offset--;
default:
Type *param_type = SharkType::to_stackType(arg_type(i));
param_types.push_back(param_type);
param_values.push_back(
builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
}
}
int pc_offset = code_buffer()->create_unique_offset();
_oop_maps = new OopMapSet();
oop_maps()->add_gc_map(pc_offset, oopmap);
builder()->CreateStore(
builder()->code_buffer_address(pc_offset),
stack()->slot_addr(stack()->pc_slot_offset()));
stack()->CreateSetLastJavaFrame();
if (is_synchronized())
Unimplemented();
CreateSetThreadState(_thread_in_native);
BasicType result_type = target()->result_type();
Type* return_type;
if (result_type == T_VOID)
return_type = SharkType::void_type();
else if (is_returning_oop())
return_type = box_type;
else
return_type = SharkType::to_arrayType(result_type);
Value* native_function = builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) target()->native_function()),
PointerType::getUnqual(
FunctionType::get(return_type, param_types, false)));
Value *result = builder()->CreateCall(
native_function, llvm::makeArrayRef(param_values));
CreateSetThreadState(_thread_in_native_trans);
if (os::is_MP()) {
if (UseMembar)
builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread);
else
CreateWriteMemorySerializePage();
}
BasicBlock *check_thread = CreateBlock("check_thread");
BasicBlock *do_safepoint = CreateBlock("do_safepoint");
BasicBlock *safepointed = CreateBlock("safepointed");
Value *global_state = builder()->CreateLoad(
builder()->CreateIntToPtr(
LLVMValue::intptr_constant(
(intptr_t) SafepointSynchronize::address_of_state()),
PointerType::getUnqual(SharkType::jint_type())),
"global_state");
builder()->CreateCondBr(
builder()->CreateICmpNE(
global_state,
LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
do_safepoint, check_thread);
builder()->SetInsertPoint(check_thread);
Value *thread_state = builder()->CreateValueOfStructEntry(
thread,
JavaThread::suspend_flags_offset(),
SharkType::jint_type(),
"thread_state");
builder()->CreateCondBr(
builder()->CreateICmpNE(
thread_state,
LLVMValue::jint_constant(0)),
do_safepoint, safepointed);
builder()->SetInsertPoint(do_safepoint);
builder()->CreateCall(
builder()->check_special_condition_for_native_trans(), thread);
builder()->CreateBr(safepointed);
builder()->SetInsertPoint(safepointed);
CreateSetThreadState(_thread_in_Java);
stack()->CreateResetLastJavaFrame();
BasicBlock *exception = CreateBlock("exception");
BasicBlock *no_exception = CreateBlock("no_exception");
builder()->CreateCondBr(
builder()->CreateICmpEQ(
CreateLoadPendingException(),
LLVMValue::null()),
no_exception, exception);
builder()->SetInsertPoint(exception);
CreateResetHandleBlock();
stack()->CreatePopFrame(0);
builder()->CreateRet(LLVMValue::jint_constant(0));
builder()->SetInsertPoint(no_exception);
if (is_returning_oop()) {
BasicBlock *null = builder()->GetInsertBlock();
BasicBlock *not_null = CreateBlock("not_null");
BasicBlock *merge = CreateBlock("merge");
builder()->CreateCondBr(
builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
not_null, merge);
builder()->SetInsertPoint(not_null);
Value *unboxed_result = builder()->CreateLoad(result);
builder()->CreateBr(merge);
builder()->SetInsertPoint(merge);
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result");
phi->addIncoming(LLVMValue::null(), null);
phi->addIncoming(unboxed_result, not_null);
result = phi;
}
CreateResetHandleBlock();
if (is_synchronized())
Unimplemented();
Value *result_addr = stack()->CreatePopFrame(type2size[result_type]);
if (result_type != T_VOID) {
bool needs_cast = false;
bool is_signed = false;
switch (result_type) {
case T_BOOLEAN:
result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0));
needs_cast = true;
break;
case T_CHAR:
needs_cast = true;
break;
case T_BYTE:
case T_SHORT:
needs_cast = true;
is_signed = true;
break;
}
if (needs_cast) {
result = builder()->CreateIntCast(
result, SharkType::to_stackType(result_type), is_signed);
}
builder()->CreateStore(
result,
builder()->CreateIntToPtr(
result_addr,
PointerType::getUnqual(SharkType::to_stackType(result_type))));
}
builder()->CreateRet(LLVMValue::jint_constant(0));
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkNativeWrapper.hpp
#ifndef SHARE_VM_SHARK_SHARKNATIVEWRAPPER_HPP
#define SHARE_VM_SHARK_SHARKNATIVEWRAPPER_HPP
#include "runtime/handles.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkContext.hpp"
#include "shark/sharkInvariants.hpp"
#include "shark/sharkStack.hpp"
class SharkNativeWrapper : public SharkCompileInvariants {
friend class SharkStackWithNativeFrame;
public:
static SharkNativeWrapper* build(SharkBuilder* builder,
methodHandle target,
const char* name,
BasicType* arg_types,
BasicType return_type) {
return new SharkNativeWrapper(builder,
target,
name,
arg_types,
return_type);
}
private:
SharkNativeWrapper(SharkBuilder* builder,
methodHandle target,
const char* name,
BasicType* arg_types,
BasicType return_type)
: SharkCompileInvariants(NULL, builder),
_target(target),
_arg_types(arg_types),
_return_type(return_type),
_lock_slot_offset(0) { initialize(name); }
private:
void initialize(const char* name);
private:
methodHandle _target;
BasicType* _arg_types;
BasicType _return_type;
llvm::Function* _function;
SharkStack* _stack;
llvm::Value* _oop_tmp_slot;
OopMapSet* _oop_maps;
int _receiver_slot_offset;
int _lock_slot_offset;
protected:
methodHandle target() const {
return _target;
}
protected:
int arg_size() const {
return target()->size_of_parameters();
}
BasicType arg_type(int i) const {
return _arg_types[i];
}
BasicType return_type() const {
return _return_type;
}
bool is_static() const {
return target()->is_static();
}
bool is_synchronized() const {
return target()->is_synchronized();
}
bool is_returning_oop() const {
return target()->is_returning_oop();
}
public:
llvm::Function* function() const {
return _function;
}
protected:
SharkStack* stack() const {
return _stack;
}
protected:
llvm::Value* oop_tmp_slot() const {
assert(is_static() || is_returning_oop(), "should be");
return _oop_tmp_slot;
}
public:
int frame_size() const {
return stack()->oopmap_frame_size();
}
ByteSize receiver_offset() const {
return in_ByteSize(_receiver_slot_offset * wordSize);
}
ByteSize lock_offset() const {
return in_ByteSize(_lock_slot_offset * wordSize);
}
OopMapSet* oop_maps() const {
return _oop_maps;
}
private:
llvm::BasicBlock* CreateBlock(const char* name = "") const {
return llvm::BasicBlock::Create(SharkContext::current(), name, function());
}
llvm::Value* thread_state_address() const {
return builder()->CreateAddressOfStructEntry(
thread(), JavaThread::thread_state_offset(),
llvm::PointerType::getUnqual(SharkType::jint_type()),
"thread_state_address");
}
llvm::Value* pending_exception_address() const {
return builder()->CreateAddressOfStructEntry(
thread(), Thread::pending_exception_offset(),
llvm::PointerType::getUnqual(SharkType::oop_type()),
"pending_exception_address");
}
void CreateSetThreadState(JavaThreadState state) const {
builder()->CreateStore(
LLVMValue::jint_constant(state), thread_state_address());
}
void CreateWriteMemorySerializePage() const {
builder()->CreateStore(
LLVMValue::jint_constant(1),
builder()->CreateIntToPtr(
builder()->CreateAdd(
LLVMValue::intptr_constant(
(intptr_t) os::get_memory_serialize_page()),
builder()->CreateAnd(
builder()->CreateLShr(
builder()->CreatePtrToInt(thread(), SharkType::intptr_type()),
LLVMValue::intptr_constant(os::get_serialize_page_shift_count())),
LLVMValue::intptr_constant(os::get_serialize_page_mask()))),
llvm::PointerType::getUnqual(SharkType::jint_type())));
}
void CreateResetHandleBlock() const {
llvm::Value *active_handles = builder()->CreateValueOfStructEntry(
thread(),
JavaThread::active_handles_offset(),
SharkType::jniHandleBlock_type(),
"active_handles");
builder()->CreateStore(
LLVMValue::intptr_constant(0),
builder()->CreateAddressOfStructEntry(
active_handles,
in_ByteSize(JNIHandleBlock::top_offset_in_bytes()),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"top"));
}
llvm::LoadInst* CreateLoadPendingException() const {
return builder()->CreateLoad(
pending_exception_address(), "pending_exception");
}
};
#endif // SHARE_VM_SHARK_SHARKNATIVEWRAPPER_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkRuntime.cpp
#include "precompiled.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/thread.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkRuntime.hpp"
#ifdef TARGET_ARCH_zero
# include "stack_zero.inline.hpp"
#endif
using namespace llvm;
JRT_ENTRY(int, SharkRuntime::find_exception_handler(JavaThread* thread,
int* indexes,
int num_indexes))
constantPoolHandle pool(thread, method(thread)->constants());
KlassHandle exc_klass(thread, ((oop) tos_at(thread, 0))->klass());
for (int i = 0; i < num_indexes; i++) {
Klass* tmp = pool->klass_at(indexes[i], CHECK_0);
KlassHandle chk_klass(thread, tmp);
if (exc_klass() == chk_klass())
return i;
if (exc_klass()->is_subtype_of(chk_klass()))
return i;
}
return -1;
JRT_END
JRT_ENTRY(void, SharkRuntime::monitorenter(JavaThread* thread,
BasicObjectLock* lock))
if (PrintBiasedLockingStatistics)
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
Handle object(thread, lock->obj());
assert(Universe::heap()->is_in_reserved_or_null(object()), "should be");
if (UseBiasedLocking) {
ObjectSynchronizer::fast_enter(object, lock->lock(), true, CHECK);
} else {
ObjectSynchronizer::slow_enter(object, lock->lock(), CHECK);
}
assert(Universe::heap()->is_in_reserved_or_null(lock->obj()), "should be");
JRT_END
JRT_ENTRY(void, SharkRuntime::monitorexit(JavaThread* thread,
BasicObjectLock* lock))
Handle object(thread, lock->obj());
assert(Universe::heap()->is_in_reserved_or_null(object()), "should be");
if (lock == NULL || object()->is_unlocked()) {
THROW(vmSymbols::java_lang_IllegalMonitorStateException());
}
ObjectSynchronizer::slow_exit(object(), lock->lock(), thread);
JRT_END
JRT_ENTRY(void, SharkRuntime::new_instance(JavaThread* thread, int index))
Klass* k_oop = method(thread)->constants()->klass_at(index, CHECK);
instanceKlassHandle klass(THREAD, k_oop);
klass->check_valid_for_instantiation(true, CHECK);
klass->initialize(CHECK);
oop obj = klass->allocate_instance(CHECK);
thread->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, SharkRuntime::newarray(JavaThread* thread,
BasicType type,
int size))
oop obj = oopFactory::new_typeArray(type, size, CHECK);
thread->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, SharkRuntime::anewarray(JavaThread* thread,
int index,
int size))
Klass* klass = method(thread)->constants()->klass_at(index, CHECK);
objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
thread->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, SharkRuntime::multianewarray(JavaThread* thread,
int index,
int ndims,
int* dims))
Klass* klass = method(thread)->constants()->klass_at(index, CHECK);
oop obj = ArrayKlass::cast(klass)->multi_allocate(ndims, dims, CHECK);
thread->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, SharkRuntime::register_finalizer(JavaThread* thread,
oop object))
assert(object->is_oop(), "should be");
assert(object->klass()->has_finalizer(), "should have");
InstanceKlass::register_finalizer(instanceOop(object), CHECK);
JRT_END
JRT_ENTRY(void, SharkRuntime::throw_ArithmeticException(JavaThread* thread,
const char* file,
int line))
Exceptions::_throw_msg(
thread, file, line,
vmSymbols::java_lang_ArithmeticException(),
"");
JRT_END
JRT_ENTRY(void, SharkRuntime::throw_ArrayIndexOutOfBoundsException(
JavaThread* thread,
const char* file,
int line,
int index))
char msg[jintAsStringSize];
snprintf(msg, sizeof(msg), "%d", index);
Exceptions::_throw_msg(
thread, file, line,
vmSymbols::java_lang_ArrayIndexOutOfBoundsException(),
msg);
JRT_END
JRT_ENTRY(void, SharkRuntime::throw_ClassCastException(JavaThread* thread,
const char* file,
int line))
Exceptions::_throw_msg(
thread, file, line,
vmSymbols::java_lang_ClassCastException(),
"");
JRT_END
JRT_ENTRY(void, SharkRuntime::throw_NullPointerException(JavaThread* thread,
const char* file,
int line))
Exceptions::_throw_msg(
thread, file, line,
vmSymbols::java_lang_NullPointerException(),
"");
JRT_END
void SharkRuntime::dump(const char *name, intptr_t value) {
oop valueOop = (oop) value;
tty->print("%s = ", name);
if (valueOop->is_oop(true))
valueOop->print_on(tty);
else if (value >= ' ' && value <= '~')
tty->print("'%c' (%d)", value, value);
else
tty->print("%p", value);
tty->print_cr("");
}
bool SharkRuntime::is_subtype_of(Klass* check_klass, Klass* object_klass) {
return object_klass->is_subtype_of(check_klass);
}
int SharkRuntime::uncommon_trap(JavaThread* thread, int trap_request) {
Thread *THREAD = thread;
FakeStubFrame *stubframe = FakeStubFrame::build(CHECK_0);
thread->push_zero_frame(stubframe);
thread->set_last_Java_frame();
Deoptimization::UnrollBlock *urb =
Deoptimization::uncommon_trap(thread, trap_request);
thread->reset_last_Java_frame();
thread->pop_zero_frame();
thread->pop_zero_frame();
int number_of_frames = urb->number_of_frames();
for (int i = 0; i < number_of_frames; i++) {
intptr_t size = urb->frame_sizes()[i];
InterpreterFrame *frame = InterpreterFrame::build(size, CHECK_0);
thread->push_zero_frame(frame);
}
stubframe = FakeStubFrame::build(CHECK_0);
thread->push_zero_frame(stubframe);
thread->set_last_Java_frame();
Deoptimization::unpack_frames(thread, Deoptimization::Unpack_uncommon_trap);
thread->reset_last_Java_frame();
thread->pop_zero_frame();
return number_of_frames;
}
FakeStubFrame* FakeStubFrame::build(TRAPS) {
ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack();
stack->overflow_check(header_words, CHECK_NULL);
stack->push(0); // next_frame, filled in later
intptr_t *fp = stack->sp();
assert(fp - stack->sp() == next_frame_off, "should be");
stack->push(FAKE_STUB_FRAME);
assert(fp - stack->sp() == frame_type_off, "should be");
return (FakeStubFrame *) fp;
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkRuntime.hpp
#ifndef SHARE_VM_SHARK_SHARKRUNTIME_HPP
#define SHARE_VM_SHARK_SHARKRUNTIME_HPP
#include "memory/allocation.hpp"
#include "runtime/thread.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
class SharkRuntime : public AllStatic {
public:
static int find_exception_handler(JavaThread* thread,
int* indexes,
int num_indexes);
static void monitorenter(JavaThread* thread, BasicObjectLock* lock);
static void monitorexit(JavaThread* thread, BasicObjectLock* lock);
static void new_instance(JavaThread* thread, int index);
static void newarray(JavaThread* thread, BasicType type, int size);
static void anewarray(JavaThread* thread, int index, int size);
static void multianewarray(JavaThread* thread,
int index,
int ndims,
int* dims);
static void register_finalizer(JavaThread* thread, oop object);
static void throw_ArithmeticException(JavaThread* thread,
const char* file,
int line);
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread,
const char* file,
int line,
int index);
static void throw_ClassCastException(JavaThread* thread,
const char* file,
int line);
static void throw_NullPointerException(JavaThread* thread,
const char* file,
int line);
private:
static const SharkFrame* last_frame(JavaThread *thread) {
return thread->last_frame().zero_sharkframe();
}
static Method* method(JavaThread *thread) {
return last_frame(thread)->method();
}
static address bcp(JavaThread *thread, int bci) {
return method(thread)->code_base() + bci;
}
static int two_byte_index(JavaThread *thread, int bci) {
return Bytes::get_Java_u2(bcp(thread, bci) + 1);
}
static intptr_t tos_at(JavaThread *thread, int offset) {
return *(thread->zero_stack()->sp() + offset);
}
public:
static void dump(const char *name, intptr_t value);
static bool is_subtype_of(Klass* check_klass, Klass* object_klass);
static int uncommon_trap(JavaThread* thread, int trap_request);
};
#endif // SHARE_VM_SHARK_SHARKRUNTIME_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkStack.cpp
#include "precompiled.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkFunction.hpp"
#include "shark/sharkNativeWrapper.hpp"
#include "shark/sharkStack.hpp"
#include "shark/sharkType.hpp"
using namespace llvm;
void SharkStack::initialize(Value* method) {
bool setup_sp_and_method = (method != NULL);
int locals_words = max_locals();
int extra_locals = locals_words - arg_size();
int header_words = SharkFrame::header_words;
int monitor_words = max_monitors()*frame::interpreter_frame_monitor_size();
int stack_words = max_stack();
int frame_words = header_words + monitor_words + stack_words;
_extended_frame_size = frame_words + locals_words;
Value *stack_pointer = builder()->CreateSub(
CreateLoadStackPointer(),
LLVMValue::intptr_constant((frame_words + extra_locals) * wordSize));
CreateStackOverflowCheck(stack_pointer);
if (setup_sp_and_method)
CreateStoreStackPointer(stack_pointer);
_frame = builder()->CreateIntToPtr(
stack_pointer,
PointerType::getUnqual(
ArrayType::get(SharkType::intptr_type(), extended_frame_size())),
"frame");
int offset = 0;
_stack_slots_offset = offset;
offset += stack_words;
_monitors_slots_offset = offset;
offset += monitor_words;
_oop_tmp_slot_offset = offset++;
_method_slot_offset = offset++;
if (setup_sp_and_method) {
builder()->CreateStore(
method, slot_addr(method_slot_offset(), SharkType::Method_type()));
}
builder()->CreateStore(stack_pointer, slot_addr(offset++));
_pc_slot_offset = offset++;
builder()->CreateStore(
LLVMValue::intptr_constant(ZeroFrame::SHARK_FRAME), slot_addr(offset++));
Value *fp = slot_addr(offset++);
_locals_slots_offset = offset;
offset += locals_words;
assert(offset == extended_frame_size(), "should do");
builder()->CreateStore(CreateLoadFramePointer(), fp);
CreateStoreFramePointer(
builder()->CreatePtrToInt(fp, SharkType::intptr_type()));
}
void SharkStack::CreateStackOverflowCheck(Value* sp) {
BasicBlock *zero_ok = CreateBlock("zero_stack_ok");
BasicBlock *overflow = CreateBlock("stack_overflow");
BasicBlock *abi_ok = CreateBlock("abi_stack_ok");
builder()->CreateCondBr(
builder()->CreateICmpULT(sp, stack_base()),
overflow, zero_ok);
builder()->SetInsertPoint(zero_ok);
Value *stack_top = builder()->CreateSub(
builder()->CreateValueOfStructEntry(
thread(),
Thread::stack_base_offset(),
SharkType::intptr_type(),
"abi_base"),
builder()->CreateValueOfStructEntry(
thread(),
Thread::stack_size_offset(),
SharkType::intptr_type(),
"abi_size"));
Value *free_stack = builder()->CreateSub(
builder()->CreatePtrToInt(
builder()->CreateGetFrameAddress(),
SharkType::intptr_type(),
"abi_sp"),
stack_top);
builder()->CreateCondBr(
builder()->CreateICmpULT(
free_stack,
LLVMValue::intptr_constant(StackShadowPages * os::vm_page_size())),
overflow, abi_ok);
builder()->SetInsertPoint(overflow);
builder()->CreateCall(builder()->throw_StackOverflowError(), thread());
builder()->CreateRet(LLVMValue::jint_constant(0));
builder()->SetInsertPoint(abi_ok);
}
Value* SharkStack::CreatePopFrame(int result_slots) {
assert(result_slots >= 0 && result_slots <= 2, "should be");
int locals_to_pop = max_locals() - result_slots;
Value *fp = CreateLoadFramePointer();
Value *sp = builder()->CreateAdd(
fp,
LLVMValue::intptr_constant((1 + locals_to_pop) * wordSize));
CreateStoreStackPointer(sp);
CreateStoreFramePointer(
builder()->CreateLoad(
builder()->CreateIntToPtr(
fp, PointerType::getUnqual(SharkType::intptr_type()))));
return sp;
}
Value* SharkStack::slot_addr(int offset,
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;
}
SharkStack* SharkStack::CreateBuildAndPushFrame(SharkFunction* function,
Value* method) {
return new SharkStackWithNormalFrame(function, method);
}
SharkStack* SharkStack::CreateBuildAndPushFrame(SharkNativeWrapper* wrapper,
Value* method) {
return new SharkStackWithNativeFrame(wrapper, method);
}
SharkStackWithNormalFrame::SharkStackWithNormalFrame(SharkFunction* function,
Value* method)
: SharkStack(function), _function(function) {
initialize(PRODUCT_ONLY(NULL) NOT_PRODUCT(method));
}
SharkStackWithNativeFrame::SharkStackWithNativeFrame(SharkNativeWrapper* wrp,
Value* method)
: SharkStack(wrp), _wrapper(wrp) {
initialize(method);
}
int SharkStackWithNormalFrame::arg_size() const {
return function()->arg_size();
}
int SharkStackWithNativeFrame::arg_size() const {
return wrapper()->arg_size();
}
int SharkStackWithNormalFrame::max_locals() const {
return function()->max_locals();
}
int SharkStackWithNativeFrame::max_locals() const {
return wrapper()->arg_size();
}
int SharkStackWithNormalFrame::max_stack() const {
return function()->max_stack();
}
int SharkStackWithNativeFrame::max_stack() const {
return 0;
}
int SharkStackWithNormalFrame::max_monitors() const {
return function()->max_monitors();
}
int SharkStackWithNativeFrame::max_monitors() const {
return wrapper()->is_synchronized() ? 1 : 0;
}
BasicBlock* SharkStackWithNormalFrame::CreateBlock(const char* name) const {
return function()->CreateBlock(name);
}
BasicBlock* SharkStackWithNativeFrame::CreateBlock(const char* name) const {
return wrapper()->CreateBlock(name);
}
address SharkStackWithNormalFrame::interpreter_entry_point() const {
return (address) CppInterpreter::normal_entry;
}
address SharkStackWithNativeFrame::interpreter_entry_point() const {
return (address) CppInterpreter::native_entry;
}
#ifndef PRODUCT
void SharkStack::CreateAssertLastJavaSPIsNull() const {
#ifdef ASSERT
BasicBlock *fail = CreateBlock("assert_failed");
BasicBlock *pass = CreateBlock("assert_ok");
builder()->CreateCondBr(
builder()->CreateICmpEQ(
builder()->CreateLoad(last_Java_sp_addr()),
LLVMValue::intptr_constant(0)),
pass, fail);
builder()->SetInsertPoint(fail);
builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
builder()->CreateUnreachable();
builder()->SetInsertPoint(pass);
#endif // ASSERT
}
#endif // !PRODUCT
C:\hotspot-69087d08d473\src\share\vm/shark/sharkStack.hpp
#ifndef SHARE_VM_SHARK_SHARKSTACK_HPP
#define SHARE_VM_SHARK_SHARKSTACK_HPP
#include "shark/llvmHeaders.hpp"
#include "shark/sharkInvariants.hpp"
#include "shark/sharkType.hpp"
class SharkFunction;
class SharkNativeWrapper;
class SharkStackWithNormalFrame;
class SharkStackWithNativeFrame;
class SharkStack : public SharkCompileInvariants {
public:
static SharkStack* CreateBuildAndPushFrame(
SharkFunction* function, llvm::Value* method);
static SharkStack* CreateBuildAndPushFrame(
SharkNativeWrapper* wrapper, llvm::Value* method);
protected:
SharkStack(const SharkCompileInvariants* parent)
: SharkCompileInvariants(parent) {}
protected:
void initialize(llvm::Value* method);
protected:
void CreateStackOverflowCheck(llvm::Value* sp);
protected:
virtual int arg_size() const = 0;
virtual int max_locals() const = 0;
virtual int max_stack() const = 0;
virtual int max_monitors() const = 0;
protected:
virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0;
protected:
virtual address interpreter_entry_point() const = 0;
private:
llvm::Value* zero_stack() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::zero_stack_offset(),
SharkType::zeroStack_type(),
"zero_stack");
}
llvm::Value* stack_base() const {
return builder()->CreateValueOfStructEntry(
zero_stack(),
ZeroStack::base_offset(),
SharkType::intptr_type(),
"stack_base");
}
llvm::Value* stack_pointer_addr() const {
return builder()->CreateAddressOfStructEntry(
zero_stack(),
ZeroStack::sp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"stack_pointer_addr");
}
llvm::Value* frame_pointer_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::top_zero_frame_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"frame_pointer_addr");
}
public:
llvm::LoadInst* CreateLoadStackPointer(const char *name = "") {
return builder()->CreateLoad(stack_pointer_addr(), name);
}
llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) {
return builder()->CreateStore(value, stack_pointer_addr());
}
llvm::LoadInst* CreateLoadFramePointer(const char *name = "") {
return builder()->CreateLoad(frame_pointer_addr(), name);
}
llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) {
return builder()->CreateStore(value, frame_pointer_addr());
}
llvm::Value* CreatePopFrame(int result_slots);
private:
llvm::Value* last_Java_sp_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::last_Java_sp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"last_Java_sp_addr");
}
llvm::Value* last_Java_fp_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::last_Java_fp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"last_Java_fp_addr");
}
public:
void CreateSetLastJavaFrame() {
NOT_PRODUCT(CreateAssertLastJavaSPIsNull());
builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr());
builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr());
}
void CreateResetLastJavaFrame() {
builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr());
}
private:
void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN;
private:
llvm::Value* _frame;
int _extended_frame_size;
int _stack_slots_offset;
public:
int extended_frame_size() const {
return _extended_frame_size;
}
int oopmap_frame_size() const {
return extended_frame_size() - arg_size();
}
private:
int _monitors_slots_offset;
int _oop_tmp_slot_offset;
int _method_slot_offset;
int _pc_slot_offset;
int _locals_slots_offset;
public:
int stack_slots_offset() const {
return _stack_slots_offset;
}
int oop_tmp_slot_offset() const {
return _oop_tmp_slot_offset;
}
int method_slot_offset() const {
return _method_slot_offset;
}
int pc_slot_offset() const {
return _pc_slot_offset;
}
int locals_slots_offset() const {
return _locals_slots_offset;
}
int monitor_offset(int index) const {
assert(index >= 0 && index < max_monitors(), "invalid monitor index");
return _monitors_slots_offset +
(max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size();
}
int monitor_object_offset(int index) const {
return monitor_offset(index) +
(BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
}
int monitor_header_offset(int index) const {
return monitor_offset(index) +
((BasicObjectLock::lock_offset_in_bytes() +
BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord);
}
public:
llvm::Value* slot_addr(int offset,
llvm::Type* type = NULL,
const char* name = "") const;
llvm::Value* monitor_addr(int index) const {
return slot_addr(
monitor_offset(index),
SharkType::monitor_type(),
"monitor");
}
llvm::Value* monitor_object_addr(int index) const {
return slot_addr(
monitor_object_offset(index),
SharkType::oop_type(),
"object_addr");
}
llvm::Value* monitor_header_addr(int index) const {
return slot_addr(
monitor_header_offset(index),
SharkType::intptr_type(),
"displaced_header_addr");
}
public:
static int oopmap_slot_munge(int offset) {
return offset << (LogBytesPerWord - LogBytesPerInt);
}
static VMReg slot2reg(int offset) {
return VMRegImpl::stack2reg(oopmap_slot_munge(offset));
}
};
class SharkStackWithNormalFrame : public SharkStack {
friend class SharkStack;
protected:
SharkStackWithNormalFrame(SharkFunction* function, llvm::Value* method);
private:
SharkFunction* _function;
private:
SharkFunction* function() const {
return _function;
}
private:
int arg_size() const;
int max_locals() const;
int max_stack() const;
int max_monitors() const;
private:
llvm::BasicBlock* CreateBlock(const char* name = "") const;
private:
address interpreter_entry_point() const;
};
class SharkStackWithNativeFrame : public SharkStack {
friend class SharkStack;
protected:
SharkStackWithNativeFrame(SharkNativeWrapper* wrapper, llvm::Value* method);
private:
SharkNativeWrapper* _wrapper;
private:
SharkNativeWrapper* wrapper() const {
return _wrapper;
}
private:
int arg_size() const;
int max_locals() const;
int max_stack() const;
int max_monitors() const;
private:
llvm::BasicBlock* CreateBlock(const char* name = "") const;
private:
address interpreter_entry_point() const;
};
#endif // SHARE_VM_SHARK_SHARKSTACK_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkState.cpp
#include "precompiled.hpp"
#include "ci/ciType.hpp"
#include "ci/ciTypeFlow.hpp"
#include "memory/allocation.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkCacheDecache.hpp"
#include "shark/sharkState.hpp"
#include "shark/sharkTopLevelBlock.hpp"
#include "shark/sharkType.hpp"
#include "shark/sharkValue.hpp"
using namespace llvm;
void SharkState::initialize(const SharkState *state) {
_locals = NEW_RESOURCE_ARRAY(SharkValue*, max_locals());
_stack = NEW_RESOURCE_ARRAY(SharkValue*, max_stack());
NOT_PRODUCT(memset(_locals, 23, max_locals() * sizeof(SharkValue *)));
NOT_PRODUCT(memset(_stack, 23, max_stack() * sizeof(SharkValue *)));
_sp = _stack;
if (state) {
for (int i = 0; i < max_locals(); i++) {
SharkValue *value = state->local(i);
if (value)
value = value->clone();
set_local(i, value);
}
for (int i = state->stack_depth() - 1; i >= 0; i--) {
SharkValue *value = state->stack(i);
if (value)
value = value->clone();
push(value);
}
}
set_num_monitors(state ? state->num_monitors() : 0);
}
bool SharkState::equal_to(SharkState *other) {
if (target() != other->target())
return false;
if (method() != other->method())
return false;
if (oop_tmp() != other->oop_tmp())
return false;
if (max_locals() != other->max_locals())
return false;
if (stack_depth() != other->stack_depth())
return false;
if (num_monitors() != other->num_monitors())
return false;
if (has_safepointed() != other->has_safepointed())
return false;
for (int i = 0; i < max_locals(); i++) {
SharkValue *value = local(i);
SharkValue *other_value = other->local(i);
if (value == NULL) {
if (other_value != NULL)
return false;
}
else {
if (other_value == NULL)
return false;
if (!value->equal_to(other_value))
return false;
}
}
for (int i = 0; i < stack_depth(); i++) {
SharkValue *value = stack(i);
SharkValue *other_value = other->stack(i);
if (value == NULL) {
if (other_value != NULL)
return false;
}
else {
if (other_value == NULL)
return false;
if (!value->equal_to(other_value))
return false;
}
}
return true;
}
void SharkState::merge(SharkState* other,
BasicBlock* other_block,
BasicBlock* this_block) {
Value *this_method = this->method();
Value *other_method = other->method();
if (this_method != other_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);
}
Value *this_oop_tmp = this->oop_tmp();
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(), 0, "oop_tmp");
phi->addIncoming(this_oop_tmp, this_block);
phi->addIncoming(other_oop_tmp, other_block);
set_oop_tmp(phi);
}
assert(this->num_monitors() == other->num_monitors(), "should be");
assert(this->max_locals() == other->max_locals(), "should be");
for (int i = 0; i < max_locals(); i++) {
SharkValue *this_value = this->local(i);
SharkValue *other_value = other->local(i);
assert((this_value == NULL) == (other_value == NULL), "should be");
if (this_value != NULL) {
char name[18];
snprintf(name, sizeof(name), "local_%d_", i);
set_local(i, this_value->merge(
builder(), other_value, other_block, this_block, name));
}
}
assert(this->stack_depth() == other->stack_depth(), "should be");
for (int i = 0; i < stack_depth(); i++) {
SharkValue *this_value = this->stack(i);
SharkValue *other_value = other->stack(i);
assert((this_value == NULL) == (other_value == NULL), "should be");
if (this_value != NULL) {
char name[18];
snprintf(name, sizeof(name), "stack_%d_", i);
set_stack(i, this_value->merge(
builder(), other_value, other_block, this_block, name));
}
}
set_has_safepointed(this->has_safepointed() && other->has_safepointed());
}
void SharkState::replace_all(SharkValue* old_value, SharkValue* new_value) {
for (int i = 0; i < max_locals(); i++) {
if (local(i) == old_value)
set_local(i, new_value);
}
for (int i = 0; i < stack_depth(); i++) {
if (stack(i) == old_value)
set_stack(i, new_value);
}
}
SharkNormalEntryState::SharkNormalEntryState(SharkTopLevelBlock* block,
Value* method)
: SharkState(block) {
assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
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 >= arg_size()) {
ShouldNotReachHere();
}
value = SharkValue::create_generic(type, NULL, i == 0 && !is_static());
break;
case ciTypeFlow::StateVector::T_NULL:
value = SharkValue::null();
break;
case ciTypeFlow::StateVector::T_BOTTOM:
break;
case ciTypeFlow::StateVector::T_LONG2:
case ciTypeFlow::StateVector::T_DOUBLE2:
break;
default:
ShouldNotReachHere();
}
set_local(i, value);
}
SharkNormalEntryCacher(block->function(), method).scan(this);
}
SharkOSREntryState::SharkOSREntryState(SharkTopLevelBlock* block,
Value* method,
Value* osr_buf)
: SharkState(block) {
assert(block->stack_depth_at_entry() == 0, "entry block shouldn't have stack");
set_num_monitors(block->ciblock()->monitor_count());
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:
value = SharkValue::create_generic(type, NULL, false);
break;
case ciTypeFlow::StateVector::T_NULL:
value = SharkValue::null();
break;
case ciTypeFlow::StateVector::T_BOTTOM:
break;
case ciTypeFlow::StateVector::T_LONG2:
case ciTypeFlow::StateVector::T_DOUBLE2:
break;
default:
ShouldNotReachHere();
}
set_local(i, value);
}
SharkOSREntryCacher(block->function(), method, osr_buf).scan(this);
}
SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
: SharkState(block), _block(block) {
BasicBlock *saved_insert_point = builder()->GetInsertBlock();
builder()->SetInsertPoint(block->entry_block());
char name[18];
set_method(builder()->CreatePHI(SharkType::Method_type(), 0, "method"));
for (int i = 0; i < max_locals(); i++) {
ciType *type = block->local_type_at_entry(i);
if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
}
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:
snprintf(name, sizeof(name), "local_%d_", i);
value = SharkValue::create_phi(
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
break;
case T_ADDRESS:
value = SharkValue::address_constant(type->as_return_address()->bci());
break;
case ciTypeFlow::StateVector::T_BOTTOM:
break;
case ciTypeFlow::StateVector::T_LONG2:
case ciTypeFlow::StateVector::T_DOUBLE2:
break;
default:
ShouldNotReachHere();
}
set_local(i, value);
}
for (int i = 0; i < block->stack_depth_at_entry(); i++) {
ciType *type = block->stack_type_at_entry(i);
if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
}
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:
snprintf(name, sizeof(name), "stack_%d_", i);
value = SharkValue::create_phi(
type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name));
break;
case T_ADDRESS:
value = SharkValue::address_constant(type->as_return_address()->bci());
break;
case ciTypeFlow::StateVector::T_LONG2:
case ciTypeFlow::StateVector::T_DOUBLE2:
break;
default:
ShouldNotReachHere();
}
push(value);
}
set_num_monitors(block->ciblock()->monitor_count());
builder()->SetInsertPoint(saved_insert_point);
}
void SharkPHIState::add_incoming(SharkState* incoming_state) {
BasicBlock *predecessor = builder()->GetInsertBlock();
((PHINode *) method())->addIncoming(incoming_state->method(), predecessor);
for (int i = 0; i < max_locals(); i++) {
if (local(i) != NULL)
local(i)->addIncoming(incoming_state->local(i), predecessor);
}
int stack_depth = block()->stack_depth_at_entry();
assert(stack_depth == incoming_state->stack_depth(), "should be");
for (int i = 0; i < stack_depth; i++) {
assert((stack(i) == NULL) == (incoming_state->stack(i) == NULL), "oops");
if (stack(i))
stack(i)->addIncoming(incoming_state->stack(i), predecessor);
}
assert(num_monitors() == incoming_state->num_monitors(), "should be");
assert(oop_tmp() == incoming_state->oop_tmp(), "should be");
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkState.hpp
#ifndef SHARE_VM_SHARK_SHARKSTATE_HPP
#define SHARE_VM_SHARK_SHARKSTATE_HPP
#include "ci/ciMethod.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkInvariants.hpp"
#include "shark/sharkValue.hpp"
class SharkState : public SharkTargetInvariants {
public:
SharkState(const SharkTargetInvariants* parent)
: SharkTargetInvariants(parent),
_method(NULL),
_oop_tmp(NULL),
_has_safepointed(false) { initialize(NULL); }
SharkState(const SharkState* state)
: SharkTargetInvariants(state),
_method(state->_method),
_oop_tmp(state->_oop_tmp),
_has_safepointed(state->_has_safepointed) { initialize(state); }
private:
void initialize(const SharkState* state);
private:
llvm::Value* _method;
SharkValue** _locals;
SharkValue** _stack;
SharkValue** _sp;
int _num_monitors;
llvm::Value* _oop_tmp;
bool _has_safepointed;
public:
llvm::Value** method_addr() {
return &_method;
}
llvm::Value* method() const {
return _method;
}
protected:
void set_method(llvm::Value* method) {
_method = method;
}
public:
SharkValue** local_addr(int index) const {
assert(index >= 0 && index < max_locals(), "bad local variable index");
return &_locals[index];
}
SharkValue* local(int index) const {
return *local_addr(index);
}
void set_local(int index, SharkValue* value) {
}
public:
SharkValue** stack_addr(int slot) const {
assert(slot >= 0 && slot < stack_depth(), "bad stack slot");
return &_sp[-(slot + 1)];
}
SharkValue* stack(int slot) const {
return *stack_addr(slot);
}
protected:
void set_stack(int slot, SharkValue* value) {
}
public:
int stack_depth() const {
return _sp - _stack;
}
void push(SharkValue* value) {
assert(stack_depth() < max_stack(), "stack overrun");
}
SharkValue* pop() {
assert(stack_depth() > 0, "stack underrun");
return *(--_sp);
}
public:
int num_monitors() const {
return _num_monitors;
}
void set_num_monitors(int num_monitors) {
_num_monitors = num_monitors;
}
public:
llvm::Value** oop_tmp_addr() {
return &_oop_tmp;
}
llvm::Value* oop_tmp() const {
return _oop_tmp;
}
void set_oop_tmp(llvm::Value* oop_tmp) {
_oop_tmp = oop_tmp;
}
public:
bool has_safepointed() const {
return _has_safepointed;
}
void set_has_safepointed(bool has_safepointed) {
_has_safepointed = has_safepointed;
}
public:
bool equal_to(SharkState* other);
public:
SharkState* copy() const {
return new SharkState(this);
}
void merge(SharkState* other,
llvm::BasicBlock* other_block,
llvm::BasicBlock* this_block);
public:
void replace_all(SharkValue* old_value, SharkValue* new_value);
};
class SharkTopLevelBlock;
class SharkNormalEntryState : public SharkState {
public:
SharkNormalEntryState(SharkTopLevelBlock* block,
llvm::Value* method);
};
class SharkOSREntryState : public SharkState {
public:
SharkOSREntryState(SharkTopLevelBlock* block,
llvm::Value* method,
llvm::Value* osr_buf);
};
class SharkPHIState : public SharkState {
public:
SharkPHIState(SharkTopLevelBlock* block);
private:
SharkTopLevelBlock* _block;
private:
SharkTopLevelBlock* block() const {
return _block;
}
public:
void add_incoming(SharkState* incoming_state);
};
#endif // SHARE_VM_SHARK_SHARKSTATE_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkStateScanner.cpp
#include "precompiled.hpp"
#include "shark/sharkState.hpp"
#include "shark/sharkStateScanner.hpp"
using namespace llvm;
void SharkStateScanner::scan(SharkState* state) {
start_frame();
stack_integrity_checks(state);
start_stack(state->stack_depth());
for (int i = state->stack_depth() - 1; i >= 0; i--) {
process_stack_slot(
i,
state->stack_addr(i),
stack()->stack_slots_offset() +
i + max_stack() - state->stack_depth());
}
end_stack();
start_monitors(state->num_monitors());
for (int i = 0; i < state->num_monitors(); i++) {
process_monitor(
i,
stack()->monitor_offset(i),
stack()->monitor_object_offset(i));
}
end_monitors();
start_frame_header();
process_oop_tmp_slot(
state->oop_tmp_addr(), stack()->oop_tmp_slot_offset());
process_method_slot(state->method_addr(), stack()->method_slot_offset());
process_pc_slot(stack()->pc_slot_offset());
end_frame_header();
locals_integrity_checks(state);
start_locals();
for (int i = 0; i < max_locals(); i++) {
process_local_slot(
i,
state->local_addr(i),
stack()->locals_slots_offset() + max_locals() - 1 - i);
}
end_locals();
end_frame();
}
#ifndef PRODUCT
void SharkStateScanner::stack_integrity_checks(SharkState* state) {
for (int i = 0; i < state->stack_depth(); i++) {
if (state->stack(i)) {
if (state->stack(i)->is_two_word())
assert(state->stack(i - 1) == NULL, "should be");
}
else {
assert(state->stack(i + 1)->is_two_word(), "should be");
}
}
}
void SharkStateScanner::locals_integrity_checks(SharkState* state) {
for (int i = 0; i < max_locals(); i++) {
if (state->local(i)) {
if (state->local(i)->is_two_word())
assert(state->local(i + 1) == NULL, "should be");
}
}
}
#endif // !PRODUCT
C:\hotspot-69087d08d473\src\share\vm/shark/sharkStateScanner.hpp
#ifndef SHARE_VM_SHARK_SHARKSTATESCANNER_HPP
#define SHARE_VM_SHARK_SHARKSTATESCANNER_HPP
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkFunction.hpp"
#include "shark/sharkInvariants.hpp"
class SharkState;
class SharkStateScanner : public SharkTargetInvariants {
protected:
SharkStateScanner(SharkFunction* function)
: SharkTargetInvariants(function), _stack(function->stack()) {}
private:
SharkStack* _stack;
protected:
SharkStack* stack() const {
return _stack;
}
public:
void scan(SharkState* state);
protected:
virtual void start_frame() {}
virtual void start_stack(int stack_depth) {}
virtual void process_stack_slot(int index, SharkValue** value, int offset) {}
virtual void end_stack() {}
virtual void start_monitors(int num_monitors) {}
virtual void process_monitor(int index, int box_offset, int obj_offset) {}
virtual void end_monitors() {}
virtual void start_frame_header() {}
virtual void process_oop_tmp_slot(llvm::Value** value, int offset) {}
virtual void process_method_slot(llvm::Value** value, int offset) {}
virtual void process_pc_slot(int offset) {}
virtual void end_frame_header() {}
virtual void start_locals() {}
virtual void process_local_slot(int index, SharkValue** value, int offset) {}
virtual void end_locals() {}
virtual void end_frame() {}
private:
void stack_integrity_checks(SharkState* state) PRODUCT_RETURN;
void locals_integrity_checks(SharkState* state) PRODUCT_RETURN;
};
#endif // SHARE_VM_SHARK_SHARKSTATESCANNER_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkTopLevelBlock.cpp
#include "precompiled.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciStreams.hpp"
#include "ci/ciType.hpp"
#include "ci/ciTypeFlow.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.hpp"
#include "runtime/deoptimization.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkCacheDecache.hpp"
#include "shark/sharkConstant.hpp"
#include "shark/sharkInliner.hpp"
#include "shark/sharkState.hpp"
#include "shark/sharkTopLevelBlock.hpp"
#include "shark/sharkValue.hpp"
#include "shark/shark_globals.hpp"
#include "utilities/debug.hpp"
using namespace llvm;
void SharkTopLevelBlock::scan_for_traps() {
int limit_bci = ciblock()->has_trap() ? ciblock()->trap_bci() : limit();
iter()->reset_to_bci(start());
while (iter()->next_bci() < limit_bci) {
iter()->next();
ciField *field;
ciMethod *method;
ciInstanceKlass *klass;
bool will_link;
bool is_field;
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(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret), bci());
return;
}
break;
case Bytecodes::_getfield:
case Bytecodes::_getstatic:
case Bytecodes::_putfield:
case Bytecodes::_putstatic:
field = iter()->get_field(will_link);
assert(will_link, "typeflow responsibility");
is_field = (bc() == Bytecodes::_getfield || bc() == Bytecodes::_putfield);
if (is_field == field->is_static()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_unhandled,
Deoptimization::Action_none), bci());
return;
}
if (!is_field && !field->holder()->is_initialized()) {
if (!static_field_ok_in_clinit(field)) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret), bci());
return;
}
}
break;
case Bytecodes::_invokestatic:
case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
ciSignature* sig;
method = iter()->get_method(will_link, &sig);
assert(will_link, "typeflow responsibility");
if (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()) {
if (SharkPerformanceWarnings) {
warning("JSR292 optimization not yet implemented in Shark");
}
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_unhandled,
Deoptimization::Action_make_not_compilable), bci());
return;
}
if (!method->holder()->is_linked()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret), bci());
return;
}
if (bc() == Bytecodes::_invokevirtual) {
klass = ciEnv::get_instance_klass_for_declared_method_holder(
iter()->get_declared_method_holder());
if (!klass->is_linked()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret), bci());
return;
}
}
break;
case Bytecodes::_new:
klass = iter()->get_klass(will_link)->as_instance_klass();
assert(will_link, "typeflow responsibility");
if (iter()->is_unresolved_klass() || !klass->is_initialized()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret), bci());
return;
}
if (klass->is_abstract() || klass->is_interface() ||
klass->name() == ciSymbol::java_lang_Class()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_unhandled,
Deoptimization::Action_reinterpret), bci());
return;
}
break;
case Bytecodes::_invokedynamic:
case Bytecodes::_invokehandle:
if (SharkPerformanceWarnings) {
warning("JSR292 optimization not yet implemented in Shark");
}
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_unhandled,
Deoptimization::Action_make_not_compilable), bci());
return;
}
}
if (ciblock()->has_trap()) {
set_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret,
ciblock()->trap_index()), ciblock()->trap_bci());
return;
}
}
bool SharkTopLevelBlock::static_field_ok_in_clinit(ciField* field) {
assert(field->is_static(), "should be");
bool access_OK = false;
if (target()->holder()->is_subclass_of(field->holder())) {
if (target()->is_static()) {
if (target()->name() == ciSymbol::class_initializer_name()) {
access_OK = true;
}
}
else {
if (target()->name() == ciSymbol::object_initializer_name()) {
access_OK = true;
}
}
}
return access_OK;
}
SharkState* SharkTopLevelBlock::entry_state() {
if (_entry_state == NULL) {
assert(needs_phis(), "should do");
_entry_state = new SharkPHIState(this);
}
return _entry_state;
}
void SharkTopLevelBlock::add_incoming(SharkState* incoming_state) {
if (needs_phis()) {
((SharkPHIState *) entry_state())->add_incoming(incoming_state);
}
else if (_entry_state == NULL) {
_entry_state = incoming_state;
}
else {
assert(entry_state()->equal_to(incoming_state), "should be");
}
}
void SharkTopLevelBlock::enter(SharkTopLevelBlock* predecessor,
bool is_exception) {
if (!needs_phis() &&
(entered() ||
is_exception ||
(predecessor && predecessor->index() >= index())))
_needs_phis = true;
if (!entered()) {
_entered = true;
scan_for_traps();
if (!has_trap()) {
for (int i = 0; i < num_successors(); i++) {
successor(i)->enter(this, false);
}
}
compute_exceptions();
for (int i = 0; i < num_exceptions(); i++) {
SharkTopLevelBlock *handler = exception(i);
if (handler)
handler->enter(this, true);
}
}
}
void SharkTopLevelBlock::initialize() {
char name[28];
snprintf(name, sizeof(name),
"bci_%d%s",
start(), is_backedge_copy() ? "_backedge_copy" : "");
_entry_block = function()->CreateBlock(name);
}
void SharkTopLevelBlock::decache_for_Java_call(ciMethod *callee) {
SharkJavaCallDecacher(function(), bci(), callee).scan(current_state());
for (int i = 0; i < callee->arg_size(); i++)
xpop();
}
void SharkTopLevelBlock::cache_after_Java_call(ciMethod *callee) {
if (callee->return_type()->size()) {
ciType *type;
switch (callee->return_type()->basic_type()) {
case T_BOOLEAN:
case T_BYTE:
case T_CHAR:
case T_SHORT:
type = ciType::make(T_INT);
break;
default:
type = callee->return_type();
}
push(SharkValue::create_generic(type, NULL, false));
}
SharkJavaCallCacher(function(), callee).scan(current_state());
}
void SharkTopLevelBlock::decache_for_VM_call() {
SharkVMCallDecacher(function(), bci()).scan(current_state());
}
void SharkTopLevelBlock::cache_after_VM_call() {
SharkVMCallCacher(function()).scan(current_state());
}
void SharkTopLevelBlock::decache_for_trap() {
SharkTrapDecacher(function(), bci()).scan(current_state());
}
void SharkTopLevelBlock::emit_IR() {
builder()->SetInsertPoint(entry_block());
parse_bytecode(start(), limit());
if (falls_through() && !has_trap())
do_branch(ciTypeFlow::FALL_THROUGH);
}
SharkTopLevelBlock* SharkTopLevelBlock::bci_successor(int bci) const {
for (int i = 0; i < num_successors(); i++) {
ciTypeFlow::Block *successor = ciblock()->successors()->at(i);
if (successor->start() == bci)
return function()->block(successor->pre_order());
}
ShouldNotReachHere();
}
void SharkTopLevelBlock::do_zero_check(SharkValue *value) {
if (value->is_phi() && value->as_phi()->all_incomers_zero_checked()) {
function()->add_deferred_zero_check(this, value);
}
else {
BasicBlock *continue_block = function()->CreateBlock("not_zero");
SharkState *saved_state = current_state();
set_current_state(saved_state->copy());
zero_check_value(value, continue_block);
builder()->SetInsertPoint(continue_block);
set_current_state(saved_state);
}
value->set_zero_checked(true);
}
void SharkTopLevelBlock::do_deferred_zero_check(SharkValue* value,
int bci,
SharkState* saved_state,
BasicBlock* continue_block) {
if (value->as_phi()->all_incomers_zero_checked()) {
builder()->CreateBr(continue_block);
}
else {
iter()->force_bci(start());
set_current_state(saved_state);
zero_check_value(value, continue_block);
}
}
void SharkTopLevelBlock::zero_check_value(SharkValue* value,
BasicBlock* continue_block) {
BasicBlock *zero_block = builder()->CreateBlock(continue_block, "zero");
Value *a, *b;
switch (value->basic_type()) {
case T_BYTE:
case T_CHAR:
case T_SHORT:
case T_INT:
a = value->jint_value();
b = LLVMValue::jint_constant(0);
break;
case T_LONG:
a = value->jlong_value();
b = LLVMValue::jlong_constant(0);
break;
case T_OBJECT:
case T_ARRAY:
a = value->jobject_value();
b = LLVMValue::LLVMValue::null();
break;
default:
tty->print_cr("Unhandled type %s", type2name(value->basic_type()));
ShouldNotReachHere();
}
builder()->CreateCondBr(
builder()->CreateICmpNE(a, b), continue_block, zero_block);
builder()->SetInsertPoint(zero_block);
if (value->is_jobject()) {
call_vm(
builder()->throw_NullPointerException(),
builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) __FILE__),
PointerType::getUnqual(SharkType::jbyte_type())),
LLVMValue::jint_constant(__LINE__),
EX_CHECK_NONE);
}
else {
call_vm(
builder()->throw_ArithmeticException(),
builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) __FILE__),
PointerType::getUnqual(SharkType::jbyte_type())),
LLVMValue::jint_constant(__LINE__),
EX_CHECK_NONE);
}
Value *pending_exception = get_pending_exception();
clear_pending_exception();
handle_exception(pending_exception, EX_CHECK_FULL);
}
void SharkTopLevelBlock::check_bounds(SharkValue* array, SharkValue* index) {
BasicBlock *out_of_bounds = function()->CreateBlock("out_of_bounds");
BasicBlock *in_bounds = function()->CreateBlock("in_bounds");
Value *length = builder()->CreateArrayLength(array->jarray_value());
builder()->CreateCondBr(
builder()->CreateICmpULT(index->jint_value(), length),
in_bounds, out_of_bounds);
builder()->SetInsertPoint(out_of_bounds);
SharkState *saved_state = current_state()->copy();
call_vm(
builder()->throw_ArrayIndexOutOfBoundsException(),
builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) __FILE__),
PointerType::getUnqual(SharkType::jbyte_type())),
LLVMValue::jint_constant(__LINE__),
index->jint_value(),
EX_CHECK_NONE);
Value *pending_exception = get_pending_exception();
clear_pending_exception();
handle_exception(pending_exception, EX_CHECK_FULL);
set_current_state(saved_state);
builder()->SetInsertPoint(in_bounds);
}
void SharkTopLevelBlock::check_pending_exception(int action) {
assert(action & EAM_CHECK, "should be");
BasicBlock *exception = function()->CreateBlock("exception");
BasicBlock *no_exception = function()->CreateBlock("no_exception");
Value *pending_exception = get_pending_exception();
builder()->CreateCondBr(
builder()->CreateICmpEQ(pending_exception, LLVMValue::null()),
no_exception, exception);
builder()->SetInsertPoint(exception);
SharkState *saved_state = current_state()->copy();
if (action & EAM_MONITOR_FUDGE) {
set_num_monitors(num_monitors() - 1);
action ^= EAM_MONITOR_FUDGE;
}
clear_pending_exception();
handle_exception(pending_exception, action);
set_current_state(saved_state);
builder()->SetInsertPoint(no_exception);
}
void SharkTopLevelBlock::compute_exceptions() {
ciExceptionHandlerStream str(target(), start());
int exc_count = str.count();
_exc_handlers = new GrowableArray<ciExceptionHandler*>(exc_count);
_exceptions = new GrowableArray<SharkTopLevelBlock*>(exc_count);
int index = 0;
for (; !str.is_done(); str.next()) {
ciExceptionHandler *handler = str.handler();
if (handler->handler_bci() == -1)
break;
_exc_handlers->append(handler);
SharkTopLevelBlock *block = NULL;
ciInstanceKlass* klass;
if (handler->is_catch_all()) {
klass = java_lang_Throwable_klass();
}
else {
klass = handler->catch_klass();
}
for (int i = 0; i < ciblock()->exceptions()->length(); i++) {
if (klass == ciblock()->exc_klasses()->at(i)) {
block = function()->block(ciblock()->exceptions()->at(i)->pre_order());
if (block->start() == handler->handler_bci())
break;
else
block = NULL;
}
}
if (block == NULL) {
for (int i = 0; i < function()->block_count(); i++) {
SharkTopLevelBlock *candidate = function()->block(i);
if (candidate->start() == handler->handler_bci()) {
if (block != NULL) {
NOT_PRODUCT(warning("there may be trouble ahead"));
block = NULL;
break;
}
block = candidate;
}
}
}
_exceptions->append(block);
}
}
void SharkTopLevelBlock::handle_exception(Value* exception, int action) {
if (action & EAM_HANDLE && num_exceptions() != 0) {
while (xstack_depth())
pop();
push(SharkValue::create_jobject(exception, true));
bool has_catch_all = exc_handler(num_exceptions() - 1)->is_catch_all();
int num_options = num_exceptions();
if (has_catch_all)
num_options--;
if (num_options > 0) {
bool all_loaded = true;
for (int i = 0; i < num_options; i++) {
if (!exc_handler(i)->catch_klass()->is_loaded()) {
all_loaded = false;
break;
}
}
if (all_loaded)
marshal_exception_fast(num_options);
else
marshal_exception_slow(num_options);
}
if (has_catch_all) {
SharkTopLevelBlock* handler = this->exception(num_options);
assert(handler != NULL, "catch-all handler cannot be unloaded");
builder()->CreateBr(handler->entry_block());
handler->add_incoming(current_state());
return;
}
}
handle_return(T_VOID, exception);
}
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::klass_type(),
"exception_klass");
for (int i = 0; i < num_options; i++) {
Value *check_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");
builder()->CreateCondBr(
builder()->CreateICmpEQ(check_klass, exception_klass),
handler_for_exception(i), not_exact);
builder()->SetInsertPoint(not_exact);
builder()->CreateCondBr(
builder()->CreateICmpNE(
builder()->CreateCall2(
builder()->is_subtype_of(), check_klass, exception_klass),
LLVMValue::jbyte_constant(0)),
handler_for_exception(i), not_subtype);
builder()->SetInsertPoint(not_subtype);
}
}
void SharkTopLevelBlock::marshal_exception_slow(int num_options) {
int *indexes = NEW_RESOURCE_ARRAY(int, num_options);
for (int i = 0; i < num_options; i++)
indexes[i] = exc_handler(i)->catch_klass_index();
Value *index = call_vm(
builder()->find_exception_handler(),
builder()->CreateInlineData(
indexes,
num_options * sizeof(int),
PointerType::getUnqual(SharkType::jint_type())),
LLVMValue::jint_constant(num_options),
EX_CHECK_NO_CATCH);
BasicBlock *no_handler = function()->CreateBlock("no_handler");
SwitchInst *switchinst = builder()->CreateSwitch(
index, no_handler, num_options);
for (int i = 0; i < num_options; i++) {
switchinst->addCase(
LLVMValue::jint_constant(i),
handler_for_exception(i));
}
builder()->SetInsertPoint(no_handler);
}
BasicBlock* SharkTopLevelBlock::handler_for_exception(int index) {
SharkTopLevelBlock *successor = this->exception(index);
if (successor) {
successor->add_incoming(current_state());
return successor->entry_block();
}
else {
return make_trap(
exc_handler(index)->handler_bci(),
Deoptimization::make_trap_request(
Deoptimization::Reason_unhandled,
Deoptimization::Action_reinterpret));
}
}
void SharkTopLevelBlock::maybe_add_safepoint() {
if (current_state()->has_safepointed())
return;
BasicBlock *orig_block = builder()->GetInsertBlock();
SharkState *orig_state = current_state()->copy();
BasicBlock *do_safepoint = function()->CreateBlock("do_safepoint");
BasicBlock *safepointed = function()->CreateBlock("safepointed");
Value *state = builder()->CreateLoad(
builder()->CreateIntToPtr(
LLVMValue::intptr_constant(
(intptr_t) SafepointSynchronize::address_of_state()),
PointerType::getUnqual(SharkType::jint_type())),
"state");
builder()->CreateCondBr(
builder()->CreateICmpEQ(
state,
LLVMValue::jint_constant(SafepointSynchronize::_synchronizing)),
do_safepoint, safepointed);
builder()->SetInsertPoint(do_safepoint);
call_vm(builder()->safepoint(), EX_CHECK_FULL);
BasicBlock *safepointed_block = builder()->GetInsertBlock();
builder()->CreateBr(safepointed);
builder()->SetInsertPoint(safepointed);
current_state()->merge(orig_state, orig_block, safepointed_block);
current_state()->set_has_safepointed(true);
}
void SharkTopLevelBlock::maybe_add_backedge_safepoint() {
if (current_state()->has_safepointed())
return;
for (int i = 0; i < num_successors(); i++) {
if (successor(i)->can_reach(this)) {
maybe_add_safepoint();
break;
}
}
}
bool SharkTopLevelBlock::can_reach(SharkTopLevelBlock* other) {
for (int i = 0; i < function()->block_count(); i++)
function()->block(i)->_can_reach_visited = false;
return can_reach_helper(other);
}
bool SharkTopLevelBlock::can_reach_helper(SharkTopLevelBlock* other) {
if (this == other)
return true;
if (_can_reach_visited)
return false;
_can_reach_visited = true;
if (!has_trap()) {
for (int i = 0; i < num_successors(); i++) {
if (successor(i)->can_reach_helper(other))
return true;
}
}
for (int i = 0; i < num_exceptions(); i++) {
SharkTopLevelBlock *handler = exception(i);
if (handler && handler->can_reach_helper(other))
return true;
}
return false;
}
BasicBlock* SharkTopLevelBlock::make_trap(int trap_bci, int trap_request) {
BasicBlock *trap_block = function()->CreateBlock("trap");
BasicBlock *orig_block = builder()->GetInsertBlock();
builder()->SetInsertPoint(trap_block);
int orig_bci = bci();
iter()->force_bci(trap_bci);
do_trap(trap_request);
builder()->SetInsertPoint(orig_block);
iter()->force_bci(orig_bci);
return trap_block;
}
void SharkTopLevelBlock::do_trap(int trap_request) {
decache_for_trap();
builder()->CreateRet(
builder()->CreateCall2(
builder()->uncommon_trap(),
thread(),
LLVMValue::jint_constant(trap_request)));
}
void SharkTopLevelBlock::call_register_finalizer(Value *receiver) {
BasicBlock *orig_block = builder()->GetInsertBlock();
SharkState *orig_state = current_state()->copy();
BasicBlock *do_call = function()->CreateBlock("has_finalizer");
BasicBlock *done = function()->CreateBlock("done");
Value *klass = builder()->CreateValueOfStructEntry(
receiver,
in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
"klass");
Value *access_flags = builder()->CreateValueOfStructEntry(
klass,
Klass::access_flags_offset(),
SharkType::jint_type(),
"access_flags");
builder()->CreateCondBr(
builder()->CreateICmpNE(
builder()->CreateAnd(
access_flags,
LLVMValue::jint_constant(JVM_ACC_HAS_FINALIZER)),
LLVMValue::jint_constant(0)),
do_call, done);
builder()->SetInsertPoint(do_call);
call_vm(builder()->register_finalizer(), receiver, EX_CHECK_FULL);
BasicBlock *branch_block = builder()->GetInsertBlock();
builder()->CreateBr(done);
builder()->SetInsertPoint(done);
current_state()->merge(orig_state, orig_block, branch_block);
}
void SharkTopLevelBlock::handle_return(BasicType type, Value* exception) {
assert (exception == NULL || type == T_VOID, "exception OR result, please");
if (num_monitors()) {
if (exception)
set_oop_tmp(exception);
while (num_monitors())
release_lock(EX_CHECK_NONE);
if (exception)
exception = get_oop_tmp();
}
if (exception) {
builder()->CreateStore(exception, pending_exception_address());
}
Value *result_addr = stack()->CreatePopFrame(type2size[type]);
if (type != T_VOID) {
builder()->CreateStore(
pop_result(type)->generic_value(),
builder()->CreateIntToPtr(
result_addr,
PointerType::getUnqual(SharkType::to_stackType(type))));
}
builder()->CreateRet(LLVMValue::jint_constant(0));
}
void SharkTopLevelBlock::do_arraylength() {
SharkValue *array = pop();
check_null(array);
Value *length = builder()->CreateArrayLength(array->jarray_value());
push(SharkValue::create_jint(length, false));
}
void SharkTopLevelBlock::do_aload(BasicType basic_type) {
SharkValue *index = pop();
SharkValue *array = pop();
check_null(array);
check_bounds(array, index);
Value *value = builder()->CreateLoad(
builder()->CreateArrayAddress(
array->jarray_value(), basic_type, index->jint_value()));
Type *stack_type = SharkType::to_stackType(basic_type);
if (value->getType() != stack_type)
value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR);
switch (basic_type) {
case T_BYTE:
case T_CHAR:
case T_SHORT:
case T_INT:
push(SharkValue::create_jint(value, false));
break;
case T_LONG:
push(SharkValue::create_jlong(value, false));
break;
case T_FLOAT:
push(SharkValue::create_jfloat(value));
break;
case T_DOUBLE:
push(SharkValue::create_jdouble(value));
break;
case T_OBJECT:
push(
SharkValue::create_generic(
array->type()->is_array_klass() ?
((ciArrayKlass *) array->type())->element_type() :
ciType::make(basic_type),
value, false));
break;
default:
tty->print_cr("Unhandled type %s", type2name(basic_type));
ShouldNotReachHere();
}
}
void SharkTopLevelBlock::do_astore(BasicType basic_type) {
SharkValue *svalue = pop();
SharkValue *index = pop();
SharkValue *array = pop();
check_null(array);
check_bounds(array, index);
Value *value;
switch (basic_type) {
case T_BYTE:
case T_CHAR:
case T_SHORT:
case T_INT:
value = svalue->jint_value();
break;
case T_LONG:
value = svalue->jlong_value();
break;
case T_FLOAT:
value = svalue->jfloat_value();
break;
case T_DOUBLE:
value = svalue->jdouble_value();
break;
case T_OBJECT:
value = svalue->jobject_value();
break;
default:
tty->print_cr("Unhandled type %s", type2name(basic_type));
ShouldNotReachHere();
}
Type *array_type = SharkType::to_arrayType(basic_type);
if (value->getType() != array_type)
value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR);
Value *addr = builder()->CreateArrayAddress(
array->jarray_value(), basic_type, index->jint_value(), "addr");
builder()->CreateStore(value, addr);
if (basic_type == T_OBJECT) // XXX or T_ARRAY?
builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
}
void SharkTopLevelBlock::do_return(BasicType type) {
if (target()->intrinsic_id() == vmIntrinsics::_Object_init)
call_register_finalizer(local(0)->jobject_value());
maybe_add_safepoint();
handle_return(type, NULL);
}
void SharkTopLevelBlock::do_athrow() {
SharkValue *exception = pop();
check_null(exception);
handle_exception(exception->jobject_value(), EX_CHECK_FULL);
}
void SharkTopLevelBlock::do_goto() {
do_branch(ciTypeFlow::GOTO_TARGET);
}
void SharkTopLevelBlock::do_jsr() {
push(SharkValue::address_constant(iter()->next_bci()));
do_branch(ciTypeFlow::GOTO_TARGET);
}
void SharkTopLevelBlock::do_ret() {
assert(local(iter()->get_index())->address_value() ==
successor(ciTypeFlow::GOTO_TARGET)->start(), "should be");
do_branch(ciTypeFlow::GOTO_TARGET);
}
void SharkTopLevelBlock::do_branch(int successor_index) {
SharkTopLevelBlock *dest = successor(successor_index);
builder()->CreateBr(dest->entry_block());
dest->add_incoming(current_state());
}
void SharkTopLevelBlock::do_if(ICmpInst::Predicate p,
SharkValue* b,
SharkValue* a) {
Value *llvm_a, *llvm_b;
if (a->is_jobject()) {
llvm_a = a->intptr_value(builder());
llvm_b = b->intptr_value(builder());
}
else {
llvm_a = a->jint_value();
llvm_b = b->jint_value();
}
do_if_helper(p, llvm_b, llvm_a, current_state(), current_state());
}
void SharkTopLevelBlock::do_if_helper(ICmpInst::Predicate p,
Value* b,
Value* a,
SharkState* if_taken_state,
SharkState* not_taken_state) {
SharkTopLevelBlock *if_taken = successor(ciTypeFlow::IF_TAKEN);
SharkTopLevelBlock *not_taken = successor(ciTypeFlow::IF_NOT_TAKEN);
builder()->CreateCondBr(
builder()->CreateICmp(p, a, b),
if_taken->entry_block(), not_taken->entry_block());
if_taken->add_incoming(if_taken_state);
not_taken->add_incoming(not_taken_state);
}
void SharkTopLevelBlock::do_switch() {
int len = switch_table_length();
SharkTopLevelBlock *dest_block = successor(ciTypeFlow::SWITCH_DEFAULT);
SwitchInst *switchinst = builder()->CreateSwitch(
pop()->jint_value(), dest_block->entry_block(), len);
dest_block->add_incoming(current_state());
for (int i = 0; i < len; i++) {
int dest_bci = switch_dest(i);
if (dest_bci != switch_default_dest()) {
dest_block = bci_successor(dest_bci);
switchinst->addCase(
LLVMValue::jint_constant(switch_key(i)),
dest_block->entry_block());
dest_block->add_incoming(current_state());
}
}
}
ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller,
ciInstanceKlass* klass,
ciMethod* dest_method,
ciType* receiver_type) {
if (dest_method->can_be_statically_bound())
return dest_method;
if (receiver_type->is_array_klass() &&
dest_method->holder() == java_lang_Object_klass())
return dest_method;
if (!receiver_type->is_instance_klass())
return NULL;
ciInstanceKlass* actual_receiver = klass;
ciInstanceKlass *improved_receiver = receiver_type->as_instance_klass();
if (improved_receiver->is_loaded() &&
improved_receiver->is_initialized() &&
!improved_receiver->is_interface() &&
improved_receiver->is_subtype_of(actual_receiver)) {
actual_receiver = improved_receiver;
}
ciInstanceKlass *calling_klass = caller->holder();
ciMethod* monomorphic_target =
dest_method->find_monomorphic_target(calling_klass, klass, actual_receiver);
if (monomorphic_target != NULL) {
assert(!monomorphic_target->is_abstract(), "shouldn't be");
function()->dependencies()->assert_unique_concrete_method(actual_receiver, monomorphic_target);
if (monomorphic_target != dest_method) {
if (SharkPerformanceWarnings) {
warning("found monomorphic target, but inhibited cast:");
tty->print(" dest_method = ");
dest_method->print_short_name(tty);
tty->cr();
tty->print(" monomorphic_target = ");
monomorphic_target->print_short_name(tty);
tty->cr();
}
monomorphic_target = NULL;
}
}
if (monomorphic_target != NULL) {
dependencies()->assert_unique_concrete_method(
actual_receiver, monomorphic_target);
return monomorphic_target;
}
return NULL;
}
Value *SharkTopLevelBlock::get_direct_callee(ciMethod* method) {
return builder()->CreateBitCast(
builder()->CreateInlineMetadata(method, SharkType::Method_type()),
SharkType::Method_type(),
"callee");
}
Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver,
int vtable_index) {
Value *klass = builder()->CreateValueOfStructEntry(
receiver->jobject_value(),
in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::oop_type(),
"klass");
return builder()->CreateLoad(
builder()->CreateArrayAddress(
klass,
SharkType::Method_type(),
vtableEntry::size() * wordSize,
in_ByteSize(InstanceKlass::vtable_start_offset() * wordSize),
LLVMValue::intptr_constant(vtable_index)),
"callee");
}
Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver,
ciMethod* method) {
BasicBlock *loop = function()->CreateBlock("loop");
BasicBlock *got_null = function()->CreateBlock("got_null");
BasicBlock *not_null = function()->CreateBlock("not_null");
BasicBlock *next = function()->CreateBlock("next");
BasicBlock *got_entry = function()->CreateBlock("got_entry");
Value *object_klass = builder()->CreateValueOfStructEntry(
receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::klass_type(),
"object_klass");
Value *vtable_start = builder()->CreateAdd(
builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()),
LLVMValue::intptr_constant(
InstanceKlass::vtable_start_offset() * HeapWordSize),
"vtable_start");
Value *vtable_length = builder()->CreateValueOfStructEntry(
object_klass,
in_ByteSize(InstanceKlass::vtable_length_offset() * HeapWordSize),
SharkType::jint_type(),
"vtable_length");
vtable_length =
builder()->CreateIntCast(vtable_length, SharkType::intptr_type(), false);
bool needs_aligning = HeapWordsPerLong > 1;
Value *itable_start = builder()->CreateAdd(
vtable_start,
builder()->CreateShl(
vtable_length,
LLVMValue::intptr_constant(exact_log2(vtableEntry::size() * wordSize))),
needs_aligning ? "" : "itable_start");
if (needs_aligning) {
itable_start = builder()->CreateAnd(
builder()->CreateAdd(
itable_start, LLVMValue::intptr_constant(BytesPerLong - 1)),
LLVMValue::intptr_constant(~(BytesPerLong - 1)),
"itable_start");
}
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(), 0, "itable_entry_addr");
itable_entry_addr->addIncoming(itable_start, loop_entry);
Value *itable_entry = builder()->CreateIntToPtr(
itable_entry_addr, SharkType::itableOffsetEntry_type(), "itable_entry");
Value *itable_iklass = builder()->CreateValueOfStructEntry(
itable_entry,
in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()),
SharkType::klass_type(),
"itable_iklass");
builder()->CreateCondBr(
builder()->CreateICmpEQ(itable_iklass, LLVMValue::nullKlass()),
got_null, not_null);
builder()->SetInsertPoint(got_null);
builder()->CreateUnimplemented(__FILE__, __LINE__);
builder()->CreateUnreachable();
builder()->SetInsertPoint(not_null);
builder()->CreateCondBr(
builder()->CreateICmpEQ(itable_iklass, iklass),
got_entry, next);
builder()->SetInsertPoint(next);
Value *next_entry = builder()->CreateAdd(
itable_entry_addr,
LLVMValue::intptr_constant(itableOffsetEntry::size() * wordSize));
builder()->CreateBr(loop);
itable_entry_addr->addIncoming(next_entry, next);
builder()->SetInsertPoint(got_entry);
Value *offset = builder()->CreateValueOfStructEntry(
itable_entry,
in_ByteSize(itableOffsetEntry::offset_offset_in_bytes()),
SharkType::jint_type(),
"offset");
offset =
builder()->CreateIntCast(offset, SharkType::intptr_type(), false);
return builder()->CreateLoad(
builder()->CreateIntToPtr(
builder()->CreateAdd(
builder()->CreateAdd(
builder()->CreateAdd(
builder()->CreatePtrToInt(
object_klass, SharkType::intptr_type()),
offset),
LLVMValue::intptr_constant(
method->itable_index() * itableMethodEntry::size() * wordSize)),
LLVMValue::intptr_constant(
itableMethodEntry::method_offset_in_bytes())),
PointerType::getUnqual(SharkType::Method_type())),
"callee");
}
void SharkTopLevelBlock::do_call() {
bool is_static = bc() == Bytecodes::_invokestatic;
bool is_virtual = bc() == Bytecodes::_invokevirtual;
bool is_interface = bc() == Bytecodes::_invokeinterface;
bool 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");
ciInstanceKlass *holder_klass = dest_method->holder();
assert(holder_klass->is_loaded(), "scan_for_traps responsibility");
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();
}
SharkValue *receiver = NULL;
if (!is_static) {
receiver = xstack(dest_method->arg_size() - 1);
check_null(receiver);
}
bool call_is_virtual = is_virtual || is_interface;
ciMethod *call_method = dest_method;
if (call_is_virtual) {
ciMethod *optimized_method = improve_virtual_call(
target(), klass, dest_method, receiver->type());
if (optimized_method) {
call_method = optimized_method;
call_is_virtual = false;
}
}
if (!call_is_virtual) {
if (SharkInliner::attempt_inline(call_method, current_state())) {
return;
}
}
Value *callee;
if (call_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);
assert(vtable_index >= 0, "should be");
callee = get_virtual_callee(receiver, vtable_index);
}
else {
assert(is_interface, "should be");
callee = get_interface_callee(receiver, call_method);
}
}
else {
callee = get_direct_callee(call_method);
}
Value *base_pc = builder()->CreateValueOfStructEntry(
callee, Method::from_interpreted_offset(),
SharkType::intptr_type(),
"base_pc");
Value *entry_point = builder()->CreateLoad(
builder()->CreateIntToPtr(
builder()->CreateAdd(
base_pc,
LLVMValue::intptr_constant(in_bytes(ZeroEntry::entry_point_offset()))),
PointerType::getUnqual(
PointerType::getUnqual(SharkType::entry_point_type()))),
"entry_point");
decache_for_Java_call(call_method);
Value *deoptimized_frames = builder()->CreateCall3(
entry_point, callee, base_pc, thread());
BasicBlock *reexecute = function()->CreateBlock("reexecute");
BasicBlock *call_completed = function()->CreateBlock("call_completed");
builder()->CreateCondBr(
builder()->CreateICmpNE(deoptimized_frames, LLVMValue::jint_constant(0)),
reexecute, call_completed);
builder()->SetInsertPoint(reexecute);
builder()->CreateCall2(
builder()->deoptimized_entry_point(),
builder()->CreateSub(deoptimized_frames, LLVMValue::jint_constant(1)),
thread());
builder()->CreateBr(call_completed);
builder()->SetInsertPoint(call_completed);
cache_after_Java_call(call_method);
check_pending_exception(EX_CHECK_FULL);
current_state()->set_has_safepointed(true);
}
bool SharkTopLevelBlock::static_subtype_check(ciKlass* check_klass,
ciKlass* object_klass) {
if (check_klass == java_lang_Object_klass())
return true;
if (object_klass->is_loaded() && !object_klass->is_interface()) {
if (object_klass == check_klass)
return true;
if (check_klass->is_loaded() && object_klass->is_subtype_of(check_klass))
return true;
}
return false;
}
void SharkTopLevelBlock::do_instance_check() {
bool will_link;
ciKlass *check_klass = iter()->get_klass(will_link);
ciKlass *object_klass = xstack(0)->type()->as_klass();
if (static_subtype_check(check_klass, object_klass)) {
if (bc() == Bytecodes::_instanceof) {
pop();
push(SharkValue::jint_constant(1));
}
return;
}
if (will_link)
do_full_instance_check(check_klass);
else
do_trapping_instance_check(check_klass);
}
bool SharkTopLevelBlock::maybe_do_instanceof_if() {
bool will_link;
ciKlass *check_klass = iter()->get_klass(will_link);
if (!will_link)
return false;
SharkValue *old_object = xstack(0);
ciKlass *object_klass = old_object->type()->as_klass();
if (static_subtype_check(check_klass, object_klass))
return false;
do_full_instance_check(check_klass);
Value *result = pop()->jint_value();
SharkValue *new_object = SharkValue::create_generic(
check_klass, old_object->jobject_value(), old_object->zero_checked());
SharkState *new_state = current_state();
SharkState *old_state = new_state->copy();
new_state->replace_all(old_object, new_object);
switch (iter()->next_bc()) {
case Bytecodes::_ifeq:
do_if_helper(
ICmpInst::ICMP_EQ,
LLVMValue::jint_constant(0), result,
old_state, new_state);
break;
case Bytecodes::_ifne:
do_if_helper(
ICmpInst::ICMP_NE,
LLVMValue::jint_constant(0), result,
new_state, old_state);
break;
default:
ShouldNotReachHere();
}
return true;
}
void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) {
BasicBlock *not_null = function()->CreateBlock("not_null");
BasicBlock *subtype_check = function()->CreateBlock("subtype_check");
BasicBlock *is_instance = function()->CreateBlock("is_instance");
BasicBlock *not_instance = function()->CreateBlock("not_instance");
BasicBlock *merge1 = function()->CreateBlock("merge1");
BasicBlock *merge2 = function()->CreateBlock("merge2");
enum InstanceCheckStates {
IC_IS_NULL,
IC_IS_INSTANCE,
IC_NOT_INSTANCE,
};
Value *object = pop()->jobject_value();
builder()->CreateCondBr(
builder()->CreateICmpEQ(object, LLVMValue::null()),
merge2, not_null);
BasicBlock *null_block = builder()->GetInsertBlock();
builder()->SetInsertPoint(not_null);
Value *check_klass = builder()->CreateInlineMetadata(klass, SharkType::klass_type());
Value *object_klass = builder()->CreateValueOfStructEntry(
object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
SharkType::klass_type(),
"object_klass");
builder()->CreateCondBr(
builder()->CreateICmpEQ(check_klass, object_klass),
is_instance, subtype_check);
builder()->SetInsertPoint(subtype_check);
builder()->CreateCondBr(
builder()->CreateICmpNE(
builder()->CreateCall2(
builder()->is_subtype_of(), check_klass, object_klass),
LLVMValue::jbyte_constant(0)),
is_instance, not_instance);
builder()->SetInsertPoint(is_instance);
builder()->CreateBr(merge1);
builder()->SetInsertPoint(not_instance);
builder()->CreateBr(merge1);
builder()->SetInsertPoint(merge1);
PHINode *nonnull_result = builder()->CreatePHI(
SharkType::jint_type(), 0, "nonnull_result");
nonnull_result->addIncoming(
LLVMValue::jint_constant(IC_IS_INSTANCE), is_instance);
nonnull_result->addIncoming(
LLVMValue::jint_constant(IC_NOT_INSTANCE), not_instance);
BasicBlock *nonnull_block = builder()->GetInsertBlock();
builder()->CreateBr(merge2);
builder()->SetInsertPoint(merge2);
PHINode *result = builder()->CreatePHI(
SharkType::jint_type(), 0, "result");
result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block);
result->addIncoming(nonnull_result, nonnull_block);
if (bc() == Bytecodes::_checkcast) {
BasicBlock *failure = function()->CreateBlock("failure");
BasicBlock *success = function()->CreateBlock("success");
builder()->CreateCondBr(
builder()->CreateICmpNE(
result, LLVMValue::jint_constant(IC_NOT_INSTANCE)),
success, failure);
builder()->SetInsertPoint(failure);
SharkState *saved_state = current_state()->copy();
call_vm(
builder()->throw_ClassCastException(),
builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) __FILE__),
PointerType::getUnqual(SharkType::jbyte_type())),
LLVMValue::jint_constant(__LINE__),
EX_CHECK_NONE);
Value *pending_exception = get_pending_exception();
clear_pending_exception();
handle_exception(pending_exception, EX_CHECK_FULL);
set_current_state(saved_state);
builder()->SetInsertPoint(success);
push(SharkValue::create_generic(klass, object, false));
}
else {
push(
SharkValue::create_jint(
builder()->CreateIntCast(
builder()->CreateICmpEQ(
result, LLVMValue::jint_constant(IC_IS_INSTANCE)),
SharkType::jint_type(), false), false));
}
}
void SharkTopLevelBlock::do_trapping_instance_check(ciKlass* klass) {
BasicBlock *not_null = function()->CreateBlock("not_null");
BasicBlock *is_null = function()->CreateBlock("null");
builder()->CreateCondBr(
builder()->CreateICmpEQ(xstack(0)->jobject_value(), LLVMValue::null()),
is_null, not_null);
SharkState *saved_state = current_state()->copy();
builder()->SetInsertPoint(not_null);
set_current_state(saved_state->copy());
do_trap(
Deoptimization::make_trap_request(
Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret));
builder()->SetInsertPoint(is_null);
set_current_state(saved_state);
if (bc() == Bytecodes::_checkcast) {
push(SharkValue::create_generic(klass, pop()->jobject_value(), false));
}
else {
pop();
push(SharkValue::jint_constant(0));
}
}
void SharkTopLevelBlock::do_new() {
bool will_link;
ciInstanceKlass* klass = iter()->get_klass(will_link)->as_instance_klass();
assert(will_link, "typeflow responsibility");
BasicBlock *got_tlab = NULL;
BasicBlock *heap_alloc = NULL;
BasicBlock *retry = NULL;
BasicBlock *got_heap = NULL;
BasicBlock *initialize = NULL;
BasicBlock *got_fast = NULL;
BasicBlock *slow_alloc_and_init = NULL;
BasicBlock *got_slow = NULL;
BasicBlock *push_object = NULL;
SharkState *fast_state = NULL;
Value *tlab_object = NULL;
Value *heap_object = NULL;
Value *fast_object = NULL;
Value *slow_object = NULL;
Value *object = NULL;
if (!Klass::layout_helper_needs_slow_path(klass->layout_helper())) {
if (UseTLAB) {
got_tlab = function()->CreateBlock("got_tlab");
heap_alloc = function()->CreateBlock("heap_alloc");
}
retry = function()->CreateBlock("retry");
got_heap = function()->CreateBlock("got_heap");
initialize = function()->CreateBlock("initialize");
slow_alloc_and_init = function()->CreateBlock("slow_alloc_and_init");
push_object = function()->CreateBlock("push_object");
size_t size_in_bytes = klass->size_helper() << LogHeapWordSize;
if (UseTLAB) {
Value *top_addr = builder()->CreateAddressOfStructEntry(
thread(), Thread::tlab_top_offset(),
PointerType::getUnqual(SharkType::intptr_type()),
"top_addr");
Value *end = builder()->CreateValueOfStructEntry(
thread(), Thread::tlab_end_offset(),
SharkType::intptr_type(),
"end");
Value *old_top = builder()->CreateLoad(top_addr, "old_top");
Value *new_top = builder()->CreateAdd(
old_top, LLVMValue::intptr_constant(size_in_bytes));
builder()->CreateCondBr(
builder()->CreateICmpULE(new_top, end),
got_tlab, heap_alloc);
builder()->SetInsertPoint(got_tlab);
tlab_object = builder()->CreateIntToPtr(
old_top, SharkType::oop_type(), "tlab_object");
builder()->CreateStore(new_top, top_addr);
builder()->CreateBr(initialize);
builder()->SetInsertPoint(heap_alloc);
}
Value *top_addr = builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) Universe::heap()->top_addr()),
PointerType::getUnqual(SharkType::intptr_type()),
"top_addr");
Value *end = builder()->CreateLoad(
builder()->CreateIntToPtr(
LLVMValue::intptr_constant((intptr_t) Universe::heap()->end_addr()),
PointerType::getUnqual(SharkType::intptr_type())),
"end");
builder()->CreateBr(retry);
builder()->SetInsertPoint(retry);
Value *old_top = builder()->CreateLoad(top_addr, "top");
Value *new_top = builder()->CreateAdd(
old_top, LLVMValue::intptr_constant(size_in_bytes));
builder()->CreateCondBr(
builder()->CreateICmpULE(new_top, end),
got_heap, slow_alloc_and_init);
builder()->SetInsertPoint(got_heap);
heap_object = builder()->CreateIntToPtr(
old_top, SharkType::oop_type(), "heap_object");
Value *check = builder()->CreateAtomicCmpXchg(top_addr, old_top, new_top, llvm::SequentiallyConsistent);
builder()->CreateCondBr(
builder()->CreateICmpEQ(old_top, check),
initialize, retry);
builder()->SetInsertPoint(initialize);
if (tlab_object) {
PHINode *phi = builder()->CreatePHI(
SharkType::oop_type(), 0, "fast_object");
phi->addIncoming(tlab_object, got_tlab);
phi->addIncoming(heap_object, got_heap);
fast_object = phi;
}
else {
fast_object = heap_object;
}
builder()->CreateMemset(
builder()->CreateBitCast(
fast_object, PointerType::getUnqual(SharkType::jbyte_type())),
LLVMValue::jbyte_constant(0),
LLVMValue::jint_constant(size_in_bytes),
LLVMValue::jint_constant(HeapWordSize));
Value *mark_addr = builder()->CreateAddressOfStructEntry(
fast_object, in_ByteSize(oopDesc::mark_offset_in_bytes()),
PointerType::getUnqual(SharkType::intptr_type()),
"mark_addr");
Value *klass_addr = builder()->CreateAddressOfStructEntry(
fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
PointerType::getUnqual(SharkType::klass_type()),
"klass_addr");
intptr_t mark;
if (UseBiasedLocking) {
Unimplemented();
}
else {
mark = (intptr_t) markOopDesc::prototype();
}
builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr);
Value *rtklass = builder()->CreateInlineMetadata(klass, SharkType::klass_type());
builder()->CreateStore(rtklass, klass_addr);
got_fast = builder()->GetInsertBlock();
builder()->CreateBr(push_object);
builder()->SetInsertPoint(slow_alloc_and_init);
fast_state = current_state()->copy();
}
call_vm(
builder()->new_instance(),
LLVMValue::jint_constant(iter()->get_klass_index()),
EX_CHECK_FULL);
slow_object = get_vm_result();
got_slow = builder()->GetInsertBlock();
if (push_object) {
builder()->CreateBr(push_object);
builder()->SetInsertPoint(push_object);
}
if (fast_object) {
PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "object");
phi->addIncoming(fast_object, got_fast);
phi->addIncoming(slow_object, got_slow);
object = phi;
current_state()->merge(fast_state, got_fast, got_slow);
}
else {
object = slow_object;
}
push(SharkValue::create_jobject(object, true));
}
void SharkTopLevelBlock::do_newarray() {
BasicType type = (BasicType) iter()->get_index();
call_vm(
builder()->newarray(),
LLVMValue::jint_constant(type),
pop()->jint_value(),
EX_CHECK_FULL);
ciArrayKlass *array_klass = ciArrayKlass::make(ciType::make(type));
push(SharkValue::create_generic(array_klass, get_vm_result(), true));
}
void SharkTopLevelBlock::do_anewarray() {
bool will_link;
ciKlass *klass = iter()->get_klass(will_link);
assert(will_link, "typeflow responsibility");
ciObjArrayKlass *array_klass = ciObjArrayKlass::make(klass);
if (!array_klass->is_loaded()) {
Unimplemented();
}
call_vm(
builder()->anewarray(),
LLVMValue::jint_constant(iter()->get_klass_index()),
pop()->jint_value(),
EX_CHECK_FULL);
push(SharkValue::create_generic(array_klass, get_vm_result(), true));
}
void SharkTopLevelBlock::do_multianewarray() {
bool will_link;
ciArrayKlass *array_klass = iter()->get_klass(will_link)->as_array_klass();
assert(will_link, "typeflow responsibility");
int ndims = iter()->get_dimensions();
Value *dimensions = stack()->slot_addr(
stack()->stack_slots_offset() + max_stack() - xstack_depth(),
ArrayType::get(SharkType::jint_type(), ndims),
"dimensions");
for (int i = 0; i < ndims; i++) {
builder()->CreateStore(
xstack(ndims - 1 - i)->jint_value(),
builder()->CreateStructGEP(dimensions, i));
}
call_vm(
builder()->multianewarray(),
LLVMValue::jint_constant(iter()->get_klass_index()),
LLVMValue::jint_constant(ndims),
builder()->CreateStructGEP(dimensions, 0),
EX_CHECK_FULL);
for (int i = 0; i < ndims; i++)
pop();
push(SharkValue::create_generic(array_klass, get_vm_result(), true));
}
void SharkTopLevelBlock::acquire_method_lock() {
Value *lockee;
if (target()->is_static()) {
lockee = builder()->CreateInlineOop(target()->holder()->java_mirror());
}
else
lockee = local(0)->jobject_value();
iter()->force_bci(start()); // for the decache in acquire_lock
acquire_lock(lockee, EX_CHECK_NO_CATCH);
}
void SharkTopLevelBlock::do_monitorenter() {
SharkValue *lockee = pop();
check_null(lockee);
acquire_lock(lockee->jobject_value(), EX_CHECK_FULL);
}
void SharkTopLevelBlock::do_monitorexit() {
pop(); // don't need this (monitors are block structured)
release_lock(EX_CHECK_NO_CATCH);
}
void SharkTopLevelBlock::acquire_lock(Value *lockee, int exception_action) {
BasicBlock *try_recursive = function()->CreateBlock("try_recursive");
BasicBlock *got_recursive = function()->CreateBlock("got_recursive");
BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
BasicBlock *acquired_fast = function()->CreateBlock("acquired_fast");
BasicBlock *lock_acquired = function()->CreateBlock("lock_acquired");
int monitor = num_monitors();
Value *monitor_addr = stack()->monitor_addr(monitor);
Value *monitor_object_addr = stack()->monitor_object_addr(monitor);
Value *monitor_header_addr = stack()->monitor_header_addr(monitor);
builder()->CreateStore(lockee, monitor_object_addr);
set_num_monitors(monitor + 1);
Value *mark_addr = builder()->CreateAddressOfStructEntry(
lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
PointerType::getUnqual(SharkType::intptr_type()),
"mark_addr");
Value *mark = builder()->CreateLoad(mark_addr, "mark");
Value *disp = builder()->CreateOr(
mark, LLVMValue::intptr_constant(markOopDesc::unlocked_value), "disp");
builder()->CreateStore(disp, monitor_header_addr);
Value *lock = builder()->CreatePtrToInt(
monitor_header_addr, SharkType::intptr_type());
Value *check = builder()->CreateAtomicCmpXchg(mark_addr, disp, lock, llvm::Acquire);
builder()->CreateCondBr(
builder()->CreateICmpEQ(disp, check),
acquired_fast, try_recursive);
builder()->SetInsertPoint(try_recursive);
Value *addr = builder()->CreateAnd(
disp,
LLVMValue::intptr_constant(~markOopDesc::lock_mask_in_place));
Value *stack_limit = builder()->CreateValueOfStructEntry(
thread(), Thread::stack_base_offset(),
SharkType::intptr_type(),
"stack_limit");
assert(sizeof(size_t) == sizeof(intptr_t), "should be");
Value *stack_size = builder()->CreateValueOfStructEntry(
thread(), Thread::stack_size_offset(),
SharkType::intptr_type(),
"stack_size");
Value *stack_start =
builder()->CreateSub(stack_limit, stack_size, "stack_start");
builder()->CreateCondBr(
builder()->CreateAnd(
builder()->CreateICmpUGE(addr, stack_start),
builder()->CreateICmpULT(addr, stack_limit)),
got_recursive, not_recursive);
builder()->SetInsertPoint(got_recursive);
builder()->CreateStore(LLVMValue::intptr_constant(0), monitor_header_addr);
builder()->CreateBr(acquired_fast);
builder()->SetInsertPoint(acquired_fast);
SharkState *fast_state = current_state()->copy();
builder()->CreateBr(lock_acquired);
builder()->SetInsertPoint(not_recursive);
call_vm(
builder()->monitorenter(), monitor_addr,
exception_action | EAM_MONITOR_FUDGE);
BasicBlock *acquired_slow = builder()->GetInsertBlock();
builder()->CreateBr(lock_acquired);
builder()->SetInsertPoint(lock_acquired);
current_state()->merge(fast_state, acquired_fast, acquired_slow);
}
void SharkTopLevelBlock::release_lock(int exception_action) {
BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
BasicBlock *released_fast = function()->CreateBlock("released_fast");
BasicBlock *slow_path = function()->CreateBlock("slow_path");
BasicBlock *lock_released = function()->CreateBlock("lock_released");
int monitor = num_monitors() - 1;
Value *monitor_addr = stack()->monitor_addr(monitor);
Value *monitor_object_addr = stack()->monitor_object_addr(monitor);
Value *monitor_header_addr = stack()->monitor_header_addr(monitor);
Value *disp = builder()->CreateLoad(monitor_header_addr);
builder()->CreateCondBr(
builder()->CreateICmpEQ(disp, LLVMValue::intptr_constant(0)),
released_fast, not_recursive);
builder()->SetInsertPoint(not_recursive);
Value *lock = builder()->CreatePtrToInt(
monitor_header_addr, SharkType::intptr_type());
Value *lockee = builder()->CreateLoad(monitor_object_addr);
Value *mark_addr = builder()->CreateAddressOfStructEntry(
lockee, in_ByteSize(oopDesc::mark_offset_in_bytes()),
PointerType::getUnqual(SharkType::intptr_type()),
"mark_addr");
Value *check = builder()->CreateAtomicCmpXchg(mark_addr, lock, disp, llvm::Release);
builder()->CreateCondBr(
builder()->CreateICmpEQ(lock, check),
released_fast, slow_path);
builder()->SetInsertPoint(released_fast);
SharkState *fast_state = current_state()->copy();
builder()->CreateBr(lock_released);
builder()->SetInsertPoint(slow_path);
call_vm(builder()->monitorexit(), monitor_addr, exception_action);
BasicBlock *released_slow = builder()->GetInsertBlock();
builder()->CreateBr(lock_released);
builder()->SetInsertPoint(lock_released);
current_state()->merge(fast_state, released_fast, released_slow);
set_num_monitors(monitor);
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkTopLevelBlock.hpp
#ifndef SHARE_VM_SHARK_SHARKTOPLEVELBLOCK_HPP
#define SHARE_VM_SHARK_SHARKTOPLEVELBLOCK_HPP
#include "ci/ciStreams.hpp"
#include "ci/ciType.hpp"
#include "ci/ciTypeFlow.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkBlock.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkFunction.hpp"
#include "shark/sharkState.hpp"
#include "shark/sharkValue.hpp"
class SharkTopLevelBlock : public SharkBlock {
public:
SharkTopLevelBlock(SharkFunction* function, ciTypeFlow::Block* ciblock)
: SharkBlock(function),
_function(function),
_ciblock(ciblock),
_entered(false),
_has_trap(false),
_needs_phis(false),
_entry_state(NULL),
_entry_block(NULL) {}
private:
SharkFunction* _function;
ciTypeFlow::Block* _ciblock;
public:
SharkFunction* function() const {
return _function;
}
ciTypeFlow::Block* ciblock() const {
return _ciblock;
}
public:
SharkStack* stack() const {
return function()->stack();
}
public:
int index() const {
return ciblock()->pre_order();
}
bool is_backedge_copy() const {
return ciblock()->is_backedge_copy();
}
int stack_depth_at_entry() const {
return ciblock()->stack_size();
}
ciType* local_type_at_entry(int index) const {
return ciblock()->local_type_at(index);
}
ciType* stack_type_at_entry(int slot) const {
return ciblock()->stack_type_at(slot);
}
int start() const {
return ciblock()->start();
}
int limit() const {
return ciblock()->limit();
}
bool falls_through() const {
return ciblock()->control() == ciBlock::fall_through_bci;
}
int num_successors() const {
return ciblock()->successors()->length();
}
SharkTopLevelBlock* successor(int index) const {
return function()->block(ciblock()->successors()->at(index)->pre_order());
}
SharkTopLevelBlock* bci_successor(int bci) const;
private:
GrowableArray<ciExceptionHandler*>* _exc_handlers;
GrowableArray<SharkTopLevelBlock*>* _exceptions;
private:
void compute_exceptions();
private:
int num_exceptions() const {
return _exc_handlers->length();
}
ciExceptionHandler* exc_handler(int index) const {
return _exc_handlers->at(index);
}
SharkTopLevelBlock* exception(int index) const {
return _exceptions->at(index);
}
private:
bool _has_trap;
int _trap_request;
int _trap_bci;
void set_trap(int trap_request, int trap_bci) {
assert(!has_trap(), "shouldn't have");
_has_trap = true;
_trap_request = trap_request;
_trap_bci = trap_bci;
}
private:
bool has_trap() {
return _has_trap;
}
int trap_request() {
assert(has_trap(), "should have");
return _trap_request;
}
int trap_bci() {
assert(has_trap(), "should have");
return _trap_bci;
}
private:
void scan_for_traps();
private:
bool static_field_ok_in_clinit(ciField* field);
private:
bool _entered;
bool _needs_phis;
public:
bool entered() const {
return _entered;
}
bool needs_phis() const {
return _needs_phis;
}
private:
void enter(SharkTopLevelBlock* predecessor, bool is_exception);
public:
void enter() {
enter(NULL, false);
}
private:
SharkState* _entry_state;
private:
SharkState* entry_state();
private:
llvm::BasicBlock* _entry_block;
public:
llvm::BasicBlock* entry_block() const {
return _entry_block;
}
public:
void initialize();
public:
void add_incoming(SharkState* incoming_state);
public:
llvm::Value* method() {
return current_state()->method();
}
public:
void set_oop_tmp(llvm::Value* value) {
assert(value, "value must be non-NULL (will be reset by get_oop_tmp)");
assert(!current_state()->oop_tmp(), "oop_tmp gets and sets must match");
current_state()->set_oop_tmp(value);
}
llvm::Value* get_oop_tmp() {
llvm::Value* value = current_state()->oop_tmp();
assert(value, "oop_tmp gets and sets must match");
current_state()->set_oop_tmp(NULL);
return value;
}
private:
void decache_for_Java_call(ciMethod* callee);
void cache_after_Java_call(ciMethod* callee);
void decache_for_VM_call();
void cache_after_VM_call();
void decache_for_trap();
private:
int num_monitors() {
return current_state()->num_monitors();
}
int set_num_monitors(int num_monitors) {
current_state()->set_num_monitors(num_monitors);
}
public:
void emit_IR();
private:
void do_branch(int successor_index);
private:
void do_zero_check(SharkValue* value);
void zero_check_value(SharkValue* value, llvm::BasicBlock* continue_block);
public:
void do_deferred_zero_check(SharkValue* value,
int bci,
SharkState* saved_state,
llvm::BasicBlock* continue_block);
private:
llvm::Value* pending_exception_address() const {
return builder()->CreateAddressOfStructEntry(
thread(), Thread::pending_exception_offset(),
llvm::PointerType::getUnqual(SharkType::oop_type()),
"pending_exception_addr");
}
llvm::LoadInst* get_pending_exception() const {
return builder()->CreateLoad(
pending_exception_address(), "pending_exception");
}
void clear_pending_exception() const {
builder()->CreateStore(LLVMValue::null(), pending_exception_address());
}
public:
enum ExceptionActionMask {
EAM_CHECK = 1, // whether to check for pending exceptions
EAM_HANDLE = 2, // whether to attempt to handle pending exceptions
EAM_MONITOR_FUDGE = 4, // whether the monitor count needs adjusting
EX_CHECK_NONE = 0,
EX_CHECK_NO_CATCH = EAM_CHECK,
EX_CHECK_FULL = EAM_CHECK | EAM_HANDLE
};
void check_pending_exception(int action);
void handle_exception(llvm::Value* exception, int action);
void marshal_exception_fast(int num_options);
void marshal_exception_slow(int num_options);
llvm::BasicBlock* handler_for_exception(int index);
private:
llvm::CallInst* call_vm(llvm::Value* callee,
llvm::Value** args_start,
llvm::Value** args_end,
int exception_action) {
decache_for_VM_call();
stack()->CreateSetLastJavaFrame();
llvm::CallInst *res = builder()->CreateCall(callee, llvm::makeArrayRef(args_start, args_end));
stack()->CreateResetLastJavaFrame();
cache_after_VM_call();
if (exception_action & EAM_CHECK) {
check_pending_exception(exception_action);
current_state()->set_has_safepointed(true);
}
return res;
}
public:
llvm::CallInst* call_vm(llvm::Value* callee,
int exception_action) {
llvm::Value *args[] = {thread()};
return call_vm(callee, args, args + 1, exception_action);
}
llvm::CallInst* call_vm(llvm::Value* callee,
llvm::Value* arg1,
int exception_action) {
llvm::Value *args[] = {thread(), arg1};
return call_vm(callee, args, args + 2, exception_action);
}
llvm::CallInst* call_vm(llvm::Value* callee,
llvm::Value* arg1,
llvm::Value* arg2,
int exception_action) {
llvm::Value *args[] = {thread(), arg1, arg2};
return call_vm(callee, args, args + 3, exception_action);
}
llvm::CallInst* call_vm(llvm::Value* callee,
llvm::Value* arg1,
llvm::Value* arg2,
llvm::Value* arg3,
int exception_action) {
llvm::Value *args[] = {thread(), arg1, arg2, arg3};
return call_vm(callee, args, args + 4, exception_action);
}
private:
llvm::LoadInst* get_vm_result() const {
llvm::Value *addr = builder()->CreateAddressOfStructEntry(
thread(), JavaThread::vm_result_offset(),
llvm::PointerType::getUnqual(SharkType::oop_type()),
"vm_result_addr");
llvm::LoadInst *result = builder()->CreateLoad(addr, "vm_result");
builder()->CreateStore(LLVMValue::null(), addr);
return result;
}
private:
void acquire_lock(llvm::Value* lockee, int exception_action);
void release_lock(int exception_action);
public:
void acquire_method_lock();
private:
void check_bounds(SharkValue* array, SharkValue* index);
private:
void maybe_add_safepoint();
void maybe_add_backedge_safepoint();
private:
bool _can_reach_visited;
bool can_reach(SharkTopLevelBlock* other);
bool can_reach_helper(SharkTopLevelBlock* other);
private:
llvm::BasicBlock* make_trap(int trap_bci, int trap_request);
void do_trap(int trap_request);
private:
void call_register_finalizer(llvm::Value* receiver);
void handle_return(BasicType type, llvm::Value* exception);
private:
void do_arraylength();
private:
void do_aload(BasicType basic_type);
void do_astore(BasicType basic_type);
private:
void do_return(BasicType type);
void do_athrow();
private:
void do_goto();
private:
void do_jsr();
void do_ret();
private:
void do_if_helper(llvm::ICmpInst::Predicate p,
llvm::Value* b,
llvm::Value* a,
SharkState* if_taken_state,
SharkState* not_taken_state);
void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
private:
void do_switch();
private:
ciMethod* improve_virtual_call(ciMethod* caller,
ciInstanceKlass* klass,
ciMethod* dest_method,
ciType* receiver_type);
llvm::Value* get_direct_callee(ciMethod* method);
llvm::Value* get_virtual_callee(SharkValue* receiver, int vtable_index);
llvm::Value* get_interface_callee(SharkValue* receiver, ciMethod* method);
void do_call();
private:
bool static_subtype_check(ciKlass* check_klass, ciKlass* object_klass);
void do_full_instance_check(ciKlass* klass);
void do_trapping_instance_check(ciKlass* klass);
void do_instance_check();
bool maybe_do_instanceof_if();
private:
void do_new();
void do_newarray();
void do_anewarray();
void do_multianewarray();
private:
void do_monitorenter();
void do_monitorexit();
};
#endif // SHARE_VM_SHARK_SHARKTOPLEVELBLOCK_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkType.hpp
#ifndef SHARE_VM_SHARK_SHARKTYPE_HPP
#define SHARE_VM_SHARK_SHARKTYPE_HPP
#include "ci/ciType.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/sharkContext.hpp"
#include "utilities/globalDefinitions.hpp"
class SharkType : public AllStatic {
private:
static SharkContext& context() {
return SharkContext::current();
}
public:
static llvm::Type* void_type() {
return context().void_type();
}
static llvm::IntegerType* bit_type() {
return context().bit_type();
}
static llvm::IntegerType* jbyte_type() {
return context().jbyte_type();
}
static llvm::IntegerType* jshort_type() {
return context().jshort_type();
}
static llvm::IntegerType* jint_type() {
return context().jint_type();
}
static llvm::IntegerType* jlong_type() {
return context().jlong_type();
}
static llvm::Type* jfloat_type() {
return context().jfloat_type();
}
static llvm::Type* jdouble_type() {
return context().jdouble_type();
}
static llvm::IntegerType* intptr_type() {
return context().intptr_type();
}
public:
static llvm::PointerType* itableOffsetEntry_type() {
return context().itableOffsetEntry_type();
}
static llvm::PointerType* jniEnv_type() {
return context().jniEnv_type();
}
static llvm::PointerType* jniHandleBlock_type() {
return context().jniHandleBlock_type();
}
static llvm::PointerType* Metadata_type() {
return context().Metadata_type();
}
static llvm::PointerType* klass_type() {
return context().klass_type();
}
static llvm::PointerType* Method_type() {
return context().Method_type();
}
static llvm::ArrayType* monitor_type() {
return context().monitor_type();
}
static llvm::PointerType* oop_type() {
return context().oop_type();
}
static llvm::PointerType* thread_type() {
return context().thread_type();
}
static llvm::PointerType* zeroStack_type() {
return context().zeroStack_type();
}
static llvm::FunctionType* entry_point_type() {
return context().entry_point_type();
}
static llvm::FunctionType* osr_entry_point_type() {
return context().osr_entry_point_type();
}
public:
static llvm::Type* to_stackType(BasicType type) {
return context().to_stackType(type);
}
static llvm::Type* to_stackType(ciType* type) {
return to_stackType(type->basic_type());
}
static llvm::Type* to_arrayType(BasicType type) {
return context().to_arrayType(type);
}
static llvm::Type* to_arrayType(ciType* type) {
return to_arrayType(type->basic_type());
}
};
#endif // SHARE_VM_SHARK_SHARKTYPE_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/sharkValue.cpp
#include "precompiled.hpp"
#include "ci/ciType.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
#include "shark/sharkBuilder.hpp"
#include "shark/sharkValue.hpp"
using namespace llvm;
SharkValue* SharkNormalValue::clone() const {
return SharkValue::create_generic(type(), generic_value(), zero_checked());
}
SharkValue* SharkPHIValue::clone() const {
return SharkValue::create_phi(type(), (PHINode *) generic_value(), this);
}
SharkValue* SharkAddressValue::clone() const {
return SharkValue::address_constant(address_value());
}
bool SharkValue::is_phi() const {
return false;
}
bool SharkPHIValue::is_phi() const {
return true;
}
SharkPHIValue* SharkValue::as_phi() {
ShouldNotCallThis();
}
SharkPHIValue* SharkPHIValue::as_phi() {
return this;
}
bool SharkNormalValue::equal_to(SharkValue *other) const {
return (this->type() == other->type() &&
this->generic_value() == other->generic_value() &&
this->zero_checked() == other->zero_checked());
}
bool SharkAddressValue::equal_to(SharkValue *other) const {
return (this->address_value() == other->address_value());
}
ciType* SharkValue::type() const {
ShouldNotCallThis();
}
ciType* SharkNormalValue::type() const {
return _type;
}
BasicType SharkNormalValue::basic_type() const {
return type()->basic_type();
}
BasicType SharkAddressValue::basic_type() const {
return T_ADDRESS;
}
int SharkNormalValue::size() const {
return type()->size();
}
int SharkAddressValue::size() const {
return 1;
}
bool SharkValue::is_jint() const {
return false;
}
bool SharkValue::is_jlong() const {
return false;
}
bool SharkValue::is_jfloat() const {
return false;
}
bool SharkValue::is_jdouble() const {
return false;
}
bool SharkValue::is_jobject() const {
return false;
}
bool SharkValue::is_jarray() const {
return false;
}
bool SharkValue::is_address() const {
return false;
}
bool SharkNormalValue::is_jint() const {
return llvm_value()->getType() == SharkType::jint_type();
}
bool SharkNormalValue::is_jlong() const {
return llvm_value()->getType() == SharkType::jlong_type();
}
bool SharkNormalValue::is_jfloat() const {
return llvm_value()->getType() == SharkType::jfloat_type();
}
bool SharkNormalValue::is_jdouble() const {
return llvm_value()->getType() == SharkType::jdouble_type();
}
bool SharkNormalValue::is_jobject() const {
return llvm_value()->getType() == SharkType::oop_type();
}
bool SharkNormalValue::is_jarray() const {
return basic_type() == T_ARRAY;
}
bool SharkAddressValue::is_address() const {
return true;
}
Value* SharkValue::jint_value() const {
ShouldNotCallThis();
}
Value* SharkValue::jlong_value() const {
ShouldNotCallThis();
}
Value* SharkValue::jfloat_value() const {
ShouldNotCallThis();
}
Value* SharkValue::jdouble_value() const {
ShouldNotCallThis();
}
Value* SharkValue::jobject_value() const {
ShouldNotCallThis();
}
Value* SharkValue::jarray_value() const {
ShouldNotCallThis();
}
int SharkValue::address_value() const {
ShouldNotCallThis();
}
Value* SharkNormalValue::jint_value() const {
assert(is_jint(), "should be");
return llvm_value();
}
Value* SharkNormalValue::jlong_value() const {
assert(is_jlong(), "should be");
return llvm_value();
}
Value* SharkNormalValue::jfloat_value() const {
assert(is_jfloat(), "should be");
return llvm_value();
}
Value* SharkNormalValue::jdouble_value() const {
assert(is_jdouble(), "should be");
return llvm_value();
}
Value* SharkNormalValue::jobject_value() const {
assert(is_jobject(), "should be");
return llvm_value();
}
Value* SharkNormalValue::jarray_value() const {
assert(is_jobject(), "should be");
return llvm_value();
}
int SharkAddressValue::address_value() const {
return _bci;
}
Value* SharkNormalValue::generic_value() const {
return llvm_value();
}
Value* SharkAddressValue::generic_value() const {
return LLVMValue::intptr_constant(address_value());
}
Value* SharkValue::intptr_value(SharkBuilder* builder) const {
ShouldNotCallThis();
}
Value* SharkNormalValue::intptr_value(SharkBuilder* builder) const {
return builder->CreatePtrToInt(jobject_value(), SharkType::intptr_type());
}
void SharkValue::addIncoming(SharkValue *value, BasicBlock* block) {
ShouldNotCallThis();
}
void SharkPHIValue::addIncoming(SharkValue *value, BasicBlock* block) {
assert(!is_clone(), "shouldn't be");
((llvm::PHINode *) generic_value())->addIncoming(
value->generic_value(), block);
if (!value->zero_checked())
_all_incomers_zero_checked = false;
}
void SharkAddressValue::addIncoming(SharkValue *value, BasicBlock* block) {
assert(this->equal_to(value), "should be");
}
SharkValue* SharkNormalValue::merge(SharkBuilder* builder,
SharkValue* other,
BasicBlock* other_block,
BasicBlock* this_block,
const char* name) {
assert(type() == other->type(), "should be");
assert(zero_checked() == other->zero_checked(), "should be");
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());
}
SharkValue* SharkAddressValue::merge(SharkBuilder* builder,
SharkValue* other,
BasicBlock* other_block,
BasicBlock* this_block,
const char* name) {
assert(this->equal_to(other), "should be");
return this;
}
bool SharkValue::zero_checked() const {
ShouldNotCallThis();
}
void SharkValue::set_zero_checked(bool zero_checked) {
ShouldNotCallThis();
}
bool SharkNormalValue::zero_checked() const {
return _zero_checked;
}
void SharkNormalValue::set_zero_checked(bool zero_checked) {
_zero_checked = zero_checked;
}
C:\hotspot-69087d08d473\src\share\vm/shark/sharkValue.hpp
#ifndef SHARE_VM_SHARK_SHARKVALUE_HPP
#define SHARE_VM_SHARK_SHARKVALUE_HPP
#include "ci/ciType.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
#include "shark/sharkType.hpp"
class SharkBuilder;
class SharkPHIValue;
class SharkValue : public ResourceObj {
protected:
SharkValue() {}
public:
virtual SharkValue* clone() const = 0;
public:
virtual bool is_phi() const;
virtual SharkPHIValue* as_phi();
public:
virtual bool equal_to(SharkValue* other) const = 0;
public:
virtual BasicType basic_type() const = 0;
virtual ciType* type() const;
virtual bool is_jint() const;
virtual bool is_jlong() const;
virtual bool is_jfloat() const;
virtual bool is_jdouble() const;
virtual bool is_jobject() const;
virtual bool is_jarray() const;
virtual bool is_address() const;
virtual int size() const = 0;
bool is_one_word() const {
return size() == 1;
}
bool is_two_word() const {
return size() == 2;
}
public:
virtual llvm::Value* jint_value() const;
virtual llvm::Value* jlong_value() const;
virtual llvm::Value* jfloat_value() const;
virtual llvm::Value* jdouble_value() const;
virtual llvm::Value* jobject_value() const;
virtual llvm::Value* jarray_value() const;
virtual int address_value() const;
public:
static SharkValue* create_jint(llvm::Value* value, bool zero_checked) {
assert(value->getType() == SharkType::jint_type(), "should be");
return create_generic(ciType::make(T_INT), value, zero_checked);
}
static SharkValue* create_jlong(llvm::Value* value, bool zero_checked) {
assert(value->getType() == SharkType::jlong_type(), "should be");
return create_generic(ciType::make(T_LONG), value, zero_checked);
}
static SharkValue* create_jfloat(llvm::Value* value) {
assert(value->getType() == SharkType::jfloat_type(), "should be");
return create_generic(ciType::make(T_FLOAT), value, false);
}
static SharkValue* create_jdouble(llvm::Value* value) {
assert(value->getType() == SharkType::jdouble_type(), "should be");
return create_generic(ciType::make(T_DOUBLE), value, false);
}
static SharkValue* create_jobject(llvm::Value* value, bool zero_checked) {
assert(value->getType() == SharkType::oop_type(), "should be");
return create_generic(ciType::make(T_OBJECT), value, zero_checked);
}
public:
static SharkValue* jint_constant(jint value) {
return create_jint(LLVMValue::jint_constant(value), value != 0);
}
static SharkValue* jlong_constant(jlong value) {
return create_jlong(LLVMValue::jlong_constant(value), value != 0);
}
static SharkValue* jfloat_constant(jfloat value) {
return create_jfloat(LLVMValue::jfloat_constant(value));
}
static SharkValue* jdouble_constant(jdouble value) {
return create_jdouble(LLVMValue::jdouble_constant(value));
}
static SharkValue* null() {
return create_jobject(LLVMValue::null(), false);
}
static inline SharkValue* address_constant(int bci);
public:
virtual llvm::Value* generic_value() const = 0;
virtual llvm::Value* intptr_value(SharkBuilder* builder) const;
static inline SharkValue* create_generic(ciType* type,
llvm::Value* value,
bool zero_checked);
static inline SharkValue* create_phi(ciType* type,
llvm::PHINode* phi,
const SharkPHIValue* parent = NULL);
public:
virtual void addIncoming(SharkValue* value, llvm::BasicBlock* block);
virtual SharkValue* merge(SharkBuilder* builder,
SharkValue* other,
llvm::BasicBlock* other_block,
llvm::BasicBlock* this_block,
const char* name) = 0;
public:
virtual bool zero_checked() const;
virtual void set_zero_checked(bool zero_checked);
};
class SharkNormalValue : public SharkValue {
friend class SharkValue;
protected:
SharkNormalValue(ciType* type, llvm::Value* value, bool zero_checked)
: _type(type), _llvm_value(value), _zero_checked(zero_checked) {}
private:
ciType* _type;
llvm::Value* _llvm_value;
bool _zero_checked;
private:
llvm::Value* llvm_value() const {
return _llvm_value;
}
public:
SharkValue* clone() const;
public:
bool equal_to(SharkValue* other) const;
public:
ciType* type() const;
BasicType basic_type() const;
int size() const;
public:
bool is_jint() const;
bool is_jlong() const;
bool is_jfloat() const;
bool is_jdouble() const;
bool is_jobject() const;
bool is_jarray() const;
public:
llvm::Value* jint_value() const;
llvm::Value* jlong_value() const;
llvm::Value* jfloat_value() const;
llvm::Value* jdouble_value() const;
llvm::Value* jobject_value() const;
llvm::Value* jarray_value() const;
public:
llvm::Value* generic_value() const;
llvm::Value* intptr_value(SharkBuilder* builder) const;
public:
SharkValue* merge(SharkBuilder* builder,
SharkValue* other,
llvm::BasicBlock* other_block,
llvm::BasicBlock* this_block,
const char* name);
public:
bool zero_checked() const;
void set_zero_checked(bool zero_checked);
};
class SharkPHIValue : public SharkNormalValue {
friend class SharkValue;
protected:
SharkPHIValue(ciType* type, llvm::PHINode* phi, const SharkPHIValue *parent)
: SharkNormalValue(type, phi, parent && parent->zero_checked()),
_parent(parent),
_all_incomers_zero_checked(true) {}
private:
const SharkPHIValue* _parent;
bool _all_incomers_zero_checked;
private:
const SharkPHIValue* parent() const {
return _parent;
}
bool is_clone() const {
return parent() != NULL;
}
public:
bool all_incomers_zero_checked() const {
if (is_clone())
return parent()->all_incomers_zero_checked();
return _all_incomers_zero_checked;
}
public:
SharkValue* clone() const;
public:
bool is_phi() const;
SharkPHIValue* as_phi();
public:
void addIncoming(SharkValue *value, llvm::BasicBlock* block);
};
class SharkAddressValue : public SharkValue {
friend class SharkValue;
protected:
SharkAddressValue(int bci)
: _bci(bci) {}
private:
int _bci;
public:
SharkValue* clone() const;
public:
bool equal_to(SharkValue* other) const;
public:
BasicType basic_type() const;
int size() const;
bool is_address() const;
public:
int address_value() const;
public:
llvm::Value* generic_value() const;
public:
void addIncoming(SharkValue *value, llvm::BasicBlock* block);
SharkValue* merge(SharkBuilder* builder,
SharkValue* other,
llvm::BasicBlock* other_block,
llvm::BasicBlock* this_block,
const char* name);
};
inline SharkValue* SharkValue::create_generic(ciType* type,
llvm::Value* value,
bool zero_checked) {
return new SharkNormalValue(type, value, zero_checked);
}
inline SharkValue* SharkValue::create_phi(ciType* type,
llvm::PHINode* phi,
const SharkPHIValue* parent) {
return new SharkPHIValue(type, phi, parent);
}
inline SharkValue* SharkValue::address_constant(int bci) {
return new SharkAddressValue(bci);
}
#endif // SHARE_VM_SHARK_SHARKVALUE_HPP
C:\hotspot-69087d08d473\src\share\vm/shark/shark_globals.cpp
#include "precompiled.hpp"
#include "shark/shark_globals.hpp"
SHARK_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
C:\hotspot-69087d08d473\src\share\vm/shark/shark_globals.hpp
#ifndef SHARE_VM_SHARK_SHARK_GLOBALS_HPP
#define SHARE_VM_SHARK_SHARK_GLOBALS_HPP
#include "runtime/globals.hpp"
#ifdef TARGET_ARCH_zero
# include "shark_globals_zero.hpp"
#endif
#define SHARK_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
\
product(intx, MaxNodeLimit, 65000, \
"Maximum number of nodes") \
\
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") \
\
develop(ccstr, SharkPrintTypeflowOf, NULL, \
"Print the typeflow of the specified method") \
\
diagnostic(ccstr, SharkPrintBitcodeOf, NULL, \
"Print the LLVM bitcode of the specified method") \
\
diagnostic(ccstr, SharkPrintAsmOf, NULL, \
"Print the asm of the specified method") \
\
develop(bool, SharkTraceBytecodes, false, \
"Trace bytecode compilation") \
\
diagnostic(bool, SharkTraceInstalls, false, \
"Trace method installation") \
\
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)
#endif // SHARE_VM_SHARK_SHARK_GLOBALS_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/accessFlags.cpp
#include "precompiled.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/accessFlags.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
void AccessFlags::atomic_set_bits(jint bits) {
jint old_flags, new_flags, f;
do {
old_flags = _flags;
new_flags = old_flags | bits;
f = Atomic::cmpxchg(new_flags, &_flags, old_flags);
} while(f != old_flags);
}
void AccessFlags::atomic_clear_bits(jint bits) {
jint old_flags, new_flags, f;
do {
old_flags = _flags;
new_flags = old_flags & ~bits;
f = Atomic::cmpxchg(new_flags, &_flags, old_flags);
} while(f != old_flags);
}
bool AccessFlags::atomic_set_one_bit(jint bit) {
jint old_flags, new_flags, f;
bool is_setting_bit = false;
do {
old_flags = _flags;
new_flags = old_flags | bit;
is_setting_bit = old_flags != new_flags;
f = Atomic::cmpxchg(new_flags, &_flags, old_flags);
} while(f != old_flags);
return is_setting_bit;
}
#if !defined(PRODUCT) || INCLUDE_JVMTI
void AccessFlags::print_on(outputStream* st) const {
if (is_public ()) st->print("public " );
if (is_private ()) st->print("private " );
if (is_protected ()) st->print("protected " );
if (is_static ()) st->print("static " );
if (is_final ()) st->print("final " );
if (is_synchronized()) st->print("synchronized ");
if (is_volatile ()) st->print("volatile " );
if (is_transient ()) st->print("transient " );
if (is_native ()) st->print("native " );
if (is_interface ()) st->print("interface " );
if (is_abstract ()) st->print("abstract " );
if (is_strict ()) st->print("strict " );
if (is_synthetic ()) st->print("synthetic " );
if (is_old ()) st->print("{old} " );
if (is_obsolete ()) st->print("{obsolete} " );
if (on_stack ()) st->print("{on_stack} " );
}
#endif // !PRODUCT || INCLUDE_JVMTI
void accessFlags_init() {
assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
}
C:\hotspot-69087d08d473\src\share\vm/utilities/accessFlags.hpp
#ifndef SHARE_VM_UTILITIES_ACCESSFLAGS_HPP
#define SHARE_VM_UTILITIES_ACCESSFLAGS_HPP
#include "prims/jvm.h"
#include "utilities/top.hpp"
enum {
JVM_ACC_WRITTEN_FLAGS = 0x00007FFF,
JVM_ACC_MONITOR_MATCH = 0x10000000, // True if we know that monitorenter/monitorexit bytecodes match
JVM_ACC_HAS_MONITOR_BYTECODES = 0x20000000, // Method contains monitorenter/monitorexit bytecodes
JVM_ACC_HAS_LOOPS = 0x40000000, // Method has loops
JVM_ACC_LOOPS_FLAG_INIT = (int)0x80000000,// The loop flag has been initialized
JVM_ACC_QUEUED = 0x01000000, // Queued for compilation
JVM_ACC_NOT_C2_COMPILABLE = 0x02000000,
JVM_ACC_NOT_C1_COMPILABLE = 0x04000000,
JVM_ACC_NOT_C2_OSR_COMPILABLE = 0x08000000,
JVM_ACC_HAS_LINE_NUMBER_TABLE = 0x00100000,
JVM_ACC_HAS_CHECKED_EXCEPTIONS = 0x00400000,
JVM_ACC_HAS_JSRS = 0x00800000,
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
JVM_ACC_ON_STACK = 0x00080000, // RedefineClasses() was used on the stack
JVM_ACC_IS_DELETED = 0x00008000, // RedefineClasses() has deleted this method
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
JVM_ACC_HAS_VANILLA_CONSTRUCTOR = 0x20000000, // True if klass has a vanilla default constructor
JVM_ACC_HAS_FINALIZER = 0x40000000, // True if klass has a non-empty finalize() method
JVM_ACC_IS_CLONEABLE = (int)0x80000000,// True if klass supports the Clonable interface
JVM_ACC_HAS_FINAL_METHOD = 0x01000000, // True if klass has final method
JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00200000,
JVM_ACC_PROMOTED_FLAGS = 0x00200000, // flags promoted from methods to the holding klass
JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI
JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI
JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT
JVM_ACC_FIELD_STABLE = 0x00000020, // @Stable field, same as JVM_ACC_SYNCHRONIZED and JVM_ACC_SUPER
JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE = 0x00000100, // (static) final field updated outside (class) initializer, same as JVM_ACC_NATIVE
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature
JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED |
JVM_ACC_FIELD_MODIFICATION_WATCHED |
JVM_ACC_FIELD_INTERNAL |
JVM_ACC_FIELD_STABLE |
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE,
JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS
};
class AccessFlags VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
jint _flags;
public:
bool is_public () const { return (_flags & JVM_ACC_PUBLIC ) != 0; }
bool is_private () const { return (_flags & JVM_ACC_PRIVATE ) != 0; }
bool is_protected () const { return (_flags & JVM_ACC_PROTECTED ) != 0; }
bool is_static () const { return (_flags & JVM_ACC_STATIC ) != 0; }
bool is_final () const { return (_flags & JVM_ACC_FINAL ) != 0; }
bool is_synchronized() const { return (_flags & JVM_ACC_SYNCHRONIZED) != 0; }
bool is_super () const { return (_flags & JVM_ACC_SUPER ) != 0; }
bool is_volatile () const { return (_flags & JVM_ACC_VOLATILE ) != 0; }
bool is_transient () const { return (_flags & JVM_ACC_TRANSIENT ) != 0; }
bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; }
bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; }
bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 0; }
bool is_strict () const { return (_flags & JVM_ACC_STRICT ) != 0; }
bool is_synthetic () const { return (_flags & JVM_ACC_SYNTHETIC ) != 0; }
bool is_monitor_matching () const { return (_flags & JVM_ACC_MONITOR_MATCH ) != 0; }
bool has_monitor_bytecodes () const { return (_flags & JVM_ACC_HAS_MONITOR_BYTECODES ) != 0; }
bool has_loops () const { return (_flags & JVM_ACC_HAS_LOOPS ) != 0; }
bool loops_flag_init () const { return (_flags & JVM_ACC_LOOPS_FLAG_INIT ) != 0; }
bool queued_for_compilation () const { return (_flags & JVM_ACC_QUEUED ) != 0; }
bool is_not_c1_compilable () const { return (_flags & JVM_ACC_NOT_C1_COMPILABLE ) != 0; }
bool is_not_c2_compilable () const { return (_flags & JVM_ACC_NOT_C2_COMPILABLE ) != 0; }
bool is_not_c2_osr_compilable() const { return (_flags & JVM_ACC_NOT_C2_OSR_COMPILABLE ) != 0; }
bool has_linenumber_table () const { return (_flags & JVM_ACC_HAS_LINE_NUMBER_TABLE ) != 0; }
bool has_checked_exceptions () const { return (_flags & JVM_ACC_HAS_CHECKED_EXCEPTIONS ) != 0; }
bool has_jsrs () const { return (_flags & JVM_ACC_HAS_JSRS ) != 0; }
bool is_old () const { return (_flags & JVM_ACC_IS_OLD ) != 0; }
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
bool is_deleted () const { return (_flags & JVM_ACC_IS_DELETED ) != 0; }
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; }
bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; }
bool has_finalizer () const { return (_flags & JVM_ACC_HAS_FINALIZER ) != 0; }
bool has_final_method () const { return (_flags & JVM_ACC_HAS_FINAL_METHOD ) != 0; }
bool is_cloneable () const { return (_flags & JVM_ACC_IS_CLONEABLE ) != 0; }
bool has_localvariable_table () const { return (_flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) != 0; }
void set_has_localvariable_table() { atomic_set_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); }
void clear_has_localvariable_table() { atomic_clear_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); }
bool is_field_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; }
bool is_field_modification_watched() const
{ return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
bool has_field_initialized_final_update() const
{ return (_flags & JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE) != 0; }
bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; }
bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
bool is_stable() const { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
bool field_has_generic_signature() const
{ return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; }
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); }
void set_field_flags(jint flags) {
assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags");
_flags = (flags & JVM_ACC_FIELD_FLAGS);
}
void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); }
void clear_queued_for_compilation() { atomic_clear_bits(JVM_ACC_QUEUED); }
void atomic_set_bits(jint bits);
bool atomic_set_one_bit(jint bit);
void atomic_clear_bits(jint bits);
private:
friend class Method;
friend class Klass;
friend class ClassFileParser;
void set_is_synthetic() { atomic_set_bits(JVM_ACC_SYNTHETIC); }
void set_monitor_matching() { atomic_set_bits(JVM_ACC_MONITOR_MATCH); }
void set_has_monitor_bytecodes() { atomic_set_bits(JVM_ACC_HAS_MONITOR_BYTECODES); }
void set_has_loops() { atomic_set_bits(JVM_ACC_HAS_LOOPS); }
void set_loops_flag_init() { atomic_set_bits(JVM_ACC_LOOPS_FLAG_INIT); }
void set_not_c1_compilable() { atomic_set_bits(JVM_ACC_NOT_C1_COMPILABLE); }
void set_not_c2_compilable() { atomic_set_bits(JVM_ACC_NOT_C2_COMPILABLE); }
void set_not_c2_osr_compilable() { atomic_set_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); }
void set_has_linenumber_table() { atomic_set_bits(JVM_ACC_HAS_LINE_NUMBER_TABLE); }
void set_has_checked_exceptions() { atomic_set_bits(JVM_ACC_HAS_CHECKED_EXCEPTIONS); }
void set_has_jsrs() { atomic_set_bits(JVM_ACC_HAS_JSRS); }
void set_is_old() { atomic_set_bits(JVM_ACC_IS_OLD); }
void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); }
void set_is_deleted() { atomic_set_bits(JVM_ACC_IS_DELETED); }
void set_is_prefixed_native() { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE); }
void clear_not_c1_compilable() { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE); }
void clear_not_c2_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE); }
void clear_not_c2_osr_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); }
void set_has_vanilla_constructor() { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); }
void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); }
void set_has_final_method() { atomic_set_bits(JVM_ACC_HAS_FINAL_METHOD); }
void set_is_cloneable() { atomic_set_bits(JVM_ACC_IS_CLONEABLE); }
void set_has_miranda_methods() { atomic_set_bits(JVM_ACC_HAS_MIRANDA_METHODS); }
public:
void set_is_field_access_watched(const bool value)
{
if (value) {
atomic_set_bits(JVM_ACC_FIELD_ACCESS_WATCHED);
} else {
atomic_clear_bits(JVM_ACC_FIELD_ACCESS_WATCHED);
}
}
void set_is_field_modification_watched(const bool value)
{
if (value) {
atomic_set_bits(JVM_ACC_FIELD_MODIFICATION_WATCHED);
} else {
atomic_clear_bits(JVM_ACC_FIELD_MODIFICATION_WATCHED);
}
}
void set_has_field_initialized_final_update(const bool value) {
if (value) {
atomic_set_bits(JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE);
} else {
atomic_clear_bits(JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE);
}
}
void set_field_has_generic_signature()
{
atomic_set_bits(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE);
}
bool set_on_stack(const bool value)
{
if (value) {
return atomic_set_one_bit(JVM_ACC_ON_STACK);
} else {
atomic_clear_bits(JVM_ACC_ON_STACK);
return true; // Ignored
}
}
jshort as_short() const { return (jshort)_flags; }
jint as_int() const { return _flags; }
inline friend AccessFlags accessFlags_from(jint flags);
#if INCLUDE_JVMTI
void print_on(outputStream* st) const;
#else
void print_on(outputStream* st) const PRODUCT_RETURN;
#endif
};
inline AccessFlags accessFlags_from(jint flags) {
AccessFlags af;
af._flags = flags;
return af;
}
#endif // SHARE_VM_UTILITIES_ACCESSFLAGS_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/align.hpp
#ifndef SHARE_VM_UTILITIES_ALIGN_HPP
#define SHARE_VM_UTILITIES_ALIGN_HPP
#include "utilities/globalDefinitions.hpp"
#define align_mask(alignment) ((alignment) - 1)
#define widen_to_type_of(what, type_carrier) (true ? (what) : (type_carrier))
#define align_mask_widened(alignment, type_carrier) widen_to_type_of(align_mask(alignment), (type_carrier))
#define align_down_(size, alignment) ((size) & ~align_mask_widened((alignment), (size)))
#define align_up_(size, alignment) (align_down_((size) + align_mask(alignment), (alignment)))
#define is_aligned_(size, alignment) (((size) & align_mask(alignment)) == 0)
template <typename T>
bool is_power_of_2_t(T x) {
return (x != T(0)) && ((x & (x - 1)) == T(0));
}
template <typename T, typename A>
inline T align_up(T size, A alignment) {
assert(is_power_of_2_t(alignment), "must be a power of 2");
T ret = align_up_(size, alignment);
assert(is_aligned_(ret, alignment), "must be aligned");
return ret;
}
template <typename T, typename A>
inline T align_down(T size, A alignment) {
assert(is_power_of_2_t(alignment), "must be a power of 2");
T ret = align_down_(size, alignment);
assert(is_aligned_(ret, alignment), "must be aligned");
return ret;
}
template <typename T, typename A>
inline bool is_aligned(T size, A alignment) {
assert(is_power_of_2_t(alignment), "must be a power of 2");
return is_aligned_(size, alignment);
}
template <typename T, typename A>
inline T align_down_bounded(T size, A alignment) {
A aligned_size = align_down(size, alignment);
return aligned_size > 0 ? aligned_size : alignment;
}
template <typename T, typename A>
inline T* align_up(T* ptr, A alignment) {
return (T*)align_up((uintptr_t)ptr, alignment);
}
template <typename T, typename A>
inline T* align_down(T* ptr, A alignment) {
return (T*)align_down((uintptr_t)ptr, alignment);
}
template <typename T, typename A>
inline bool is_aligned(T* ptr, A alignment) {
return is_aligned((uintptr_t)ptr, alignment);
}
template <typename T>
inline T align_metadata_size(T size) {
return align_up(size, 1);
}
template <typename T>
inline T align_object_size(T word_size) {
return align_up(word_size, MinObjAlignment);
}
inline bool is_object_aligned(size_t word_size) {
return is_aligned(word_size, MinObjAlignment);
}
inline bool is_object_aligned(const void* addr) {
return is_aligned(addr, MinObjAlignmentInBytes);
}
template <typename T>
inline T align_object_offset(T offset) {
return align_up(offset, HeapWordsPerLong);
}
template <typename T>
inline T* clamp_address_in_page(T* addr, T* page_address, size_t page_size) {
if (align_down(addr, page_size) == align_down(page_address, page_size)) {
return addr;
} else if (addr > page_address) {
return align_down(page_address, page_size) + page_size;
} else {
return align_down(page_address, page_size);
}
}
#endif // SHARE_VM_UTILITIES_ALIGN_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/array.cpp
#include "precompiled.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/array.hpp"
#ifdef ASSERT
void ResourceArray::init_nesting() {
_nesting = Thread::current()->resource_area()->nesting();
}
#endif
void ResourceArray::sort(size_t esize, ftype f) {
if (!is_empty()) qsort(_data, length(), esize, f);
}
template <MEMFLAGS F> void CHeapArray<F>::sort(size_t esize, ftype f) {
if (!is_empty()) qsort(_data, length(), esize, f);
}
void ResourceArray::expand(size_t esize, int i, int& size) {
assert(
_nesting == Thread::current()->resource_area()->nesting(),
"allocating outside original resource mark"
);
if (size == 0) size = 4; // prevent endless loop
while (i >= size) size *= 2;
void* data = resource_allocate_bytes(esize * size);
memcpy(data, _data, esize * length());
_data = data;
}
template <MEMFLAGS F> void CHeapArray<F>::expand(size_t esize, int i, int& size) {
if (size == 0) size = 4; // prevent endless loop
while (i >= size) size *= 2;
void* data = NEW_C_HEAP_ARRAY(char*, esize * size, F);
memcpy(data, _data, esize * length());
FREE_C_HEAP_ARRAY(char*, _data, F);
_data = data;
}
void ResourceArray::remove_at(size_t esize, int i) {
assert(0 <= i && i < length(), "index out of bounds");
_length--;
void* dst = (char*)_data + i*esize;
void* src = (char*)dst + esize;
size_t cnt = (length() - i)*esize;
memmove(dst, src, cnt);
}
template <MEMFLAGS F> void CHeapArray<F>::remove_at(size_t esize, int i) {
assert(0 <= i && i < length(), "index out of bounds");
_length--;
void* dst = (char*)_data + i*esize;
void* src = (char*)dst + esize;
size_t cnt = (length() - i)*esize;
memmove(dst, src, cnt);
}
C:\hotspot-69087d08d473\src\share\vm/utilities/array.hpp
#ifndef SHARE_VM_UTILITIES_ARRAY_HPP
#define SHARE_VM_UTILITIES_ARRAY_HPP
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metaspace.hpp"
#include "runtime/orderAccess.hpp"
extern "C" { typedef int (*ftype)(const void*, const void*); }
class ResourceArray: public ResourceObj {
protected:
int _length; // the number of array elements
void* _data; // the array memory
#ifdef ASSERT
int _nesting; // the resource area nesting level
#endif
ResourceArray() {
_length = 0;
_data = NULL;
DEBUG_ONLY(init_nesting();)
}
ResourceArray(size_t esize, int length) {
DEBUG_ONLY(_data = NULL);
initialize(esize, length);
}
void initialize(size_t esize, int length) {
assert(length >= 0, "illegal length");
assert(StressRewriter || _data == NULL, "must be new object");
_length = length;
_data = resource_allocate_bytes(esize * length);
DEBUG_ONLY(init_nesting();)
}
#ifdef ASSERT
void init_nesting();
#endif
void sort (size_t esize, ftype f); // sort the array
void expand (size_t esize, int i, int& size);// expand the array to include slot i
void remove_at(size_t esize, int i); // remove the element in slot i
public:
int length() const { return _length; }
bool is_empty() const { return length() == 0; }
};
template <MEMFLAGS F>class CHeapArray: public CHeapObj<F> {
protected:
int _length; // the number of array elements
void* _data; // the array memory
CHeapArray() {
_length = 0;
_data = NULL;
}
CHeapArray(size_t esize, int length) {
assert(length >= 0, "illegal length");
_length = length;
_data = (void*) NEW_C_HEAP_ARRAY(char *, esize * length, F);
}
void initialize(size_t esize, int length) {
}
#ifdef ASSERT
void init_nesting();
#endif
void sort (size_t esize, ftype f); // sort the array
void expand (size_t esize, int i, int& size);// expand the array to include slot i
void remove_at(size_t esize, int i); // remove the element in slot i
public:
int length() const { return _length; }
bool is_empty() const { return length() == 0; }
};
#define define_generic_array(array_name,element_type, base_class) \
class array_name: public base_class { \
protected: \
typedef element_type etype; \
enum { esize = sizeof(etype) }; \
\
void base_remove_at(size_t size, int i) { base_class::remove_at(size, i); } \
\
public: \
array_name() : base_class() {} \
explicit array_name(const int length) : base_class(esize, length) {} \
array_name(const int length, const etype fx) { initialize(length, fx); } \
void initialize(const int length) { base_class::initialize(esize, length); } \
void initialize(const int length, const etype fx) { \
initialize(length); \
for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx; \
} \
\
etype& operator [] (const int i) const { \
assert(0 <= i && i < length(), "index out of bounds"); \
return ((etype*)_data)[i]; \
} \
\
int index_of(const etype x) const { \
int i = length(); \
while (i-- > 0 && ((etype*)_data)[i] != x) ; \
return i; \
} \
\
void sort(int f(etype*, etype*)) { base_class::sort(esize, (ftype)f); } \
bool contains(const etype x) const { return index_of(x) >= 0; } \
\
etype at(const int i) const { return (*this)[i]; } \
void at_put(const int i, const etype x) { (*this)[i] = x; } \
etype* adr_at(const int i) { return &(*this)[i]; } \
int find(const etype x) { return index_of(x); } \
}; \
#define define_array(array_name,element_type) \
define_generic_array(array_name, element_type, ResourceArray)
#define define_stack(stack_name,array_name) \
class stack_name: public array_name { \
protected: \
int _size; \
\
void grow(const int i, const etype fx) { \
assert(i >= length(), "index too small"); \
if (i >= size()) expand(esize, i, _size); \
for (int j = length(); j <= i; j++) ((etype*)_data)[j] = fx; \
_length = i+1; \
} \
\
public: \
stack_name() : array_name() { _size = 0; } \
stack_name(const int size) { initialize(size); } \
stack_name(const int size, const etype fx) { initialize(size, fx); } \
void initialize(const int size, const etype fx) { \
_size = size; \
array_name::initialize(size, fx); \
} \
void initialize(const int size) { \
_size = size; \
array_name::initialize(size); \
_length = 0; /* reset length to zero; _size records the allocation */ \
} \
\
int size() const { return _size; } \
\
int push(const etype x) { \
int len = length(); \
if (len >= size()) expand(esize, len, _size); \
((etype*)_data)[len] = x; \
_length = len+1; \
return len; \
} \
\
etype pop() { \
assert(!is_empty(), "stack is empty"); \
return ((etype*)_data)[--_length]; \
} \
\
etype top() const { \
assert(!is_empty(), "stack is empty"); \
return ((etype*)_data)[length() - 1]; \
} \
\
void push_all(const stack_name* stack) { \
const int l = stack->length(); \
for (int i = 0; i < l; i++) push(((etype*)(stack->_data))[i]); \
} \
\
etype at_grow(const int i, const etype fx) { \
if (i >= length()) grow(i, fx); \
return ((etype*)_data)[i]; \
} \
\
void at_put_grow(const int i, const etype x, const etype fx) { \
if (i >= length()) grow(i, fx); \
((etype*)_data)[i] = x; \
} \
\
void truncate(const int length) { \
assert(0 <= length && length <= this->length(), "illegal length"); \
_length = length; \
} \
\
void remove_at(int i) { base_remove_at(esize, i); } \
void remove(etype x) { remove_at(index_of(x)); } \
\
void insert_before(const int i, const etype el) { \
int len = length(); \
int new_length = len + 1; \
if (new_length >= size()) expand(esize, new_length, _size); \
for (int j = len - 1; j >= i; j--) { \
((etype*)_data)[j + 1] = ((etype*)_data)[j]; \
} \
_length = new_length; \
at_put(i, el); \
} \
\
void insert_before(const int i, const stack_name *st) { \
if (st->length() == 0) return; \
int len = length(); \
int st_len = st->length(); \
int new_length = len + st_len; \
if (new_length >= size()) expand(esize, new_length, _size); \
int j; \
for (j = len - 1; j >= i; j--) { \
((etype*)_data)[j + st_len] = ((etype*)_data)[j]; \
} \
for (j = 0; j < st_len; j++) { \
((etype*)_data)[i + j] = ((etype*)st->_data)[j]; \
} \
_length = new_length; \
} \
\
int capacity() const { return size(); } \
void clear() { truncate(0); } \
void trunc_to(const int length) { truncate(length); } \
int append(const etype x) { return push(x); } \
void appendAll(const stack_name* stack) { push_all(stack); } \
etype last() const { return top(); } \
}; \
#define define_resource_list(element_type) \
define_generic_array(element_type##Array, element_type, ResourceArray) \
define_stack(element_type##List, element_type##Array)
#define define_resource_pointer_list(element_type) \
define_generic_array(element_type##Array, element_type *, ResourceArray) \
define_stack(element_type##List, element_type##Array)
#define define_c_heap_list(element_type) \
define_generic_array(element_type##Array, element_type, CHeapArray) \
define_stack(element_type##List, element_type##Array)
#define define_c_heap_pointer_list(element_type) \
define_generic_array(element_type##Array, element_type *, CHeapArray) \
define_stack(element_type##List, element_type##Array)
define_array(boolArray, bool) define_stack(boolStack, boolArray)
define_array(intArray , int ) define_stack(intStack , intArray )
template <typename T>
sssssss85
最新推荐文章于 2024-08-03 21:02:21 发布