blob: d4e739fad2f0f9ae33955831181aad8892450805 [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 <cstring>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Instructions.h>
#include <llvm/Module.h>
#include <llvm/Type.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/Support/CFG.h>
#include "mvm/JIT.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"
using namespace jnjvm;
using namespace llvm;
static bool needsInitialisationCheck(Class* cl, Class* compilingClass) {
#ifdef SERVICE
return true;
#else
return !(cl->isReadyForCompilation() || compilingClass->subclassOf(cl));
#endif
}
bool JavaJIT::canBeInlined(JavaMethod* meth) {
return (meth->canBeInlined &&
meth != compilingMethod && inlineMethods[meth] == 0 &&
meth->classDef->classLoader == compilingClass->classLoader);
}
void JavaJIT::invokeVirtual(uint16 index) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
CommonClass* cl = 0;
JavaMethod* meth = 0;
ctpInfo->infoOfMethod(index, ACC_VIRTUAL, cl, meth);
if ((cl && isFinal(cl->access)) ||
(meth && (isFinal(meth->access) || isPrivate(meth->access))))
return invokeSpecial(index);
// If the method is in fact a method defined in an interface,
// call invokeInterfaceOrVirtual instead.
if (meth && isInterface(meth->classDef->access)) {
return invokeInterfaceOrVirtual(index, true);
}
#if !defined(WITHOUT_VTABLE)
const UTF8* name = 0;
Signdef* signature = ctpInfo->infoOfInterfaceOrVirtualMethod(index, name);
Typedef* retTypedef = signature->getReturnType();
std::vector<Value*> args; // size = [signature->nbIn + 3];
LLVMSignatureInfo* LSI = module->getSignatureInfo(signature);
const llvm::FunctionType* virtualType = LSI->getVirtualType();
FunctionType::param_iterator it = virtualType->param_end();
makeArgs(it, index, args, signature->nbArguments + 1);
const llvm::Type* retType = virtualType->getReturnType();
JITVerifyNull(args[0]);
BasicBlock* endBlock = 0;
PHINode* node = 0;
if (meth && !isAbstract(meth->access) && canBeInlined(meth)) {
Value* cl = CallInst::Create(module->GetClassFunction, args[0], "",
currentBlock);
Value* cl2 = module->getNativeClass((Class*)cl, currentBlock);
Value* test = new ICmpInst(ICmpInst::ICMP_EQ, cl, cl2, "", currentBlock);
BasicBlock* trueBlock = createBasicBlock("true virtual invoke");
BasicBlock* falseBlock = createBasicBlock("false virtual invoke");
endBlock = createBasicBlock("end virtual invoke");
BranchInst::Create(trueBlock, falseBlock, test, currentBlock);
currentBlock = trueBlock;
Value* res = invokeInline(meth, args);
BranchInst::Create(endBlock, currentBlock);
if (retType != Type::VoidTy) {
node = PHINode::Create(virtualType->getReturnType(), "", endBlock);
node->addIncoming(res, currentBlock);
}
currentBlock = falseBlock;
}
Value* VT = CallInst::Create(module->GetVTFunction, args[0], "",
currentBlock);
Value* indexes2[2];
indexes2[0] = module->constantZero;
#ifdef ISOLATE_SHARING
Value* indexesCtp; //[3];
#endif
if (meth) {
LLVMMethodInfo* LMI = module->getMethodInfo(meth);
ConstantInt* Offset = LMI->getOffset();
indexes2[1] = Offset;
#ifdef ISOLATE_SHARING
indexesCtp = ConstantInt::get(Type::Int32Ty,
Offset->getZExtValue() * -1);
#endif
} else {
Value* val = getConstantPoolAt(index, module->VirtualLookupFunction,
Type::Int32Ty, args[0], true);
indexes2[1] = val;
#ifdef ISOLATE_SHARING
Value* mul = BinaryOperator::CreateMul(val, module->constantMinusOne,
"", currentBlock);
indexesCtp = mul;
#endif
}
Value* FuncPtr = GetElementPtrInst::Create(VT, indexes2, indexes2 + 2, "",
currentBlock);
Value* Func = new LoadInst(FuncPtr, "", currentBlock);
Func = new BitCastInst(Func, LSI->getVirtualPtrType(), "", currentBlock);
#ifdef ISOLATE_SHARING
Value* CTP = GetElementPtrInst::Create(VT, indexesCtp, "", currentBlock);
CTP = new LoadInst(CTP, "", currentBlock);
CTP = new BitCastInst(CTP, module->ConstantPoolType, "", currentBlock);
args.push_back(CTP);
#endif
Value* val = invoke(Func, args, "", currentBlock);
if (endBlock) {
if (node) {
node->addIncoming(val, currentBlock);
val = node;
}
BranchInst::Create(endBlock, currentBlock);
currentBlock = endBlock;
}
if (retType != Type::VoidTy) {
push(val, retTypedef->isUnsigned());
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(module->constantZero, false);
}
}
#else
return invokeInterfaceOrVirtual(index);
#endif
}
llvm::Function* JavaJIT::nativeCompile(intptr_t natPtr) {
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "native compile %s\n",
compilingMethod->printString());
bool stat = isStatic(compilingMethod->access);
const FunctionType *funcType = llvmFunction->getFunctionType();
bool jnjvm = false;
natPtr = natPtr ? natPtr :
NativeUtil::nativeLookup(compilingClass, compilingMethod, jnjvm);
if (!natPtr && !module->isStaticCompiling()) {
fprintf(stderr, "Native function %s not found. Probably "
"not implemented by JnJVM?\n", compilingMethod->printString());
JavaJIT::printBacktrace();
JavaThread::get()->getJVM()->unknownError("can not find native method %s",
compilingMethod->printString());
}
Function* func = llvmFunction;
if (jnjvm) {
module->executionEngine->addGlobalMapping(func, (void*)natPtr);
return llvmFunction;
}
currentExceptionBlock = endExceptionBlock = 0;
currentBlock = createBasicBlock("start");
BasicBlock* executeBlock = createBasicBlock("execute");
endBlock = createBasicBlock("end block");
returnType = funcType->getReturnType();
Value* buf = llvm::CallInst::Create(module->GetSJLJBufferFunction,
"", currentBlock);
Value* test = llvm::CallInst::Create(module->setjmpLLVM, buf, "",
currentBlock);
test = new ICmpInst(ICmpInst::ICMP_EQ, test, module->constantZero, "",
currentBlock);
llvm::BranchInst::Create(executeBlock, endBlock, test, currentBlock);
if (returnType != Type::VoidTy) {
endNode = llvm::PHINode::Create(returnType, "", endBlock);
endNode->addIncoming(Constant::getNullValue(returnType),
currentBlock);
}
currentBlock = executeBlock;
if (isSynchro(compilingMethod->access))
beginSynchronize();
uint32 nargs = func->arg_size() + 1 + (stat ? 1 : 0);
std::vector<Value*> nativeArgs;
int64_t jniEnv = (int64_t)&(JavaThread::get()->getJVM()->jniEnv);
nativeArgs.push_back(
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, jniEnv),
module->ptrType));
uint32 index = 0;
if (stat) {
#ifdef ISOLATE_SHARING
Value* val = getClassCtp();
Value* res = CallInst::Create(module->GetClassDelegateeFunction,
val, "", currentBlock);
nativeArgs.push_back(res);
#else
Value* cl = module->getJavaClass(compilingClass, currentBlock);
nativeArgs.push_back(cl);
#endif
index = 2;
} else {
index = 1;
}
for (Function::arg_iterator i = func->arg_begin();
index < nargs; ++i, ++index) {
nativeArgs.push_back(i);
}
Value* nativeFunc = module->getNativeFunction(compilingMethod, (void*)natPtr,
currentBlock);
Value* result = llvm::CallInst::Create(nativeFunc, nativeArgs.begin(),
nativeArgs.end(), "", currentBlock);
if (returnType != Type::VoidTy)
endNode->addIncoming(result, currentBlock);
llvm::BranchInst::Create(endBlock, currentBlock);
currentBlock = endBlock;
if (isSynchro(compilingMethod->access))
endSynchronize();
llvm::CallInst::Create(module->JniProceedPendingExceptionFunction, "",
currentBlock);
if (returnType != Type::VoidTy)
llvm::ReturnInst::Create(endNode, currentBlock);
else
llvm::ReturnInst::Create(currentBlock);
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "end native compile %s\n",
compilingMethod->printString());
func->setLinkage(GlobalValue::ExternalLinkage);
return llvmFunction;
}
void JavaJIT::monitorEnter(Value* obj) {
Value* gep[2] = { module->constantZero,
module->JavaObjectLockOffsetConstant };
Value* lockPtr = GetElementPtrInst::Create(obj, gep, gep + 2, "",
currentBlock);
Value* lock = new LoadInst(lockPtr, "", currentBlock);
lock = new PtrToIntInst(lock, module->pointerSizeType, "", currentBlock);
Value* lockMask = BinaryOperator::CreateAnd(lock,
module->constantThreadFreeMask,
"", currentBlock);
Value* threadId = CallInst::Create(module->llvm_frameaddress,
module->constantZero, "", currentBlock);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", currentBlock);
Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lockMask, threadId, "",
currentBlock);
BasicBlock* ThinLockBB = createBasicBlock("thread local");
BasicBlock* FatLockBB = createBasicBlock("fat lock");
BasicBlock* EndLockBB = createBasicBlock("End lock");
BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock);
currentBlock = ThinLockBB;
Value* increment = BinaryOperator::CreateAdd(lock, module->constantPtrOne, "",
currentBlock);
increment = new IntToPtrInst(increment, module->ptrType, "", currentBlock);
new StoreInst(increment, lockPtr, false, currentBlock);
BranchInst::Create(EndLockBB, currentBlock);
currentBlock = FatLockBB;
// Either it's a fat lock or there is contention or it's not thread local or
// it's locked at least once.
CallInst::Create(module->AquireObjectFunction, obj, "", currentBlock);
BranchInst::Create(EndLockBB, currentBlock);
currentBlock = EndLockBB;
}
void JavaJIT::monitorExit(Value* obj) {
Value* gep[2] = { module->constantZero,
module->JavaObjectLockOffsetConstant };
Value* lockPtr = GetElementPtrInst::Create(obj, gep, gep + 2, "",
currentBlock);
Value* lock = new LoadInst(lockPtr, "", currentBlock);
lock = new PtrToIntInst(lock, module->pointerSizeType, "", currentBlock);
Value* lockMask = BinaryOperator::CreateAnd(lock, module->constantLockedMask,
"", currentBlock);
Value* threadId = CallInst::Create(module->llvm_frameaddress,
module->constantZero, "", currentBlock);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", currentBlock);
Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, lockMask, threadId, "",
currentBlock);
BasicBlock* EndUnlock = createBasicBlock("end unlock");
BasicBlock* ThinLockBB = createBasicBlock("desynchronize thin lock");
BasicBlock* FatLockBB = createBasicBlock("fat lock");
BranchInst::Create(ThinLockBB, FatLockBB, cmp, currentBlock);
// Locked by the thread, decrement.
currentBlock = ThinLockBB;
Value* decrement = BinaryOperator::CreateSub(lock, module->constantPtrOne, "",
currentBlock);
decrement = new IntToPtrInst(decrement, module->ptrType, "", currentBlock);
new StoreInst(decrement, lockPtr, false, currentBlock);
BranchInst::Create(EndUnlock, currentBlock);
// Either it's a fat lock or there is contention or it's not thread local.
currentBlock = FatLockBB;
CallInst::Create(module->ReleaseObjectFunction, obj, "", currentBlock);
BranchInst::Create(EndUnlock, currentBlock);
currentBlock = EndUnlock;
}
#ifdef ISOLATE_SHARING
Value* JavaJIT::getStaticInstanceCtp() {
Value* cl = getClassCtp();
Value* indexes[2] = { module->constantZero, module->constantSeven };
Value* arg1 = GetElementPtrInst::Create(cl, indexes, indexes + 2,
"", currentBlock);
arg1 = new LoadInst(arg1, "", false, currentBlock);
return arg1;
}
Value* JavaJIT::getClassCtp() {
Value* indexes = module->constantOne;
Value* arg1 = GetElementPtrInst::Create(ctpCache, indexes.begin(),
indexes.end(), "", currentBlock);
arg1 = new LoadInst(arg1, "", false, currentBlock);
arg1 = new BitCastInst(arg1, module->JavaClassType, "", currentBlock);
return arg1;
}
#endif
void JavaJIT::beginSynchronize() {
Value* obj = 0;
if (isVirtual(compilingMethod->access)) {
obj = llvmFunction->arg_begin();
} else {
obj = module->getJavaClass(compilingClass, currentBlock);
}
monitorEnter(obj);
}
void JavaJIT::endSynchronize() {
Value* obj = 0;
if (isVirtual(compilingMethod->access)) {
obj = llvmFunction->arg_begin();
} else {
obj = module->getJavaClass(compilingClass, currentBlock);
}
monitorExit(obj);
}
Instruction* JavaJIT::inlineCompile(BasicBlock*& curBB,
BasicBlock* endExBlock,
std::vector<Value*>& args) {
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "inline compile %s\n",
compilingMethod->printString());
Attribut* codeAtt = compilingMethod->lookupAttribut(Attribut::codeAttribut);
if (!codeAtt) {
Jnjvm* vm = JavaThread::get()->getJVM();
vm->unknownError("unable to find the code attribut in %s",
compilingMethod->printString());
}
Reader reader(codeAtt, compilingClass->bytes);
maxStack = reader.readU2();
maxLocals = reader.readU2();
codeLen = reader.readU4();
uint32 start = reader.cursor;
reader.seek(codeLen, Reader::SeekCur);
LLVMMethodInfo* LMI = module->getMethodInfo(compilingMethod);
assert(LMI);
Function* func = LMI->getMethod();
returnType = func->getReturnType();
endBlock = createBasicBlock("end");
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(module->JavaObjectType, "",
currentBlock));
}
uint32 index = 0;
uint32 count = 0;
#if defined(ISOLATE_SHARING)
uint32 max = args.size() - 2;
#else
uint32 max = args.size();
#endif
Signdef* sign = compilingMethod->getSignature();
Typedef* const* arguments = sign->getArgumentsType();
uint32 type = 0;
std::vector<Value*>::iterator i = args.begin();
if (isVirtual(compilingMethod->access)) {
new StoreInst(*i, objectLocals[0], false, currentBlock);
++i;
++index;
++count;
}
for (;count < max; ++i, ++index, ++count, ++type) {
const Typedef* cur = arguments[type];
const Type* curType = (*i)->getType();
if (curType == Type::Int64Ty){
new StoreInst(*i, longLocals[index], false, currentBlock);
++index;
} else if (cur->isUnsigned()) {
new StoreInst(new ZExtInst(*i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (curType == Type::Int8Ty || curType == Type::Int16Ty) {
new StoreInst(new SExtInst(*i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (curType == Type::Int32Ty) {
new StoreInst(*i, intLocals[index], false, currentBlock);
} else if (curType == Type::DoubleTy) {
new StoreInst(*i, doubleLocals[index], false, currentBlock);
++index;
} else if (curType == Type::FloatTy) {
new StoreInst(*i, floatLocals[index], false, currentBlock);
} else {
new StoreInst(*i, objectLocals[index], false, currentBlock);
}
}
exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
nbEnveloppes = 0;
if (returnType != Type::VoidTy) {
endNode = llvm::PHINode::Create(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 = compilingMethod->lookupAttribut(Attribut::codeAttribut);
if (!codeAtt) {
Jnjvm* vm = JavaThread::get()->getJVM();
vm->unknownError("unable to find the code attribut in %s",
compilingMethod->printString());
}
Reader reader(codeAtt, compilingClass->bytes);
maxStack = reader.readU2();
maxLocals = reader.readU2();
codeLen = reader.readU4();
uint32 start = reader.cursor;
reader.seek(codeLen, Reader::SeekCur);
const FunctionType *funcType = llvmFunction->getFunctionType();
returnType = funcType->getReturnType();
Function* func = llvmFunction;
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
{
Value* arg = ConstantExpr::getIntToPtr(
ConstantInt::get(Type::Int64Ty, uint64_t (compilingMethod)),
module->ptrType);
llvm::CallInst::Create(module->PrintMethodStartFunction, arg, "",
currentBlock);
}
#endif
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(module->JavaObjectType, "",
currentBlock));
}
uint32 index = 0;
uint32 count = 0;
#if defined(ISOLATE_SHARING)
uint32 max = func->arg_size() - 2;
#else
uint32 max = func->arg_size();
#endif
Function::arg_iterator i = func->arg_begin();
Signdef* sign = compilingMethod->getSignature();
Typedef* const* arguments = sign->getArgumentsType();
uint32 type = 0;
if (isVirtual(compilingMethod->access)) {
new StoreInst(i, objectLocals[0], false, currentBlock);
++i;
++index;
++count;
}
for (;count < max; ++i, ++index, ++count, ++type) {
const Typedef* cur = arguments[type];
const llvm::Type* curType = i->getType();
if (curType == Type::Int64Ty){
new StoreInst(i, longLocals[index], false, currentBlock);
++index;
} else if (cur->isUnsigned()) {
new StoreInst(new ZExtInst(i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (curType == Type::Int8Ty || curType == Type::Int16Ty) {
new StoreInst(new SExtInst(i, Type::Int32Ty, "", currentBlock),
intLocals[index], false, currentBlock);
} else if (curType == Type::Int32Ty) {
new StoreInst(i, intLocals[index], false, currentBlock);
} else if (curType == Type::DoubleTy) {
new StoreInst(i, doubleLocals[index], false, currentBlock);
++index;
} else if (curType == Type::FloatTy) {
new StoreInst(i, floatLocals[index], false, currentBlock);
} else {
new StoreInst(i, objectLocals[index], false, currentBlock);
}
}
#if defined(ISOLATE_SHARING)
ctpCache = i;
Value* addrCtpCache = new AllocaInst(module->ConstantPoolType, "",
currentBlock);
/// make it volatile to be sure it's on the stack
new StoreInst(ctpCache, addrCtpCache, true, currentBlock);
#endif
#if defined(SERVICE)
JnjvmClassLoader* loader = compilingClass->classLoader;
Value* Cmp = 0;
Value* threadId = 0;
Value* OldIsolateID = 0;
Value* IsolateIDPtr = 0;
Value* OldIsolate = 0;
Value* NewIsolate = 0;
Value* IsolatePtr = 0;
if (loader != loader->bootstrapLoader && isPublic(compilingMethod->access)) {
threadId = CallInst::Create(module->llvm_frameaddress, module->constantZero,
"", currentBlock);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", currentBlock);
threadId = new IntToPtrInst(threadId, module->ptrPtrType, "", currentBlock);
IsolateIDPtr = GetElementPtrInst::Create(threadId, module->constantThree,
"", currentBlock);
const Type* realType = PointerType::getUnqual(module->pointerSizeType);
IsolateIDPtr = new BitCastInst(IsolateIDPtr, realType, "",
currentBlock);
OldIsolateID = new LoadInst(IsolateIDPtr, "", currentBlock);
Value* MyID = ConstantInt::get(module->pointerSizeType,
loader->getIsolate()->IsolateID);
Cmp = new ICmpInst(ICmpInst::ICMP_EQ, OldIsolateID, MyID, "", currentBlock);
BasicBlock* EndBB = createBasicBlock("After service check");
BasicBlock* ServiceBB = createBasicBlock("Begin service call");
BranchInst::Create(EndBB, ServiceBB, Cmp, currentBlock);
currentBlock = ServiceBB;
new StoreInst(MyID, IsolateIDPtr, currentBlock);
IsolatePtr = GetElementPtrInst::Create(threadId, module->constantFour, "",
currentBlock);
OldIsolate = new LoadInst(IsolatePtr, "", currentBlock);
NewIsolate = module->getIsolate(loader->getIsolate(), currentBlock);
new StoreInst(NewIsolate, IsolatePtr, currentBlock);
#if DEBUG
Value* GEP[2] = { OldIsolate, NewIsolate };
CallInst::Create(module->ServiceCallStartFunction, GEP, GEP + 2,
"", currentBlock);
#endif
BranchInst::Create(EndBB, currentBlock);
currentBlock = EndBB;
}
#endif
unsigned nbe = readExceptionTable(reader);
exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
compilingMethod->enveloppes =
new (compilingClass->classLoader->allocator) Enveloppe[nbEnveloppes];
compilingMethod->nbEnveloppes = nbEnveloppes;
nbEnveloppes = 0;
endBlock = createBasicBlock("end");
if (returnType != Type::VoidTy) {
endNode = llvm::PHINode::Create(returnType, "", endBlock);
}
if (isSynchro(compilingMethod->access))
beginSynchronize();
compileOpcodes(&compilingClass->bytes->elements[start], codeLen);
assert(stack.size() == 0 && "Stack not empty after compiling bytecode");
// Fix a javac(?) bug where a method only throws an exception and des
// not return.
pred_iterator PI = pred_begin(endBlock);
pred_iterator PE = pred_end(endBlock);
if (PI == PE && returnType != Type::VoidTy) {
Instruction* I = currentBlock->getTerminator();
assert((isa<UnreachableInst>(I) || isa<InvokeInst>(I)) &&
"Malformed end Java block");
if (isa<UnreachableInst>(I)) {
I->eraseFromParent();
BranchInst::Create(endBlock, currentBlock);
} else if (InvokeInst* II = dyn_cast<InvokeInst>(I)) {
II->setNormalDest(endBlock);
}
endNode->addIncoming(Constant::getNullValue(returnType),
currentBlock);
}
currentBlock = endBlock;
if (isSynchro(compilingMethod->access))
endSynchronize();
#if JNJVM_EXECUTE > 0
{
Value* arg = ConstantExpr::getIntToPtr(
ConstantInt::get(Type::Int64Ty, uint64_t (compilingMethod)),
module->ptrType);
CallInst::Create(module->PrintMethodEndFunction, arg, "", currentBlock);
}
#endif
#if defined(SERVICE)
if (Cmp) {
BasicBlock* EndBB = createBasicBlock("After service check");
BasicBlock* ServiceBB = createBasicBlock("End Service call");
BranchInst::Create(EndBB, ServiceBB, Cmp, currentBlock);
currentBlock = ServiceBB;
new StoreInst(OldIsolateID, IsolateIDPtr, currentBlock);
new StoreInst(OldIsolate, IsolatePtr, currentBlock);
#if DEBUG
Value* GEP[2] = { OldIsolate, NewIsolate };
CallInst::Create(module->ServiceCallStopFunction, GEP, GEP + 2,
"", currentBlock);
#endif
BranchInst::Create(EndBB, currentBlock);
currentBlock = EndBB;
}
#endif
PI = pred_begin(currentBlock);
PE = pred_end(currentBlock);
if (PI == PE) {
currentBlock->eraseFromParent();
} else {
if (returnType != Type::VoidTy)
ReturnInst::Create(endNode, currentBlock);
else
ReturnInst::Create(currentBlock);
}
PI = pred_begin(endExceptionBlock);
PE = pred_end(endExceptionBlock);
if (PI == PE) {
endExceptionBlock->eraseFromParent();
} else {
CallInst* ptr_eh_ptr = CallInst::Create(module->GetExceptionFunction,
"eh_ptr", endExceptionBlock);
llvm::CallInst::Create(module->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);
}
func->setLinkage(GlobalValue::ExternalLinkage);
PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end compiling %s\n",
compilingMethod->printString());
if (nbe == 0 && codeLen < 50 && !callsStackWalker)
compilingMethod->canBeInlined = false;
return llvmFunction;
}
unsigned JavaJIT::readExceptionTable(Reader& reader) {
BasicBlock* temp = currentBlock;
sint16 nbe = reader.readU2();
sint16 sync = isSynchro(compilingMethod->access) ? 1 : 0;
nbe += sync;
BasicBlock* realEndExceptionBlock = endExceptionBlock;
BasicBlock* endExceptionBlockCatcher = endExceptionBlock;
currentExceptionBlock = endExceptionBlock;
if (sync) {
BasicBlock* synchronizeExceptionBlock =
createBasicBlock("synchronizeExceptionBlock");
BasicBlock* trySynchronizeExceptionBlock =
createBasicBlock("trySynchronizeExceptionBlock");
realEndExceptionBlock = synchronizeExceptionBlock;
endExceptionBlockCatcher = trySynchronizeExceptionBlock;
Value* argsSync = 0;
if (isVirtual(compilingMethod->access)) {
argsSync = llvmFunction->arg_begin();
} else {
Value* cl = module->getJavaClass(compilingClass,
synchronizeExceptionBlock);
argsSync = cl;
}
CallInst::Create(module->ReleaseObjectFunction, argsSync, "",
synchronizeExceptionBlock);
BranchInst::Create(endExceptionBlock, synchronizeExceptionBlock);
const PointerType* PointerTy_0 = module->ptrType;
Instruction* ptr_eh_ptr = CallInst::Create(module->llvmGetException,
"eh_ptr",
trySynchronizeExceptionBlock);
Constant* C = ConstantExpr::getCast(Instruction::BitCast,
module->personality, PointerTy_0);
Value* int32_eh_select_params[3] =
{ ptr_eh_ptr, C, module->constantPtrNull };
CallInst::Create(module->exceptionSelector, int32_eh_select_params,
int32_eh_select_params + 3, "eh_select",
trySynchronizeExceptionBlock);
BranchInst::Create(synchronizeExceptionBlock,
trySynchronizeExceptionBlock);
for (uint16 i = 0; i < codeLen; ++i) {
if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
opcodeInfos[i].exceptionBlock = trySynchronizeExceptionBlock;
}
}
}
// We don't need the lock here, and Java requires to load the classes in the
// try clause, which may require compilation. Therefore we release the lock
// and acquire it after the exception table is read.
module->executionEngine->lock.release();
Exception* exceptions = (Exception*)alloca(sizeof(Exception) * (nbe - sync));
for (uint16 i = 0; i < nbe - sync; ++i) {
Exception* ex = &exceptions[i];
ex->startpc = reader.readU2();
ex->endpc = reader.readU2();
ex->handlerpc = reader.readU2();
ex->catche = reader.readU2();
#ifndef ISOLATE_SHARING
if (ex->catche) {
JavaObject* exc = 0;
UserClass* cl = 0;
try {
cl = (UserClass*)(compilingClass->ctpInfo->loadClass(ex->catche));
} catch(...) {
compilingClass->release();
exc = JavaThread::getJavaException();
assert(exc && "no exception?");
JavaThread::clearException();
}
if (exc) {
Jnjvm* vm = JavaThread::get()->getJVM();
vm->noClassDefFoundError(exc);
}
ex->catchClass = cl;
} else {
ex->catchClass = Classpath::newThrowable;
}
#endif
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 == endExceptionBlockCatcher) {
opcodeInfos[i].exceptionBlock = ex->test;
}
}
if (!(opcodeInfos[ex->handlerpc].newBlock)) {
opcodeInfos[ex->handlerpc].newBlock =
createBasicBlock("javaHandler");
}
ex->javaHandler = opcodeInfos[ex->handlerpc].newBlock;
ex->nativeHandler = createBasicBlock("nativeHandler");
opcodeInfos[ex->handlerpc].reqSuppl = true;
}
module->executionEngine->lock.acquire();
bool first = true;
for (sint16 i = 0; i < nbe - sync; ++i) {
Exception* cur = &exceptions[i];
Exception* next = 0;
if (i + 1 != nbe - sync) {
next = &exceptions[i + 1];
}
if (first) {
cur->realTest = createBasicBlock("realTestException");
} else {
cur->realTest = cur->test;
}
cur->exceptionPHI = llvm::PHINode::Create(module->ptrType, "",
cur->realTest);
if (next && cur->startpc == next->startpc && cur->endpc == next->endpc)
first = false;
else
first = true;
}
for (sint16 i = 0; i < nbe - sync; ++i) {
Exception* cur = &exceptions[i];
Exception* next = 0;
BasicBlock* bbNext = 0;
PHINode* nodeNext = 0;
currentExceptionBlock = opcodeInfos[cur->handlerpc].exceptionBlock;
if (i + 1 != nbe - sync) {
next = &exceptions[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 = module->ptrType;
Instruction* ptr_eh_ptr =
llvm::CallInst::Create(module->llvmGetException, "eh_ptr", cur->test);
Constant* C = ConstantExpr::getCast(Instruction::BitCast,
module->personality, PointerTy_0);
Value* int32_eh_select_params[3] =
{ ptr_eh_ptr, C, module->constantPtrNull };
llvm::CallInst::Create(module->exceptionSelector,
int32_eh_select_params,
int32_eh_select_params + 3, "eh_select",
cur->test);
llvm::BranchInst::Create(cur->realTest, cur->test);
cur->exceptionPHI->addIncoming(ptr_eh_ptr, cur->test);
}
Value* cl = 0;
currentBlock = cur->realTest;
#ifdef ISOLATE_SHARING
// We're dealing with exceptions, don't catch the exception if the class can
// not be found.
if (cur->catche) cl = getResolvedClass(cur->catche, false, false, 0);
else cl = CallInst::Create(module->GetJnjvmExceptionClassFunction,
isolateLocal, "", currentBlock);
#else
assert(cur->catchClass);
cl = module->getNativeClass(cur->catchClass, currentBlock);
#endif
#ifdef SERVICE
JnjvmClassLoader* loader = compilingClass->classLoader;;
if (loader != loader->bootstrapLoader) {
Value* threadId = CallInst::Create(module->llvm_frameaddress,
module->constantZero,
"", currentBlock);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", currentBlock);
threadId = new IntToPtrInst(threadId, module->ptrPtrType, "",
currentBlock);
Value* Isolate = GetElementPtrInst::Create(threadId,
module->constantFour, "",
currentBlock);
Isolate = new LoadInst(Isolate, "", currentBlock);
Isolate = new BitCastInst(Isolate, module->ptrPtrType, "", currentBlock);
Value* Status = GetElementPtrInst::Create(Isolate, module->constantOne, "",
currentBlock);
Status = new LoadInst(Status, "", currentBlock);
Status = new PtrToIntInst(Status, Type::Int32Ty, "", currentBlock);
Value* stopping = new ICmpInst(ICmpInst::ICMP_EQ, Status,
module->constantOne, "", currentBlock);
BasicBlock* raiseBlock = createBasicBlock("raiseBlock");
BasicBlock* continueBlock = createBasicBlock("continueBlock");
BranchInst::Create(raiseBlock, continueBlock, stopping, currentBlock);
currentBlock = raiseBlock;
BranchInst::Create(endExceptionBlock, currentBlock);
currentBlock = continueBlock;
}
#endif
Value* cmp = CallInst::Create(module->CompareExceptionFunction, cl, "",
currentBlock);
BranchInst::Create(cur->nativeHandler, bbNext, cmp, currentBlock);
if (nodeNext)
nodeNext->addIncoming(cur->exceptionPHI, currentBlock);
cur->handlerPHI = llvm::PHINode::Create(module->ptrType, "",
cur->nativeHandler);
cur->handlerPHI->addIncoming(cur->exceptionPHI, currentBlock);
Value* exc = CallInst::Create(module->GetJavaExceptionFunction,
"", cur->nativeHandler);
CallInst::Create(module->ClearExceptionFunction, "", cur->nativeHandler);
CallInst::Create(module->exceptionBeginCatch, cur->handlerPHI,
"tmp8", cur->nativeHandler);
CallInst::Create(module->exceptionEndCatch, "", cur->nativeHandler);
BranchInst::Create(cur->javaHandler, cur->nativeHandler);
if (cur->javaHandler->empty()) {
PHINode* node = PHINode::Create(JnjvmModule::JavaObjectType, "",
cur->javaHandler);
node->addIncoming(exc, cur->nativeHandler);
} else {
Instruction* insn = cur->javaHandler->begin();
PHINode* node = dyn_cast<PHINode>(insn);
assert(node && "malformed exceptions");
node->addIncoming(exc, cur->nativeHandler);
}
#if defined(SERVICE)
Value* threadId = 0;
Value* OldIsolateID = 0;
Value* IsolateIDPtr = 0;
Value* OldIsolate = 0;
Value* NewIsolate = 0;
Value* IsolatePtr = 0;
if (loader != loader->bootstrapLoader) {
threadId = CallInst::Create(module->llvm_frameaddress, module->constantZero,
"", cur->javaHandler);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
cur->javaHandler);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", cur->javaHandler);
threadId = new IntToPtrInst(threadId, module->ptrPtrType, "",
cur->javaHandler);
IsolateIDPtr = GetElementPtrInst::Create(threadId, module->constantThree,
"", cur->javaHandler);
const Type* realType = PointerType::getUnqual(module->pointerSizeType);
IsolateIDPtr = new BitCastInst(IsolateIDPtr, realType, "",
cur->javaHandler);
OldIsolateID = new LoadInst(IsolateIDPtr, "", cur->javaHandler);
Value* MyID = ConstantInt::get(module->pointerSizeType,
loader->getIsolate()->IsolateID);
new StoreInst(MyID, IsolateIDPtr, cur->javaHandler);
IsolatePtr = GetElementPtrInst::Create(threadId, module->constantFour, "",
cur->javaHandler);
OldIsolate = new LoadInst(IsolatePtr, "", cur->javaHandler);
NewIsolate = module->getIsolate(loader->getIsolate(), currentBlock);
new StoreInst(NewIsolate, IsolatePtr, cur->javaHandler);
}
#endif
}
currentBlock = temp;
return nbe;
}
void JavaJIT::compareFP(Value* val1, Value* val2, const Type* ty, bool l) {
Value* one = module->constantOne;
Value* zero = module->constantZero;
Value* minus = module->constantMinusOne;
Value* c = new FCmpInst(FCmpInst::FCMP_UGT, val1, val2, "", currentBlock);
Value* r = llvm::SelectInst::Create(c, one, zero, "", currentBlock);
c = new FCmpInst(FCmpInst::FCMP_ULT, val1, val2, "", currentBlock);
r = llvm::SelectInst::Create(c, minus, r, "", currentBlock);
c = new FCmpInst(FCmpInst::FCMP_UNO, val1, val2, "", currentBlock);
r = llvm::SelectInst::Create(c, l ? one : minus, r, "", currentBlock);
push(r, false);
}
void JavaJIT::_ldc(uint16 index) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
uint8 type = ctpInfo->typeAt(index);
if (type == JavaConstantPool::ConstantString) {
#if defined(ISOLATE)
if (compilingClass->classLoader !=
compilingClass->classLoader->bootstrapLoader) {
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8);
Value* val = module->getString(str, currentBlock);
push(val, false);
} else {
// Lookup the constant pool cache
Value* val = getConstantPoolAt(index, module->StringLookupFunction,
module->JavaObjectType, 0, false);
push(val, false);
}
#elif defined(ISOLATE_SHARING)
// Lookup the constant pool cache
Value* val = getConstantPoolAt(index, module->StringLookupFunction,
module->JavaObjectType, 0, false);
push(val, false);
#else
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
JavaString* str = compilingClass->classLoader->UTF8ToStr(utf8);
Value* val = module->getString(str, currentBlock);
push(val, false);
#endif
} else if (type == JavaConstantPool::ConstantLong) {
push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)),
false);
} else if (type == JavaConstantPool::ConstantDouble) {
push(ConstantFP::get(Type::DoubleTy, ctpInfo->DoubleAt(index)),
false);
} else if (type == JavaConstantPool::ConstantInteger) {
push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)),
false);
} else if (type == JavaConstantPool::ConstantFloat) {
push(ConstantFP::get(Type::FloatTy, ctpInfo->FloatAt(index)),
false);
} else if (type == JavaConstantPool::ConstantClass) {
UserCommonClass* cl = 0;
Value* res = getResolvedCommonClass(index, false, &cl);
#ifndef ISOLATE
if (cl) res = module->getJavaClass(cl, currentBlock);
else
#endif
res = CallInst::Create(module->GetClassDelegateeFunction, res, "",
currentBlock);
push(res, false);
} else {
JavaThread::get()->getJVM()->unknownError("unknown type %d", type);
}
}
void JavaJIT::JITVerifyNull(Value* obj) {
Constant* zero = module->JavaObjectNullConstant;
Value* test = new ICmpInst(ICmpInst::ICMP_EQ, obj, zero, "",
currentBlock);
BasicBlock* exit = createBasicBlock("verifyNullExit");
BasicBlock* cont = createBasicBlock("verifyNullCont");
llvm::BranchInst::Create(exit, cont, test, currentBlock);
if (currentExceptionBlock != endExceptionBlock) {
Value** val = 0;
InvokeInst::Create(module->NullPointerExceptionFunction,
unifiedUnreachable,
currentExceptionBlock, val, val,
"", exit);
} else {
llvm::CallInst::Create(module->NullPointerExceptionFunction,
"", exit);
new UnreachableInst(exit);
}
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);
Value* args[2] = { obj, index };
if (currentExceptionBlock != endExceptionBlock) {
InvokeInst::Create(module->IndexOutOfBoundsExceptionFunction,
unifiedUnreachable,
currentExceptionBlock, args, args + 2,
"", ifFalse);
} else {
CallInst::Create(module->IndexOutOfBoundsExceptionFunction,
args, args + 2, "", ifFalse);
new UnreachableInst(ifFalse);
}
currentBlock = ifTrue;
}
Constant* zero = module->constantZero;
Value* val = new BitCastInst(obj, arrayType, "", currentBlock);
Value* indexes[3] = { zero, module->JavaArrayElementsOffsetConstant, index };
Value* ptr = GetElementPtrInst::Create(val, indexes, indexes + 3, "",
currentBlock);
return ptr;
}
void JavaJIT::setCurrentBlock(BasicBlock* newBlock) {
stack.clear();
uint32 index = 0;
for (BasicBlock::iterator i = newBlock->begin(), e = newBlock->end(); i != e;
++i, ++index) {
if (!(isa<PHINode>(i))) {
break;
} else {
stack.push_back(std::make_pair(i, false));
}
}
currentBlock = newBlock;
}
static void testPHINodes(BasicBlock* dest, BasicBlock* insert, JavaJIT* jit) {
if(dest->empty()) {
for (std::vector< std::pair<Value*, bool> >::iterator i =
jit->stack.begin(),
e = jit->stack.end(); i!= e; ++i) {
Value* cur = i->first;
bool unsign = i->second;
PHINode* node = 0;
const Type* type = cur->getType();
if (unsign) {
node = llvm::PHINode::Create(Type::Int32Ty, "", dest);
cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else if (type == Type::Int8Ty || type == Type::Int16Ty) {
node = llvm::PHINode::Create(Type::Int32Ty, "", dest);
cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else {
node = llvm::PHINode::Create(cur->getType(), "", dest);
}
assert(node->getType() == cur->getType() && "wrong 1");
node->addIncoming(cur, insert);
}
} else {
std::vector< std::pair<Value*, bool> >::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 Type* type = cur->getType();
bool unsign = stackit->second;
if (unsign) {
cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
} else if (type == Type::Int8Ty || type == Type::Int16Ty) {
cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
}
assert(ins->getType() == cur->getType() && "wrong 2");
((PHINode*)ins)->addIncoming(cur, insert);
++stackit;
}
}
}
}
void JavaJIT::branch(llvm::BasicBlock* dest, llvm::BasicBlock* insert) {
testPHINodes(dest, insert, this);
llvm::BranchInst::Create(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);
llvm::BranchInst::Create(ifTrue, ifFalse, test, insert);
}
void JavaJIT::makeArgs(FunctionType::param_iterator it,
uint32 index, std::vector<Value*>& Args, uint32 nb) {
#if defined(ISOLATE_SHARING)
nb += 1;
#endif
Args.reserve(nb + 2);
Value** args = (Value**)alloca(nb*sizeof(Value*));
#if defined(ISOLATE_SHARING)
args[nb - 1] = isolateLocal;
sint32 start = nb - 2;
it--;
it--;
#else
sint32 start = nb - 1;
#endif
for (sint32 i = start; i >= 0; --i) {
it--;
if (it->get() == Type::Int64Ty || it->get() == Type::DoubleTy) {
pop();
}
bool unsign = topFunc();
Value* tmp = pop();
const Type* type = it->get();
if (tmp->getType() != type) { // int8 or int16
convertValue(tmp, type, currentBlock, unsign);
}
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) {
JnjvmBootstrapLoader* loader = compilingClass->classLoader->bootstrapLoader;
if (name->equals(loader->abs)) {
const Type* Ty = args[0]->getType();
if (Ty == Type::Int32Ty) {
Constant* const_int32_9 = module->constantZero;
ConstantInt* const_int32_10 = module->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 llvm::SelectInst::Create(int1_abscond, args[0], int32_tmpneg,
"abs", currentBlock);
} else if (Ty == Type::Int64Ty) {
Constant* const_int64_9 = module->constantLongZero;
ConstantInt* const_int64_10 = module->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 llvm::SelectInst::Create(int1_abscond, args[0], int64_tmpneg,
"abs", currentBlock);
} else if (Ty == Type::FloatTy) {
return llvm::CallInst::Create(module->func_llvm_fabs_f32, args[0],
"tmp1", currentBlock);
} else if (Ty == Type::DoubleTy) {
return llvm::CallInst::Create(module->func_llvm_fabs_f64, args[0],
"tmp1", currentBlock);
}
} else if (name->equals(loader->sqrt)) {
return llvm::CallInst::Create(module->func_llvm_sqrt_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->sin)) {
return llvm::CallInst::Create(module->func_llvm_sin_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->cos)) {
return llvm::CallInst::Create(module->func_llvm_cos_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->tan)) {
return llvm::CallInst::Create(module->func_llvm_tan_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->asin)) {
return llvm::CallInst::Create(module->func_llvm_asin_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->acos)) {
return llvm::CallInst::Create(module->func_llvm_acos_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->atan)) {
return llvm::CallInst::Create(module->func_llvm_atan_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->atan2)) {
return llvm::CallInst::Create(module->func_llvm_atan2_f64,
args.begin(), args.end(), "tmp1",
currentBlock);
} else if (name->equals(loader->exp)) {
return llvm::CallInst::Create(module->func_llvm_exp_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->log)) {
return llvm::CallInst::Create(module->func_llvm_log_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->pow)) {
return llvm::CallInst::Create(module->func_llvm_pow_f64, args.begin(),
args.end(), "tmp1", currentBlock);
} else if (name->equals(loader->ceil)) {
return llvm::CallInst::Create(module->func_llvm_ceil_f64, args[0], "tmp1",
currentBlock);
} else if (name->equals(loader->floor)) {
return llvm::CallInst::Create(module->func_llvm_floor_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->rint)) {
return llvm::CallInst::Create(module->func_llvm_rint_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->cbrt)) {
return llvm::CallInst::Create(module->func_llvm_cbrt_f64, args[0], "tmp1",
currentBlock);
} else if (name->equals(loader->cosh)) {
return llvm::CallInst::Create(module->func_llvm_cosh_f64, args[0], "tmp1",
currentBlock);
} else if (name->equals(loader->expm1)) {
return llvm::CallInst::Create(module->func_llvm_expm1_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->hypot)) {
return llvm::CallInst::Create(module->func_llvm_hypot_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->log10)) {
return llvm::CallInst::Create(module->func_llvm_log10_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->log1p)) {
return llvm::CallInst::Create(module->func_llvm_log1p_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->sinh)) {
return llvm::CallInst::Create(module->func_llvm_sinh_f64, args[0],
"tmp1", currentBlock);
} else if (name->equals(loader->tanh)) {
return llvm::CallInst::Create(module->func_llvm_tanh_f64, args[0],
"tmp1", currentBlock);
}
return 0;
}
Instruction* JavaJIT::invokeInline(JavaMethod* meth,
std::vector<Value*>& args) {
JavaJIT jit(meth, llvmFunction);
jit.unifiedUnreachable = unifiedUnreachable;
jit.inlineMethods = inlineMethods;
jit.inlineMethods[meth] = true;
jit.inlining = true;
Instruction* ret = jit.inlineCompile(currentBlock,
currentExceptionBlock, args);
inlineMethods[meth] = false;
return ret;
}
void JavaJIT::invokeSpecial(uint16 index) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
JavaMethod* meth = 0;
Signdef* signature = 0;
const UTF8* name = 0;
const UTF8* cl = 0;
ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
LLVMSignatureInfo* LSI = module->getSignatureInfo(signature);
const llvm::FunctionType* virtualType = LSI->getVirtualType();
llvm::Instruction* val = 0;
std::vector<Value*> args;
FunctionType::param_iterator it = virtualType->param_end();
makeArgs(it, index, args, signature->nbArguments + 1);
JITVerifyNull(args[0]);
#if defined(ISOLATE_SHARING)
const Type* Ty = module->ConstantPoolType;
Constant* Nil = Constant::getNullValue(Ty);
GlobalVariable* GV = new GlobalVariable(Ty, false,
GlobalValue::ExternalLinkage, Nil,
"", module);
Value* res = new LoadInst(GV, "", false, currentBlock);
Value* test = new ICmpInst(ICmpInst::ICMP_EQ, res, Nil, "", currentBlock);
BasicBlock* trueCl = createBasicBlock("UserCtp OK");
BasicBlock* falseCl = createBasicBlock("UserCtp Not OK");
PHINode* node = llvm::PHINode::Create(Ty, "", trueCl);
node->addIncoming(res, currentBlock);
BranchInst::Create(falseCl, trueCl, test, currentBlock);
std::vector<Value*> Args;
Args.push_back(ctpCache);
Args.push_back(ConstantInt::get(Type::Int32Ty, index));
Args.push_back(GV);
res = CallInst::Create(module->SpecialCtpLookupFunction, Args.begin(),
Args.end(), "", falseCl);
node->addIncoming(res, falseCl);
BranchInst::Create(trueCl, falseCl);
currentBlock = trueCl;
args.push_back(node);
#endif
Function* func =
(Function*)ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_VIRTUAL,
signature, meth);
if (meth && canBeInlined(meth)) {
val = invokeInline(meth, args);
} else {
val = invoke(func, args, "", currentBlock);
}
const llvm::Type* retType = virtualType->getReturnType();
if (retType != Type::VoidTy) {
push(val, signature->getReturnType()->isUnsigned());
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(module->constantZero, false);
}
}
}
void JavaJIT::invokeStatic(uint16 index) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
JavaMethod* meth = 0;
Signdef* signature = 0;
const UTF8* name = 0;
const UTF8* cl = 0;
ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
LLVMSignatureInfo* LSI = module->getSignatureInfo(signature);
const llvm::FunctionType* staticType = LSI->getStaticType();
llvm::Instruction* val = 0;
std::vector<Value*> args; // size = [signature->nbIn + 2];
FunctionType::param_iterator it = staticType->param_end();
makeArgs(it, index, args, signature->nbArguments);
ctpInfo->markAsStaticCall(index);
JnjvmBootstrapLoader* loader = compilingClass->classLoader->bootstrapLoader;
if (cl->equals(loader->mathName)) {
val = lowerMathOps(name, args);
}
else if (cl->equals(loader->stackWalkerName)) {
callsStackWalker = true;
}
if (!val) {
Function* func = (Function*)
ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_STATIC,
signature, meth);
#if defined(ISOLATE_SHARING)
Value* newCtpCache = getConstantPoolAt(index,
module->StaticCtpLookupFunction,
module->ConstantPoolType, 0,
false);
args.push_back(newCtpCache);
#endif
// If we're not static compiling or we're not in an isolate environment,
// the callback will do the initialization
#ifndef ISOLATE
if (module->isStaticCompiling()) {
#endif
uint32 clIndex = ctpInfo->getClassIndexFromMethod(index);
UserClass* cl = 0;
Value* Cl = getResolvedClass(clIndex, true, true, &cl);
if (!meth || (cl && needsInitialisationCheck(cl, compilingClass))) {
CallInst::Create(module->ForceInitialisationCheckFunction, Cl, "",
currentBlock);
}
#ifndef ISOLATE
}
#endif
if (meth && canBeInlined(meth)) {
val = invokeInline(meth, args);
} else {
val = invoke(func, args, "", currentBlock);
}
}
const llvm::Type* retType = staticType->getReturnType();
if (retType != Type::VoidTy) {
push(val, signature->getReturnType()->isUnsigned());
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(module->constantZero, false);
}
}
}
Value* JavaJIT::getConstantPoolAt(uint32 index, Function* resolver,
const Type* returnType,
Value* additionalArg, bool doThrow) {
// This makes unswitch loop very unhappy time-wise, but makes GVN happy
// number-wise. IMO, it's better to have this than Unswitch.
#ifdef ISOLATE_SHARING
Value* CTP = ctpCache;
Value* Cl = GetElementPtrInst::Create(CTP, module->ConstantOne, "",
currentBlock);
Cl = new LoadInst(Cl, "", currentBlock);
#else
JavaConstantPool* ctp = compilingClass->ctpInfo;
Value* CTP = module->getConstantPool(ctp, currentBlock);
Value* Cl = module->getNativeClass(compilingClass, currentBlock);
#endif
std::vector<Value*> Args;
Args.push_back(resolver);
Args.push_back(CTP);
Args.push_back(Cl);
Args.push_back(ConstantInt::get(Type::Int32Ty, index));
if (additionalArg) Args.push_back(additionalArg);
Value* res = 0;
if (doThrow) {
res = invoke(module->GetConstantPoolAtFunction, Args, "",
currentBlock);
} else {
res = CallInst::Create(module->GetConstantPoolAtFunction, Args.begin(),
Args.end(), "", currentBlock);
}
const Type* realType =
module->GetConstantPoolAtFunction->getReturnType();
if (returnType == Type::Int32Ty) {
return new PtrToIntInst(res, Type::Int32Ty, "", currentBlock);
} else if (returnType != realType) {
return new BitCastInst(res, returnType, "", currentBlock);
}
return res;
}
Value* JavaJIT::getResolvedCommonClass(uint16 index, bool doThrow,
UserCommonClass** alreadyResolved) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
CommonClass* cl = ctpInfo->getMethodClassIfLoaded(index);
Value* node = 0;
if (cl && (!cl->isClass() || cl->asClass()->isResolved())) {
if (alreadyResolved) *alreadyResolved = cl;
node = module->getNativeClass(cl, currentBlock);
if (node->getType() != module->JavaCommonClassType) {
node = new BitCastInst(node, module->JavaCommonClassType, "",
currentBlock);
}
} else {
node = getConstantPoolAt(index, module->ClassLookupFunction,
module->JavaCommonClassType, 0, doThrow);
}
return node;
}
Value* JavaJIT::getResolvedClass(uint16 index, bool clinit, bool doThrow,
Class** alreadyResolved) {
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
Class* cl = (Class*)(ctpInfo->getMethodClassIfLoaded(index));
Value* node = 0;
if (cl && cl->isResolved()) {
if (alreadyResolved) (*alreadyResolved) = cl;
node = module->getNativeClass(cl, currentBlock);
} else {
node = getConstantPoolAt(index, module->ClassLookupFunction,
module->JavaCommonClassType, 0, doThrow);
}
if (!(!clinit || (cl && !needsInitialisationCheck(cl, compilingClass)))) {
if (node->getType() != module->JavaClassType) {
node = new BitCastInst(node, module->JavaClassType, "", currentBlock);
}
return invoke(module->InitialisationCheckFunction, node, "",
currentBlock);
} else {
return node;
}
}
void JavaJIT::invokeNew(uint16 index) {
Class* cl = 0;
Value* Cl = getResolvedClass(index, true, true, &cl);
Value* VT = 0;
Value* Size = 0;
if (cl) {
VT = module->getVirtualTable(cl, currentBlock);
LLVMClassInfo* LCI = module->getClassInfo(cl);
Size = LCI->getVirtualSize();
} else {
VT = CallInst::Create(module->GetVTFromClassFunction, Cl, "",
currentBlock);
Size = CallInst::Create(module->GetObjectSizeFromClassFunction, Cl,
"", currentBlock);
}
Value* val = invoke(module->JavaObjectAllocateFunction, Size, VT, "",
currentBlock);
// Set the class
Value* gep[2] = { module->constantZero,
module->JavaObjectClassOffsetConstant };
Value* GEP = GetElementPtrInst::Create(val, gep, gep + 2, "",
currentBlock);
Cl = new BitCastInst(Cl, module->JavaCommonClassType, "", currentBlock);
new StoreInst(Cl, GEP, currentBlock);
Value* gep2[2] = { module->constantZero, module->JavaObjectLockOffsetConstant };
Value* lockPtr = GetElementPtrInst::Create(val, gep2, gep2 + 2, "",
currentBlock);
Value* threadId = CallInst::Create(module->llvm_frameaddress,
module->constantZero, "", currentBlock);
threadId = new PtrToIntInst(threadId, module->pointerSizeType, "",
currentBlock);
threadId = BinaryOperator::CreateAnd(threadId, module->constantThreadIDMask,
"", currentBlock);
threadId = new IntToPtrInst(threadId, module->ptrType, "", currentBlock);
new StoreInst(threadId, lockPtr, currentBlock);
push(val, false);
}
Value* JavaJIT::arraySize(Value* val) {
return CallInst::Create(module->ArrayLengthFunction, val, "", currentBlock);
}
static Value* fieldGetter(JavaJIT* jit, const Type* type, Value* object,
Value* offset) {
Value* objectConvert = new BitCastInst(object, type, "",
jit->currentBlock);
Constant* zero = jit->module->constantZero;
Value* args[2] = { zero, offset };
llvm::Value* ptr = llvm::GetElementPtrInst::Create(objectConvert,
args, args + 2, "",
jit->currentBlock);
return ptr;
}
Value* JavaJIT::ldResolved(uint16 index, bool stat, Value* object,
const Type* fieldType, const Type* fieldTypePtr) {
JavaConstantPool* info = compilingClass->ctpInfo;
JavaField* field = info->lookupField(index, stat);
if (field && field->classDef->isResolved()) {
LLVMClassInfo* LCI = (LLVMClassInfo*)module->getClassInfo(field->classDef);
LLVMFieldInfo* LFI = module->getFieldInfo(field);
const Type* type = 0;
if (stat) {
type = LCI->getStaticType();
Value* Cl = module->getNativeClass(field->classDef, currentBlock);
bool needsCheck = needsInitialisationCheck(field->classDef,
compilingClass);
if (needsCheck) {
Cl = invoke(module->InitialisationCheckFunction, Cl, "",
currentBlock);
}
#if !defined(ISOLATE) && !defined(ISOLATE_SHARING)
if (needsCheck) {
CallInst::Create(module->ForceInitialisationCheckFunction, Cl, "",
currentBlock);
}
object = module->getStaticInstance(field->classDef, currentBlock);
#else
object = CallInst::Create(module->GetStaticInstanceFunction, Cl, "",
currentBlock);
#endif
} else {
type = LCI->getVirtualType();
}
return fieldGetter(this, type, object, LFI->getOffset());
}
const Type* Pty = module->arrayPtrType;
Constant* zero = module->constantZero;
Function* func = stat ? module->StaticFieldLookupFunction :
module->VirtualFieldLookupFunction;
const Type* returnType = 0;
if (stat)
returnType = module->ptrType;
else
returnType = Type::Int32Ty;
Value* ptr = getConstantPoolAt(index, func, returnType, 0, true);
if (!stat) {
Value* tmp = new BitCastInst(object, Pty, "", currentBlock);
Value* args[2] = { zero, ptr };
ptr = GetElementPtrInst::Create(tmp, args, args + 2, "", currentBlock);
}
return new BitCastInst(ptr, fieldTypePtr, "", currentBlock);
}
void JavaJIT::convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock,
bool usign) {
const Type* t2 = val->getType();
if (t1 != t2) {
if (t1->isInteger() && t2->isInteger()) {
if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) {
if (usign) {
val = new ZExtInst(val, t1, "", currentBlock);
} else {
val = new SExtInst(val, t1, "", currentBlock);
}
} else {
val = new TruncInst(val, t1, "", currentBlock);
}
} else if (t1->isFloatingPoint() && t2->isFloatingPoint()) {
if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) {
val = new FPExtInst(val, t1, "", currentBlock);
} else {
val = new FPTruncInst(val, t1, "", currentBlock);
}
} else if (isa<PointerType>(t1) && isa<PointerType>(t2)) {
val = new BitCastInst(val, t1, "", currentBlock);
}
}
}
void JavaJIT::setStaticField(uint16 index) {
bool unsign = topFunc();
Value* val = pop();
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
LLVMAssessorInfo& LAI = module->getTypedefInfo(sign);
const Type* type = LAI.llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
val = pop();
}
Value* ptr = ldResolved(index, true, 0, type, LAI.llvmTypePtr);
if (type != val->getType()) { // int1, int8, int16
convertValue(val, type, currentBlock, unsign);
}
new StoreInst(val, ptr, false, currentBlock);
}
void JavaJIT::getStaticField(uint16 index) {
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
LLVMAssessorInfo& LAI = module->getTypedefInfo(sign);
const Type* type = LAI.llvmType;
Value* ptr = ldResolved(index, true, 0, type, LAI.llvmTypePtr);
push(new LoadInst(ptr, "", currentBlock), sign->isUnsigned());
if (type == Type::Int64Ty || type == Type::DoubleTy) {
push(module->constantZero, false);
}
}
void JavaJIT::setVirtualField(uint16 index) {
bool unsign = topFunc();
Value* val = pop();
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
LLVMAssessorInfo& LAI = module->getTypedefInfo(sign);
const Type* type = LAI.llvmType;
if (type == Type::Int64Ty || type == Type::DoubleTy) {
val = pop();
}
Value* object = pop();
JITVerifyNull(object);
Value* ptr = ldResolved(index, false, object, type, LAI.llvmTypePtr);
if (type != val->getType()) { // int1, int8, int16
convertValue(val, type, currentBlock, unsign);
}
new StoreInst(val, ptr, false, currentBlock);
}
void JavaJIT::getVirtualField(uint16 index) {
Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
LLVMAssessorInfo& LAI = module->getTypedefInfo(sign);
const Type* type = LAI.llvmType;
Value* obj = pop();
JITVerifyNull(obj);
Value* ptr = ldResolved(index, false, obj, type, LAI.llvmTypePtr);
push(new LoadInst(ptr, "", currentBlock), sign->isUnsigned());
if (type == Type::Int64Ty || type == Type::DoubleTy) {
push(module->constantZero, false);
}
}
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 llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
args.begin(),
args.end(), Name, InsertAtEnd);
} else {
return llvm::CallInst::Create(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;
Value* arg[1] = { arg1 };
return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
arg, arg + 1, Name, InsertAtEnd);
} else {
return CallInst::Create(F, arg1, Name, InsertAtEnd);
}
}
Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
const char* Name, BasicBlock *InsertAtEnd) {
Value* args[2] = { arg1, arg2 };
// means: is there a handler for me?
if (currentExceptionBlock != endExceptionBlock) {
BasicBlock* ifNormal = createBasicBlock("no exception block");
currentBlock = ifNormal;
return InvokeInst::Create(F, ifNormal, currentExceptionBlock,
args, args + 2, Name, InsertAtEnd);
} else {
return CallInst::Create(F, args, args + 2, 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;
Value* args[1];
return llvm::InvokeInst::Create(F, ifNormal, currentExceptionBlock,
args, args, Name,
InsertAtEnd);
} else {
return llvm::CallInst::Create(F, Name, InsertAtEnd);
}
}
void JavaJIT::invokeInterfaceOrVirtual(uint16 index, bool buggyVirtual) {
// Do the usual
JavaConstantPool* ctpInfo = compilingClass->ctpInfo;
const UTF8* name = 0;
Signdef* signature = ctpInfo->infoOfInterfaceOrVirtualMethod(index, name);
LLVMSignatureInfo* LSI = module->getSignatureInfo(signature);
const llvm::FunctionType* virtualType = LSI->getVirtualType();
const llvm::PointerType* virtualPtrType = LSI->getVirtualPtrType();
std::vector<Value*> args; // size = [signature->nbIn + 3];
FunctionType::param_iterator it = virtualType->param_end();
makeArgs(it, index, args, signature->nbArguments + 1);
const llvm::Type* retType = virtualType->getReturnType();
BasicBlock* endBlock = createBasicBlock("end virtual invoke");
PHINode * node = 0;
if (retType != Type::VoidTy) {
node = PHINode::Create(retType, "", endBlock);
}
JITVerifyNull(args[0]);
Value* zero = module->constantZero;
Value* one = module->constantOne;
#ifndef ISOLATE_SHARING
// ok now the cache
Enveloppe& enveloppe = buggyVirtual ?
*(new (compilingClass->classLoader->allocator) Enveloppe()) :
compilingMethod->enveloppes[nbEnveloppes++];
if (!inlining)
enveloppe.initialise(compilingClass->classLoader->allocator, name,
signature->keyName);
Value* llvmEnv = module->getEnveloppe(&enveloppe, currentBlock);
#else
Value* llvmEnv = getConstantPoolAt(index,
module->EnveloppeLookupFunction,
module->EnveloppeType, 0, false);
#endif
Value* args1[2] = { zero, zero };
Value* cachePtr = GetElementPtrInst::Create(llvmEnv, args1, args1 + 2,
"", currentBlock);
Value* cache = new LoadInst(cachePtr, "", currentBlock);
Value* cl = CallInst::Create(module->GetClassFunction, args[0], "",
currentBlock);
Value* args3[2] = { zero, one };
Value* lastCiblePtr = GetElementPtrInst::Create(cache, args3, args3 + 2, "",
currentBlock);
Value* lastCible = new LoadInst(lastCiblePtr, "", currentBlock);
Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, cl, lastCible, "", currentBlock);
BasicBlock* ifTrue = createBasicBlock("cache ok");
BasicBlock* ifFalse = createBasicBlock("cache not ok");
BranchInst::Create(ifTrue, ifFalse, cmp, currentBlock);
currentBlock = ifFalse;
Value* _meth = invoke(module->InterfaceLookupFunction, cache, args[0],
"", ifFalse);
Value* meth = new BitCastInst(_meth, virtualPtrType, "",
currentBlock);
#ifdef ISOLATE_SHARING
Value* cache2 = new LoadInst(cachePtr, "", currentBlock);
Value* newCtpCache = CallInst::Create(module->GetCtpCacheNodeFunction,
cache2, "", currentBlock);
args.push_back(newCtpCache);
#endif
Value* ret = invoke(meth, args, "", currentBlock);
if (node) {
node->addIncoming(ret, currentBlock);
}
BranchInst::Create(endBlock, currentBlock);
currentBlock = ifTrue;
Value* methPtr = GetElementPtrInst::Create(cache, args1, args1 + 2,
"", currentBlock);
_meth = new LoadInst(methPtr, "", currentBlock);
meth = new BitCastInst(_meth, virtualPtrType, "", currentBlock);
#ifdef ISOLATE_SHARING
args.pop_back();
cache = new LoadInst(cachePtr, "", currentBlock);
newCtpCache = CallInst::Create(module->GetCtpCacheNodeFunction,
cache, "", currentBlock);
args.push_back(newCtpCache);
#endif
ret = invoke(meth, args, "", currentBlock);
BranchInst::Create(endBlock, currentBlock);
if (node) {
node->addIncoming(ret, currentBlock);
}
currentBlock = endBlock;
if (node) {
push(node, signature->getReturnType()->isUnsigned());
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(module->constantZero, false);
}
}
}