blob: 3d68828e8cabab545e34b22323c70088257a7d11 [file] [log] [blame]
//===--- JnjvmModuleProvider.cpp - LLVM Module Provider for Jnjvm ---------===//
//
// Jnjvm
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/LinkAllPasses.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/MutexGuard.h"
#include "mvm/JIT.h"
#include "JavaAccess.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaThread.h"
#include "Jnjvm.h"
#include "JnjvmModule.h"
#include "JnjvmModuleProvider.h"
using namespace llvm;
using namespace jnjvm;
JavaMethod* JnjvmModuleProvider::staticLookup(Class* caller, uint32 index) {
JavaConstantPool* ctpInfo = caller->getConstantPool();
bool isStatic = ctpInfo->isAStaticCall(index);
CommonClass* cl = 0;
const UTF8* utf8 = 0;
Signdef* sign = 0;
ctpInfo->resolveMethod(index, cl, utf8, sign);
JavaMethod* meth = cl->lookupMethod(utf8, sign->keyName, isStatic, true,
0);
#ifndef ISOLATE_SHARING
// A multi environment would have already initialized the class. Besides,
// a callback does not involve UserClass, therefore we wouldn't know
// which class to initialize.
if (!isVirtual(meth->access))
cl->initialiseClass(JavaThread::get()->isolate);
#endif
meth->compiledPtr();
return meth;
}
std::pair<Class*, uint32>* JnjvmModuleProvider::lookupCallback(Function* F) {
callback_iterator CI = callbacks.find(F);
if (CI != callbacks.end()) {
return &(CI->second);
} else {
return 0;
}
}
JavaMethod* JnjvmModuleProvider::lookupFunction(Function* F) {
function_iterator CI = functions.find(F);
if (CI != functions.end()) {
return CI->second;
} else {
return 0;
}
}
bool JnjvmModuleProvider::materializeFunction(Function *F,
std::string *ErrInfo) {
if (mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(F))
return false;
if (!(F->hasNotBeenReadFromBitcode()))
return false;
JavaMethod* meth = lookupFunction(F);
if (!meth) {
// It's a callback
std::pair<Class*, uint32> * p = lookupCallback(F);
assert(p && "No callback where there should be one");
meth = staticLookup(p->first, p->second);
}
void* val = meth->compiledPtr();
if (F->isDeclaration())
mvm::MvmModule::executionEngine->updateGlobalMapping(F, val);
if (isVirtual(meth->access)) {
LLVMMethodInfo* LMI = ((JnjvmModule*)TheModule)->getMethodInfo(meth);
uint64_t offset = LMI->getOffset()->getZExtValue();
assert(meth->classDef->isResolved() && "Class not resolved");
#ifndef ISOLATE_SHARING
assert(meth->classDef->isReady() && "Class not ready");
#endif
assert(meth->classDef->virtualVT && "Class has no VT");
assert(meth->classDef->virtualTableSize > offset &&
"The method's offset is greater than the virtual table size");
((void**)meth->classDef->virtualVT)[offset] = val;
} else {
#ifndef ISOLATE_SHARING
meth->classDef->initialiseClass(JavaThread::get()->isolate);
#endif
}
return false;
}
void* JnjvmModuleProvider::materializeFunction(JavaMethod* meth) {
Function* func = parseFunction(meth);
void* res = mvm::MvmModule::executionEngine->getPointerToGlobal(func);
mvm::Code* m = mvm::MvmModule::getCodeFromPointer(res);
if (m) m->setMetaInfo(meth);
func->deleteBody();
return res;
}
Function* JnjvmModuleProvider::parseFunction(JavaMethod* meth) {
LLVMMethodInfo* LMI = ((JnjvmModule*)TheModule)->getMethodInfo(meth);
Function* func = LMI->getMethod();
if (func->hasNotBeenReadFromBitcode()) {
// We are jitting. Take the lock.
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
JavaJIT jit(meth, func);
if (isNative(meth->access)) {
jit.nativeCompile();
} else {
jit.javaCompile();
mvm::MvmModule::runPasses(func, perFunctionPasses);
}
}
return func;
}
llvm::Function* JnjvmModuleProvider::addCallback(Class* cl, uint32 index,
Signdef* sign, bool stat) {
void* key = &(cl->getConstantPool()->ctpRes[index]);
reverse_callback_iterator CI = reverseCallbacks.find(key);
if (CI != reverseCallbacks.end()) {
return CI->second;
}
const llvm::FunctionType* type = 0;
JnjvmModule* M = cl->classLoader->getModule();
LLVMSignatureInfo* LSI = M->getSignatureInfo(sign);
if (stat) {
type = LSI->getStaticType();
} else {
type = LSI->getVirtualType();
}
Function* func = llvm::Function::Create(type,
llvm::GlobalValue::GhostLinkage,
"callback",
TheModule);
callbacks.insert(std::make_pair(func, std::make_pair(cl, index)));
reverseCallbacks.insert(std::make_pair(key, func));
return func;
}
void JnjvmModuleProvider::addFunction(Function* F, JavaMethod* meth) {
functions.insert(std::make_pair(F, meth));
}
namespace mvm {
llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*);
llvm::FunctionPass* createLowerConstantCallsPass();
llvm::FunctionPass* createLowerForcedCallsPass();
}
static void addPass(FunctionPassManager *PM, Pass *P) {
// Add the pass to the pass manager...
PM->add(P);
}
// This is equivalent to:
// opt -simplifycfg -mem2reg -instcombine -jump-threading -scalarrepl -instcombine
// -condprop -simplifycfg -reassociate -licm essai.bc -loop-unswitch
// -indvars -loop-unroll -instcombine -gvn -sccp -simplifycfg
// -instcombine -condprop -dse -adce -simplifycfg
//
static void AddStandardCompilePasses(JnjvmModule* mod, FunctionPassManager *PM) {
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
// TODO: enable this when
// - we can call multiple times the makeLLVMModuleContents function generated
// by llc -march=cpp -cppgen=contents
// - intrinsics won't be in the .ll files
// - each module will have its declaration of external functions
//
//PM->add(llvm::createVerifierPass()); // Verify that input is correct
addPass(PM, llvm::createCFGSimplificationPass()); // Clean up disgusting code
addPass(PM, llvm::createPromoteMemoryToRegisterPass());// Kill useless allocas
addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
addPass(PM, createJumpThreadingPass()); // Thread jumps.
addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
addPass(PM, createCondPropagationPass()); // Propagate conditionals
addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
//addPass(PM, createPredicateSimplifierPass());
addPass(PM, createReassociatePass()); // Reassociate expressions
addPass(PM, createLICMPass()); // Hoist loop invariants
addPass(PM, createLoopUnswitchPass()); // Unswitch loops.
addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars
addPass(PM, createLoopDeletionPass()); // Delete dead loops
addPass(PM, createLoopUnrollPass()); // Unroll small loops*/
addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
addPass(PM, createGVNPass()); // Remove redundancies
addPass(PM, createSCCPPass()); // Constant prop with SCCP
addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
Function* func = mod->JavaObjectAllocateFunction;
addPass(PM, mvm::createEscapeAnalysisPass(func));
addPass(PM, mvm::createLowerConstantCallsPass());
// Run instcombine after redundancy elimination to exploit opportunities
// opened up by them.
addPass(PM, createInstructionCombiningPass());
addPass(PM, createCondPropagationPass()); // Propagate conditionals
addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
addPass(PM, createAggressiveDCEPass()); // Delete dead instructions
addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs
addPass(PM, mvm::createLowerForcedCallsPass());
}
JnjvmModuleProvider::JnjvmModuleProvider(JnjvmModule *m) {
TheModule = (Module*)m;
mvm::MvmModule::protectEngine->lock();
mvm::MvmModule::executionEngine->addModuleProvider(this);
mvm::MvmModule::protectEngine->unlock();
perFunctionPasses = new llvm::FunctionPassManager(this);
perFunctionPasses->add(new llvm::TargetData(m));
AddStandardCompilePasses(m, perFunctionPasses);
}
JnjvmModuleProvider::~JnjvmModuleProvider() {
mvm::MvmModule::protectEngine->lock();
mvm::MvmModule::executionEngine->removeModuleProvider(this);
mvm::MvmModule::protectEngine->unlock();
delete TheModule;
}