blob: fea3dfe86a028f72477f1bd6de2f1a82b51b6ccf [file] [log] [blame]
//===----------- JavaJIT.cpp - Java just in time compiler -----------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG 0
#define JNJVM_COMPILE 0
#define JNJVM_EXECUTE 0
#include <string.h>
#include <llvm/Type.h>
#include <llvm/Support/CFG.h>
#include <llvm/Module.h>
#include <llvm/Constants.h>
#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Instructions.h>
#include <llvm/ModuleProvider.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/PassManager.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Target/TargetOptions.h>
#include <llvm/CodeGen/MachineCodeEmitter.h>
#include <llvm/CodeGen/MachineBasicBlock.h>
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include <llvm/Transforms/IPO.h>
#include "mvm/JIT.h"
#include "mvm/Method.h"
#include "debug.h"
#include "JavaArray.h"
#include "JavaCache.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaObject.h"
#include "JavaJIT.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "JnjvmModuleProvider.h"
#include "NativeUtil.h"
#include "Reader.h"
#include "Zip.h"
#include <iostream>
using namespace jnjvm;
using namespace llvm;
void Exception::print(mvm::PrintBuffer* buf) const {
buf->write("Exception<>");
}
void JavaJIT::print(mvm::PrintBuffer* buf) const {
buf->write("JavaJIT<>");
}
BasicBlock* JavaJIT::createBasicBlock(const char* name) {
return new BasicBlock(name, llvmFunction);
}
Value* JavaJIT::top() {
return stack.back().first;
}
Value* JavaJIT::pop() {
llvm::Value * ret = top();
stack.pop_back();
return ret;
}
Value* JavaJIT::popAsInt() {
llvm::Value * ret = top();
const AssessorDesc* ass = topFunc();
stack.pop_back();
if (ret->getType() != Type::Int32Ty) {
if (ass == AssessorDesc::dChar) {
ret = new ZExtInst(ret, Type::Int32Ty, "", currentBlock);
} else {
ret = new SExtInst(ret, Type::Int32Ty, "", currentBlock);
}
}
return ret;
}
void JavaJIT::push(llvm::Value* val, const AssessorDesc* ass) {
assert(ass->llvmType == val->getType());
stack.push_back(std::make_pair(val, ass));
}
void JavaJIT::push(std::pair<llvm::Value*, const AssessorDesc*> pair) {
assert(pair.second->llvmType == pair.first->getType());
stack.push_back(pair);
}
const AssessorDesc* JavaJIT::topFunc() {
return stack.back().second;
}
uint32 JavaJIT::stackSize() {
return stack.size();
}
std::pair<llvm::Value*, const AssessorDesc*> JavaJIT::popPair() {
std::pair<Value*, const AssessorDesc*> ret = stack.back();
stack.pop_back();
return ret;
}
llvm::Function* JavaJIT::nativeCompile(void* natPtr) {
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "native compile %s\n",
compilingMethod->printString());
bool stat = isStatic(compilingMethod->access);
const FunctionType *funcType = compilingMethod->llvmType;
bool jnjvm = false;
natPtr = natPtr ? natPtr :
NativeUtil::nativeLookup(compilingClass, compilingMethod, jnjvm);
compilingClass->isolate->protectModule->lock();
Function* func = llvmFunction = new llvm::Function(funcType,
GlobalValue::ExternalLinkage,
compilingMethod->printString(),
compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
if (jnjvm) {
mvm::jit::executionEngine->addGlobalMapping(func, natPtr);
return llvmFunction;
}
currentBlock = createBasicBlock("start");
BasicBlock* executeBlock = createBasicBlock("execute");
endBlock = createBasicBlock("end block");
if (funcType->getReturnType() != Type::VoidTy)
endNode = new PHINode(funcType->getReturnType(), "", endBlock);
Value* buf = new CallInst(getSJLJBufferLLVM, "", currentBlock);
Value* test = new CallInst(mvm::jit::setjmpLLVM, buf, "", currentBlock);
test = new ICmpInst(ICmpInst::ICMP_EQ, test, mvm::jit::constantZero, "", currentBlock);
new BranchInst(executeBlock, endBlock, test, currentBlock);
if (compilingMethod->signature->ret->funcs != AssessorDesc::dVoid)
endNode->addIncoming(compilingMethod->signature->ret->funcs->llvmNullConstant, currentBlock);
currentBlock = executeBlock;
if (isSynchro(compilingMethod->access))
beginSynchronize();
uint32 nargs = func->arg_size() + 1 + (stat ? 1 : 0); // + vm + cl/obj
std::vector<Value*> nativeArgs;
mvm::jit::protectConstants();//->lock();
nativeArgs.push_back(
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
(int64_t)&(compilingClass->isolate->jniEnv)),
mvm::jit::ptrType));
mvm::jit::unprotectConstants();//->unlock();
uint32 index = 0;
if (stat) {
#ifdef SINGLE_VM
nativeArgs.push_back(new LoadInst(compilingClass->llvmDelegatee(), "", currentBlock));
#else
Value* ld = new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module), "", currentBlock);
nativeArgs.push_back(new CallInst(getClassDelegateeLLVM, ld, "", currentBlock));
#endif
index = 2;
} else {
index = 1;
}
for (Function::arg_iterator i = func->arg_begin();
index < nargs; ++i, ++index) {
nativeArgs.push_back(i);
}
const llvm::Type* valPtrType = compilingMethod->signature->nativeTypePtr;
mvm::jit::protectConstants();//->lock();
Value* valPtr =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (uint64)natPtr),
valPtrType);
mvm::jit::unprotectConstants();//->unlock();
Value* result = new CallInst(valPtr, nativeArgs.begin(), nativeArgs.end(), "", currentBlock);
if (funcType->getReturnType() != Type::VoidTy)
endNode->addIncoming(result, currentBlock);
new BranchInst(endBlock, currentBlock);
currentBlock = endBlock;
if (isSynchro(compilingMethod->access))
endSynchronize();
new CallInst(jniProceedPendingExceptionLLVM, "", currentBlock);
if (funcType->getReturnType() != Type::VoidTy)
new ReturnInst(result, currentBlock);
else
new ReturnInst(currentBlock);
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "end native compile %s\n",
compilingMethod->printString());
return llvmFunction;
}
void JavaJIT::beginSynchronize() {
std::vector<Value*> argsSync;
if (isVirtual(compilingMethod->access)) {
argsSync.push_back(llvmFunction->arg_begin());
} else {
Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
#ifndef SINGLE_VM
if (compilingClass->isolate == Jnjvm::bootstrapVM) {
arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
}
#endif
argsSync.push_back(arg);
}
new CallInst(aquireObjectLLVM, argsSync.begin(), argsSync.end(), "", currentBlock);
}
void JavaJIT::endSynchronize() {
std::vector<Value*> argsSync;
if (isVirtual(compilingMethod->access)) {
argsSync.push_back(llvmFunction->arg_begin());
} else {
Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
#ifndef SINGLE_VM
if (compilingClass->isolate == Jnjvm::bootstrapVM) {
arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
}
#endif
argsSync.push_back(arg);
}
new CallInst(releaseObjectLLVM, argsSync.begin(), argsSync.end(), "", currentBlock);
}
Instruction* JavaJIT::inlineCompile(Function* parentFunction, BasicBlock*& curBB,
BasicBlock* endExBlock,
std::vector<Value*>& args) {
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "inline compile %s\n",
compilingMethod->printString());
Attribut* codeAtt = Attribut::lookup(&compilingMethod->attributs,
Attribut::codeAttribut);
if (!codeAtt)
JavaThread::get()->isolate->unknownError("unable to find the code attribut in %s",
compilingMethod->printString());
Reader* reader = codeAtt->toReader(compilingClass->bytes, codeAtt);
maxStack = reader->readU2();
maxLocals = reader->readU2();
codeLen = reader->readU4();
uint32 start = reader->cursor;
reader->seek(codeLen, Reader::SeekCur);
const FunctionType *funcType = compilingMethod->llvmType;
returnType = funcType->getReturnType();
llvmFunction = parentFunction;
currentBlock = curBB;
endExceptionBlock = 0;
opcodeInfos = (Opinfo*)alloca(codeLen * sizeof(Opinfo));
memset(opcodeInfos, 0, codeLen * sizeof(Opinfo));
for (uint32 i = 0; i < codeLen; ++i) {
opcodeInfos[i].exceptionBlock = endExBlock;
}
for (int i = 0; i < maxLocals; i++) {
intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock));
doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock));
longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock));
floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock));
objectLocals.push_back(new AllocaInst(JavaObject::llvmType, "",
currentBlock));
}
uint32 index = 0;
uint32 count = 0;
for (std::vector<Value*>::iterator i = args.begin();
count < args.size(); ++i, ++index, ++count) {
const Type* cur = (*i)->getType();
if (cur == Type::Int64Ty ){
new StoreInst(*i, longLocals[index], false, currentBlock);
++index;
} else if (cur == Type::Int8Ty || cur == Type::Int16Ty) {
new StoreInst(new ZExtInst(*i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (cur == Type::Int32Ty) {
new StoreInst(*i, intLocals[index], false, currentBlock);
} else if (cur == Type::DoubleTy) {
new StoreInst(*i, doubleLocals[index], false, currentBlock);
++index;
} else if (cur == Type::FloatTy) {
new StoreInst(*i, floatLocals[index], false, currentBlock);
} else {
new StoreInst(*i, objectLocals[index], false, currentBlock);
}
}
exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
endBlock = createBasicBlock("end");
if (returnType != Type::VoidTy) {
endNode = new PHINode(returnType, "", endBlock);
}
compileOpcodes(&compilingClass->bytes->elements[start], codeLen);
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end inline compiling %s\n",
compilingMethod->printString());
curBB = endBlock;
return endNode;
}
llvm::Function* JavaJIT::javaCompile() {
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "compiling %s\n",
compilingMethod->printString());
Attribut* codeAtt = Attribut::lookup(&compilingMethod->attributs,
Attribut::codeAttribut);
if (!codeAtt)
JavaThread::get()->isolate->unknownError("unable to find the code attribut in %s",
compilingMethod->printString());
Reader* reader = codeAtt->toReader(compilingClass->bytes, codeAtt);
maxStack = reader->readU2();
maxLocals = reader->readU2();
codeLen = reader->readU4();
uint32 start = reader->cursor;
reader->seek(codeLen, Reader::SeekCur);
const FunctionType *funcType = compilingMethod->llvmType;
returnType = funcType->getReturnType();
compilingClass->isolate->protectModule->lock();
Function* func = llvmFunction = new llvm::Function(funcType,
GlobalValue::ExternalLinkage,
compilingMethod->printString(),
compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
currentBlock = createBasicBlock("start");
endExceptionBlock = createBasicBlock("endExceptionBlock");
unifiedUnreachable = createBasicBlock("unifiedUnreachable");
opcodeInfos = (Opinfo*)alloca(codeLen * sizeof(Opinfo));
memset(opcodeInfos, 0, codeLen * sizeof(Opinfo));
for (uint32 i = 0; i < codeLen; ++i) {
opcodeInfos[i].exceptionBlock = endExceptionBlock;
}
#if JNJVM_EXECUTE > 0
{
std::vector<llvm::Value*> args;
mvm::jit::protectConstants();//->lock();
args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
mvm::jit::unprotectConstants();//->unlock();
new CallInst(printMethodStartLLVM, args.begin(), args.end(), "", currentBlock);
}
#endif
unsigned nbe = readExceptionTable(reader);
for (int i = 0; i < maxLocals; i++) {
intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock));
doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock));
longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock));
floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock));
objectLocals.push_back(new AllocaInst(JavaObject::llvmType, "",
currentBlock));
}
uint32 index = 0;
uint32 count = 0;
for (Function::arg_iterator i = func->arg_begin();
count < func->arg_size(); ++i, ++index, ++count) {
const Type* cur = i->getType();
if (cur == Type::Int64Ty ){
new StoreInst(i, longLocals[index], false, currentBlock);
++index;
} else if (cur == Type::Int8Ty || cur == Type::Int16Ty) {
new StoreInst(new ZExtInst(i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (cur == Type::Int32Ty) {
new StoreInst(i, intLocals[index], false, currentBlock);
} else if (cur == Type::DoubleTy) {
new StoreInst(i, doubleLocals[index], false, currentBlock);
++index;
} else if (cur == Type::FloatTy) {
new StoreInst(i, floatLocals[index], false, currentBlock);
} else {
new StoreInst(i, objectLocals[index], false, currentBlock);
}
}
exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
endBlock = createBasicBlock("end");
if (returnType != Type::VoidTy) {
endNode = new PHINode(returnType, "", endBlock);
}
if (isSynchro(compilingMethod->access))
beginSynchronize();
compileOpcodes(&compilingClass->bytes->elements[start], codeLen);
currentBlock = endBlock;
if (isSynchro(compilingMethod->access))
endSynchronize();
#if JNJVM_EXECUTE > 0
{
std::vector<llvm::Value*> args;
mvm::jit::protectConstants();//->lock();
args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
mvm::jit::unprotectConstants();//->unlock();
new CallInst(printMethodEndLLVM, args.begin(), args.end(), "", currentBlock);
}
#endif
if (returnType != Type::VoidTy)
new ReturnInst(endNode, endBlock);
else
new ReturnInst(endBlock);
pred_iterator PI = pred_begin(endExceptionBlock);
pred_iterator PE = pred_end(endExceptionBlock);
if (PI == PE) {
endExceptionBlock->eraseFromParent();
} else {
CallInst* ptr_eh_ptr = new CallInst(getExceptionLLVM, "eh_ptr",
endExceptionBlock);
new CallInst(mvm::jit::unwindResume, ptr_eh_ptr, "", endExceptionBlock);
new UnreachableInst(endExceptionBlock);
}
PI = pred_begin(unifiedUnreachable);
PE = pred_end(unifiedUnreachable);
if (PI == PE) {
unifiedUnreachable->eraseFromParent();
} else {
new UnreachableInst(unifiedUnreachable);
}
mvm::jit::runPasses(llvmFunction, JavaThread::get()->perFunctionPasses);
/*
if (compilingMethod->name == compilingClass->isolate->asciizConstructUTF8("main")) {
llvmFunction->print(llvm::cout);
void* res = mvm::jit::executionEngine->getPointerToGlobal(llvmFunction);
void* base = res;
while (base < (void*)((char*)res + ((mvm::Code*)res)->objectSize())) {
printf("%08x\t", (unsigned)base);
int n= mvm::jit::disassemble((unsigned int *)base);
printf("\n");
base= ((void *)((char *)base + n));
}
printf("\n");
fflush(stdout);
}*/
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end compiling %s\n",
compilingMethod->printString());
if (nbe == 0 && codeLen < 50)
compilingMethod->canBeInlined = false;
return llvmFunction;
}
unsigned JavaJIT::readExceptionTable(Reader* reader) {
uint16 nbe = reader->readU2();
unsigned sync = isSynchro(compilingMethod->access) ? 1 : 0;
nbe += sync;
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
if (nbe) {
supplLocal = new AllocaInst(JavaObject::llvmType, "exceptionVar",
currentBlock);
}
BasicBlock* realEndExceptionBlock = endExceptionBlock;
if (sync) {
BasicBlock* synchronizeExceptionBlock = createBasicBlock("synchronizeExceptionBlock");
BasicBlock* trySynchronizeExceptionBlock = createBasicBlock("trySynchronizeExceptionBlock");
realEndExceptionBlock = synchronizeExceptionBlock;
std::vector<Value*> argsSync;
if (isVirtual(compilingMethod->access)) {
argsSync.push_back(llvmFunction->arg_begin());
} else {
Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
#ifndef SINGLE_VM
if (compilingClass->isolate == Jnjvm::bootstrapVM) {
arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
}
#endif
argsSync.push_back(arg);
}
new CallInst(releaseObjectLLVM, argsSync.begin(), argsSync.end(), "", synchronizeExceptionBlock);
new BranchInst(endExceptionBlock, synchronizeExceptionBlock);
const PointerType* PointerTy_0 = mvm::jit::ptrType;
std::vector<Value*> int32_eh_select_params;
Instruction* ptr_eh_ptr = new CallInst(mvm::jit::llvmGetException, "eh_ptr", trySynchronizeExceptionBlock);
int32_eh_select_params.push_back(ptr_eh_ptr);
int32_eh_select_params.push_back(ConstantExpr::getCast(Instruction::BitCast, mvm::jit::personality, PointerTy_0));
int32_eh_select_params.push_back(mvm::jit::constantPtrNull);
new CallInst(mvm::jit::exceptionSelector, int32_eh_select_params.begin(), int32_eh_select_params.end(), "eh_select", trySynchronizeExceptionBlock);
new BranchInst(synchronizeExceptionBlock, trySynchronizeExceptionBlock);
for (uint16 i = 0; i < codeLen; ++i) {
if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
opcodeInfos[i].exceptionBlock = trySynchronizeExceptionBlock;
}
}
}
for (uint16 i = 0; i < nbe - sync; ++i) {
Exception* ex = gc_new(Exception)();
ex->startpc = reader->readU2();
ex->endpc = reader->readU2();
ex->handlerpc = reader->readU2();
uint16 catche = reader->readU2();
if (catche) {
ex->catchClass = (Class*)ctpInfo->loadClass(catche);
} else {
ex->catchClass = Classpath::newThrowable;
}
ex->test = createBasicBlock("testException");
// We can do this because readExceptionTable is the first function to be
// called after creation of Opinfos
for (uint16 i = ex->startpc; i < ex->endpc; ++i) {
if (opcodeInfos[i].exceptionBlock == realEndExceptionBlock) {
opcodeInfos[i].exceptionBlock = ex->test;
}
}
if (!(opcodeInfos[ex->handlerpc].newBlock)) {
opcodeInfos[ex->handlerpc].newBlock = createBasicBlock("handlerException");
}
ex->handler = opcodeInfos[ex->handlerpc].newBlock;
opcodeInfos[ex->handlerpc].reqSuppl = true;
exceptions.push_back(ex);
}
bool first = true;
for (std::vector<Exception*>::iterator i = exceptions.begin(),
e = exceptions.end(); i!= e; ++i) {
Exception* cur = *i;
Exception* next = 0;
if (i + 1 != e) {
next = *(i + 1);
}
if (first) {
cur->realTest = createBasicBlock("realTestException");
} else {
cur->realTest = cur->test;
}
cur->exceptionPHI = new PHINode(mvm::jit::ptrType, "", cur->realTest);
if (next && cur->startpc == next->startpc && cur->endpc == next->endpc)
first = false;
else
first = true;
}
for (std::vector<Exception*>::iterator i = exceptions.begin(),
e = exceptions.end(); i!= e; ++i) {
Exception* cur = *i;
Exception* next = 0;
BasicBlock* bbNext = 0;
PHINode* nodeNext = 0;
if (i + 1 != e) {
next = *(i + 1);
if (!(cur->startpc >= next->startpc && cur->endpc <= next->endpc)) {
bbNext = realEndExceptionBlock;
} else {
bbNext = next->realTest;
nodeNext = next->exceptionPHI;
}
} else {
bbNext = realEndExceptionBlock;
}
if (cur->realTest != cur->test) {
const PointerType* PointerTy_0 = mvm::jit::ptrType;
std::vector<Value*> int32_eh_select_params;
Instruction* ptr_eh_ptr = new CallInst(mvm::jit::llvmGetException, "eh_ptr", cur->test);
int32_eh_select_params.push_back(ptr_eh_ptr);
int32_eh_select_params.push_back(ConstantExpr::getCast(Instruction::BitCast, mvm::jit::personality, PointerTy_0));
int32_eh_select_params.push_back(mvm::jit::constantPtrNull);
new CallInst(mvm::jit::exceptionSelector, int32_eh_select_params.begin(), int32_eh_select_params.end(), "eh_select", cur->test);
new BranchInst(cur->realTest, cur->test);
cur->exceptionPHI->addIncoming(ptr_eh_ptr, cur->test);
}
Value* cl = new LoadInst(cur->catchClass->llvmVar(compilingClass->isolate->module), "", cur->realTest);
Value* cmp = new CallInst(compareExceptionLLVM, cl, "", cur->realTest);
new BranchInst(cur->handler, bbNext, cmp, cur->realTest);
if (nodeNext)
nodeNext->addIncoming(cur->exceptionPHI, cur->realTest);
if (cur->handler->empty()) {
cur->handlerPHI = new PHINode(mvm::jit::ptrType, "", cur->handler);
cur->handlerPHI->addIncoming(cur->exceptionPHI, cur->realTest);
Value* exc = new CallInst(getJavaExceptionLLVM, "", cur->handler);
new CallInst(clearExceptionLLVM, "", cur->handler);
new CallInst(mvm::jit::exceptionBeginCatch, cur->handlerPHI, "tmp8", cur->handler);
std::vector<Value*> void_28_params;
new CallInst(mvm::jit::exceptionEndCatch, void_28_params.begin(), void_28_params.end(), "", cur->handler);
new StoreInst(exc, supplLocal, false, cur->handler);
} else {
Instruction* insn = cur->handler->begin();
((PHINode*)insn)->addIncoming(cur->exceptionPHI, cur->realTest);
}
}
return nbe;
}
void JavaJIT::compareFP(Value* val1, Value* val2, const Type* ty, bool l) {
Value* one = mvm::jit::constantOne;
Value* zero = mvm::jit::constantZero;
Value* minus = mvm::jit::constantMinusOne;
Value* c = new FCmpInst(FCmpInst::FCMP_UGT, val1, val2, "", currentBlock);
Value* r = new SelectInst(c, one, zero, "", currentBlock);
c = new FCmpInst(FCmpInst::FCMP_ULT, val1, val2, "", currentBlock);
r = new SelectInst(c, minus, r, "", currentBlock);
c = new FCmpInst(FCmpInst::FCMP_UNO, val1, val2, "", currentBlock);
r = new SelectInst(c, l ? one : minus, r, "", currentBlock);
push(r, AssessorDesc::dInt);
}
void JavaJIT::_ldc(uint16 index) {
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
uint8 type = ctpInfo->typeAt(index);
if (type == JavaCtpInfo::ConstantString) {
Value* toPush = 0;
if (ctpInfo->ctpRes[index] == 0) {
compilingClass->aquire();
if (ctpInfo->ctpRes[index] == 0) {
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
void* val = 0;
GlobalVariable* gv = 0;
#ifndef SINGLE_VM
if (compilingClass->isolate != Jnjvm::bootstrapVM) {
#endif
val = compilingClass->isolate->UTF8ToStr(utf8);
compilingClass->isolate->protectModule->lock();
gv =
new GlobalVariable(JavaObject::llvmType, false,
GlobalValue::ExternalLinkage,
constantJavaObjectNull, "",
compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
#ifndef SINGLE_VM
} else {
val = (void*)utf8;
compilingClass->isolate->protectModule->lock();
gv =
new GlobalVariable(UTF8::llvmType, false,
GlobalValue::ExternalLinkage,
constantUTF8Null, "",
compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
}
#endif
// TODO: put an initializer in here
void* ptr = mvm::jit::executionEngine->getPointerToGlobal(gv);
GenericValue Val = GenericValue(val);
llvm::GenericValue * Ptr = (llvm::GenericValue*)ptr;
mvm::jit::executionEngine->StoreValueToMemory(Val, Ptr, JavaObject::llvmType);
toPush = new LoadInst(gv, "", currentBlock);
ctpInfo->ctpRes[index] = gv;
compilingClass->release();
} else {
compilingClass->release();
toPush = new LoadInst((GlobalVariable*)ctpInfo->ctpRes[index], "", currentBlock);
}
} else {
toPush = new LoadInst((GlobalVariable*)ctpInfo->ctpRes[index], "", currentBlock);
}
#ifndef SINGLE_VM
if (compilingClass->isolate == Jnjvm::bootstrapVM)
push(new CallInst(runtimeUTF8ToStrLLVM, toPush, "", currentBlock), AssessorDesc::dRef);
else
#endif
push(toPush, AssessorDesc::dRef);
} else if (type == JavaCtpInfo::ConstantLong) {
mvm::jit::protectConstants();//->lock();
push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)), AssessorDesc::dLong);
mvm::jit::unprotectConstants();//->unlock();
} else if (type == JavaCtpInfo::ConstantDouble) {
mvm::jit::protectConstants();//->lock();
push(ConstantFP::get(Type::DoubleTy, APFloat(ctpInfo->DoubleAt(index))), AssessorDesc::dDouble);
mvm::jit::unprotectConstants();//->unlock();
} else if (type == JavaCtpInfo::ConstantInteger) {
mvm::jit::protectConstants();//->lock();
push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)), AssessorDesc::dInt);
mvm::jit::unprotectConstants();//->unlock();
} else if (type == JavaCtpInfo::ConstantFloat) {
mvm::jit::protectConstants();//->lock();
push(ConstantFP::get(Type::FloatTy, APFloat(ctpInfo->FloatAt(index))), AssessorDesc::dFloat);
mvm::jit::unprotectConstants();//->unlock();
} else if (type == JavaCtpInfo::ConstantClass) {
assert(0 && "implement ConstantClass in ldc!");
} else {
JavaThread::get()->isolate->unknownError("unknown type %d", type);
}
}
void JavaJIT::JITVerifyNull(Value* obj) {
JavaJIT* jit = this;
Constant* zero = constantJavaObjectNull;
Value* test = new ICmpInst(ICmpInst::ICMP_EQ, obj, zero, "",
jit->currentBlock);
BasicBlock* exit = jit->createBasicBlock("verifyNullExit");
BasicBlock* cont = jit->createBasicBlock("verifyNullCont");
new BranchInst(exit, cont, test, jit->currentBlock);
std::vector<Value*> args;
if (currentExceptionBlock != endExceptionBlock) {
new InvokeInst(JavaJIT::nullPointerExceptionLLVM, unifiedUnreachable,
currentExceptionBlock, args.begin(),
args.end(), "", exit);
} else {
new CallInst(JavaJIT::nullPointerExceptionLLVM, args.begin(),
args.end(), "", exit);
new UnreachableInst(exit);
}
jit->currentBlock = cont;
}
Value* JavaJIT::verifyAndComputePtr(Value* obj, Value* index,
const Type* arrayType, bool verif) {
JITVerifyNull(obj);
if (index->getType() != Type::Int32Ty) {
index = new SExtInst(index, Type::Int32Ty, "", currentBlock);
}
if (true) {
Value* size = arraySize(obj);
Value* cmp = new ICmpInst(ICmpInst::ICMP_ULT, index, size, "", currentBlock);
BasicBlock* ifTrue = createBasicBlock("true verifyAndComputePtr");
BasicBlock* ifFalse = createBasicBlock("false verifyAndComputePtr");
branch(cmp, ifTrue, ifFalse, currentBlock);
std::vector<Value*>args;
args.push_back(obj);
args.push_back(index);
if (currentExceptionBlock != endExceptionBlock) {
new InvokeInst(JavaJIT::indexOutOfBoundsExceptionLLVM, unifiedUnreachable,
currentExceptionBlock, args.begin(),
args.end(), "", ifFalse);
} else {
new CallInst(JavaJIT::indexOutOfBoundsExceptionLLVM, args.begin(),
args.end(), "", ifFalse);
new UnreachableInst(ifFalse);
}
currentBlock = ifTrue;
}
Constant* zero = mvm::jit::constantZero;
Value* val = new BitCastInst(obj, arrayType, "", currentBlock);
std::vector<Value*> indexes; //[3];
indexes.push_back(zero);
indexes.push_back(JavaArray::elementsOffset());
indexes.push_back(index);
Value* ptr = new GetElementPtrInst(val, indexes.begin(), indexes.end(),
"", currentBlock);
return ptr;
}
void JavaJIT::setCurrentBlock(BasicBlock* newBlock) {
std::vector< std::pair<Value*, const AssessorDesc*> > newStack;
uint32 index = 0;
for (BasicBlock::iterator i = newBlock->begin(), e = newBlock->end(); i != e;
++i, ++index) {
// case 2 happens with handlers
if (!(isa<PHINode>(i)) || i->getType() == mvm::jit::ptrType) {
break;
} else {
const llvm::Type* type = i->getType();
if (type == Type::Int32Ty || type == Type::Int16Ty ||
type == Type::Int8Ty) {
newStack.push_back(std::make_pair(i, AssessorDesc::dInt));
} else {
newStack.push_back(std::make_pair(i, stack[index].second));
}
}
}
stack = newStack;
currentBlock = newBlock;
}
static void testPHINodes(BasicBlock* dest, BasicBlock* insert, JavaJIT* jit) {
if(dest->empty()) {
for (std::vector< std::pair<Value*, const AssessorDesc*> >::iterator i = jit->stack.begin(),
e = jit->stack.end(); i!= e; ++i) {
Value* cur = i->first;
const AssessorDesc* func = i->second;
PHINode* node = 0;
if (func == AssessorDesc::dChar || func == AssessorDesc::dBool) {
node = new PHINode(Type::Int32Ty, "", dest);
cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else if (func == AssessorDesc::dByte || func == AssessorDesc::dShort) {
node = new PHINode(Type::Int32Ty, "", dest);
cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else {
node = new PHINode(cur->getType(), "", dest);
}
node->addIncoming(cur, insert);
}
} else {
std::vector< std::pair<Value*, const AssessorDesc*> >::iterator stackit = jit->stack.begin();
for (BasicBlock::iterator i = dest->begin(), e = dest->end(); i != e;
++i) {
if (!(isa<PHINode>(i))) {
break;
} else {
Instruction* ins = i;
Value* cur = stackit->first;
const AssessorDesc* func = stackit->second;
if (func == AssessorDesc::dChar || func == AssessorDesc::dBool) {
cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else if (func == AssessorDesc::dByte || func == AssessorDesc::dShort) {
cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
}
((PHINode*)ins)->addIncoming(cur, insert);
++stackit;
}
}
}
}
void JavaJIT::branch(llvm::BasicBlock* dest, llvm::BasicBlock* insert) {
testPHINodes(dest, insert, this);
new BranchInst(dest, insert);
}
void JavaJIT::branch(llvm::Value* test, llvm::BasicBlock* ifTrue,
llvm::BasicBlock* ifFalse, llvm::BasicBlock* insert) {
testPHINodes(ifTrue, insert, this);
testPHINodes(ifFalse, insert, this);
new BranchInst(ifTrue, ifFalse, test, insert);
}
void JavaJIT::makeArgs(FunctionType::param_iterator it,
uint32 index, std::vector<Value*>& Args, uint32 nb) {
Args.reserve(nb + 2);
Value* args[nb];
for (sint32 i = nb - 1; i >= 0; --i) {
it--;
if (it->get() == Type::Int64Ty || it->get() == Type::DoubleTy) {
pop();
}
const AssessorDesc* func = topFunc();
Value* tmp = pop();
const Type* type = it->get();
if (tmp->getType() != type) { // int8 or int16
if (type == Type::Int32Ty) {
if (func == AssessorDesc::dChar) {
tmp = new ZExtInst(tmp, type, "", currentBlock);
} else {
tmp = new SExtInst(tmp, type, "", currentBlock);
}
} else {
tmp = new TruncInst(tmp, type, "", currentBlock);
}
}
args[i] = tmp;
}
for (uint32 i = 0; i < nb; ++i) {
Args.push_back(args[i]);
}
}
Instruction* JavaJIT::lowerMathOps(const UTF8* name,
std::vector<Value*>& args) {
if (name == Jnjvm::abs) {
const Type* Ty = args[0]->getType();
if (Ty == Type::Int32Ty) {
Constant* const_int32_9 = mvm::jit::constantZero;
ConstantInt* const_int32_10 = mvm::jit::constantMinusOne;
BinaryOperator* int32_tmpneg = BinaryOperator::create(Instruction::Sub, const_int32_9, args[0], "tmpneg", currentBlock);
ICmpInst* int1_abscond = new ICmpInst(ICmpInst::ICMP_SGT, args[0], const_int32_10, "abscond", currentBlock);
return new SelectInst(int1_abscond, args[0], int32_tmpneg, "abs", currentBlock);
} else if (Ty == Type::Int64Ty) {
Constant* const_int64_9 = mvm::jit::constantLongZero;
ConstantInt* const_int64_10 = mvm::jit::constantLongMinusOne;
BinaryOperator* int64_tmpneg = BinaryOperator::create(Instruction::Sub, const_int64_9, args[0], "tmpneg", currentBlock);
ICmpInst* int1_abscond = new ICmpInst(ICmpInst::ICMP_SGT, args[0], const_int64_10, "abscond", currentBlock);
return new SelectInst(int1_abscond, args[0], int64_tmpneg, "abs", currentBlock);
} else if (Ty == Type::FloatTy) {
return new CallInst(mvm::jit::func_llvm_fabs_f32, args[0], "tmp1", currentBlock);
} else if (Ty == Type::DoubleTy) {
return new CallInst(mvm::jit::func_llvm_fabs_f64, args[0], "tmp1", currentBlock);
}
} else if (name == Jnjvm::sqrt) {
return new CallInst(mvm::jit::func_llvm_sqrt_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::sin) {
return new CallInst(mvm::jit::func_llvm_sin_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::cos) {
return new CallInst(mvm::jit::func_llvm_cos_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::tan) {
return new CallInst(mvm::jit::func_llvm_tan_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::asin) {
return new CallInst(mvm::jit::func_llvm_asin_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::acos) {
return new CallInst(mvm::jit::func_llvm_acos_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::atan) {
return new CallInst(mvm::jit::func_llvm_atan_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::atan2) {
return new CallInst(mvm::jit::func_llvm_atan2_f64, args.begin(), args.end(), "tmp1", currentBlock);
} else if (name == Jnjvm::exp) {
return new CallInst(mvm::jit::func_llvm_exp_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::log) {
return new CallInst(mvm::jit::func_llvm_log_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::pow) {
return new CallInst(mvm::jit::func_llvm_pow_f64, args.begin(), args.end(), "tmp1", currentBlock);
} else if (name == Jnjvm::ceil) {
return new CallInst(mvm::jit::func_llvm_ceil_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::floor) {
return new CallInst(mvm::jit::func_llvm_floor_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::rint) {
return new CallInst(mvm::jit::func_llvm_rint_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::cbrt) {
return new CallInst(mvm::jit::func_llvm_cbrt_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::cosh) {
return new CallInst(mvm::jit::func_llvm_cosh_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::expm1) {
return new CallInst(mvm::jit::func_llvm_expm1_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::hypot) {
return new CallInst(mvm::jit::func_llvm_hypot_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::log10) {
return new CallInst(mvm::jit::func_llvm_log10_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::log1p) {
return new CallInst(mvm::jit::func_llvm_log1p_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::sinh) {
return new CallInst(mvm::jit::func_llvm_sinh_f64, args[0], "tmp1", currentBlock);
} else if (name == Jnjvm::tanh) {
return new CallInst(mvm::jit::func_llvm_tanh_f64, args[0], "tmp1", currentBlock);
}
return 0;
}
Instruction* JavaJIT::invokeInline(JavaMethod* meth,
std::vector<Value*>& args) {
JavaJIT* jit = gc_new(JavaJIT)();
jit->compilingClass = meth->classDef;
jit->compilingMethod = meth;
jit->unifiedUnreachable = unifiedUnreachable;
jit->inlineMethods = inlineMethods;
jit->inlineMethods[meth] = true;
Instruction* ret = jit->inlineCompile(llvmFunction, currentBlock,
currentExceptionBlock, args);
inlineMethods[meth] = false;
return ret;
}
void JavaJIT::invokeSpecial(uint16 index) {
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
JavaMethod* meth = 0;
Signdef* signature = 0;
const UTF8* name = 0;
const UTF8* cl = 0;
ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
llvm::Instruction* val = 0;
std::vector<Value*> args;
FunctionType::param_iterator it = signature->virtualType->param_end();
makeArgs(it, index, args, signature->nbIn + 1);
JITVerifyNull(args[0]);
if (cl == Jnjvm::mathName) {
val = lowerMathOps(name, args);
}
if (!val) {
Function* func = ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_VIRTUAL,
signature, meth);
if (meth && meth->canBeInlined && meth != compilingMethod &&
inlineMethods[meth] == 0) {
val = invokeInline(meth, args);
} else {
val = invoke(func, args, "", currentBlock);
}
}
const llvm::Type* retType = signature->virtualType->getReturnType();
if (retType != Type::VoidTy) {
push(val, signature->ret->funcs);
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(mvm::jit::constantZero, AssessorDesc::dInt);
}
}
}
void JavaJIT::invokeStatic(uint16 index) {
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
JavaMethod* meth = 0;
Signdef* signature = 0;
const UTF8* name = 0;
const UTF8* cl = 0;
ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
llvm::Instruction* val = 0;
std::vector<Value*> args; // size = [signature->nbIn + 2];
FunctionType::param_iterator it = signature->staticType->param_end();
makeArgs(it, index, args, signature->nbIn);
ctpInfo->markAsStaticCall(index);
if (cl == Jnjvm::mathName) {
val = lowerMathOps(name, args);
}
if (!val) {
Function* func = ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_STATIC,
signature, meth);
if (meth && meth->canBeInlined && meth != compilingMethod &&
inlineMethods[meth] == 0) {
val = invokeInline(meth, args);
} else {
val = invoke(func, args, "", currentBlock);
}
}
const llvm::Type* retType = signature->staticType->getReturnType();
if (retType != Type::VoidTy) {
push(val, signature->ret->funcs);
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(mvm::jit::constantZero, AssessorDesc::dInt);
}
}
}
Value* JavaJIT::getInitializedClass(uint16 index) {
const Type* PtrTy = mvm::jit::ptrType;
compilingClass->isolate->protectModule->lock();
GlobalVariable * gv =
new GlobalVariable(PtrTy, false,
GlobalValue::ExternalLinkage,
mvm::jit::constantPtrNull, "",
compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
Value* arg1 = new LoadInst(gv, "", false, currentBlock);
Value* test = new ICmpInst(ICmpInst::ICMP_EQ, arg1,
mvm::jit::constantPtrNull, "", currentBlock);
BasicBlock* trueCl = createBasicBlock("Cl OK");
BasicBlock* falseCl = createBasicBlock("Cl Not OK");
PHINode* node = new PHINode(PtrTy, "", trueCl);
node->addIncoming(arg1, currentBlock);
new BranchInst(falseCl, trueCl, test, currentBlock);
currentBlock = falseCl;
std::vector<Value*> Args;
Value* v =
new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module),
"", currentBlock);
Args.push_back(v);
mvm::jit::protectConstants();
ConstantInt* CI = ConstantInt::get(Type::Int32Ty, index);
mvm::jit::unprotectConstants();
Args.push_back(CI);
Args.push_back(gv);
Value* res = invoke(newLookupLLVM, Args, "", currentBlock);
node->addIncoming(res, currentBlock);
new BranchInst(trueCl, currentBlock);
currentBlock = trueCl;
return node;
}
void JavaJIT::invokeNew(uint16 index) {
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
ctpInfo->checkInfoOfClass(index);
Class* cl = (Class*)(ctpInfo->getMethodClassIfLoaded(index));
Value* val = 0;
if (!cl || !cl->isReady()) {
Value* node = getInitializedClass(index);
val = invoke(doNewUnknownLLVM, node, "", currentBlock);
} else {
Value* load = new LoadInst(cl->llvmVar(compilingClass->isolate->module), "", currentBlock);
val = invoke(doNewLLVM, load, "", currentBlock);
// give the real type info, escape analysis uses it
new BitCastInst(val, cl->virtualType, "", currentBlock);
}
push(val, AssessorDesc::dRef);
}
Value* JavaJIT::arraySize(Value* val) {
return new CallInst(arrayLengthLLVM, val, "", currentBlock);
/*
Value* array = new BitCastInst(val, JavaArray::llvmType, "", currentBlock);
std::vector<Value*> args; //size= 2
args.push_back(mvm::jit::constantZero);
args.push_back(JavaArray::sizeOffset());
Value* ptr = new GetElementPtrInst(array, args.begin(), args.end(),
"", currentBlock);
return new LoadInst(ptr, "", currentBlock);*/
}
static llvm::Value* fieldGetter(JavaJIT* jit, const Type* type, Value* object,
Value* offset) {
llvm::Value* objectConvert = new BitCastInst(object, type, "",
jit->currentBlock);
Constant* zero = mvm::jit::constantZero;
std::vector<Value*> args; // size = 2
args.push_back(zero);
args.push_back(offset);
llvm::Value* ptr = new GetElementPtrInst(objectConvert, args.begin(),
args.end(), "", jit->currentBlock);
return ptr;
}
Value* JavaJIT::ldResolved(uint16 index, bool stat, Value* object,
const Type* fieldType, const Type* fieldTypePtr) {
JavaCtpInfo* info = compilingClass->ctpInfo;
JavaField* field = info->lookupField(index, stat);
if (field && field->classDef->isReady()) {
if (stat) object = new LoadInst(field->classDef->staticVar(compilingClass->isolate->module), "",
currentBlock);
const Type* type = stat ? field->classDef->staticType :
field->classDef->virtualType;
#ifndef SINGLE_VM
if (stat && field->classDef->isolate == Jnjvm::bootstrapVM) {
object = new CallInst(getStaticInstanceLLVM, object, "", currentBlock);
}
#endif
return fieldGetter(this, type, object, field->offset);
} else {
const Type* Pty = mvm::jit::arrayPtrType;
compilingClass->isolate->protectModule->lock();
GlobalVariable* gvStaticInstance =
new GlobalVariable(mvm::jit::ptrType, false,
GlobalValue::ExternalLinkage,
mvm::jit::constantPtrNull,
"", compilingClass->isolate->module);
Constant* zero = mvm::jit::constantZero;
GlobalVariable* gv =
new GlobalVariable(Type::Int32Ty, false, GlobalValue::ExternalLinkage,
zero, "", compilingClass->isolate->module);
compilingClass->isolate->protectModule->unlock();
// set is volatile
Value* val = new LoadInst(gv, "", true, currentBlock);
Value * cmp = new ICmpInst(ICmpInst::ICMP_NE, val, zero, "", currentBlock);
BasicBlock* ifTrue = createBasicBlock("true ldResolved");
BasicBlock* ifFalse = createBasicBlock("false ldResolved");
BasicBlock* endBlock = createBasicBlock("end ldResolved");
PHINode * node = new PHINode(mvm::jit::ptrType, "", endBlock);
new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
// ---------- In case we already resolved something --------------------- //
currentBlock = ifTrue;
Value* resPtr = 0;
if (object) {
Value* ptr = new BitCastInst(object, Pty, "", currentBlock);
std::vector<Value*> gepArgs; // size = 1
gepArgs.push_back(zero);
gepArgs.push_back(val);
resPtr = new GetElementPtrInst(ptr, gepArgs.begin(), gepArgs.end(),
"", currentBlock);
} else {
resPtr = new LoadInst(gvStaticInstance, "", currentBlock);
}
node->addIncoming(resPtr, currentBlock);
new BranchInst(endBlock, currentBlock);
// ---------- In case we have to resolve -------------------------------- //
currentBlock = ifFalse;
std::vector<Value*> args;
if (object) {
args.push_back(object);
} else {
args.push_back(constantJavaObjectNull);
}
args.push_back(new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module), "",
currentBlock));
mvm::jit::protectConstants();//->lock();
args.push_back(ConstantInt::get(Type::Int32Ty, index));
mvm::jit::unprotectConstants();//->unlock();
args.push_back(stat ? mvm::jit::constantOne : mvm::jit::constantZero);
args.push_back(gvStaticInstance);
args.push_back(gv);
Value* tmp = invoke(JavaJIT::fieldLookupLLVM, args, "", currentBlock);
node->addIncoming(tmp, currentBlock);
new BranchInst(endBlock, currentBlock);
currentBlock = endBlock;;
return new BitCastInst(node, fieldTypePtr, "", currentBlock);
}
}
extern void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock, bool usign);
void JavaJIT::setStaticField(uint16 index) {
const AssessorDesc* ass = topFunc();
Value* val = pop();
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
const Type* type = sign->funcs->llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
val = pop();
}
Value* ptr = ldResolved(index, true, 0, type, sign->funcs->llvmTypePtr);
if (type != val->getType()) { // int1, int8, int16
convertValue(val, type, currentBlock,
ass == AssessorDesc::dChar || ass == AssessorDesc::dBool);
}
new StoreInst(val, ptr, false, currentBlock);
}
void JavaJIT::getStaticField(uint16 index) {
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
Value* ptr = ldResolved(index, true, 0, sign->funcs->llvmType,
sign->funcs->llvmTypePtr);
push(new LoadInst(ptr, "", currentBlock), sign->funcs);
const Type* type = sign->funcs->llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
push(mvm::jit::constantZero, AssessorDesc::dInt);
}
}
void JavaJIT::setVirtualField(uint16 index) {
const AssessorDesc* ass = topFunc();
Value* val = pop();
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
const Type* type = sign->funcs->llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
val = pop();
}
Value* object = pop();
JITVerifyNull(object);
Value* ptr = ldResolved(index, false, object, type,
sign->funcs->llvmTypePtr);
if (type != val->getType()) { // int1, int8, int16
convertValue(val, type, currentBlock,
ass == AssessorDesc::dChar || ass == AssessorDesc::dBool);
}
new StoreInst(val, ptr, false, currentBlock);
}
void JavaJIT::getVirtualField(uint16 index) {
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
Value* obj = pop();
JITVerifyNull(obj);
Value* ptr = ldResolved(index, false, obj, sign->funcs->llvmType,
sign->funcs->llvmTypePtr);
push(new LoadInst(ptr, "", currentBlock), sign->funcs);
const Type* type = sign->funcs->llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
push(mvm::jit::constantZero, AssessorDesc::dInt);
}
}
Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
const char* Name,
BasicBlock *InsertAtEnd) {
// means: is there a handler for me?
if (currentExceptionBlock != endExceptionBlock) {
BasicBlock* ifNormal = createBasicBlock("no exception block");
currentBlock = ifNormal;
return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
args.end(), Name, InsertAtEnd);
} else {
return new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
}
}
Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
BasicBlock *InsertAtEnd) {
// means: is there a handler for me?
if (currentExceptionBlock != endExceptionBlock) {
BasicBlock* ifNormal = createBasicBlock("no exception block");
currentBlock = ifNormal;
std::vector<Value*> arg;
arg.push_back(arg1);
return new InvokeInst(F, ifNormal, currentExceptionBlock, arg.begin(),
arg.end(), Name, InsertAtEnd);
} else {
return new CallInst(F, arg1, Name, InsertAtEnd);
}
}
Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
const char* Name, BasicBlock *InsertAtEnd) {
std::vector<Value*> args;
args.push_back(arg1);
args.push_back(arg2);
// means: is there a handler for me?
if (currentExceptionBlock != endExceptionBlock) {
BasicBlock* ifNormal = createBasicBlock("no exception block");
currentBlock = ifNormal;
return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
args.end(), Name, InsertAtEnd);
} else {
return new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
}
}
Instruction* JavaJIT::invoke(Value *F, const char* Name,
BasicBlock *InsertAtEnd) {
// means: is there a handler for me?
if (currentExceptionBlock != endExceptionBlock) {
BasicBlock* ifNormal = createBasicBlock("no exception block");
currentBlock = ifNormal;
std::vector<Value*> args;
return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
args.end(), Name, InsertAtEnd);
} else {
return new CallInst(F, Name, InsertAtEnd);
}
}