| //===--------- 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/BasicBlock.h" |
| #include "llvm/CallingConv.h" |
| #include "llvm/Constants.h" |
| #include "llvm/Instructions.h" |
| #include "llvm/Support/MutexGuard.h" |
| |
| |
| #include "mvm/JIT.h" |
| |
| #include "JavaCache.h" |
| #include "JavaJIT.h" |
| #include "JavaString.h" |
| #include "JavaThread.h" |
| #include "JavaTypes.h" |
| #include "JavaUpcalls.h" |
| #include "Jnjvm.h" |
| #include "JnjvmModule.h" |
| #include "JnjvmModuleProvider.h" |
| |
| #include <cstdio> |
| |
| using namespace jnjvm; |
| using namespace llvm; |
| |
| llvm::Constant* JnjvmModule::PrimitiveArrayVT; |
| llvm::Constant* JnjvmModule::ReferenceArrayVT; |
| llvm::Function* JnjvmModule::StaticInitializer; |
| llvm::Function* JnjvmModule::NativeLoader; |
| |
| extern void* JavaArrayVT[]; |
| extern void* ArrayObjectVT[]; |
| extern void* JavaObjectVT[]; |
| |
| extern ClassArray ArrayOfBool; |
| extern ClassArray ArrayOfByte; |
| extern ClassArray ArrayOfChar; |
| extern ClassArray ArrayOfShort; |
| extern ClassArray ArrayOfInt; |
| extern ClassArray ArrayOfFloat; |
| extern ClassArray ArrayOfDouble; |
| extern ClassArray ArrayOfLong; |
| |
| #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::ConstantPoolType = 0; |
| const llvm::Type* JnjvmModule::UTF8Type = 0; |
| const llvm::Type* JnjvmModule::JavaFieldType = 0; |
| const llvm::Type* JnjvmModule::JavaMethodType = 0; |
| const llvm::Type* JnjvmModule::AttributType = 0; |
| const llvm::Type* JnjvmModule::JavaThreadType = 0; |
| |
| #ifdef ISOLATE_SHARING |
| const llvm::Type* JnjvmModule::JnjvmType = 0; |
| #endif |
| |
| llvm::Constant* JnjvmModule::JavaObjectNullConstant; |
| llvm::Constant* JnjvmModule::MaxArraySizeConstant; |
| llvm::Constant* JnjvmModule::JavaArraySizeConstant; |
| llvm::ConstantInt* JnjvmModule::OffsetObjectSizeInClassConstant; |
| llvm::ConstantInt* JnjvmModule::OffsetVTInClassConstant; |
| llvm::ConstantInt* JnjvmModule::OffsetDepthInClassConstant; |
| llvm::ConstantInt* JnjvmModule::OffsetDisplayInClassConstant; |
| 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::JavaClassPrimitiveType; |
| const llvm::Type* JnjvmModule::JavaClassArrayType; |
| const llvm::Type* JnjvmModule::JavaCommonClassType; |
| const llvm::Type* JnjvmModule::VTType; |
| llvm::ConstantInt* JnjvmModule::JavaArrayElementsOffsetConstant; |
| llvm::ConstantInt* JnjvmModule::JavaArraySizeOffsetConstant; |
| llvm::ConstantInt* JnjvmModule::JavaObjectLockOffsetConstant; |
| llvm::ConstantInt* JnjvmModule::JavaObjectClassOffsetConstant; |
| |
| |
| bool JnjvmModule::isCompiling(const CommonClass* cl) const { |
| if (cl->isClass()) { |
| // A class is being static compiled if owner class is not null. |
| return (((Class*)cl)->getOwnerClass() != 0); |
| } else if (cl->isArray()) { |
| return isCompiling(((ClassArray*)cl)->baseClass()); |
| } else { |
| return false; |
| } |
| } |
| |
| Constant* JnjvmModule::getNativeClass(CommonClass* classDef) { |
| |
| if (staticCompilation) { |
| |
| if (classDef->isClass() || |
| (classDef->isArray() && isCompiling(classDef))) { |
| native_class_iterator End = nativeClasses.end(); |
| native_class_iterator I = nativeClasses.find(classDef); |
| if (I == End) { |
| const llvm::Type* Ty = 0; |
| |
| if (classDef->isArray()) { |
| Ty = JavaClassArrayType->getContainedType(0); |
| } else { |
| Ty = JavaClassType->getContainedType(0); |
| } |
| |
| GlobalVariable* varGV = |
| new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, 0, |
| classDef->printString(), this); |
| |
| nativeClasses.insert(std::make_pair((Class*)classDef, varGV)); |
| |
| if (classDef->isClass() && isCompiling(classDef->asClass())) { |
| Constant* C = CreateConstantFromClass((Class*)classDef); |
| varGV->setInitializer(C); |
| } else if (classDef->isArray()) { |
| Constant* C = CreateConstantFromClassArray((ClassArray*)classDef); |
| varGV->setInitializer(C); |
| } |
| |
| return varGV; |
| |
| } else { |
| return I->second; |
| } |
| } else if (classDef->isArray()) { |
| array_class_iterator End = arrayClasses.end(); |
| array_class_iterator I = arrayClasses.find((ClassArray*)classDef); |
| if (I == End) { |
| const llvm::Type* Ty = JavaClassArrayType; |
| |
| GlobalVariable* varGV = |
| new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, |
| Constant::getNullValue(Ty), "", this); |
| |
| arrayClasses.insert(std::make_pair((ClassArray*)classDef, varGV)); |
| return varGV; |
| } else { |
| return I->second; |
| } |
| } else if (classDef->isPrimitive()) { |
| assert(0 && "implement me"); |
| } |
| return 0; |
| } else { |
| const llvm::Type* Ty = classDef->isClass() ? JavaClassType : |
| JavaCommonClassType; |
| |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(classDef)); |
| return ConstantExpr::getIntToPtr(CI, Ty); |
| } |
| } |
| |
| Constant* JnjvmModule::getConstantPool(JavaConstantPool* ctp) { |
| if (staticCompilation) { |
| llvm::Constant* varGV = 0; |
| constant_pool_iterator End = constantPools.end(); |
| constant_pool_iterator I = constantPools.find(ctp); |
| if (I == End) { |
| varGV = new GlobalVariable(ConstantPoolType->getContainedType(0), false, |
| GlobalValue::ExternalLinkage, |
| 0, "", this); |
| constantPools.insert(std::make_pair(ctp, varGV)); |
| return varGV; |
| } else { |
| return I->second; |
| } |
| |
| } else { |
| void* ptr = ctp->ctpRes; |
| assert(ptr && "No constant pool found"); |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); |
| return ConstantExpr::getIntToPtr(CI, ConstantPoolType); |
| } |
| } |
| |
| Constant* JnjvmModule::getString(JavaString* str) { |
| if (staticCompilation) { |
| string_iterator SI = strings.find(str); |
| if (SI != strings.end()) { |
| return SI->second; |
| } else { |
| assert(str && "No string given"); |
| LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo((Class*)str->classOf); |
| const llvm::Type* Ty = LCI->getVirtualType(); |
| GlobalVariable* varGV = |
| new GlobalVariable(Ty->getContainedType(0), true, |
| GlobalValue::ExternalLinkage, |
| 0, "", this); |
| Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, |
| JavaObjectType); |
| strings.insert(std::make_pair(str, res)); |
| Constant* C = CreateConstantFromJavaString(str); |
| varGV->setInitializer(C); |
| return res; |
| } |
| |
| } else { |
| assert(str && "No string given"); |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(str)); |
| return ConstantExpr::getIntToPtr(CI, JavaObjectType); |
| } |
| } |
| |
| Constant* JnjvmModule::getEnveloppe(Enveloppe* enveloppe) { |
| if (staticCompilation) { |
| enveloppe_iterator SI = enveloppes.find(enveloppe); |
| if (SI != enveloppes.end()) { |
| return SI->second; |
| } else { |
| GlobalVariable* varGV = |
| new GlobalVariable(EnveloppeType->getContainedType(0), false, |
| GlobalValue::ExternalLinkage, 0, "", this); |
| enveloppes.insert(std::make_pair(enveloppe, varGV)); |
| |
| Constant* C = CreateConstantFromEnveloppe(enveloppe); |
| varGV->setInitializer(C); |
| return varGV; |
| } |
| |
| } else { |
| assert(enveloppe && "No enveloppe given"); |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64(enveloppe)); |
| return ConstantExpr::getIntToPtr(CI, EnveloppeType); |
| } |
| } |
| |
| Constant* JnjvmModule::getJavaClass(CommonClass* cl) { |
| if (staticCompilation) { |
| java_class_iterator End = javaClasses.end(); |
| java_class_iterator I = javaClasses.find(cl); |
| if (I == End) { |
| Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass; |
| LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(javaClass); |
| const llvm::Type* Ty = LCI->getVirtualType(); |
| |
| GlobalVariable* varGV = |
| new GlobalVariable(Ty->getContainedType(0), false, |
| GlobalValue::ExternalLinkage, 0, "", this); |
| |
| Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, |
| JavaObjectType); |
| |
| javaClasses.insert(std::make_pair(cl, res)); |
| varGV->setInitializer(CreateConstantFromJavaClass(cl)); |
| return res; |
| } else { |
| return I->second; |
| } |
| |
| } else { |
| JavaObject* obj = cl->getClassDelegatee(JavaThread::get()->getJVM()); |
| assert(obj && "Delegatee not created"); |
| Constant* CI = ConstantInt::get(Type::Int64Ty, uint64(obj)); |
| return ConstantExpr::getIntToPtr(CI, JavaObjectType); |
| } |
| } |
| |
| Constant* JnjvmModule::getStaticInstance(Class* classDef) { |
| #ifdef ISOLATE |
| assert(0 && "Should not be here"); |
| abort(); |
| #endif |
| if (staticCompilation) { |
| llvm::Constant* varGV = 0; |
| static_instance_iterator End = staticInstances.end(); |
| static_instance_iterator I = staticInstances.find(classDef); |
| if (I == End) { |
| LLVMClassInfo* LCI = getClassInfo(classDef); |
| const Type* Ty = LCI->getStaticType(); |
| Ty = Ty->getContainedType(0); |
| varGV = new GlobalVariable(Ty, false, |
| GlobalValue::ExternalLinkage, |
| Constant::getNullValue(Ty), "", this); |
| |
| Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, |
| ptrType); |
| staticInstances.insert(std::make_pair(classDef, res)); |
| return res; |
| } else { |
| return I->second; |
| } |
| |
| } else { |
| void* obj = ((Class*)classDef)->getStaticInstance(); |
| if (!obj) { |
| 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(); |
| } |
| Constant* CI = ConstantInt::get(Type::Int64Ty, (uint64_t(obj))); |
| return ConstantExpr::getIntToPtr(CI, ptrType); |
| } |
| } |
| |
| Constant* JnjvmModule::getVirtualTable(Class* classDef) { |
| LLVMClassInfo* LCI = getClassInfo((Class*)classDef); |
| LCI->getVirtualType(); |
| if (staticCompilation) { |
| llvm::Constant* res = 0; |
| virtual_table_iterator End = virtualTables.end(); |
| virtual_table_iterator I = virtualTables.find(classDef); |
| if (I == End) { |
| |
| if (isCompiling(classDef)) { |
| makeVT(classDef); |
| } |
| |
| const ArrayType* ATy = dyn_cast<ArrayType>(VTType->getContainedType(0)); |
| const PointerType* PTy = dyn_cast<PointerType>(ATy->getContainedType(0)); |
| ATy = ArrayType::get(PTy, classDef->virtualTableSize); |
| GlobalVariable* varGV = new GlobalVariable(ATy, true, |
| GlobalValue::ExternalLinkage, |
| 0, "", this); |
| |
| res = ConstantExpr::getCast(Instruction::BitCast, varGV, VTType); |
| virtualTables.insert(std::make_pair(classDef, res)); |
| |
| if (isCompiling(classDef)) { |
| makeVT(classDef); |
| Function* Finalizer = ((Function**)classDef->virtualVT)[0]; |
| Function* Tracer = LCI->getVirtualTracer(); |
| Constant* C = CreateConstantFromVT(classDef->virtualVT, |
| classDef->virtualTableSize, |
| Finalizer, Tracer); |
| varGV->setInitializer(C); |
| } |
| |
| return res; |
| } else { |
| return I->second; |
| } |
| |
| } else { |
| assert(classDef->virtualVT && "Virtual VT not created"); |
| void* ptr = classDef->virtualVT; |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); |
| return ConstantExpr::getIntToPtr(CI, VTType); |
| } |
| } |
| |
| Constant* JnjvmModule::getNativeFunction(JavaMethod* meth, void* ptr) { |
| if (staticCompilation) { |
| llvm::Constant* 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(); |
| |
| varGV = new GlobalVariable(valPtrType, true, |
| GlobalValue::InternalLinkage, |
| Constant::getNullValue(valPtrType), "", this); |
| |
| nativeFunctions.insert(std::make_pair(meth, varGV)); |
| return varGV; |
| } else { |
| return I->second; |
| } |
| |
| } else { |
| LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature()); |
| const llvm::Type* valPtrType = LSI->getNativePtrType(); |
| |
| assert(ptr && "No native function given"); |
| |
| Constant* CI = ConstantInt::get(Type::Int64Ty, uint64_t(ptr)); |
| return ConstantExpr::getIntToPtr(CI, valPtrType); |
| } |
| } |
| |
| #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 { |
| VT = JavaObjectVT; |
| } |
| cl->virtualVT = VT; |
| 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) { |
| if (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; |
| } |
| |
| Constant* JnjvmModule::CreateConstantForJavaObject(CommonClass* cl) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaObjectType->getContainedType(0)); |
| |
| std::vector<Constant*> Elmts; |
| |
| // virtual table |
| if (cl->isClass()) { |
| Elmts.push_back(getVirtualTable(cl->asClass())); |
| } else { |
| ClassArray* clA = cl->asArrayClass(); |
| if (clA->baseClass()->isPrimitive()) { |
| Elmts.push_back(PrimitiveArrayVT); |
| } else { |
| Elmts.push_back(ReferenceArrayVT); |
| } |
| } |
| |
| // classof |
| Constant* Cl = getNativeClass(cl); |
| Constant* ClGEPs[2] = { constantZero, constantZero }; |
| Cl = ConstantExpr::getGetElementPtr(Cl, ClGEPs, 2); |
| |
| Elmts.push_back(Cl); |
| |
| // lock |
| Elmts.push_back(Constant::getNullValue(ptrType)); |
| |
| return ConstantStruct::get(STy, Elmts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromJavaClass(CommonClass* cl) { |
| Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass; |
| LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(javaClass); |
| const StructType* STy = |
| dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0)); |
| |
| std::vector<Constant*> Elmts; |
| |
| // JavaObject |
| Elmts.push_back(CreateConstantForJavaObject(cl)); |
| |
| // signers |
| Elmts.push_back(Constant::getNullValue(JavaObjectType)); |
| |
| // pd |
| Elmts.push_back(Constant::getNullValue(JavaObjectType)); |
| |
| // vmdata |
| Constant* Cl = getNativeClass(cl); |
| Cl = ConstantExpr::getCast(Instruction::BitCast, Cl, JavaObjectType); |
| Elmts.push_back(Cl); |
| |
| // constructor |
| Elmts.push_back(Constant::getNullValue(JavaObjectType)); |
| |
| return ConstantStruct::get(STy, Elmts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromJavaString(JavaString* str) { |
| Class* cl = (Class*)str->classOf; |
| LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); |
| const StructType* STy = |
| dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0)); |
| |
| std::vector<Constant*> Elmts; |
| |
| Elmts.push_back(CreateConstantForJavaObject(cl)); |
| |
| Constant* Array = getUTF8(str->value); |
| Constant* ObjGEPs[2] = { constantZero, constantZero }; |
| Array = ConstantExpr::getGetElementPtr(Array, ObjGEPs, 2); |
| Elmts.push_back(Array); |
| |
| Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->count)); |
| Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->cachedHashCode)); |
| Elmts.push_back(ConstantInt::get(Type::Int32Ty, str->offset)); |
| |
| return ConstantStruct::get(STy, Elmts); |
| } |
| |
| |
| Constant* JnjvmModule::CreateConstantFromCacheNode(CacheNode* CN) { |
| const StructType* STy = |
| dyn_cast<StructType>(CacheNodeType->getContainedType(0)); |
| |
| std::vector<Constant*> Elmts; |
| Elmts.push_back(Constant::getNullValue(STy->getContainedType(0))); |
| Elmts.push_back(Constant::getNullValue(STy->getContainedType(1))); |
| Elmts.push_back(Constant::getNullValue(STy->getContainedType(2))); |
| Elmts.push_back(getEnveloppe(CN->enveloppe)); |
| |
| return ConstantStruct::get(STy, Elmts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromEnveloppe(Enveloppe* val) { |
| |
| const StructType* STy = |
| dyn_cast<StructType>(EnveloppeType->getContainedType(0)); |
| const StructType* CNTy = |
| dyn_cast<StructType>(CacheNodeType->getContainedType(0)); |
| |
| std::vector<Constant*> Elmts; |
| |
| Constant* firstCache = CreateConstantFromCacheNode(val->firstCache); |
| Elmts.push_back(new GlobalVariable(CNTy, false, |
| GlobalValue::InternalLinkage, |
| firstCache, "", this)); |
| Elmts.push_back(getUTF8(val->methodName)); |
| Elmts.push_back(getUTF8(val->methodSign)); |
| |
| Elmts.push_back(Constant::getNullValue(Type::Int8Ty)); |
| Elmts.push_back(getNativeClass(val->classDef)); |
| Elmts.push_back(firstCache); |
| |
| return ConstantStruct::get(STy, Elmts); |
| |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromAttribut(Attribut& attribut) { |
| const StructType* STy = |
| dyn_cast<StructType>(AttributType->getContainedType(0)); |
| |
| |
| std::vector<Constant*> Elmts; |
| |
| // name |
| Elmts.push_back(getUTF8(attribut.name)); |
| |
| // start |
| Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.start)); |
| |
| // nbb |
| Elmts.push_back(ConstantInt::get(Type::Int32Ty, attribut.nbb)); |
| |
| return ConstantStruct::get(STy, Elmts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromCommonClass(CommonClass* cl) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaCommonClassType->getContainedType(0)); |
| |
| const ArrayType* ATy = ArrayType::get(JavaCommonClassType, cl->depth + 1); |
| |
| std::vector<Constant*> CommonClassElts; |
| std::vector<Constant*> TempElmts; |
| Constant* ClGEPs[2] = { constantZero, constantZero }; |
| |
| // display |
| for (uint32 i = 0; i <= cl->depth; ++i) { |
| Constant* Cl = getNativeClass(cl->display[i]); |
| if (Cl->getType() != JavaCommonClassType) |
| Cl = ConstantExpr::getGetElementPtr(Cl, ClGEPs, 2); |
| |
| TempElmts.push_back(Cl); |
| } |
| |
| Constant* display = ConstantArray::get(ATy, TempElmts); |
| TempElmts.clear(); |
| display = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| display, "", this); |
| display = ConstantExpr::getCast(Instruction::BitCast, display, |
| PointerType::getUnqual(JavaCommonClassType)); |
| CommonClassElts.push_back(display); |
| |
| // depth |
| CommonClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->depth)); |
| |
| // delegatee |
| ATy = dyn_cast<ArrayType>(STy->getContainedType(2)); |
| assert(ATy && "Malformed type"); |
| |
| Constant* TCM[1] = { getJavaClass(cl) }; |
| CommonClassElts.push_back(ConstantArray::get(ATy, TCM, 1)); |
| |
| // access |
| CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->access)); |
| |
| // interfaces |
| if (cl->nbInterfaces) { |
| for (uint32 i = 0; i < cl->nbInterfaces; ++i) { |
| TempElmts.push_back(getNativeClass(cl->interfaces[i])); |
| } |
| |
| ATy = ArrayType::get(JavaClassType, cl->nbInterfaces); |
| Constant* interfaces = ConstantArray::get(ATy, TempElmts); |
| interfaces = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| interfaces, "", this); |
| interfaces = ConstantExpr::getCast(Instruction::BitCast, interfaces, |
| PointerType::getUnqual(JavaClassType)); |
| |
| CommonClassElts.push_back(interfaces); |
| } else { |
| const Type* Ty = PointerType::getUnqual(JavaClassType); |
| CommonClassElts.push_back(Constant::getNullValue(Ty)); |
| } |
| |
| // nbInterfaces |
| CommonClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInterfaces)); |
| |
| // name |
| CommonClassElts.push_back(getUTF8(cl->name)); |
| |
| // super |
| if (cl->super) { |
| CommonClassElts.push_back(getNativeClass(cl->super)); |
| } else { |
| CommonClassElts.push_back(Constant::getNullValue(JavaClassType)); |
| } |
| |
| // classLoader: store the static initializer, it will be overriden once |
| // the class is loaded. |
| Constant* loader = ConstantExpr::getBitCast(StaticInitializer, ptrType); |
| CommonClassElts.push_back(loader); |
| |
| return ConstantStruct::get(STy, CommonClassElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromJavaField(JavaField& field) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaFieldType->getContainedType(0)); |
| |
| std::vector<Constant*> FieldElts; |
| std::vector<Constant*> TempElts; |
| |
| // signature |
| FieldElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // access |
| FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.access)); |
| |
| // name |
| FieldElts.push_back(getUTF8(field.name)); |
| |
| // type |
| FieldElts.push_back(getUTF8(field.type)); |
| |
| // attributs |
| if (field.nbAttributs) { |
| const ArrayType* ATy = ArrayType::get(AttributType->getContainedType(0), |
| field.nbAttributs); |
| for (uint32 i = 0; i < field.nbAttributs; ++i) { |
| TempElts.push_back(CreateConstantFromAttribut(field.attributs[i])); |
| } |
| |
| Constant* attributs = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| attributs, "", this); |
| attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, |
| AttributType); |
| |
| FieldElts.push_back(attributs); |
| } else { |
| FieldElts.push_back(Constant::getNullValue(AttributType)); |
| } |
| |
| // nbAttributs |
| FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.nbAttributs)); |
| |
| // classDef |
| FieldElts.push_back(getNativeClass(field.classDef)); |
| |
| // ptrOffset |
| FieldElts.push_back(ConstantInt::get(Type::Int32Ty, field.ptrOffset)); |
| |
| // num |
| FieldElts.push_back(ConstantInt::get(Type::Int16Ty, field.num)); |
| |
| //JInfo |
| FieldElts.push_back(Constant::getNullValue(ptrType)); |
| |
| return ConstantStruct::get(STy, FieldElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromJavaMethod(JavaMethod& method) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaMethodType->getContainedType(0)); |
| |
| std::vector<Constant*> MethodElts; |
| std::vector<Constant*> TempElts; |
| |
| // signature |
| MethodElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // access |
| MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.access)); |
| |
| // attributs |
| if (method.nbAttributs) { |
| const ArrayType* ATy = ArrayType::get(AttributType->getContainedType(0), |
| method.nbAttributs); |
| for (uint32 i = 0; i < method.nbAttributs; ++i) { |
| TempElts.push_back(CreateConstantFromAttribut(method.attributs[i])); |
| } |
| |
| Constant* attributs = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| attributs, "", this); |
| attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, |
| AttributType); |
| |
| MethodElts.push_back(attributs); |
| } else { |
| MethodElts.push_back(Constant::getNullValue(AttributType)); |
| } |
| |
| // nbAttributs |
| MethodElts.push_back(ConstantInt::get(Type::Int16Ty, method.nbAttributs)); |
| |
| // enveloppes |
| // already allocated by the JIT, don't reallocate them. |
| MethodElts.push_back(Constant::getNullValue(EnveloppeType)); |
| |
| // nbEnveloppes |
| // 0 because we're not allocating here. |
| MethodElts.push_back(ConstantInt::get(Type::Int16Ty, 0)); |
| |
| // classDef |
| MethodElts.push_back(getNativeClass(method.classDef)); |
| |
| // name |
| MethodElts.push_back(getUTF8(method.name)); |
| |
| // type |
| MethodElts.push_back(getUTF8(method.type)); |
| |
| // canBeInlined |
| MethodElts.push_back(ConstantInt::get(Type::Int8Ty, method.canBeInlined)); |
| |
| // code |
| if (isAbstract(method.access)) { |
| MethodElts.push_back(Constant::getNullValue(ptrType)); |
| } else { |
| LLVMMethodInfo* LMI = getMethodInfo(&method); |
| Function* func = LMI->getMethod(); |
| MethodElts.push_back(ConstantExpr::getCast(Instruction::BitCast, func, |
| ptrType)); |
| } |
| |
| // offset |
| MethodElts.push_back(ConstantInt::get(Type::Int32Ty, method.offset)); |
| |
| //JInfo |
| MethodElts.push_back(Constant::getNullValue(ptrType)); |
| |
| return ConstantStruct::get(STy, MethodElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromClassPrimitive(ClassPrimitive* cl) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaClassPrimitiveType->getContainedType(0)); |
| |
| std::vector<Constant*> ClassElts; |
| |
| // common class |
| ClassElts.push_back(CreateConstantFromCommonClass(cl)); |
| |
| // primSize |
| ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->primSize)); |
| |
| return ConstantStruct::get(STy, ClassElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromClassArray(ClassArray* cl) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaClassArrayType->getContainedType(0)); |
| |
| std::vector<Constant*> ClassElts; |
| Constant* ClGEPs[2] = { constantZero, constantZero }; |
| |
| // common class |
| ClassElts.push_back(CreateConstantFromCommonClass(cl)); |
| |
| // baseClass |
| Constant* Cl = getNativeClass(cl->baseClass()); |
| if (Cl->getType() != JavaCommonClassType) |
| Cl = ConstantExpr::getGetElementPtr(Cl, ClGEPs, 2); |
| |
| ClassElts.push_back(Cl); |
| |
| return ConstantStruct::get(STy, ClassElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromClass(Class* cl) { |
| const StructType* STy = |
| dyn_cast<StructType>(JavaClassType->getContainedType(0)); |
| |
| std::vector<Constant*> ClassElts; |
| std::vector<Constant*> TempElts; |
| |
| // common class |
| ClassElts.push_back(CreateConstantFromCommonClass(cl)); |
| |
| // virtualSize |
| ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualSize)); |
| |
| // virtualTable |
| ClassElts.push_back(getVirtualTable(cl)); |
| |
| // IsolateInfo |
| const ArrayType* ATy = dyn_cast<ArrayType>(STy->getContainedType(3)); |
| assert(ATy && "Malformed type"); |
| |
| const StructType* TCMTy = dyn_cast<StructType>(ATy->getContainedType(0)); |
| assert(TCMTy && "Malformed type"); |
| |
| TempElts.push_back(ConstantInt::get(Type::Int32Ty, ready)); |
| TempElts.push_back(getStaticInstance(cl)); |
| Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) }; |
| TempElts.clear(); |
| ClassElts.push_back(ConstantArray::get(ATy, CStr, 1)); |
| |
| // thinlock |
| ClassElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // virtualFields |
| if (cl->nbVirtualFields) { |
| ATy = ArrayType::get(JavaFieldType->getContainedType(0), cl->nbVirtualFields); |
| |
| for (uint32 i = 0; i < cl->nbVirtualFields; ++i) { |
| TempElts.push_back(CreateConstantFromJavaField(cl->virtualFields[i])); |
| } |
| |
| Constant* fields = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| fields = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| fields, "", this); |
| fields = ConstantExpr::getCast(Instruction::BitCast, fields, JavaFieldType); |
| ClassElts.push_back(fields); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(JavaFieldType)); |
| } |
| |
| // nbVirtualFields |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbVirtualFields)); |
| |
| // staticFields |
| if (cl->nbStaticFields) { |
| ATy = ArrayType::get(JavaFieldType->getContainedType(0), cl->nbStaticFields); |
| |
| for (uint32 i = 0; i < cl->nbStaticFields; ++i) { |
| TempElts.push_back(CreateConstantFromJavaField(cl->staticFields[i])); |
| } |
| |
| Constant* fields = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| fields = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| fields, "", this); |
| fields = ConstantExpr::getCast(Instruction::BitCast, fields, JavaFieldType); |
| ClassElts.push_back(fields); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(JavaFieldType)); |
| } |
| |
| // nbStaticFields |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticFields)); |
| |
| // virtualMethods |
| if (cl->nbVirtualMethods) { |
| ATy = ArrayType::get(JavaMethodType->getContainedType(0), |
| cl->nbVirtualMethods); |
| |
| for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) { |
| TempElts.push_back(CreateConstantFromJavaMethod(cl->virtualMethods[i])); |
| } |
| |
| Constant* methods = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| methods = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| methods, "", this); |
| methods = ConstantExpr::getCast(Instruction::BitCast, methods, |
| JavaMethodType); |
| ClassElts.push_back(methods); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(JavaMethodType)); |
| } |
| |
| // nbVirtualMethods |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbVirtualMethods)); |
| |
| // staticMethods |
| if (cl->nbStaticMethods) { |
| ATy = ArrayType::get(JavaMethodType->getContainedType(0), |
| cl->nbStaticMethods); |
| |
| for (uint32 i = 0; i < cl->nbStaticMethods; ++i) { |
| TempElts.push_back(CreateConstantFromJavaMethod(cl->staticMethods[i])); |
| } |
| |
| Constant* methods = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| methods = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| methods, "", this); |
| methods = ConstantExpr::getCast(Instruction::BitCast, methods, |
| JavaMethodType); |
| ClassElts.push_back(methods); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(JavaMethodType)); |
| } |
| |
| // nbStaticMethods |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbStaticMethods)); |
| |
| // ownerClass |
| ClassElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // bytes |
| ClassElts.push_back(Constant::getNullValue(JavaArrayUInt8Type)); |
| |
| // ctpInfo |
| ClassElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // attributs |
| if (cl->nbAttributs) { |
| ATy = ArrayType::get(AttributType->getContainedType(0), |
| cl->nbAttributs); |
| |
| for (uint32 i = 0; i < cl->nbAttributs; ++i) { |
| TempElts.push_back(CreateConstantFromAttribut(cl->attributs[i])); |
| } |
| |
| Constant* attributs = ConstantArray::get(ATy, TempElts); |
| TempElts.clear(); |
| attributs = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| attributs, "", this); |
| attributs = ConstantExpr::getCast(Instruction::BitCast, attributs, |
| AttributType); |
| ClassElts.push_back(attributs); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(AttributType)); |
| } |
| |
| // nbAttributs |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbAttributs)); |
| |
| // innerClasses |
| if (cl->nbInnerClasses) { |
| for (uint32 i = 0; i < cl->nbInnerClasses; ++i) { |
| TempElts.push_back(getNativeClass(cl->innerClasses[i])); |
| } |
| |
| ATy = ArrayType::get(JavaClassType, cl->nbInnerClasses); |
| Constant* innerClasses = ConstantArray::get(ATy, TempElts); |
| innerClasses = new GlobalVariable(ATy, true, GlobalValue::InternalLinkage, |
| innerClasses, "", this); |
| innerClasses = ConstantExpr::getCast(Instruction::BitCast, innerClasses, |
| PointerType::getUnqual(JavaClassType)); |
| |
| ClassElts.push_back(innerClasses); |
| } else { |
| const Type* Ty = PointerType::getUnqual(JavaClassType); |
| ClassElts.push_back(Constant::getNullValue(Ty)); |
| } |
| |
| // nbInnerClasses |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->nbInnerClasses)); |
| |
| // outerClass |
| if (cl->outerClass) { |
| ClassElts.push_back(getNativeClass(cl->outerClass)); |
| } else { |
| ClassElts.push_back(Constant::getNullValue(JavaClassType)); |
| } |
| |
| // innerAccess |
| ClassElts.push_back(ConstantInt::get(Type::Int16Ty, cl->innerAccess)); |
| |
| // innerOuterResolved |
| ClassElts.push_back(ConstantInt::get(Type::Int8Ty, cl->innerOuterResolved)); |
| |
| // virtualTableSize |
| ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->virtualTableSize)); |
| |
| // staticSize |
| ClassElts.push_back(ConstantInt::get(Type::Int32Ty, cl->staticSize)); |
| |
| // JInfo |
| ClassElts.push_back(Constant::getNullValue(ptrType)); |
| |
| // staticTracer |
| Function* F = makeTracer(cl, true); |
| const Type* FTy = STy->getContainedType(STy->getNumContainedTypes() - 1); |
| Constant* staticTracer = ConstantExpr::getCast(Instruction::BitCast, F, FTy); |
| ClassElts.push_back(staticTracer); |
| |
| return ConstantStruct::get(STy, ClassElts); |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromUTF8(const UTF8* val) { |
| std::vector<const Type*> Elemts; |
| const ArrayType* ATy = ArrayType::get(Type::Int16Ty, val->size); |
| Elemts.push_back(JavaObjectType->getContainedType(0)); |
| Elemts.push_back(pointerSizeType == Type::Int32Ty ? Type::Int32Ty : |
| Type::Int64Ty); |
| |
| Elemts.push_back(ATy); |
| |
| const StructType* STy = StructType::get(Elemts); |
| |
| std::vector<Constant*> Cts; |
| Cts.push_back(Constant::getNullValue(JavaObjectType->getContainedType(0))); |
| Cts.push_back(ConstantInt::get(pointerSizeType, val->size)); |
| |
| std::vector<Constant*> Vals; |
| for (sint32 i = 0; i < val->size; ++i) { |
| Vals.push_back(ConstantInt::get(Type::Int16Ty, val->elements[i])); |
| } |
| |
| Cts.push_back(ConstantArray::get(ATy, Vals)); |
| |
| return ConstantStruct::get(STy, Cts); |
| |
| } |
| |
| Constant* JnjvmModule::getUTF8(const UTF8* val) { |
| utf8_iterator End = utf8s.end(); |
| utf8_iterator I = utf8s.find(val); |
| if (I == End) { |
| Constant* C = CreateConstantFromUTF8(val); |
| GlobalVariable* varGV = new GlobalVariable(C->getType(), true, |
| GlobalValue::ExternalLinkage, |
| C, "", this); |
| |
| Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV, |
| UTF8Type); |
| utf8s.insert(std::make_pair(val, res)); |
| |
| return res; |
| } else { |
| return I->second; |
| } |
| } |
| |
| Constant* JnjvmModule::CreateConstantFromVT(VirtualTable* VT, uint32 size, |
| Function* Finalizer, |
| Function* Tracer) { |
| const ArrayType* ATy = dyn_cast<ArrayType>(VTType->getContainedType(0)); |
| const PointerType* PTy = dyn_cast<PointerType>(ATy->getContainedType(0)); |
| ATy = ArrayType::get(PTy, size); |
| |
| ConstantPointerNull* N = ConstantPointerNull::get(PTy); |
| std::vector<Constant*> Elemts; |
| |
| // Destructor |
| Elemts.push_back(Finalizer ? |
| ConstantExpr::getCast(Instruction::BitCast, Finalizer, PTy) : N); |
| Elemts.push_back(N); // Delete |
| |
| // Tracer |
| Elemts.push_back(Tracer ? |
| ConstantExpr::getCast(Instruction::BitCast, Tracer, PTy) : N); |
| Elemts.push_back(N); // Printer |
| Elemts.push_back(N); // Hashcode |
| |
| for (uint32 i = VT_NB_FUNCS; i < size; ++i) { |
| Function* F = ((Function**)VT)[i]; |
| JavaMethod* meth = LLVMMethodInfo::get(F); |
| if (isAbstract(meth->access)) { |
| Elemts.push_back(Constant::getNullValue(PTy)); |
| } else { |
| Elemts.push_back(ConstantExpr::getCast(Instruction::BitCast, F, PTy)); |
| } |
| } |
| |
| Constant* Array = ConstantArray::get(ATy, Elemts); |
| |
| return Array; |
| } |
| |
| void JnjvmModule::makeVT(Class* cl) { |
| |
| VirtualTable* VT = 0; |
| #ifdef WITHOUT_VTABLE |
| mvm::BumpPtrAllocator& allocator = cl->classLoader->allocator; |
| VT = (VirtualTable*)allocator.Allocate(VT_SIZE); |
| memcpy(VT, JavaObjectVT, VT_SIZE); |
| cl->virtualVT = VT; |
| #else |
| if (cl->super) { |
| if (isStaticCompiling() && !cl->super->virtualVT) { |
| makeVT(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 && !staticCompilation) { |
| #ifdef ISOLATE_SHARING |
| ((void**)VT)[0] = 0; |
| #else |
| JnjvmClassLoader* loader = cl->classLoader; |
| Function* func = loader->getModuleProvider()->parseFunction(&meth); |
| if (!cl->super) { |
| meth.canBeInlined = true; |
| ((void**)VT)[0] = 0; |
| } else { |
| 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)) { |
| ClassArray::initialiseVT(cl); |
| } |
| #endif |
| |
| #ifdef WITH_TRACER |
| llvm::Function* func = makeTracer(cl, false); |
| |
| 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 |
| } |
| |
| |
| const Type* LLVMClassInfo::getVirtualType() { |
| if (!virtualType) { |
| std::vector<const llvm::Type*> fields; |
| |
| if (classDef->super && classDef->super->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 + 1; |
| 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()) { |
| Mod->makeVT((Class*)classDef); |
| } |
| |
| } |
| |
| return virtualType; |
| } |
| |
| const Type* LLVMClassInfo::getStaticType() { |
| |
| if (!staticType) { |
| Class* cl = (Class*)classDef; |
| std::vector<const llvm::Type*> fields; |
| |
| 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); |
| } |
| |
| uint64 size = mvm::MvmModule::getTypeSize(structType); |
| cl->staticSize = size; |
| |
| JnjvmModule* Mod = cl->classLoader->getModule(); |
| if (!Mod->isStaticCompiling()) { |
| Function* F = Mod->makeTracer(cl, true); |
| cl->staticTracer = (void (*)(void*)) (uintptr_t) |
| Mod->executionEngine->getPointerToFunction(F); |
| F->deleteBody(); |
| } |
| } |
| return staticType; |
| } |
| |
| |
| Value* LLVMClassInfo::getVirtualSize() { |
| if (!virtualSizeConstant) { |
| getVirtualType(); |
| assert(classDef->virtualSize && "Zero size for a class?"); |
| 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 + 1 + |
| ((mnlen + clen + mtlen) << 1)); |
| |
| methodDef->jniConsFromMethOverloaded(buf + 1); |
| memcpy(buf, "JnJVM", 5); |
| |
| 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); |
| } |
| |
| offsetConstant = ConstantInt::get(Type::Int32Ty, fieldDef->num); |
| } |
| 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; |
| uint32 size = signature->nbArguments; |
| Typedef* const* arguments = signature->getArgumentsType(); |
| |
| llvmArgs.push_back(JnjvmModule::JavaObjectType); |
| |
| for (uint32 i = 0; i < size; ++i) { |
| Typedef* type = arguments[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->getReturnType()); |
| 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; |
| uint32 size = signature->nbArguments; |
| Typedef* const* arguments = signature->getArgumentsType(); |
| |
| for (uint32 i = 0; i < size; ++i) { |
| Typedef* type = arguments[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->getReturnType()); |
| 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; |
| uint32 size = signature->nbArguments; |
| Typedef* const* arguments = signature->getArgumentsType(); |
| |
| llvmArgs.push_back(mvm::MvmModule::ptrType); // JNIEnv |
| llvmArgs.push_back(JnjvmModule::JavaObjectType); // Class |
| |
| for (uint32 i = 0; i < size; ++i) { |
| Typedef* type = arguments[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->getReturnType()); |
| nativeType = FunctionType::get(LAI.llvmType, llvmArgs, false); |
| } |
| return nativeType; |
| } |
| |
| |
| Function* LLVMSignatureInfo::createFunctionCallBuf(bool virt) { |
| |
| std::vector<Value*> Args; |
| |
| JnjvmModule* Mod = signature->initialLoader->getModule(); |
| const char* name = 0; |
| if (Mod->isStaticCompiling()) { |
| name = virt ? signature->printString("virtual_buf") : |
| signature->printString("static_buf"); |
| } else { |
| name = ""; |
| } |
| |
| Function* res = Function::Create(virt ? getVirtualBufType() : |
| getStaticBufType(), |
| GlobalValue::ExternalLinkage, name, Mod); |
| |
| 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; |
| |
| Typedef* const* arguments = signature->getArgumentsType(); |
| for (uint32 i = 0; i < signature->nbArguments; ++i) { |
| |
| LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(arguments[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; |
| |
| JnjvmModule* Mod = signature->initialLoader->getModule(); |
| const char* name = 0; |
| if (Mod->isStaticCompiling()) { |
| name = virt ? signature->printString("virtual_ap") : |
| signature->printString("static_ap"); |
| } else { |
| name = ""; |
| } |
| |
| Function* res = Function::Create(virt ? getVirtualBufType() : |
| getStaticBufType(), |
| GlobalValue::ExternalLinkage, name, Mod); |
| |
| 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; |
| |
| Typedef* const* arguments = signature->getArgumentsType(); |
| for (uint32 i = 0; i < signature->nbArguments; ++i) { |
| LLVMAssessorInfo& LAI = JnjvmModule::getTypedefInfo(arguments[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->getReturnType()); |
| 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->getReturnType()); |
| 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)); |
| if (!signature->initialLoader->getModule()->isStaticCompiling()) |
| // Now that it's compiled, we don't need the IR anymore |
| 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)); |
| if (!signature->initialLoader->getModule()->isStaticCompiling()) |
| // Now that it's compiled, we don't need the IR anymore |
| 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)); |
| if (!signature->initialLoader->getModule()->isStaticCompiling()) |
| // Now that it's compiled, we don't need the IR anymore |
| 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)); |
| if (!signature->initialLoader->getModule()->isStaticCompiling()) |
| // Now that it's compiled, we don't need the IR anymore |
| 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 = PointerType::getUnqual(module->getTypeByName("VT")); |
| |
| #ifdef ISOLATE_SHARING |
| JnjvmType = |
| PointerType::getUnqual(module->getTypeByName("Jnjvm")); |
| #endif |
| ConstantPoolType = ptrPtrType; |
| |
| JavaObjectType = |
| PointerType::getUnqual(module->getTypeByName("JavaObject")); |
| |
| JavaArrayType = |
| PointerType::getUnqual(module->getTypeByName("JavaArray")); |
| |
| JavaCommonClassType = |
| PointerType::getUnqual(module->getTypeByName("JavaCommonClass")); |
| JavaClassPrimitiveType = |
| PointerType::getUnqual(module->getTypeByName("JavaClassPrimitive")); |
| JavaClassArrayType = |
| PointerType::getUnqual(module->getTypeByName("JavaClassArray")); |
| 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")); |
| |
| JavaFieldType = |
| PointerType::getUnqual(module->getTypeByName("JavaField")); |
| JavaMethodType = |
| PointerType::getUnqual(module->getTypeByName("JavaMethod")); |
| UTF8Type = |
| PointerType::getUnqual(module->getTypeByName("UTF8")); |
| AttributType = |
| PointerType::getUnqual(module->getTypeByName("Attribut")); |
| JavaThreadType = |
| PointerType::getUnqual(module->getTypeByName("JavaThread")); |
| |
| #ifdef WITH_TRACER |
| MarkAndTraceType = module->getFunction("MarkAndTrace")->getFunctionType(); |
| #endif |
| |
| JavaObjectNullConstant = Constant::getNullValue(JnjvmModule::JavaObjectType); |
| MaxArraySizeConstant = ConstantInt::get(Type::Int32Ty, |
| JavaArray::MaxArraySize); |
| 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; |
| |
| OffsetDisplayInClassConstant = mvm::MvmModule::constantZero; |
| OffsetDepthInClassConstant = mvm::MvmModule::constantOne; |
| |
| OffsetObjectSizeInClassConstant = mvm::MvmModule::constantOne; |
| OffsetVTInClassConstant = mvm::MvmModule::constantTwo; |
| OffsetTaskClassMirrorInClassConstant = mvm::MvmModule::constantThree; |
| OffsetStaticInstanceInTaskClassMirrorConstant = mvm::MvmModule::constantOne; |
| OffsetStatusInTaskClassMirrorConstant = mvm::MvmModule::constantZero; |
| |
| ClassReadyConstant = ConstantInt::get(Type::Int32Ty, ready); |
| |
| |
| if (staticCompilation) { |
| const Type* ATy = VTType->getContainedType(0); |
| PrimitiveArrayVT = new GlobalVariable(ATy, true, |
| GlobalValue::ExternalLinkage, |
| 0, "JavaArrayVT", this); |
| |
| ReferenceArrayVT = new GlobalVariable(ATy, true, |
| GlobalValue::ExternalLinkage, |
| 0, "ArrayObjectVT", this); |
| |
| |
| |
| ATy = JavaClassArrayType->getContainedType(0); |
| GlobalVariable* varGV = 0; |
| |
| #define PRIMITIVE_ARRAY(name) \ |
| varGV = new GlobalVariable(ATy, true, GlobalValue::ExternalLinkage, \ |
| 0, #name, this); \ |
| arrayClasses.insert(std::make_pair(&name, varGV)); |
| |
| PRIMITIVE_ARRAY(ArrayOfBool) |
| PRIMITIVE_ARRAY(ArrayOfByte) |
| PRIMITIVE_ARRAY(ArrayOfChar) |
| PRIMITIVE_ARRAY(ArrayOfShort) |
| PRIMITIVE_ARRAY(ArrayOfInt) |
| PRIMITIVE_ARRAY(ArrayOfFloat) |
| PRIMITIVE_ARRAY(ArrayOfDouble) |
| PRIMITIVE_ARRAY(ArrayOfLong) |
| |
| #undef PRIMITIVE_ARRAY |
| |
| std::vector<const llvm::Type*> llvmArgs; |
| llvmArgs.push_back(ptrType); // class loader. |
| const FunctionType* FTy = FunctionType::get(Type::VoidTy, llvmArgs, false); |
| |
| StaticInitializer = Function::Create(FTy, GlobalValue::InternalLinkage, |
| "Init", this); |
| |
| llvmArgs.clear(); |
| llvmArgs.push_back(JavaClassType); |
| llvmArgs.push_back(ptrType); |
| |
| FTy = FunctionType::get(ptrType, llvmArgs, false); |
| |
| NativeLoader = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| "vmjcNativeLoader", this); |
| |
| } else { |
| PrimitiveArrayVT = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, |
| uint64(JavaArrayVT)), |
| VTType); |
| |
| ReferenceArrayVT = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, |
| uint64(ArrayObjectVT)), |
| VTType); |
| } |
| |
| LLVMAssessorInfo::initialise(); |
| } |
| |
| Constant* JnjvmModule::getReferenceArrayVT() { |
| return ReferenceArrayVT; |
| } |
| |
| Constant* JnjvmModule::getPrimitiveArrayVT() { |
| return PrimitiveArrayVT; |
| } |
| |
| void JnjvmModule::setMethod(JavaMethod* meth, void* ptr, const char* name) { |
| Function* func = getMethodInfo(meth)->getMethod(); |
| func->setName(name); |
| assert(ptr && "No value given"); |
| executionEngine->addGlobalMapping(func, ptr); |
| func->setLinkage(GlobalValue::ExternalLinkage); |
| } |
| |
| void JnjvmModule::printStats() { |
| fprintf(stderr, "----------------- Info from the module -----------------\n"); |
| fprintf(stderr, "Number of native classes : %llu\n", |
| (unsigned long long int) nativeClasses.size()); |
| fprintf(stderr, "Number of Java classes : %llu\n", |
| (unsigned long long int) javaClasses.size()); |
| fprintf(stderr, "Number of external array classes : %llu\n", |
| (unsigned long long int) arrayClasses.size()); |
| fprintf(stderr, "Number of virtual tables : %llu\n", |
| (unsigned long long int) virtualTables.size()); |
| fprintf(stderr, "Number of static instances : %llu\n", |
| (unsigned long long int) staticInstances.size()); |
| fprintf(stderr, "Number of constant pools : %llu\n", |
| (unsigned long long int) constantPools.size()); |
| fprintf(stderr, "Number of strings : %llu\n", |
| (unsigned long long int) strings.size()); |
| fprintf(stderr, "Number of enveloppes : %llu\n", |
| (unsigned long long int) enveloppes.size()); |
| fprintf(stderr, "Number of native functions : %llu\n", |
| (unsigned long long int) nativeFunctions.size()); |
| } |
| |
| |
| Function* 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"); |
| RuntimeDelegateeFunction = module->getFunction("jnjvmRuntimeDelegatee"); |
| 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"); |
| JavaArrayTracerFunction = module->getFunction("JavaArrayTracer"); |
| ArrayObjectTracerFunction = module->getFunction("ArrayObjectTracer"); |
| #endif |
| |
| #ifndef WITHOUT_VTABLE |
| VirtualLookupFunction = module->getFunction("vtableLookup"); |
| #endif |
| |
| GetLockFunction = module->getFunction("getLock"); |
| |
| addTypeName("JavaObject", JavaObjectType); |
| addTypeName("JavaArray", JavaArrayType); |
| addTypeName("JavaCommonClass", JavaCommonClassType); |
| addTypeName("JavaClass", JavaClassType); |
| addTypeName("JavaClassPrimitive", JavaClassPrimitiveType); |
| addTypeName("JavaClassArray", JavaClassArrayType); |
| addTypeName("ArrayUInt8", JavaArrayUInt8Type); |
| addTypeName("ArraySInt8", JavaArraySInt8Type); |
| addTypeName("ArrayUInt16", JavaArrayUInt16Type); |
| addTypeName("ArraySInt16", JavaArraySInt16Type); |
| addTypeName("ArraySInt32", JavaArraySInt32Type); |
| addTypeName("ArrayLong", JavaArrayLongType); |
| addTypeName("ArrayFloat", JavaArrayFloatType); |
| addTypeName("ArrayDouble", JavaArrayDoubleType); |
| addTypeName("ArrayObject", JavaArrayObjectType); |
| addTypeName("CacheNode", CacheNodeType); |
| addTypeName("Enveloppe", EnveloppeType); |
| } |
| |
| 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, Value* Where) { |
| if (staticCompilation) { |
| llvm::Constant* 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; |
| } |
| if (BasicBlock* BB = dyn_cast<BasicBlock>(Where)) { |
| return new LoadInst(varGV, "", BB); |
| } else { |
| assert(dyn_cast<Instruction>(Where) && "Wrong use of module"); |
| return new LoadInst(varGV, "", dyn_cast<Instruction>(Where)); |
| } |
| } else { |
| ConstantInt* CI = ConstantInt::get(Type::Int64Ty, uint64_t(isolate)); |
| return ConstantExpr::getIntToPtr(CI, ptrType); |
| } |
| } |
| #endif |
| |
| void JnjvmModule::CreateStaticInitializer() { |
| |
| // Set the linkage of all functions to External, so that the printer does |
| // not complain. |
| for (Module::iterator i = begin(), e = end(); i != e; ++i) { |
| i->setLinkage(GlobalValue::ExternalLinkage); |
| } |
| |
| std::vector<const llvm::Type*> llvmArgs; |
| llvmArgs.push_back(ptrType); // class loader |
| llvmArgs.push_back(JavaCommonClassType); // cl |
| const FunctionType* FTy = FunctionType::get(Type::VoidTy, llvmArgs, false); |
| |
| Function* AddClass = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| "vmjcAddPreCompiledClass", this); |
| |
| llvmArgs.clear(); |
| llvmArgs.push_back(ptrType); // class loader |
| llvmArgs.push_back(PointerType::getUnqual(JavaClassArrayType)); // array ptr |
| llvmArgs.push_back(UTF8Type); // name |
| FTy = FunctionType::get(Type::VoidTy, llvmArgs, false); |
| |
| Function* GetClassArray = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| "vmjcGetClassArray", this); |
| |
| llvmArgs.clear(); |
| llvmArgs.push_back(ptrType); // class loader |
| llvmArgs.push_back(UTF8Type); // name |
| FTy = FunctionType::get(Type::VoidTy, llvmArgs, false); |
| |
| Function* LoadClass = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| "vmjcLoadClass", this); |
| |
| BasicBlock* currentBlock = BasicBlock::Create("enter", StaticInitializer); |
| Function::arg_iterator loader = StaticInitializer->arg_begin(); |
| |
| Value* Args[3]; |
| // If we have defined some strings. |
| if (strings.begin() != strings.end()) { |
| llvmArgs.clear(); |
| llvmArgs.push_back(ptrType); // class loader |
| llvmArgs.push_back(strings.begin()->second->getType()); // val |
| FTy = FunctionType::get(Type::VoidTy, llvmArgs, false); |
| |
| Function* AddString = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| "vmjcAddString", this); |
| |
| |
| |
| for (string_iterator i = strings.begin(), e = strings.end(); i != e; ++i) { |
| Args[0] = loader; |
| Args[1] = i->second; |
| CallInst::Create(AddString, Args, Args + 2, "", currentBlock); |
| } |
| } |
| |
| for (native_class_iterator i = nativeClasses.begin(), |
| e = nativeClasses.end(); i != e; ++i) { |
| if (isCompiling(i->first)) { |
| Args[0] = loader; |
| Args[1] = ConstantExpr::getBitCast(i->second, JavaCommonClassType); |
| CallInst::Create(AddClass, Args, Args + 2, "", currentBlock); |
| } |
| } |
| |
| for (native_class_iterator i = nativeClasses.begin(), |
| e = nativeClasses.end(); i != e; ++i) { |
| if (!isCompiling(i->first)) { |
| Args[0] = loader; |
| Args[1] = getUTF8(i->first->name); |
| CallInst::Create(LoadClass, Args, Args + 2, "", currentBlock); |
| } |
| } |
| |
| for (array_class_iterator i = arrayClasses.begin(), |
| e = arrayClasses.end(); i != e; ++i) { |
| if (!(i->first->baseClass()->isPrimitive())) { |
| Args[0] = loader; |
| Args[1] = i->second; |
| Args[2] = getUTF8(i->first->name); |
| CallInst::Create(GetClassArray, Args, Args + 3, "", currentBlock); |
| } |
| } |
| |
| |
| ReturnInst::Create(currentBlock); |
| } |