blob: 26cf6b12a3a249bf1ccd62c218f44d891264ed15 [file] [log] [blame]
//===------ JavaCache.cpp - Inline cache for virtual calls -----------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <iostream>
#include <vector>
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "mvm/JIT.h"
#include "mvm/Object.h"
#include "mvm/PrintBuffer.h"
#include "mvm/Threads/Locks.h"
#include "JavaCache.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "Jnjvm.h"
#include "types.h"
using namespace jnjvm;
using namespace llvm;
void CacheNode::print(mvm::PrintBuffer* buf) const {
buf->write("CacheNode<");
if (lastCible) {
lastCible->print(buf);
buf->write(" -- ");
((mvm::Object*)((void**)methPtr - 1))->print(buf);
}
buf->write(" in ");
enveloppe->print(buf);
buf->write(">");
}
void Enveloppe::print(mvm::PrintBuffer* buf) const {
buf->write("Enveloppe<>");
}
CacheNode* CacheNode::allocate() {
CacheNode* cache = gc_new(CacheNode)();
cache->lastCible = 0;
cache->methPtr = 0;
cache->next = 0;
return cache;
}
Enveloppe* Enveloppe::allocate(JavaCtpInfo* ctp, uint32 index) {
Enveloppe* enveloppe = gc_new(Enveloppe)();
enveloppe->firstCache = CacheNode::allocate();
enveloppe->firstCache->enveloppe = enveloppe;
enveloppe->cacheLock = mvm::Lock::allocNormal();
enveloppe->ctpInfo = ctp;
enveloppe->index = index;
return enveloppe;
}
void JavaJIT::invokeInterfaceOrVirtual(uint16 index) {
// Do the usual
JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
Signdef* signature = ctpInfo->infoOfInterfaceOrVirtualMethod(index);
std::vector<Value*> args; // size = [signature->nbIn + 3];
FunctionType::param_iterator it = signature->virtualType->param_end();
makeArgs(it, index, args, signature->nbIn + 1);
const llvm::Type* retType = signature->virtualType->getReturnType();
BasicBlock* endBlock = createBasicBlock("end virtual invoke");
PHINode * node = 0;
if (retType != Type::VoidTy) {
node = new PHINode(retType, "", endBlock);
}
// ok now the cache
Enveloppe* enveloppe = Enveloppe::allocate(compilingClass->ctpInfo, index);
compilingMethod->caches.push_back(enveloppe);
Value* zero = mvm::jit::constantZero;
Value* one = mvm::jit::constantOne;
Value* two = mvm::jit::constantTwo;
mvm::jit::protectConstants();//->lock();
Value* llvmEnv =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (enveloppe)),
Enveloppe::llvmType);
mvm::jit::unprotectConstants();//->unlock();
JITVerifyNull(args[0]);
std::vector<Value*> args1;
args1.push_back(zero);
args1.push_back(one);
Value* cachePtr = new GetElementPtrInst(llvmEnv, args1.begin(), args1.end(),
"", currentBlock);
Value* cache = new LoadInst(cachePtr, "", currentBlock);
std::vector<Value*> args2;
args2.push_back(zero);
args2.push_back(JavaObject::classOffset());
Value* classPtr = new GetElementPtrInst(args[0], args2.begin(),
args2.end(), "",
currentBlock);
Value* cl = new LoadInst(classPtr, "", currentBlock);
std::vector<Value*> args3;
args3.push_back(zero);
args3.push_back(two);
Value* lastCiblePtr = new GetElementPtrInst(cache, args3.begin(), args3.end(),
"", 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");
new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
currentBlock = ifFalse;
Value* _meth = invoke(virtualLookupLLVM, cache, args[0], "", ifFalse);
Value* meth = new BitCastInst(_meth, signature->virtualTypePtr, "",
currentBlock);
Value* ret = invoke(meth, args, "", currentBlock);
if (node) {
node->addIncoming(ret, currentBlock);
}
new BranchInst(endBlock, currentBlock);
currentBlock = ifTrue;
Value* methPtr = new GetElementPtrInst(cache, args1.begin(), args1.end(),
"", currentBlock);
_meth = new LoadInst(methPtr, "", currentBlock);
meth = new BitCastInst(_meth, signature->virtualTypePtr, "", currentBlock);
ret = invoke(meth, args, "", currentBlock);
new BranchInst(endBlock, currentBlock);
if (node) {
node->addIncoming(ret, currentBlock);
}
currentBlock = endBlock;
if (node) {
push(node, signature->ret->funcs);
if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
push(mvm::jit::constantZero, AssessorDesc::dInt);
}
}
}