blob: 8fdad6b37f2bb722ba2cbace6162279295de57f0 [file] [log] [blame]
//===--------- JnjvmModule.cpp - Definition of a Jnjvm module -------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/CallingConv.h"
#include "llvm/Instructions.h"
#include "llvm/Support/MutexGuard.h"
#include "mvm/JIT.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "Jnjvm.h"
#include "JnjvmModule.h"
#include "JnjvmModuleProvider.h"
using namespace jnjvm;
using namespace llvm;
#ifdef WITH_TRACER
const llvm::FunctionType* JnjvmModule::MarkAndTraceType = 0;
#endif
const llvm::Type* JnjvmModule::JavaObjectType = 0;
const llvm::Type* JnjvmModule::JavaArrayType = 0;
const llvm::Type* JnjvmModule::JavaArrayUInt8Type = 0;
const llvm::Type* JnjvmModule::JavaArraySInt8Type = 0;
const llvm::Type* JnjvmModule::JavaArrayUInt16Type = 0;
const llvm::Type* JnjvmModule::JavaArraySInt16Type = 0;
const llvm::Type* JnjvmModule::JavaArrayUInt32Type = 0;
const llvm::Type* JnjvmModule::JavaArraySInt32Type = 0;
const llvm::Type* JnjvmModule::JavaArrayFloatType = 0;
const llvm::Type* JnjvmModule::JavaArrayDoubleType = 0;
const llvm::Type* JnjvmModule::JavaArrayLongType = 0;
const llvm::Type* JnjvmModule::JavaArrayObjectType = 0;
const llvm::Type* JnjvmModule::CacheNodeType = 0;
const llvm::Type* JnjvmModule::EnveloppeType = 0;
const llvm::Type* JnjvmModule::JnjvmType = 0;
const llvm::Type* JnjvmModule::ConstantPoolType = 0;
llvm::Constant* JnjvmModule::JavaObjectNullConstant;
llvm::Constant* JnjvmModule::UTF8NullConstant;
llvm::Constant* JnjvmModule::JavaClassNullConstant;
llvm::Constant* JnjvmModule::MaxArraySizeConstant;
llvm::Constant* JnjvmModule::JavaObjectSizeConstant;
llvm::Constant* JnjvmModule::JavaArraySizeConstant;
llvm::ConstantInt* JnjvmModule::OffsetObjectSizeInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetVTInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetDepthInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetDisplayInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetStatusInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetTaskClassMirrorInClassConstant;
llvm::ConstantInt* JnjvmModule::OffsetStaticInstanceInTaskClassMirrorConstant;
llvm::ConstantInt* JnjvmModule::OffsetStatusInTaskClassMirrorConstant;
llvm::ConstantInt* JnjvmModule::ClassReadyConstant;
const llvm::Type* JnjvmModule::JavaClassType;
const llvm::Type* JnjvmModule::VTType;
llvm::ConstantInt* JnjvmModule::JavaArrayElementsOffsetConstant;
llvm::ConstantInt* JnjvmModule::JavaArraySizeOffsetConstant;
llvm::ConstantInt* JnjvmModule::JavaObjectLockOffsetConstant;
llvm::ConstantInt* JnjvmModule::JavaObjectClassOffsetConstant;
Value* JnjvmModule::getNativeClass(CommonClass* classDef) {
llvm::GlobalVariable* varGV = 0;
native_class_iterator End = nativeClasses.end();
native_class_iterator I = nativeClasses.find(classDef);
if (I == End) {
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
uint64_t (classDef)),
JnjvmModule::JavaClassType);
varGV = new GlobalVariable(JnjvmModule::JavaClassType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
nativeClasses.insert(std::make_pair(classDef, varGV));
} else {
varGV = I->second;
}
return varGV;
}
Value* JnjvmModule::getConstantPool(JavaConstantPool* ctp) {
llvm::GlobalVariable* varGV = 0;
constant_pool_iterator End = constantPools.end();
constant_pool_iterator I = constantPools.find(ctp);
if (I == End) {
void* ptr = ctp->ctpRes;
assert(ptr && "No constant pool found");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64(ptr)),
mvm::MvmModule::ptrPtrType);
varGV = new GlobalVariable(mvm::MvmModule::ptrPtrType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
constantPools.insert(std::make_pair(ctp, varGV));
} else {
varGV = I->second;
}
return varGV;
}
Value* JnjvmModule::getString(JavaString* str) {
llvm::GlobalVariable* varGV;
string_iterator SI = strings.find(str);
if (SI != strings.end()) {
varGV = SI->second;
} else {
void* ptr = str;
assert(ptr && "No string given");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64(ptr)),
JnjvmModule::JavaObjectType);
varGV = new GlobalVariable(JnjvmModule::JavaObjectType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
strings.insert(std::make_pair(str, varGV));
}
return varGV;
}
Value* JnjvmModule::getEnveloppe(Enveloppe* enveloppe) {
llvm::GlobalVariable* varGV;
enveloppe_iterator SI = enveloppes.find(enveloppe);
if (SI != enveloppes.end()) {
varGV = SI->second;
} else {
void* ptr = enveloppe;
assert(ptr && "No enveloppe given");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64(ptr)),
JnjvmModule::EnveloppeType);
varGV = new GlobalVariable(JnjvmModule::EnveloppeType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
enveloppes.insert(std::make_pair(enveloppe, varGV));
}
return varGV;
}
Value* JnjvmModule::getJavaClass(CommonClass* cl) {
llvm::GlobalVariable* varGV = 0;
java_class_iterator End = javaClasses.end();
java_class_iterator I = javaClasses.find(cl);
if (I == End) {
JavaObject* obj = isStaticCompiling() ? 0 :
cl->getClassDelegatee(JavaThread::get()->getJVM());
assert((obj || isStaticCompiling()) && "Delegatee not created");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64(obj)),
JnjvmModule::JavaObjectType);
varGV = new GlobalVariable(JnjvmModule::JavaObjectType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
javaClasses.insert(std::make_pair(cl, varGV));
} else {
varGV = I->second;
}
return varGV;
}
Value* JnjvmModule::getStaticInstance(Class* classDef) {
llvm::GlobalVariable* varGV = 0;
static_instance_iterator End = staticInstances.end();
static_instance_iterator I = staticInstances.find(classDef);
if (I == End) {
LLVMClassInfo* LCI = getClassInfo(classDef);
LCI->getStaticType();
JavaObject* obj = ((Class*)classDef)->getStaticInstance();
#ifndef ISOLATE
if (!obj && !isStaticCompiling()) {
Class* cl = (Class*)classDef;
classDef->acquire();
obj = cl->getStaticInstance();
if (!obj) {
// Allocate now so that compiled code can reference it.
obj = cl->allocateStaticInstance(JavaThread::get()->getJVM());
}
classDef->release();
}
#endif
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
uint64_t (obj)), JnjvmModule::JavaObjectType);
varGV = new GlobalVariable(JnjvmModule::JavaObjectType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
staticInstances.insert(std::make_pair(classDef, varGV));
} else {
varGV = I->second;
}
return varGV;
}
Value* JnjvmModule::getVirtualTable(CommonClass* classDef) {
llvm::GlobalVariable* varGV = 0;
virtual_table_iterator End = virtualTables.end();
virtual_table_iterator I = virtualTables.find(classDef);
if (I == End) {
if (!classDef->isArray() && !classDef->isPrimitive()) {
LLVMClassInfo* LCI = getClassInfo((Class*)classDef);
LCI->getVirtualType();
}
assert((classDef->virtualVT || isStaticCompiling()) &&
"Virtual VT not created");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
uint64_t(classDef->virtualVT)),
JnjvmModule::VTType);
varGV = new GlobalVariable(JnjvmModule::VTType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
virtualTables.insert(std::make_pair(classDef, varGV));
} else {
varGV = I->second;
}
return varGV;
}
Value* JnjvmModule::getNativeFunction(JavaMethod* meth, void* ptr) {
llvm::GlobalVariable* varGV = 0;
native_function_iterator End = nativeFunctions.end();
native_function_iterator I = nativeFunctions.find(meth);
if (I == End) {
LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature());
const llvm::Type* valPtrType = LSI->getNativePtrType();
assert((ptr || isStaticCompiling()) && "No native function given");
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t(ptr)),
valPtrType);
varGV = new GlobalVariable(valPtrType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
nativeFunctions.insert(std::make_pair(meth, varGV));
} else {
varGV = I->second;
}
return varGV;
}
#ifndef WITHOUT_VTABLE
VirtualTable* JnjvmModule::allocateVT(Class* cl) {
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
JavaMethod& meth = cl->virtualMethods[i];
if (meth.name->equals(cl->classLoader->bootstrapLoader->finalize)) {
meth.offset = 0;
} else {
JavaMethod* parent = cl->super?
cl->super->lookupMethodDontThrow(meth.name, meth.type, false, true,
0) :
0;
uint64_t offset = 0;
if (!parent) {
offset = cl->virtualTableSize++;
meth.offset = offset;
} else {
offset = parent->offset;
meth.offset = parent->offset;
}
}
}
uint64 size = cl->virtualTableSize;
mvm::BumpPtrAllocator& allocator = cl->classLoader->allocator;
VirtualTable* VT = (VirtualTable*)allocator.Allocate(size * sizeof(void*));
if (cl->super) {
Class* super = (Class*)cl->super;
assert(cl->virtualTableSize >= cl->super->virtualTableSize &&
"Super VT bigger than own VT");
assert(super->virtualVT && "Super does not have a VT!");
memcpy(VT, super->virtualVT, cl->super->virtualTableSize * sizeof(void*));
} else {
memcpy(VT, JavaObject::VT, VT_SIZE);
}
return VT;
}
#endif
llvm::Function* JnjvmModule::makeTracer(Class* cl, bool stat) {
LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl);
const Type* type = stat ? LCI->getStaticType() : LCI->getVirtualType();
JavaField* fields = 0;
uint32 nbFields = 0;
if (stat) {
fields = cl->getStaticFields();
nbFields = cl->nbStaticFields;
} else {
fields = cl->getVirtualFields();
nbFields = cl->nbVirtualFields;
}
Function* func = Function::Create(JnjvmModule::MarkAndTraceType,
GlobalValue::ExternalLinkage,
"markAndTraceObject",
this);
Constant* zero = mvm::MvmModule::constantZero;
Argument* arg = func->arg_begin();
BasicBlock* block = BasicBlock::Create("", func);
llvm::Value* realArg = new BitCastInst(arg, type, "", block);
std::vector<Value*> Args;
Args.push_back(arg);
#ifdef MULTIPLE_GC
Value* GC = ++func->arg_begin();
Args.push_back(GC);
#endif
if (stat || cl->super == 0) {
CallInst::Create(JavaObjectTracerFunction, Args.begin(), Args.end(),
"", block);
} else {
LLVMClassInfo* LCP = (LLVMClassInfo*)getClassInfo((Class*)(cl->super));
CallInst::Create(LCP->getVirtualTracer(), Args.begin(),
Args.end(), "", block);
}
for (uint32 i = 0; i < nbFields; ++i) {
JavaField& cur = fields[i];
if (cur.getSignature()->trace()) {
LLVMFieldInfo* LFI = getFieldInfo(&cur);
std::vector<Value*> args; //size = 2
args.push_back(zero);
args.push_back(LFI->getOffset());
Value* ptr = GetElementPtrInst::Create(realArg, args.begin(), args.end(),
"",block);
Value* val = new LoadInst(ptr, "", block);
Value* valCast = new BitCastInst(val, JnjvmModule::JavaObjectType, "",
block);
std::vector<Value*> Args;
Args.push_back(valCast);
#ifdef MULTIPLE_GC
Args.push_back(GC);
#endif
CallInst::Create(JnjvmModule::MarkAndTraceFunction, Args.begin(),
Args.end(), "", block);
}
}
ReturnInst::Create(block);
if (!stat) {
LCI->virtualTracerFunction = func;
} else {
LCI->staticTracerFunction = func;
}
return func;
}
VirtualTable* JnjvmModule::makeVT(Class* cl, bool stat) {
VirtualTable* VT = 0;
#ifndef WITHOUT_VTABLE
if (stat) {
#endif
mvm::BumpPtrAllocator& allocator = cl->classLoader->allocator;
VT = (VirtualTable*)allocator.Allocate(VT_SIZE);
memcpy(VT, JavaObject::VT, VT_SIZE);
#ifndef WITHOUT_VTABLE
} else {
if (cl->super) {
cl->virtualTableSize = cl->super->virtualTableSize;
} else {
cl->virtualTableSize = VT_NB_FUNCS;
}
// Allocate the virtual table.
VT = allocateVT(cl);
// Fill the virtual table with function pointers.
ExecutionEngine* EE = mvm::MvmModule::executionEngine;
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
JavaMethod& meth = cl->virtualMethods[i];
LLVMMethodInfo* LMI = getMethodInfo(&meth);
Function* func = LMI->getMethod();
// Special handling for finalize method. Don't put a finalizer
// if there is none, or if it is empty.
if (meth.offset == 0) {
#ifdef ISOLATE_SHARING
((void**)VT)[0] = 0;
#else
JnjvmClassLoader* loader = cl->classLoader;
Function* func = loader->getModuleProvider()->parseFunction(&meth);
if (!cl->super) meth.canBeInlined = true;
Function::iterator BB = func->begin();
BasicBlock::iterator I = BB->begin();
if (isa<ReturnInst>(I)) {
((void**)VT)[0] = 0;
} else {
// LLVM does not allow recursive compilation. Create the code now.
((void**)VT)[0] = EE->getPointerToFunction(func);
}
}
#endif
if (staticCompilation) {
((void**)VT)[meth.offset] = func;
} else {
((void**)VT)[meth.offset] = EE->getPointerToFunctionOrStub(func);
}
}
// If there is no super, then it's the first VT that we allocate. Assign
// this VT to native types.
if (!(cl->super)) {
uint32 size = (cl->virtualTableSize - VT_NB_FUNCS) * sizeof(void*);
#define COPY(CLASS) \
memcpy((void*)((uintptr_t)CLASS::VT + VT_SIZE), \
(void*)((uintptr_t)VT + VT_SIZE), size);
COPY(JavaArray)
COPY(JavaObject)
COPY(ArrayObject)
#undef COPY
}
}
#endif
#ifdef WITH_TRACER
llvm::Function* func = makeTracer(cl, stat);
if (staticCompilation) {
((void**)VT)[VT_TRACER_OFFSET] = func;
} else {
void* codePtr = mvm::MvmModule::executionEngine->getPointerToFunction(func);
((void**)VT)[VT_TRACER_OFFSET] = codePtr;
func->deleteBody();
}
#endif
return VT;
}
const Type* LLVMClassInfo::getVirtualType() {
if (!virtualType) {
std::vector<const llvm::Type*> fields;
if (classDef->super) {
LLVMClassInfo* CLI =
JnjvmModule::getClassInfo((Class*)classDef->super);
fields.push_back(CLI->getVirtualType()->getContainedType(0));
} else {
fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0));
}
for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) {
JavaField& field = classDef->virtualFields[i];
field.num = i;
Typedef* type = field.getSignature();
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(type);
fields.push_back(LAI.llvmType);
}
StructType* structType = StructType::get(fields, false);
virtualType = PointerType::getUnqual(structType);
ExecutionEngine* engine = mvm::MvmModule::executionEngine;
const TargetData* targetData = engine->getTargetData();
const StructLayout* sl = targetData->getStructLayout(structType);
for (uint32 i = 0; i < classDef->nbVirtualFields; ++i) {
JavaField& field = classDef->virtualFields[i];
field.ptrOffset = sl->getElementOffset(i + 1);
}
uint64 size = mvm::MvmModule::getTypeSize(structType);
classDef->virtualSize = (uint32)size;
virtualSizeConstant = ConstantInt::get(Type::Int32Ty, size);
JnjvmModule* Mod = classDef->classLoader->getModule();
if (!Mod->isStaticCompiling()) {
classDef->virtualVT = Mod->makeVT((Class*)classDef, false);
}
}
return virtualType;
}
const Type* LLVMClassInfo::getStaticType() {
if (!staticType) {
Class* cl = (Class*)classDef;
std::vector<const llvm::Type*> fields;
fields.push_back(JnjvmModule::JavaObjectType->getContainedType(0));
for (uint32 i = 0; i < classDef->nbStaticFields; ++i) {
JavaField& field = classDef->staticFields[i];
field.num = i;
Typedef* type = field.getSignature();
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(type);
fields.push_back(LAI.llvmType);
}
StructType* structType = StructType::get(fields, false);
staticType = PointerType::getUnqual(structType);
ExecutionEngine* engine = mvm::MvmModule::executionEngine;
const TargetData* targetData = engine->getTargetData();
const StructLayout* sl = targetData->getStructLayout(structType);
for (uint32 i = 0; i < classDef->nbStaticFields; ++i) {
JavaField& field = classDef->staticFields[i];
field.ptrOffset = sl->getElementOffset(i + 1);
}
uint64 size = mvm::MvmModule::getTypeSize(structType);
cl->staticSize = size;
JnjvmModule* Mod = cl->classLoader->getModule();
if (!Mod->isStaticCompiling()) {
cl->staticVT = Mod->makeVT((Class*)classDef, true);
}
}
return staticType;
}
Value* LLVMClassInfo::getVirtualSize() {
if (!virtualSizeConstant) {
getVirtualType();
virtualSizeConstant =
ConstantInt::get(Type::Int32Ty, classDef->virtualSize);
}
return virtualSizeConstant;
}
Function* LLVMClassInfo::getStaticTracer() {
if (!staticTracerFunction) {
getStaticType();
}
return staticTracerFunction;
}
Function* LLVMClassInfo::getVirtualTracer() {
if (!virtualTracerFunction) {
getVirtualType();
}
return virtualTracerFunction;
}
Function* LLVMMethodInfo::getMethod() {
if (!methodFunction) {
JnjvmClassLoader* JCL = methodDef->classDef->classLoader;
JnjvmModule* Mod = JCL->getModule();
if (Mod->isStaticCompiling()) {
const UTF8* jniConsClName = methodDef->classDef->name;
const UTF8* jniConsName = methodDef->name;
const UTF8* jniConsType = methodDef->type;
sint32 clen = jniConsClName->size;
sint32 mnlen = jniConsName->size;
sint32 mtlen = jniConsType->size;
char* buf =
(char*)alloca(3 + JNI_NAME_PRE_LEN + mnlen + clen + (mtlen << 1));
methodDef->jniConsFromMeth3(buf);
methodFunction = Function::Create(getFunctionType(),
GlobalValue::GhostLinkage, buf, Mod);
} else {
methodFunction = Function::Create(getFunctionType(),
GlobalValue::GhostLinkage,
"", Mod);
}
methodFunction->addAnnotation(this);
}
return methodFunction;
}
const FunctionType* LLVMMethodInfo::getFunctionType() {
if (!functionType) {
Signdef* sign = methodDef->getSignature();
LLVMSignatureInfo* LSI = JnjvmModule::getSignatureInfo(sign);
assert(LSI);
if (isStatic(methodDef->access)) {
functionType = LSI->getStaticType();
} else {
functionType = LSI->getVirtualType();
}
}
return functionType;
}
ConstantInt* LLVMMethodInfo::getOffset() {
if (!offsetConstant) {
JnjvmModule::resolveVirtualClass(methodDef->classDef);
offsetConstant = ConstantInt::get(Type::Int32Ty, methodDef->offset);
}
return offsetConstant;
}
ConstantInt* LLVMFieldInfo::getOffset() {
if (!offsetConstant) {
if (isStatic(fieldDef->access)) {
JnjvmModule::resolveStaticClass(fieldDef->classDef);
} else {
JnjvmModule::resolveVirtualClass(fieldDef->classDef);
}
// Increment by one because zero is JavaObject
offsetConstant = ConstantInt::get(Type::Int32Ty, fieldDef->num + 1);
}
return offsetConstant;
}
const llvm::FunctionType* LLVMSignatureInfo::getVirtualType() {
if (!virtualType) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
std::vector<const llvm::Type*> llvmArgs;
unsigned int size = signature->args.size();
llvmArgs.push_back(JnjvmModule::JavaObjectType);
for (uint32 i = 0; i < size; ++i) {
Typedef* type = signature->args.at(i);
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(type);
llvmArgs.push_back(LAI.llvmType);
}
#if defined(ISOLATE_SHARING)
llvmArgs.push_back(JnjvmModule::ConstantPoolType); // cached constant pool
#endif
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(signature->ret);
virtualType = FunctionType::get(LAI.llvmType, llvmArgs, false);
}
return virtualType;
}
const llvm::FunctionType* LLVMSignatureInfo::getStaticType() {
if (!staticType) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
std::vector<const llvm::Type*> llvmArgs;
unsigned int size = signature->args.size();
for (uint32 i = 0; i < size; ++i) {
Typedef* type = signature->args.at(i);
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(type);
llvmArgs.push_back(LAI.llvmType);
}
#if defined(ISOLATE_SHARING)
llvmArgs.push_back(JnjvmModule::ConstantPoolType); // cached constant pool
#endif
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(signature->ret);
staticType = FunctionType::get(LAI.llvmType, llvmArgs, false);
}
return staticType;
}
const llvm::FunctionType* LLVMSignatureInfo::getNativeType() {
if (!nativeType) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
std::vector<const llvm::Type*> llvmArgs;
unsigned int size = signature->args.size();
llvmArgs.push_back(mvm::MvmModule::ptrType); // JNIEnv
llvmArgs.push_back(JnjvmModule::JavaObjectType); // Class
for (uint32 i = 0; i < size; ++i) {
Typedef* type = signature->args.at(i);
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(type);
llvmArgs.push_back(LAI.llvmType);
}
#if defined(ISOLATE_SHARING)
llvmArgs.push_back(JnjvmModule::ConstantPoolType); // cached constant pool
#endif
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(signature->ret);
nativeType = FunctionType::get(LAI.llvmType, llvmArgs, false);
}
return nativeType;
}
Function* LLVMSignatureInfo::createFunctionCallBuf(bool virt) {
std::vector<Value*> Args;
Function* res = Function::Create(virt ? getVirtualBufType() :
getStaticBufType(),
GlobalValue::ExternalLinkage,
signature->printString(),
signature->initialLoader->TheModule);
BasicBlock* currentBlock = BasicBlock::Create("enter", res);
Function::arg_iterator i = res->arg_begin();
Value *obj, *ptr, *func;
#if defined(ISOLATE_SHARING)
Value* ctp = i;
#endif
++i;
func = i;
++i;
if (virt) {
obj = i;
++i;
Args.push_back(obj);
}
ptr = i;
for (std::vector<Typedef*>::iterator i = signature->args.begin(),
e = signature->args.end(); i!= e; ++i) {
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(*i);
Value* val = new BitCastInst(ptr, LAI.llvmTypePtr, "", currentBlock);
Value* arg = new LoadInst(val, "", currentBlock);
Args.push_back(arg);
ptr = GetElementPtrInst::Create(ptr, JnjvmModule::constantEight, "",
currentBlock);
}
#if defined(ISOLATE_SHARING)
Args.push_back(ctp);
#endif
Value* val = CallInst::Create(func, Args.begin(), Args.end(), "",
currentBlock);
if (res->getFunctionType()->getReturnType() != Type::VoidTy)
ReturnInst::Create(val, currentBlock);
else
ReturnInst::Create(currentBlock);
return res;
}
Function* LLVMSignatureInfo::createFunctionCallAP(bool virt) {
std::vector<Value*> Args;
Function* res = Function::Create(virt ? getVirtualBufType() :
getStaticBufType(),
GlobalValue::ExternalLinkage,
signature->printString(),
signature->initialLoader->TheModule);
BasicBlock* currentBlock = BasicBlock::Create("enter", res);
Function::arg_iterator i = res->arg_begin();
Value *obj, *ap, *func;
#if defined(ISOLATE_SHARING)
Value* ctp = i;
#endif
++i;
func = i;
++i;
if (virt) {
obj = i;
Args.push_back(obj);
++i;
}
ap = i;
for (std::vector<Typedef*>::iterator i = signature->args.begin(),
e = signature->args.end(); i!= e; i++) {
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(*i);
Args.push_back(new VAArgInst(ap, LAI.llvmType, "", currentBlock));
}
#if defined(ISOLATE_SHARING)
Args.push_back(ctp);
#endif
Value* val = CallInst::Create(func, Args.begin(), Args.end(), "",
currentBlock);
if (res->getFunctionType()->getReturnType() != Type::VoidTy)
ReturnInst::Create(val, currentBlock);
else
ReturnInst::Create(currentBlock);
return res;
}
const PointerType* LLVMSignatureInfo::getStaticPtrType() {
if (!staticPtrType) {
staticPtrType = PointerType::getUnqual(getStaticType());
}
return staticPtrType;
}
const PointerType* LLVMSignatureInfo::getVirtualPtrType() {
if (!virtualPtrType) {
virtualPtrType = PointerType::getUnqual(getVirtualType());
}
return virtualPtrType;
}
const PointerType* LLVMSignatureInfo::getNativePtrType() {
if (!nativePtrType) {
nativePtrType = PointerType::getUnqual(getNativeType());
}
return nativePtrType;
}
const FunctionType* LLVMSignatureInfo::getVirtualBufType() {
if (!virtualBufType) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
std::vector<const llvm::Type*> Args2;
Args2.push_back(JnjvmModule::ConstantPoolType); // ctp
Args2.push_back(getVirtualPtrType());
Args2.push_back(JnjvmModule::JavaObjectType);
Args2.push_back(JnjvmModule::ptrType);
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(signature->ret);
virtualBufType = FunctionType::get(LAI.llvmType, Args2, false);
}
return virtualBufType;
}
const FunctionType* LLVMSignatureInfo::getStaticBufType() {
if (!staticBufType) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
std::vector<const llvm::Type*> Args;
Args.push_back(JnjvmModule::ConstantPoolType); // ctp
Args.push_back(getStaticPtrType());
Args.push_back(JnjvmModule::ptrType);
LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(signature->ret);
staticBufType = FunctionType::get(LAI.llvmType, Args, false);
}
return staticBufType;
}
Function* LLVMSignatureInfo::getVirtualBuf() {
if (!virtualBufFunction) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
virtualBufFunction = createFunctionCallBuf(true);
signature->setVirtualCallBuf((intptr_t)
mvm::MvmModule::executionEngine->getPointerToGlobal(virtualBufFunction));
virtualBufFunction->deleteBody();
}
return virtualBufFunction;
}
Function* LLVMSignatureInfo::getVirtualAP() {
if (!virtualAPFunction) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
virtualAPFunction = createFunctionCallAP(true);
signature->setVirtualCallAP((intptr_t)
mvm::MvmModule::executionEngine->getPointerToGlobal(virtualAPFunction));
virtualAPFunction->deleteBody();
}
return virtualAPFunction;
}
Function* LLVMSignatureInfo::getStaticBuf() {
if (!staticBufFunction) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
staticBufFunction = createFunctionCallBuf(false);
signature->setStaticCallBuf((intptr_t)
mvm::MvmModule::executionEngine->getPointerToGlobal(staticBufFunction));
staticBufFunction->deleteBody();
}
return staticBufFunction;
}
Function* LLVMSignatureInfo::getStaticAP() {
if (!staticAPFunction) {
// Lock here because we are called by arbitrary code
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
staticAPFunction = createFunctionCallAP(false);
signature->setStaticCallAP((intptr_t)
mvm::MvmModule::executionEngine->getPointerToGlobal(staticAPFunction));
staticAPFunction->deleteBody();
}
return staticAPFunction;
}
void JnjvmModule::resolveVirtualClass(Class* cl) {
// Lock here because we may be called by a class resolver
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl);
LCI->getVirtualType();
}
void JnjvmModule::resolveStaticClass(Class* cl) {
// Lock here because we may be called by a class initializer
llvm::MutexGuard locked(mvm::MvmModule::executionEngine->lock);
LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl);
LCI->getStaticType();
}
namespace jnjvm {
namespace llvm_runtime {
#include "LLVMRuntime.inc"
}
}
Module* JnjvmModule::initialModule;
void JnjvmModule::initialise() {
jnjvm::llvm_runtime::makeLLVMModuleContents(this);
Module* module = this;
initialModule = this;
VTType = module->getTypeByName("VT");
JnjvmType =
PointerType::getUnqual(module->getTypeByName("Jnjvm"));
ConstantPoolType =
PointerType::getUnqual(module->getTypeByName("ConstantPool"));
JavaObjectType =
PointerType::getUnqual(module->getTypeByName("JavaObject"));
JavaArrayType =
PointerType::getUnqual(module->getTypeByName("JavaArray"));
JavaClassType =
PointerType::getUnqual(module->getTypeByName("JavaClass"));
JavaArrayUInt8Type =
PointerType::getUnqual(module->getTypeByName("ArrayUInt8"));
JavaArraySInt8Type =
PointerType::getUnqual(module->getTypeByName("ArraySInt8"));
JavaArrayUInt16Type =
PointerType::getUnqual(module->getTypeByName("ArrayUInt16"));
JavaArraySInt16Type =
PointerType::getUnqual(module->getTypeByName("ArraySInt16"));
JavaArrayUInt32Type =
PointerType::getUnqual(module->getTypeByName("ArrayUInt32"));
JavaArraySInt32Type =
PointerType::getUnqual(module->getTypeByName("ArraySInt32"));
JavaArrayLongType =
PointerType::getUnqual(module->getTypeByName("ArrayLong"));
JavaArrayFloatType =
PointerType::getUnqual(module->getTypeByName("ArrayFloat"));
JavaArrayDoubleType =
PointerType::getUnqual(module->getTypeByName("ArrayDouble"));
JavaArrayObjectType =
PointerType::getUnqual(module->getTypeByName("ArrayObject"));
CacheNodeType =
PointerType::getUnqual(module->getTypeByName("CacheNode"));
EnveloppeType =
PointerType::getUnqual(module->getTypeByName("Enveloppe"));
#ifdef WITH_TRACER
MarkAndTraceType = module->getFunction("MarkAndTrace")->getFunctionType();
#endif
UTF8NullConstant = Constant::getNullValue(JavaArrayUInt16Type);
JavaClassNullConstant = Constant::getNullValue(JavaClassType);
JavaObjectNullConstant = Constant::getNullValue(JnjvmModule::JavaObjectType);
MaxArraySizeConstant = ConstantInt::get(Type::Int32Ty,
JavaArray::MaxArraySize);
JavaObjectSizeConstant = ConstantInt::get(Type::Int32Ty, sizeof(JavaObject));
JavaArraySizeConstant =
ConstantInt::get(Type::Int32Ty, sizeof(JavaObject) + sizeof(ssize_t));
JavaArrayElementsOffsetConstant = mvm::MvmModule::constantTwo;
JavaArraySizeOffsetConstant = mvm::MvmModule::constantOne;
JavaObjectLockOffsetConstant = mvm::MvmModule::constantTwo;
JavaObjectClassOffsetConstant = mvm::MvmModule::constantOne;
OffsetObjectSizeInClassConstant = mvm::MvmModule::constantOne;
OffsetVTInClassConstant = mvm::MvmModule::constantTwo;
OffsetDisplayInClassConstant = mvm::MvmModule::constantThree;
OffsetDepthInClassConstant = mvm::MvmModule::constantFour;
OffsetStatusInClassConstant = mvm::MvmModule::constantFive;
OffsetTaskClassMirrorInClassConstant = mvm::MvmModule::constantSix;
OffsetStaticInstanceInTaskClassMirrorConstant = mvm::MvmModule::constantTwo;
OffsetStatusInTaskClassMirrorConstant = mvm::MvmModule::constantZero;
ClassReadyConstant = ConstantInt::get(Type::Int32Ty, ready);
LLVMAssessorInfo::initialise();
}
void JnjvmModule::setMethod(JavaMethod* meth, const char* name) {
llvm::Function* func = getMethodInfo(meth)->getMethod();
func->setName(name);
func->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
void* JnjvmModule::getMethod(JavaMethod* meth) {
return getMethodInfo(meth)->getMethod();
}
JnjvmModule::JnjvmModule(const std::string &ModuleID, bool sc) :
MvmModule(ModuleID) {
std::string str =
mvm::MvmModule::executionEngine->getTargetData()->getStringRepresentation();
setDataLayout(str);
staticCompilation = sc;
if (!VTType) initialise();
Module* module = initialModule;
InterfaceLookupFunction = module->getFunction("jnjvmVirtualLookup");
MultiCallNewFunction = module->getFunction("multiCallNew");
InitialisationCheckFunction = module->getFunction("initialisationCheck");
ForceInitialisationCheckFunction =
module->getFunction("forceInitialisationCheck");
InitialiseClassFunction = module->getFunction("jnjvmRuntimeInitialiseClass");
GetConstantPoolAtFunction = module->getFunction("getConstantPoolAt");
ArrayLengthFunction = module->getFunction("arrayLength");
GetVTFunction = module->getFunction("getVT");
GetClassFunction = module->getFunction("getClass");
ClassLookupFunction = module->getFunction("classLookup");
GetVTFromClassFunction = module->getFunction("getVTFromClass");
GetObjectSizeFromClassFunction =
module->getFunction("getObjectSizeFromClass");
GetClassDelegateeFunction = module->getFunction("getClassDelegatee");
InstanceOfFunction = module->getFunction("instanceOf");
IsAssignableFromFunction = module->getFunction("isAssignableFrom");
ImplementsFunction = module->getFunction("implements");
InstantiationOfArrayFunction = module->getFunction("instantiationOfArray");
GetDepthFunction = module->getFunction("getDepth");
GetStaticInstanceFunction = module->getFunction("getStaticInstance");
GetDisplayFunction = module->getFunction("getDisplay");
GetClassInDisplayFunction = module->getFunction("getClassInDisplay");
AquireObjectFunction = module->getFunction("JavaObjectAquire");
ReleaseObjectFunction = module->getFunction("JavaObjectRelease");
OverflowThinLockFunction = module->getFunction("overflowThinLock");
VirtualFieldLookupFunction = module->getFunction("virtualFieldLookup");
StaticFieldLookupFunction = module->getFunction("staticFieldLookup");
GetExceptionFunction = module->getFunction("JavaThreadGetException");
GetJavaExceptionFunction = module->getFunction("JavaThreadGetJavaException");
CompareExceptionFunction = module->getFunction("JavaThreadCompareException");
JniProceedPendingExceptionFunction =
module->getFunction("jniProceedPendingException");
GetSJLJBufferFunction = module->getFunction("getSJLJBuffer");
NullPointerExceptionFunction =
module->getFunction("jnjvmNullPointerException");
ClassCastExceptionFunction = module->getFunction("jnjvmClassCastException");
IndexOutOfBoundsExceptionFunction =
module->getFunction("indexOutOfBoundsException");
NegativeArraySizeExceptionFunction =
module->getFunction("negativeArraySizeException");
OutOfMemoryErrorFunction = module->getFunction("outOfMemoryError");
JavaObjectAllocateFunction = module->getFunction("gcmalloc");
PrintExecutionFunction = module->getFunction("printExecution");
PrintMethodStartFunction = module->getFunction("printMethodStart");
PrintMethodEndFunction = module->getFunction("printMethodEnd");
ThrowExceptionFunction = module->getFunction("JavaThreadThrowException");
ClearExceptionFunction = module->getFunction("JavaThreadClearException");
GetArrayClassFunction = module->getFunction("getArrayClass");
#ifdef ISOLATE
StringLookupFunction = module->getFunction("stringLookup");
#ifdef ISOLATE_SHARING
EnveloppeLookupFunction = module->getFunction("enveloppeLookup");
GetCtpCacheNodeFunction = module->getFunction("getCtpCacheNode");
GetCtpClassFunction = module->getFunction("getCtpClass");
GetJnjvmExceptionClassFunction =
module->getFunction("getJnjvmExceptionClass");
GetJnjvmArrayClassFunction = module->getFunction("getJnjvmArrayClass");
StaticCtpLookupFunction = module->getFunction("staticCtpLookup");
SpecialCtpLookupFunction = module->getFunction("specialCtpLookup");
#endif
#endif
#ifdef SERVICE
ServiceCallStartFunction = module->getFunction("serviceCallStart");
ServiceCallStopFunction = module->getFunction("serviceCallStop");
#endif
#ifdef WITH_TRACER
MarkAndTraceFunction = module->getFunction("MarkAndTrace");
JavaObjectTracerFunction = module->getFunction("JavaObjectTracer");
#endif
#ifndef WITHOUT_VTABLE
VirtualLookupFunction = module->getFunction("vtableLookup");
#endif
GetLockFunction = module->getFunction("getLock");
}
void LLVMAssessorInfo::initialise() {
AssessorInfo[I_VOID].llvmType = Type::VoidTy;
AssessorInfo[I_VOID].llvmTypePtr = 0;
AssessorInfo[I_VOID].llvmNullConstant = 0;
AssessorInfo[I_VOID].sizeInBytesConstant = 0;
AssessorInfo[I_BOOL].llvmType = Type::Int8Ty;
AssessorInfo[I_BOOL].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty);
AssessorInfo[I_BOOL].llvmNullConstant =
Constant::getNullValue(Type::Int8Ty);
AssessorInfo[I_BOOL].sizeInBytesConstant = mvm::MvmModule::constantOne;
AssessorInfo[I_BYTE].llvmType = Type::Int8Ty;
AssessorInfo[I_BYTE].llvmTypePtr = PointerType::getUnqual(Type::Int8Ty);
AssessorInfo[I_BYTE].llvmNullConstant =
Constant::getNullValue(Type::Int8Ty);
AssessorInfo[I_BYTE].sizeInBytesConstant = mvm::MvmModule::constantOne;
AssessorInfo[I_SHORT].llvmType = Type::Int16Ty;
AssessorInfo[I_SHORT].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty);
AssessorInfo[I_SHORT].llvmNullConstant =
Constant::getNullValue(Type::Int16Ty);
AssessorInfo[I_SHORT].sizeInBytesConstant = mvm::MvmModule::constantTwo;
AssessorInfo[I_CHAR].llvmType = Type::Int16Ty;
AssessorInfo[I_CHAR].llvmTypePtr = PointerType::getUnqual(Type::Int16Ty);
AssessorInfo[I_CHAR].llvmNullConstant =
Constant::getNullValue(Type::Int16Ty);
AssessorInfo[I_CHAR].sizeInBytesConstant = mvm::MvmModule::constantTwo;
AssessorInfo[I_INT].llvmType = Type::Int32Ty;
AssessorInfo[I_INT].llvmTypePtr = PointerType::getUnqual(Type::Int32Ty);
AssessorInfo[I_INT].llvmNullConstant =
Constant::getNullValue(Type::Int32Ty);
AssessorInfo[I_INT].sizeInBytesConstant = mvm::MvmModule::constantFour;
AssessorInfo[I_FLOAT].llvmType = Type::FloatTy;
AssessorInfo[I_FLOAT].llvmTypePtr = PointerType::getUnqual(Type::FloatTy);
AssessorInfo[I_FLOAT].llvmNullConstant =
Constant::getNullValue(Type::FloatTy);
AssessorInfo[I_FLOAT].sizeInBytesConstant = mvm::MvmModule::constantFour;
AssessorInfo[I_LONG].llvmType = Type::Int64Ty;
AssessorInfo[I_LONG].llvmTypePtr = PointerType::getUnqual(Type::Int64Ty);
AssessorInfo[I_LONG].llvmNullConstant =
Constant::getNullValue(Type::Int64Ty);
AssessorInfo[I_LONG].sizeInBytesConstant = mvm::MvmModule::constantEight;
AssessorInfo[I_DOUBLE].llvmType = Type::DoubleTy;
AssessorInfo[I_DOUBLE].llvmTypePtr = PointerType::getUnqual(Type::DoubleTy);
AssessorInfo[I_DOUBLE].llvmNullConstant =
Constant::getNullValue(Type::DoubleTy);
AssessorInfo[I_DOUBLE].sizeInBytesConstant = mvm::MvmModule::constantEight;
AssessorInfo[I_TAB].llvmType = JnjvmModule::JavaObjectType;
AssessorInfo[I_TAB].llvmTypePtr =
PointerType::getUnqual(JnjvmModule::JavaObjectType);
AssessorInfo[I_TAB].llvmNullConstant =
JnjvmModule::JavaObjectNullConstant;
AssessorInfo[I_TAB].sizeInBytesConstant = mvm::MvmModule::constantPtrSize;
AssessorInfo[I_REF].llvmType = JnjvmModule::JavaObjectType;
AssessorInfo[I_REF].llvmTypePtr =
PointerType::getUnqual(JnjvmModule::JavaObjectType);
AssessorInfo[I_REF].llvmNullConstant =
JnjvmModule::JavaObjectNullConstant;
AssessorInfo[I_REF].sizeInBytesConstant = mvm::MvmModule::constantPtrSize;
}
std::map<const char, LLVMAssessorInfo> LLVMAssessorInfo::AssessorInfo;
LLVMAssessorInfo& JnjvmModule::getTypedefInfo(Typedef* type) {
return LLVMAssessorInfo::AssessorInfo[type->getKey()->elements[0]];
}
static AnnotationID JavaMethod_ID(
AnnotationManager::getID("Java::JavaMethod"));
LLVMMethodInfo::LLVMMethodInfo(JavaMethod* M) :
llvm::Annotation(JavaMethod_ID), methodDef(M), methodFunction(0),
offsetConstant(0), functionType(0) {}
JavaMethod* LLVMMethodInfo::get(const llvm::Function* F) {
LLVMMethodInfo *MI = (LLVMMethodInfo*)F->getAnnotation(JavaMethod_ID);
if (MI) return MI->methodDef;
return 0;
}
#ifdef SERVICE
Value* JnjvmModule::getIsolate(Jnjvm* isolate) {
llvm::GlobalVariable* varGV = 0;
isolate_iterator End = isolates.end();
isolate_iterator I = isolates.find(isolate);
if (I == End) {
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
uint64_t(isolate)),
ptrType);
varGV = new GlobalVariable(ptrType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "", this);
isolates.insert(std::make_pair(isolate, varGV));
} else {
varGV = I->second;
}
return varGV;
}
#endif