blob: 8b5acde5043dbc13a09f7884ffe7aa3524d8b803 [file] [log] [blame]
//===----- JavaAOTCompiler.cpp - Support for Ahead of Time Compiler --------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/BasicBlock.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "mvm/Threads/Thread.h"
#include "j3/J3Intrinsics.h"
#include "j3/JavaAOTCompiler.h"
#include "j3/JavaJITCompiler.h"
#include "JavaArray.h"
#include "JavaConstantPool.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "Reader.h"
#include "Zip.h"
#include <cstdio>
using namespace j3;
using namespace llvm;
bool JavaAOTCompiler::isCompiling(const CommonClass* cl) const {
if (cl->isClass()) {
// A class is being static compiled if owner class is not null.
return cl->asClass()->getOwnerClass() != 0;
} else if (cl->isArray()) {
// Only compile an aray if we are compiling rt.jar.
return compileRT;
} else if (cl->isPrimitive() && compileRT) {
return true;
} else {
return false;
}
}
Constant* JavaAOTCompiler::getNativeClass(CommonClass* classDef) {
if (classDef->isClass() || isCompiling(classDef) || assumeCompiled) {
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 = JavaIntrinsics.JavaClassArrayType->getContainedType(0);
} else if (classDef->isPrimitive()) {
Ty = JavaIntrinsics.JavaClassPrimitiveType->getContainedType(0);
} else {
Ty = JavaIntrinsics.JavaClassType->getContainedType(0);
}
GlobalVariable* varGV =
new GlobalVariable(*getLLVMModule(), Ty, false,
GlobalValue::ExternalLinkage, 0,
UTF8Buffer(classDef->name).toCompileName()->cString());
nativeClasses.insert(std::make_pair(classDef, varGV));
if (classDef->isClass() && isCompiling(classDef)) {
Constant* C = CreateConstantFromClass(classDef->asClass());
varGV->setInitializer(C);
} else if (classDef->isArray()) {
Constant* C = CreateConstantFromClassArray(classDef->asArrayClass());
varGV->setInitializer(C);
} else if (classDef->isPrimitive()) {
Constant* C =
CreateConstantFromClassPrimitive(classDef->asPrimitiveClass());
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(classDef->asArrayClass());
if (I == End) {
const llvm::Type* Ty = JavaIntrinsics.JavaClassArrayType;
Module& Mod = *getLLVMModule();
GlobalVariable* varGV =
new GlobalVariable(Mod, Ty, false, GlobalValue::InternalLinkage,
Constant::getNullValue(Ty),
UTF8Buffer(classDef->name).toCompileName()->cString());
arrayClasses.insert(std::make_pair(classDef->asArrayClass(), varGV));
return varGV;
} else {
return I->second;
}
} else {
assert(0 && "Implement me");
}
return 0;
}
Constant* JavaAOTCompiler::getConstantPool(JavaConstantPool* ctp) {
llvm::Constant* varGV = 0;
constant_pool_iterator End = constantPools.end();
constant_pool_iterator I = constantPools.find(ctp);
if (I == End) {
const Type* Ty = JavaIntrinsics.ConstantPoolType->getContainedType(0);
Module& Mod = *getLLVMModule();
varGV = new GlobalVariable(Mod, Ty, false,
GlobalValue::InternalLinkage,
Constant::getNullValue(Ty), "");
constantPools.insert(std::make_pair(ctp, varGV));
return varGV;
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::getMethodInClass(JavaMethod* meth) {
Class* cl = meth->classDef;
Constant* MOffset = 0;
Constant* Array = 0;
for (uint32 i = 0; i < cl->nbVirtualMethods + cl->nbStaticMethods; ++i) {
if (&cl->virtualMethods[i] == meth) {
MOffset = ConstantInt::get(Type::getInt32Ty(getLLVMContext()), i);
break;
}
}
assert(MOffset && "No offset for method");
method_iterator SI = virtualMethods.find(cl);
if (SI != virtualMethods.end()) {
Array = SI->second;
assert(Array && "No array in class");
} else {
std::string name(UTF8Buffer(cl->name).toCompileName()->cString());
name += "_VirtualMethods";
Module& Mod = *getLLVMModule();
const Type* ATy =
ArrayType::get(JavaIntrinsics.JavaMethodType->getContainedType(0),
cl->nbVirtualMethods + cl->nbStaticMethods);
Array = new GlobalVariable(Mod, ATy, false, GlobalValue::ExternalLinkage,
0, name);
virtualMethods.insert(std::make_pair(cl, Array));
}
Constant* GEPs[2] = { getIntrinsics()->constantZero, MOffset };
return ConstantExpr::getGetElementPtr(Array, GEPs, 2);
}
Constant* JavaAOTCompiler::getString(JavaString* str) {
string_iterator SI = strings.find(str);
if (SI != strings.end()) {
return SI->second;
} else {
assert(str && "No string given");
LLVMClassInfo* LCI = getClassInfo(str->getClass()->asClass());
const llvm::Type* Ty = LCI->getVirtualType();
Module& Mod = *getLLVMModule();
GlobalVariable* varGV =
new GlobalVariable(Mod, Ty->getContainedType(0), false,
GlobalValue::InternalLinkage, 0, "");
Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV,
JavaIntrinsics.JavaObjectType);
strings.insert(std::make_pair(str, res));
Constant* C = CreateConstantFromJavaString(str);
varGV->setInitializer(C);
return res;
}
}
Constant* JavaAOTCompiler::getStringPtr(JavaString** str) {
fprintf(stderr, "Implement me");
abort();
}
Constant* JavaAOTCompiler::getJavaClass(CommonClass* cl) {
java_class_iterator End = javaClasses.end();
java_class_iterator I = javaClasses.find(cl);
if (I == End) {
final_object_iterator End = finalObjects.end();
final_object_iterator I = finalObjects.find(cl->delegatee[0]);
if (I == End) {
Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass;
LLVMClassInfo* LCI = getClassInfo(javaClass);
const llvm::Type* Ty = LCI->getVirtualType();
Module& Mod = *getLLVMModule();
GlobalVariable* varGV =
new GlobalVariable(Mod, Ty->getContainedType(0), false,
GlobalValue::InternalLinkage, 0, "");
Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV,
JavaIntrinsics.JavaObjectType);
javaClasses.insert(std::make_pair(cl, res));
varGV->setInitializer(CreateConstantFromJavaClass(cl));
return res;
} else {
return I->second;
}
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::getJavaClassPtr(CommonClass* cl) {
#ifdef ISOLATE
abort();
return 0;
#else
// Make sure it's emitted.
getJavaClass(cl);
Constant* Cl = getNativeClass(cl);
Cl = ConstantExpr::getBitCast(Cl, JavaIntrinsics.JavaCommonClassType);
Constant* GEP[2] = { getIntrinsics()->constantZero,
getIntrinsics()->constantZero };
Constant* TCMArray = ConstantExpr::getGetElementPtr(Cl, GEP, 2);
Constant* GEP2[2] = { getIntrinsics()->constantZero,
getIntrinsics()->constantZero };
Constant* Ptr = ConstantExpr::getGetElementPtr(TCMArray, GEP2, 2);
return Ptr;
#endif
}
JavaObject* JavaAOTCompiler::getFinalObject(llvm::Value* obj) {
if (Constant* CI = dyn_cast<Constant>(obj)) {
reverse_final_object_iterator End = reverseFinalObjects.end();
reverse_final_object_iterator I = reverseFinalObjects.find(CI);
if (I != End) return I->second;
}
return 0;
}
Constant* JavaAOTCompiler::HandleMagic(JavaObject* obj, CommonClass* objCl) {
static const UTF8* AddressArray = objCl->classLoader->asciizConstructUTF8("org/vmmagic/unboxed/AddressArray");
static const UTF8* WordArray = objCl->classLoader->asciizConstructUTF8("org/vmmagic/unboxed/WordArray");
static const UTF8* ExtentArray = objCl->classLoader->asciizConstructUTF8("org/vmmagic/unboxed/ExtentArray");
static const UTF8* ObjectReferenceArray = objCl->classLoader->asciizConstructUTF8("org/vmmagic/unboxed/ObjectReferenceArray");
static const UTF8* OffsetArray = objCl->classLoader->asciizConstructUTF8("org/vmmagic/unboxed/OffsetArray");
const UTF8* name = objCl->name;
if (name->equals(AddressArray) || name->equals(WordArray) ||
name->equals(ExtentArray) || name->equals(ObjectReferenceArray) ||
name->equals(OffsetArray)) {
intptr_t* realObj = (intptr_t*)obj;
intptr_t size = realObj[0];
const ArrayType* ATy = ArrayType::get(JavaIntrinsics.JavaObjectType,
size + 1);
std::vector<Constant*> Vals;
for (sint32 i = 0; i < size + 1; ++i) {
Constant* CI = ConstantInt::get(Type::getInt64Ty(getLLVMContext()),
uint64_t(realObj[i]));
CI = ConstantExpr::getIntToPtr(CI, JavaIntrinsics.JavaObjectType);
Vals.push_back(CI);
}
Constant* CA = ConstantArray::get(ATy, Vals);
GlobalVariable* varGV = new GlobalVariable(*getLLVMModule(), CA->getType(),
false,
GlobalValue::InternalLinkage,
CA, "");
return ConstantExpr::getBitCast(varGV, JavaIntrinsics.JavaObjectType);
} else {
Constant* CI = ConstantInt::get(Type::getInt64Ty(getLLVMContext()),
uint64_t(obj));
CI = ConstantExpr::getIntToPtr(CI, JavaIntrinsics.JavaObjectType);
return CI;
}
}
Constant* JavaAOTCompiler::getFinalObject(JavaObject* obj, CommonClass* objCl) {
llvm::GlobalVariable* varGV = 0;
final_object_iterator End = finalObjects.end();
final_object_iterator I = finalObjects.find(obj);
if (I == End) {
if (mvm::Collector::begOf(obj)) {
const Type* Ty = 0;
CommonClass* cl = obj->getClass();
if (cl->isArray()) {
Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls;
CommonClass* subClass = cl->asArrayClass()->baseClass();
if (subClass->isPrimitive()) {
if (subClass == upcalls->OfBool) {
Ty = Type::getInt8Ty(getLLVMContext());
} else if (subClass == upcalls->OfByte) {
Ty = Type::getInt8Ty(getLLVMContext());
} else if (subClass == upcalls->OfShort) {
Ty = Type::getInt16Ty(getLLVMContext());
} else if (subClass == upcalls->OfChar) {
Ty = Type::getInt16Ty(getLLVMContext());
} else if (subClass == upcalls->OfInt) {
Ty = Type::getInt32Ty(getLLVMContext());
} else if (subClass == upcalls->OfFloat) {
Ty = Type::getFloatTy(getLLVMContext());
} else if (subClass == upcalls->OfLong) {
Ty = Type::getInt64Ty(getLLVMContext());
} else if (subClass == upcalls->OfDouble) {
Ty = Type::getDoubleTy(getLLVMContext());
} else {
abort();
}
} else {
Ty = JavaIntrinsics.JavaObjectType;
}
std::vector<const Type*> Elemts;
const ArrayType* ATy = ArrayType::get(Ty, ((JavaArray*)obj)->size);
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
Ty = StructType::get(getLLVMModule()->getContext(), Elemts);
} else {
LLVMClassInfo* LCI = getClassInfo(cl->asClass());
Ty = LCI->getVirtualType()->getContainedType(0);
}
Module& Mod = *getLLVMModule();
// Set as External, so that inlining MMTk code works.
varGV = new GlobalVariable(Mod, Ty, false, GlobalValue::ExternalLinkage,
0, "finalObject");
Constant* C = ConstantExpr::getBitCast(varGV,
JavaIntrinsics.JavaObjectType);
finalObjects.insert(std::make_pair(obj, C));
reverseFinalObjects.insert(std::make_pair(C, obj));
varGV->setInitializer(CreateConstantFromJavaObject(obj));
return C;
} else {
Constant* CI = HandleMagic(obj, objCl);
finalObjects.insert(std::make_pair(obj, CI));
return CI;
}
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::CreateConstantFromStaticInstance(Class* cl) {
LLVMClassInfo* LCI = getClassInfo(cl);
const Type* Ty = LCI->getStaticType();
const StructType* STy = dyn_cast<StructType>(Ty->getContainedType(0));
std::vector<Constant*> Elts;
for (uint32 i = 0; i < cl->nbStaticFields; ++i) {
JavaField& field = cl->staticFields[i];
const Typedef* type = field.getSignature();
LLVMAssessorInfo& LAI = getTypedefInfo(type);
const Type* Ty = LAI.llvmType;
Attribut* attribut = field.lookupAttribut(Attribut::constantAttribut);
if (!attribut) {
void* obj = cl->getStaticInstance();
if (obj) {
if (type->isPrimitive()) {
const PrimitiveTypedef* prim = (const PrimitiveTypedef*)type;
if (prim->isBool() || prim->isByte()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt8Ty(getLLVMContext()),
field.getInt8Field(obj));
Elts.push_back(CI);
} else if (prim->isShort() || prim->isChar()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt16Ty(getLLVMContext()),
field.getInt16Field(obj));
Elts.push_back(CI);
} else if (prim->isInt()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt32Ty(getLLVMContext()),
field.getInt32Field(obj));
Elts.push_back(CI);
} else if (prim->isLong()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt64Ty(getLLVMContext()),
field.getLongField(obj));
Elts.push_back(CI);
} else if (prim->isFloat()) {
Constant* CF = ConstantFP::get(
Type::getFloatTy(getLLVMContext()),
field.getFloatField(obj));
Elts.push_back(CF);
} else if (prim->isDouble()) {
Constant* CF = ConstantFP::get(
Type::getDoubleTy(getLLVMContext()),
field.getDoubleField(obj));
Elts.push_back(CF);
} else {
abort();
}
} else {
JavaObject* val = field.getObjectField(obj);
if (val) {
JnjvmClassLoader* JCL = cl->classLoader;
CommonClass* FieldCl = field.getSignature()->assocClass(JCL);
Constant* CO = getFinalObject(val, FieldCl);
Elts.push_back(CO);
} else {
Elts.push_back(Constant::getNullValue(Ty));
}
}
} else {
Elts.push_back(Constant::getNullValue(Ty));
}
} else {
Reader reader(attribut, &(cl->bytes));
JavaConstantPool * ctpInfo = cl->ctpInfo;
uint16 idx = reader.readU2();
if (type->isPrimitive()) {
if (Ty == Type::getInt64Ty(getLLVMContext())) {
Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->LongAt(idx)));
} else if (Ty == Type::getDoubleTy(getLLVMContext())) {
Elts.push_back(ConstantFP::get(Ty, ctpInfo->DoubleAt(idx)));
} else if (Ty == Type::getFloatTy(getLLVMContext())) {
Elts.push_back(ConstantFP::get(Ty, ctpInfo->FloatAt(idx)));
} else {
Elts.push_back(ConstantInt::get(Ty, (uint64)ctpInfo->IntegerAt(idx)));
}
} else if (type->isReference()){
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]);
JavaString* obj = ctpInfo->resolveString(utf8, idx);
Constant* C = getString(obj);
C = ConstantExpr::getBitCast(C, JavaIntrinsics.JavaObjectType);
Elts.push_back(C);
} else {
fprintf(stderr, "Implement me");
abort();
}
}
}
return ConstantStruct::get(STy, Elts);
}
Constant* JavaAOTCompiler::getStaticInstance(Class* classDef) {
#ifdef ISOLATE
assert(0 && "Should not be here");
abort();
#endif
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);
std::string name(UTF8Buffer(classDef->name).toCompileName()->cString());
name += "_static";
Module& Mod = *getLLVMModule();
GlobalVariable* varGV =
new GlobalVariable(Mod, Ty, false, GlobalValue::ExternalLinkage,
0, name);
Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV,
JavaIntrinsics.ptrType);
staticInstances.insert(std::make_pair(classDef, res));
if (isCompiling(classDef)) {
Constant* C = CreateConstantFromStaticInstance(classDef);
varGV->setInitializer(C);
}
return res;
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::getVirtualTable(JavaVirtualTable* VT) {
CommonClass* classDef = VT->cl;
uint32 size = 0;
if (classDef->isClass()) {
LLVMClassInfo* LCI = getClassInfo(classDef->asClass());
LCI->getVirtualType();
size = classDef->asClass()->virtualTableSize;
} else {
size = JavaVirtualTable::getBaseSize();
}
llvm::Constant* res = 0;
virtual_table_iterator End = virtualTables.end();
virtual_table_iterator I = virtualTables.find(VT);
if (I == End) {
const ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
const PointerType* PTy = dyn_cast<PointerType>(ATy->getContainedType(0));
ATy = ArrayType::get(PTy, size);
std::string name(UTF8Buffer(classDef->name).toCompileName()->cString());
name += "_VT";
// Do not set a virtual table as a constant, because the runtime may
// modify it.
Module& Mod = *getLLVMModule();
GlobalVariable* varGV = new GlobalVariable(Mod, ATy, false,
GlobalValue::ExternalLinkage,
0, name);
res = ConstantExpr::getCast(Instruction::BitCast, varGV,
JavaIntrinsics.VTType);
virtualTables.insert(std::make_pair(VT, res));
if (isCompiling(classDef) || assumeCompiled) {
Constant* C = CreateConstantFromVT(VT);
varGV->setInitializer(C);
}
return res;
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::getNativeFunction(JavaMethod* meth, void* ptr) {
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();
Module& Mod = *getLLVMModule();
varGV = new GlobalVariable(Mod, valPtrType, false,
GlobalValue::InternalLinkage,
Constant::getNullValue(valPtrType), "");
nativeFunctions.insert(std::make_pair(meth, varGV));
return varGV;
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::CreateConstantForBaseObject(CommonClass* cl) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaObjectType->getContainedType(0));
std::vector<Constant*> Elmts;
// VT
Elmts.push_back(getVirtualTable(cl->virtualVT));
// lock
Constant* L = ConstantInt::get(Type::getInt64Ty(getLLVMContext()), 0);
Elmts.push_back(ConstantExpr::getIntToPtr(L, JavaIntrinsics.ptrType));
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromJavaClass(CommonClass* cl) {
Class* javaClass = cl->classLoader->bootstrapLoader->upcalls->newClass;
LLVMClassInfo* LCI = getClassInfo(javaClass);
const StructType* STy =
dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0));
std::vector<Constant*> Elmts;
// JavaObject
Elmts.push_back(CreateConstantForBaseObject(javaClass));
// signers
Elmts.push_back(Constant::getNullValue(JavaIntrinsics.JavaObjectType));
// pd
Elmts.push_back(Constant::getNullValue(JavaIntrinsics.JavaObjectType));
// vmdata
Constant* Cl = getNativeClass(cl);
Cl = ConstantExpr::getCast(Instruction::BitCast, Cl,
JavaIntrinsics.JavaObjectType);
Elmts.push_back(Cl);
// constructor
Elmts.push_back(Constant::getNullValue(JavaIntrinsics.JavaObjectType));
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromJavaObject(JavaObject* obj) {
CommonClass* cl = obj->getClass();
if (cl->isArray()) {
Classpath* upcalls = cl->classLoader->bootstrapLoader->upcalls;
CommonClass* subClass = cl->asArrayClass()->baseClass();
if (subClass->isPrimitive()) {
if (subClass == upcalls->OfBool) {
return CreateConstantFromIntArray<ArrayUInt8>((ArrayUInt8*)obj,
Type::getInt8Ty(getLLVMContext()));
} else if (subClass == upcalls->OfByte) {
return CreateConstantFromIntArray<ArraySInt8>((ArraySInt8*)obj,
Type::getInt8Ty(getLLVMContext()));
} else if (subClass == upcalls->OfShort) {
return CreateConstantFromIntArray<ArraySInt16>((ArraySInt16*)obj,
Type::getInt16Ty(getLLVMContext()));
} else if (subClass == upcalls->OfChar) {
return CreateConstantFromIntArray<ArrayUInt16>((ArrayUInt16*)obj,
Type::getInt16Ty(getLLVMContext()));
} else if (subClass == upcalls->OfInt) {
return CreateConstantFromIntArray<ArraySInt32>((ArraySInt32*)obj,
Type::getInt32Ty(getLLVMContext()));
} else if (subClass == upcalls->OfFloat) {
return CreateConstantFromFPArray<ArrayFloat>((ArrayFloat*)obj,
Type::getFloatTy(getLLVMContext()));
} else if (subClass == upcalls->OfLong) {
return CreateConstantFromIntArray<ArrayLong>((ArrayLong*)obj,
Type::getInt64Ty(getLLVMContext()));
} else if (subClass == upcalls->OfDouble) {
return CreateConstantFromFPArray<ArrayDouble>((ArrayDouble*)obj,
Type::getDoubleTy(getLLVMContext()));
} else {
abort();
}
} else {
return CreateConstantFromObjectArray((ArrayObject*)obj);
}
} else {
std::vector<Constant*> Elmts;
// JavaObject
Constant* CurConstant = CreateConstantForBaseObject(obj->getClass());
for (uint32 j = 1; j <= cl->virtualVT->depth; ++j) {
std::vector<Constant*> TempElts;
Elmts.push_back(CurConstant);
TempElts.push_back(CurConstant);
Class* curCl = cl->virtualVT->display[j]->cl->asClass();
LLVMClassInfo* LCI = getClassInfo(curCl);
const StructType* STy =
dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0));
for (uint32 i = 0; i < curCl->nbVirtualFields; ++i) {
JavaField& field = curCl->virtualFields[i];
const Typedef* type = field.getSignature();
if (type->isPrimitive()) {
const PrimitiveTypedef* prim = (const PrimitiveTypedef*)type;
if (prim->isBool() || prim->isByte()) {
ConstantInt* CI = ConstantInt::get(Type::getInt8Ty(getLLVMContext()),
field.getInt8Field(obj));
TempElts.push_back(CI);
} else if (prim->isShort() || prim->isChar()) {
ConstantInt* CI = ConstantInt::get(Type::getInt16Ty(getLLVMContext()),
field.getInt16Field(obj));
TempElts.push_back(CI);
} else if (prim->isInt()) {
ConstantInt* CI = ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
field.getInt32Field(obj));
TempElts.push_back(CI);
} else if (prim->isLong()) {
ConstantInt* CI = ConstantInt::get(Type::getInt64Ty(getLLVMContext()),
field.getLongField(obj));
TempElts.push_back(CI);
} else if (prim->isFloat()) {
Constant* CF = ConstantFP::get(Type::getFloatTy(getLLVMContext()),
field.getFloatField(obj));
TempElts.push_back(CF);
} else if (prim->isDouble()) {
Constant* CF = ConstantFP::get(Type::getDoubleTy(getLLVMContext()),
field.getDoubleField(obj));
TempElts.push_back(CF);
} else {
abort();
}
} else {
JavaObject* val = field.getObjectField(obj);
if (val) {
JnjvmClassLoader* JCL = cl->classLoader;
CommonClass* FieldCl = field.getSignature()->assocClass(JCL);
Constant* C = getFinalObject(val, FieldCl);
TempElts.push_back(C);
} else {
const llvm::Type* Ty = JavaIntrinsics.JavaObjectType;
TempElts.push_back(Constant::getNullValue(Ty));
}
}
}
CurConstant = ConstantStruct::get(STy, TempElts);
}
return CurConstant;
}
}
Constant* JavaAOTCompiler::CreateConstantFromJavaString(JavaString* str) {
Class* cl = str->getClass()->asClass();
LLVMClassInfo* LCI = getClassInfo(cl);
const StructType* STy =
dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0));
std::vector<Constant*> Elmts;
Elmts.push_back(CreateConstantForBaseObject(cl));
Constant* Array = CreateConstantFromIntArray<ArrayUInt16>(str->value,
Type::getInt16Ty(getLLVMContext()));
Module& Mod = *getLLVMModule();
GlobalVariable* varGV = new GlobalVariable(Mod, Array->getType(), false,
GlobalValue::InternalLinkage,
Array, "");
Array = ConstantExpr::getBitCast(varGV, JavaIntrinsics.JavaObjectType);
Elmts.push_back(Array);
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->count));
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->cachedHashCode));
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->offset));
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromAttribut(Attribut& attribut) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.AttributType->getContainedType(0));
std::vector<Constant*> Elmts;
// name
Elmts.push_back(getUTF8(attribut.name));
// start
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), attribut.start));
// nbb
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), attribut.nbb));
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromCommonClass(CommonClass* cl) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaCommonClassType->getContainedType(0));
Module& Mod = *getLLVMModule();
const llvm::Type* TempTy = 0;
std::vector<Constant*> CommonClassElts;
std::vector<Constant*> TempElmts;
// delegatee
const ArrayType* ATy = dyn_cast<ArrayType>(STy->getContainedType(0));
assert(ATy && "Malformed type");
Constant* TCM[1] = { getJavaClass(cl) };
CommonClassElts.push_back(ConstantArray::get(ATy, TCM, 1));
// access
CommonClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->access));
// interfaces
if (cl->nbInterfaces) {
for (uint32 i = 0; i < cl->nbInterfaces; ++i) {
TempElmts.push_back(getNativeClass(cl->interfaces[i]));
}
ATy = ArrayType::get(JavaIntrinsics.JavaClassType, cl->nbInterfaces);
Constant* interfaces = ConstantArray::get(ATy, TempElmts);
interfaces = new GlobalVariable(Mod, ATy, true,
GlobalValue::InternalLinkage,
interfaces, "");
interfaces = ConstantExpr::getCast(Instruction::BitCast, interfaces,
PointerType::getUnqual(JavaIntrinsics.JavaClassType));
CommonClassElts.push_back(interfaces);
} else {
const Type* Ty = PointerType::getUnqual(JavaIntrinsics.JavaClassType);
CommonClassElts.push_back(Constant::getNullValue(Ty));
}
// nbInterfaces
CommonClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbInterfaces));
// name
CommonClassElts.push_back(getUTF8(cl->name));
// super
if (cl->super) {
CommonClassElts.push_back(getNativeClass(cl->super));
} else {
TempTy = JavaIntrinsics.JavaClassType;
CommonClassElts.push_back(Constant::getNullValue(TempTy));
}
// classLoader: store the static initializer, it will be overriden once
// the class is loaded.
Constant* loader = ConstantExpr::getBitCast(StaticInitializer,
JavaIntrinsics.ptrType);
CommonClassElts.push_back(loader);
// virtualTable
if (cl->virtualVT) {
CommonClassElts.push_back(getVirtualTable(cl->virtualVT));
} else {
TempTy = JavaIntrinsics.VTType;
CommonClassElts.push_back(Constant::getNullValue(TempTy));
}
return ConstantStruct::get(STy, CommonClassElts);
}
Constant* JavaAOTCompiler::CreateConstantFromJavaField(JavaField& field) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaFieldType->getContainedType(0));
std::vector<Constant*> FieldElts;
std::vector<Constant*> TempElts;
// signature
FieldElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// access
FieldElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), field.access));
// name
FieldElts.push_back(getUTF8(field.name));
// type
FieldElts.push_back(getUTF8(field.type));
// attributs
if (field.nbAttributs) {
const llvm::Type* AttrTy = JavaIntrinsics.AttributType->getContainedType(0);
const ArrayType* ATy = ArrayType::get(AttrTy, 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(*getLLVMModule(), ATy, true,
GlobalValue::InternalLinkage,
attributs, "");
attributs = ConstantExpr::getCast(Instruction::BitCast, attributs,
JavaIntrinsics.AttributType);
FieldElts.push_back(attributs);
} else {
FieldElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributType));
}
// nbAttributs
FieldElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), field.nbAttributs));
// classDef
FieldElts.push_back(getNativeClass(field.classDef));
// ptrOffset
FieldElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), field.ptrOffset));
// num
FieldElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), field.num));
return ConstantStruct::get(STy, FieldElts);
}
Constant* JavaAOTCompiler::CreateConstantFromJavaMethod(JavaMethod& method) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaMethodType->getContainedType(0));
Module& Mod = *getLLVMModule();
std::vector<Constant*> MethodElts;
std::vector<Constant*> TempElts;
// signature
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// access
MethodElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), method.access));
// attributs
if (method.nbAttributs) {
const llvm::Type* AttrTy = JavaIntrinsics.AttributType->getContainedType(0);
const ArrayType* ATy = ArrayType::get(AttrTy, 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(Mod, ATy, true,
GlobalValue::InternalLinkage,
attributs, "");
attributs = ConstantExpr::getCast(Instruction::BitCast, attributs,
JavaIntrinsics.AttributType);
MethodElts.push_back(attributs);
} else {
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributType));
}
// nbAttributs
MethodElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), method.nbAttributs));
// 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::getInt8Ty(getLLVMContext()), method.canBeInlined));
// code
if (isAbstract(method.access)) {
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
} else {
LLVMMethodInfo* LMI = getMethodInfo(&method);
Function* func = LMI->getMethod();
MethodElts.push_back(ConstantExpr::getCast(Instruction::BitCast, func,
JavaIntrinsics.ptrType));
}
// codeInfo
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.CodeLineInfoType));
// codeInfoLength
MethodElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), 0));
// offset
MethodElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), method.offset));
return ConstantStruct::get(STy, MethodElts);
}
Constant* JavaAOTCompiler::CreateConstantFromClassPrimitive(ClassPrimitive* cl) {
const llvm::Type* JCPTy =
JavaIntrinsics.JavaClassPrimitiveType->getContainedType(0);
const StructType* STy = dyn_cast<StructType>(JCPTy);
std::vector<Constant*> ClassElts;
// common class
ClassElts.push_back(CreateConstantFromCommonClass(cl));
// primSize
ClassElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), cl->logSize));
return ConstantStruct::get(STy, ClassElts);
}
Constant* JavaAOTCompiler::CreateConstantFromClassArray(ClassArray* cl) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaClassArrayType->getContainedType(0));
std::vector<Constant*> ClassElts;
Constant* ClGEPs[2] = { getIntrinsics()->constantZero,
getIntrinsics()->constantZero };
// common class
ClassElts.push_back(CreateConstantFromCommonClass(cl));
// baseClass
Constant* Cl = getNativeClass(cl->baseClass());
if (Cl->getType() != JavaIntrinsics.JavaCommonClassType)
Cl = ConstantExpr::getGetElementPtr(Cl, ClGEPs, 2);
ClassElts.push_back(Cl);
return ConstantStruct::get(STy, ClassElts);
}
Constant* JavaAOTCompiler::CreateConstantFromClass(Class* cl) {
const StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaClassType->getContainedType(0));
Module& Mod = *getLLVMModule();
std::vector<Constant*> ClassElts;
std::vector<Constant*> TempElts;
// common class
ClassElts.push_back(CreateConstantFromCommonClass(cl));
// virtualSize
ClassElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
cl->virtualSize));
// alginment
ClassElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
cl->alignment));
// 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");
uint32 status = cl->needsInitialisationCheck() ? vmjc : ready;
TempElts.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()),
status));
TempElts.push_back(ConstantInt::get(Type::getInt1Ty(getLLVMContext()),
status == ready ? 1 : 0));
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(JavaIntrinsics.ptrType));
if (cl->nbVirtualFields + cl->nbStaticFields) {
ATy = ArrayType::get(JavaIntrinsics.JavaFieldType->getContainedType(0),
cl->nbVirtualFields + cl->nbStaticFields);
}
// virtualFields
if (cl->nbVirtualFields) {
for (uint32 i = 0; i < cl->nbVirtualFields; ++i) {
TempElts.push_back(CreateConstantFromJavaField(cl->virtualFields[i]));
}
}
// staticFields
if (cl->nbStaticFields) {
for (uint32 i = 0; i < cl->nbStaticFields; ++i) {
TempElts.push_back(CreateConstantFromJavaField(cl->staticFields[i]));
}
}
Constant* fields = 0;
if (cl->nbStaticFields + cl->nbVirtualFields) {
fields = ConstantArray::get(ATy, TempElts);
TempElts.clear();
fields = new GlobalVariable(Mod, ATy, false,
GlobalValue::InternalLinkage,
fields, "");
fields = ConstantExpr::getCast(Instruction::BitCast, fields,
JavaIntrinsics.JavaFieldType);
} else {
fields = Constant::getNullValue(JavaIntrinsics.JavaFieldType);
}
// virtualFields
ClassElts.push_back(fields);
ConstantInt* nbVirtualFields =
ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbVirtualFields);
// nbVirtualFields
ClassElts.push_back(nbVirtualFields);
// staticFields
// Output null, getLLVMModule() will be set in the initializer. Otherwise, the
// assembly emitter of LLVM will try to align the data.
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.JavaFieldType));
// nbStaticFields
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbStaticFields));
// virtualMethods
if (cl->nbVirtualMethods + cl->nbStaticMethods) {
ATy = ArrayType::get(JavaIntrinsics.JavaMethodType->getContainedType(0),
cl->nbVirtualMethods + cl->nbStaticMethods);
}
if (cl->nbVirtualMethods) {
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
TempElts.push_back(CreateConstantFromJavaMethod(cl->virtualMethods[i]));
}
}
if (cl->nbStaticMethods) {
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
TempElts.push_back(CreateConstantFromJavaMethod(cl->staticMethods[i]));
}
}
Constant* methods = 0;
if (cl->nbVirtualMethods + cl->nbStaticMethods) {
methods = ConstantArray::get(ATy, TempElts);
TempElts.clear();
GlobalVariable* GV = NULL;
method_iterator SI = virtualMethods.find(cl);
if (SI != virtualMethods.end()) {
GV = dyn_cast<GlobalVariable>(SI->second);
GV->setInitializer(methods);
} else {
std::string name(UTF8Buffer(cl->name).toCompileName()->cString());
name += "_VirtualMethods";
GV = new GlobalVariable(Mod, ATy, false, GlobalValue::ExternalLinkage,
methods, name);
virtualMethods.insert(std::make_pair(cl, GV));
}
methods = ConstantExpr::getCast(Instruction::BitCast, GV,
JavaIntrinsics.JavaMethodType);
} else {
methods = Constant::getNullValue(JavaIntrinsics.JavaMethodType);
}
// virtualMethods
ClassElts.push_back(methods);
ConstantInt* nbVirtualMethods =
ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbVirtualMethods);
// nbVirtualMethods
ClassElts.push_back(nbVirtualMethods);
// staticMethods
// Output null, getLLVMModule() will be set in the initializer.
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.JavaMethodType));
// nbStaticMethods
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbStaticMethods));
// ownerClass
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// bytes
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.JavaArrayUInt8Type));
// ctpInfo
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// attributs
if (cl->nbAttributs) {
ATy = ArrayType::get(JavaIntrinsics.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(*getLLVMModule(), ATy, true,
GlobalValue::InternalLinkage,
attributs, "");
attributs = ConstantExpr::getCast(Instruction::BitCast, attributs,
JavaIntrinsics.AttributType);
ClassElts.push_back(attributs);
} else {
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributType));
}
// nbAttributs
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbAttributs));
// innerClasses
if (cl->nbInnerClasses) {
for (uint32 i = 0; i < cl->nbInnerClasses; ++i) {
TempElts.push_back(getNativeClass(cl->innerClasses[i]));
}
const llvm::Type* TempTy = JavaIntrinsics.JavaClassType;
ATy = ArrayType::get(TempTy, cl->nbInnerClasses);
Constant* innerClasses = ConstantArray::get(ATy, TempElts);
innerClasses = new GlobalVariable(*getLLVMModule(), ATy, true,
GlobalValue::InternalLinkage,
innerClasses, "");
innerClasses = ConstantExpr::getCast(Instruction::BitCast, innerClasses,
PointerType::getUnqual(TempTy));
ClassElts.push_back(innerClasses);
} else {
const Type* Ty = PointerType::getUnqual(JavaIntrinsics.JavaClassType);
ClassElts.push_back(Constant::getNullValue(Ty));
}
// nbInnerClasses
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbInnerClasses));
// outerClass
if (cl->outerClass) {
ClassElts.push_back(getNativeClass(cl->outerClass));
} else {
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.JavaClassType));
}
// innerAccess
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->innerAccess));
// innerOuterResolved
ClassElts.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()), cl->innerOuterResolved));
// isAnonymous
ClassElts.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()), cl->isAnonymous));
// virtualTableSize
ClassElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), cl->virtualTableSize));
// staticSize
ClassElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), cl->staticSize));
return ConstantStruct::get(STy, ClassElts);
}
template<typename T>
Constant* JavaAOTCompiler::CreateConstantFromIntArray(const T* val, const Type* Ty) {
std::vector<const Type*> Elemts;
const ArrayType* ATy = ArrayType::get(Ty, val->size);
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
const StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(val->getClass()));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, val->size));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < val->size; ++i) {
Vals.push_back(ConstantInt::get(Ty, (uint64)val->elements[i]));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
template<typename T>
Constant* JavaAOTCompiler::CreateConstantFromFPArray(const T* val, const Type* Ty) {
std::vector<const Type*> Elemts;
const ArrayType* ATy = ArrayType::get(Ty, val->size);
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
const StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(val->getClass()));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, val->size));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < val->size; ++i) {
Vals.push_back(ConstantFP::get(Ty, (double)val->elements[i]));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
Constant* JavaAOTCompiler::CreateConstantFromObjectArray(const ArrayObject* val) {
std::vector<const Type*> Elemts;
const llvm::Type* Ty = JavaIntrinsics.JavaObjectType;
const ArrayType* ATy = ArrayType::get(Ty, val->size);
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
const StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(val->getClass()));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, val->size));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < val->size; ++i) {
if (val->elements[i]) {
Vals.push_back(getFinalObject(val->elements[i],
val->getClass()->asArrayClass()->baseClass()));
} else {
Vals.push_back(Constant::getNullValue(JavaIntrinsics.JavaObjectType));
}
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
Constant* JavaAOTCompiler::CreateConstantFromUTF8(const UTF8* val) {
std::vector<const Type*> Elemts;
const ArrayType* ATy = ArrayType::get(Type::getInt16Ty(getLLVMContext()), val->size);
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
const StructType* STy = StructType::get(getLLVMModule()->getContext(),
Elemts);
std::vector<Constant*> Cts;
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, val->size));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < val->size; ++i) {
Vals.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), val->elements[i]));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
Constant* JavaAOTCompiler::getUTF8(const UTF8* val) {
utf8_iterator End = utf8s.end();
utf8_iterator I = utf8s.find(val);
if (I == End) {
Constant* C = CreateConstantFromUTF8(val);
Module& Mod = *getLLVMModule();
GlobalVariable* varGV = new GlobalVariable(Mod, C->getType(), true,
GlobalValue::InternalLinkage,
C, "");
Constant* res = ConstantExpr::getCast(Instruction::BitCast, varGV,
JavaIntrinsics.UTF8Type);
utf8s.insert(std::make_pair(val, res));
return res;
} else {
return I->second;
}
}
Constant* JavaAOTCompiler::CreateConstantFromVT(JavaVirtualTable* VT) {
CommonClass* classDef = VT->cl;
uint32 size = classDef->isClass() ? classDef->asClass()->virtualTableSize :
JavaVirtualTable::getBaseSize();
JavaVirtualTable* RealVT = classDef->isClass() ?
VT : ClassArray::SuperArray->virtualVT;
const ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.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
Function* Finalizer = 0;
JavaMethod* meth = (JavaMethod*)(RealVT->destructor);
if (meth) {
LLVMMethodInfo* LMI = getMethodInfo(meth);
Finalizer = LMI->getMethod();
}
Elemts.push_back(Finalizer ?
ConstantExpr::getCast(Instruction::BitCast, Finalizer, PTy) : N);
// Delete
Elemts.push_back(N);
// Tracer
Function* Tracer = 0;
if (classDef->isArray()) {
if (classDef->asArrayClass()->baseClass()->isPrimitive()) {
Tracer = JavaIntrinsics.JavaArrayTracerFunction;
} else {
Tracer = JavaIntrinsics.ArrayObjectTracerFunction;
}
} else if (classDef->isClass()) {
Tracer = JavaIntrinsics.RegularObjectTracerFunction;
}
Elemts.push_back(Tracer ?
ConstantExpr::getCast(Instruction::BitCast, Tracer, PTy) : N);
for (uint32_t i = 0; i < VirtualTable::numberOfSpecializedTracers(); i++) {
// Push null for now.
Elemts.push_back(N);
}
// Class
Elemts.push_back(ConstantExpr::getCast(Instruction::BitCast,
getNativeClass(classDef), PTy));
// depth
Elemts.push_back(ConstantExpr::getIntToPtr(
ConstantInt::get(Type::getInt64Ty(getLLVMContext()), VT->depth), PTy));
// offset
Elemts.push_back(ConstantExpr::getIntToPtr(
ConstantInt::get(Type::getInt64Ty(getLLVMContext()), VT->offset), PTy));
// cache
Elemts.push_back(N);
// display
for (uint32 i = 0; i < JavaVirtualTable::getDisplayLength(); ++i) {
if (VT->display[i]) {
Constant* Temp = getVirtualTable(VT->display[i]);
Temp = ConstantExpr::getBitCast(Temp, PTy);
Elemts.push_back(Temp);
} else {
Elemts.push_back(Constant::getNullValue(PTy));
}
}
// nbSecondaryTypes
Elemts.push_back(ConstantExpr::getIntToPtr(
ConstantInt::get(Type::getInt64Ty(getLLVMContext()), VT->nbSecondaryTypes), PTy));
// secondaryTypes
const ArrayType* DTy = ArrayType::get(JavaIntrinsics.VTType,
VT->nbSecondaryTypes);
std::vector<Constant*> TempElmts;
for (uint32 i = 0; i < VT->nbSecondaryTypes; ++i) {
assert(VT->secondaryTypes[i] && "No secondary type");
Constant* Cl = getVirtualTable(VT->secondaryTypes[i]);
TempElmts.push_back(Cl);
}
Constant* display = ConstantArray::get(DTy, TempElmts);
TempElmts.clear();
display = new GlobalVariable(*getLLVMModule(), DTy, true,
GlobalValue::InternalLinkage,
display, "");
display = ConstantExpr::getCast(Instruction::BitCast, display, PTy);
Elemts.push_back(display);
// baseClassVT
if (VT->baseClassVT) {
Constant* Temp = getVirtualTable(VT->baseClassVT);
Temp = ConstantExpr::getBitCast(Temp, PTy);
Elemts.push_back(Temp);
} else {
Elemts.push_back(Constant::getNullValue(PTy));
}
// IMT
if (!VT->IMT) {
Elemts.push_back(Constant::getNullValue(PTy));
} else {
Class* cl = classDef->asClass();
assert(cl && "Not a class");
std::set<JavaMethod*> contents[InterfaceMethodTable::NumIndexes];
classDef->asClass()->fillIMT(contents);
const ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
const PointerType* PTy = dyn_cast<PointerType>(ATy->getContainedType(0));
ATy = ArrayType::get(PTy, InterfaceMethodTable::NumIndexes);
ConstantPointerNull* N = ConstantPointerNull::get(PTy);
std::vector<Constant*> IElemts;
for (uint32_t i = 0; i < InterfaceMethodTable::NumIndexes; ++i) {
std::set<JavaMethod*>& atIndex = contents[i];
uint32_t size = atIndex.size();
if (size == 1) {
JavaMethod* Imeth = *(atIndex.begin());
JavaMethod* meth = cl->lookupMethodDontThrow(Imeth->name,
Imeth->type,
false, true, 0);
assert(meth && "No method found");
LLVMMethodInfo* LMI = getMethodInfo(meth);
Function* func = LMI->getMethod();
IElemts.push_back(ConstantExpr::getBitCast(func, PTy));
} else if (size > 1) {
std::vector<JavaMethod*> methods;
bool SameMethod = true;
JavaMethod* OldMethod = 0;
for (std::set<JavaMethod*>::iterator it = atIndex.begin(),
et = atIndex.end(); it != et; ++it) {
JavaMethod* Imeth = *it;
JavaMethod* Cmeth = cl->lookupMethodDontThrow(Imeth->name, Imeth->type,
false, true, 0);
if (OldMethod && OldMethod != Cmeth) SameMethod = false;
else OldMethod = Cmeth;
methods.push_back(Cmeth);
}
if (SameMethod) {
assert(methods[0] && "No method found");
LLVMMethodInfo* LMI = getMethodInfo(methods[0]);
Function* func = LMI->getMethod();
IElemts.push_back(ConstantExpr::getBitCast(func, PTy));
} else {
uint32_t length = 2 * size;
const ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
ATy = ArrayType::get(PTy, length);
std::vector<Constant*> InternalElemts;
std::set<JavaMethod*>::iterator Interf = atIndex.begin();
for (std::vector<JavaMethod*>::iterator it = methods.begin(),
et = methods.end(); it != et; ++it, ++Interf) {
JavaMethod* Imeth = *Interf;
JavaMethod* Cmeth = *it;
assert(Cmeth && "No method found");
LLVMMethodInfo* LMI = getMethodInfo(Cmeth);
Function* func = LMI->getMethod();
InternalElemts.push_back(
ConstantExpr::getBitCast(getMethodInClass(Imeth), PTy));
InternalElemts.push_back(ConstantExpr::getBitCast(func, PTy));
}
Constant* Array = ConstantArray::get(ATy, InternalElemts);
GlobalVariable* GV = new GlobalVariable(*getLLVMModule(), ATy, false,
GlobalValue::InternalLinkage,
Array, "");
Constant* CI =
ConstantExpr::getPtrToInt(GV, Type::getInt32Ty(getLLVMContext()));
CI = ConstantExpr::getAdd(CI, JavaIntrinsics.constantOne);
CI = ConstantExpr::getIntToPtr(CI, PTy);
IElemts.push_back(CI);
}
} else {
IElemts.push_back(N);
}
}
Constant* Array = ConstantArray::get(ATy, IElemts);
GlobalVariable* GV = new GlobalVariable(*getLLVMModule(), ATy, false,
GlobalValue::InternalLinkage,
Array, "");
Elemts.push_back(ConstantExpr::getBitCast(GV, PTy));
}
// methods
for (uint32 i = JavaVirtualTable::getFirstJavaMethodIndex(); i < size; ++i) {
JavaMethod* meth = ((JavaMethod**)RealVT)[i];
LLVMMethodInfo* LMI = getMethodInfo(meth);
Function* F = LMI->getMethod();
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;
}
namespace mvm {
llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*);
}
namespace j3 {
llvm::FunctionPass* createLowerConstantCallsPass();
}
JavaAOTCompiler::JavaAOTCompiler(const std::string& ModuleID) :
JavaLLVMCompiler(ModuleID) {
generateStubs = true;
assumeCompiled = false;
compileRT = false;
std::vector<const llvm::Type*> llvmArgs;
llvmArgs.push_back(JavaIntrinsics.ptrType); // class loader.
const FunctionType* FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()),
llvmArgs, false);
StaticInitializer = Function::Create(FTy, GlobalValue::InternalLinkage,
"Init", getLLVMModule());
llvmArgs.clear();
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Callback = Function::Create(FTy, GlobalValue::ExternalLinkage,
"staticCallback", getLLVMModule());
llvmArgs.clear();
llvmArgs.push_back(JavaIntrinsics.JavaMethodType);
FTy = FunctionType::get(JavaIntrinsics.ptrType, llvmArgs, false);
NativeLoader = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcNativeLoader", getLLVMModule());
llvmArgs.clear();
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
ObjectPrinter = Function::Create(FTy, GlobalValue::ExternalLinkage,
"printJavaObject", getLLVMModule());
addJavaPasses();
}
void JavaAOTCompiler::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 native functions : %llu\n",
(unsigned long long int) nativeFunctions.size());
fprintf(stderr, "----------------- Total size in .data ------------------\n");
uint64 size = 0;
Module* Mod = getLLVMModule();
for (Module::const_global_iterator i = Mod->global_begin(),
e = Mod->global_end(); i != e; ++i) {
size += mvm::MvmModule::getTypeSize(i->getType());
}
fprintf(stderr, "%lluB\n", (unsigned long long int)size);
}
#ifdef SERVICE
Value* JavaAOTCompiler::getIsolate(Jnjvm* isolate, Value* Where) {
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::getInt64Ty(getLLVMContext()),
uint64_t(isolate)),
ptrType);
Module& Mod = *getLLVMModule();
varGV = new GlobalVariable(Mod, ptrType, !staticCompilation,
GlobalValue::ExternalLinkage,
cons, "");
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));
}
}
#endif
void JavaAOTCompiler::CreateStaticInitializer() {
std::vector<const llvm::Type*> llvmArgs;
llvmArgs.push_back(JavaIntrinsics.ptrType); // class loader
llvmArgs.push_back(JavaIntrinsics.JavaCommonClassType); // cl
const FunctionType* FTy =
FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Function* AddClass = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcAddPreCompiledClass",
getLLVMModule());
llvmArgs.clear();
// class loader
llvmArgs.push_back(JavaIntrinsics.ptrType);
// array ptr
llvmArgs.push_back(PointerType::getUnqual(JavaIntrinsics.JavaClassArrayType));
// name
llvmArgs.push_back(JavaIntrinsics.UTF8Type);
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Function* GetClassArray = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcGetClassArray", getLLVMModule());
BasicBlock* currentBlock = BasicBlock::Create(getLLVMContext(), "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(JavaIntrinsics.ptrType); // class loader
llvmArgs.push_back(strings.begin()->second->getType()); // val
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Function* AddString = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcAddString", getLLVMModule());
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);
}
}
#if 0
// Disable initialization of UTF8s, it makes the Init method too big.
// If we have defined some UTF8s.
if (utf8s.begin() != utf8s.end()) {
llvmArgs.clear();
llvmArgs.push_back(JavaIntrinsics.ptrType); // class loader
llvmArgs.push_back(utf8s.begin()->second->getType()); // val
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Function* AddUTF8 = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcAddUTF8", getLLVMModule());
for (utf8_iterator i = utf8s.begin(), e = utf8s.end(); i != e; ++i) {
Args[0] = loader;
Args[1] = i->second;
CallInst::Create(AddUTF8, Args, Args + 2, "", currentBlock);
}
}
#endif
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,
JavaIntrinsics.JavaCommonClassType);
CallInst::Create(AddClass, Args, Args + 2, "", currentBlock);
}
}
for (array_class_iterator i = arrayClasses.begin(),
e = arrayClasses.end(); i != e; ++i) {
Args[0] = loader;
Args[1] = i->second;
Args[2] = getUTF8(i->first->name);
CallInst::Create(GetClassArray, Args, Args + 3, "", currentBlock);
}
ReturnInst::Create(getLLVMContext(), currentBlock);
}
void JavaAOTCompiler::setNoInline(Class* cl) {
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
JavaMethod& meth = cl->virtualMethods[i];
if (!isAbstract(meth.access)) {
LLVMMethodInfo* LMI = getMethodInfo(&meth);
Function* func = LMI->getMethod();
func->addFnAttr(Attribute::NoInline);
}
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
JavaMethod& meth = cl->staticMethods[i];
if (!isAbstract(meth.access)) {
LLVMMethodInfo* LMI = getMethodInfo(&meth);
Function* func = LMI->getMethod();
func->addFnAttr(Attribute::NoInline);
}
}
}
void JavaAOTCompiler::makeVT(Class* cl) {
JavaVirtualTable* VT = cl->virtualVT;
if (cl->super) {
// Copy the super VT into the current VT.
uint32 size = cl->super->virtualTableSize -
JavaVirtualTable::getFirstJavaMethodIndex();
memcpy(VT->getFirstJavaMethod(), cl->super->virtualVT->getFirstJavaMethod(),
size * sizeof(uintptr_t));
VT->destructor = cl->super->virtualVT->destructor;
}
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
JavaMethod& meth = cl->virtualMethods[i];
((void**)VT)[meth.offset] = &meth;
}
if (!cl->super) VT->destructor = 0;
}
void JavaAOTCompiler::makeIMT(Class* cl) {
}
void JavaAOTCompiler::setMethod(JavaMethod* meth, void* ptr, const char* name) {
Function* func = getMethodInfo(meth)->getMethod();
func->setName(name);
func->setLinkage(GlobalValue::ExternalLinkage);
}
Value* JavaAOTCompiler::addCallback(Class* cl, uint16 index,
Signdef* sign, bool stat,
BasicBlock* insert) {
JavaConstantPool* ctpInfo = cl->ctpInfo;
Signdef* signature = 0;
const UTF8* name = 0;
const UTF8* methCl = 0;
ctpInfo->nameOfStaticOrSpecialMethod(index, methCl, name, signature);
fprintf(stderr, "Warning: emitting a callback from %s (%s.%s)\n",
UTF8Buffer(cl->name).cString(), UTF8Buffer(methCl).cString(),
UTF8Buffer(name).cString());
LLVMSignatureInfo* LSI = getSignatureInfo(sign);
const FunctionType* type = stat ? LSI->getStaticType() :
LSI->getVirtualType();
Value* func = ConstantExpr::getBitCast(Callback,
PointerType::getUnqual(type));
return func;
}
void JavaAOTCompiler::compileClass(Class* cl) {
// Make sure the class is emitted.
getNativeClass(cl);
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
JavaMethod& meth = cl->virtualMethods[i];
if (!isAbstract(meth.access)) parseFunction(&meth);
if (generateStubs) compileAllStubs(meth.getSignature());
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
JavaMethod& meth = cl->staticMethods[i];
if (!isAbstract(meth.access)) parseFunction(&meth);
if (generateStubs) compileAllStubs(meth.getSignature());
}
}
static void extractFiles(ArrayUInt8* bytes,
JavaAOTCompiler* M,
JnjvmBootstrapLoader* bootstrapLoader,
std::vector<Class*>& classes) {
ZipArchive archive(bytes, bootstrapLoader->allocator);
char* realName = (char*)alloca(4096);
for (ZipArchive::table_iterator i = archive.filetable.begin(),
e = archive.filetable.end(); i != e; ++i) {
ZipFile* file = i->second;
char* name = file->filename;
uint32 size = strlen(name);
if (size > 6 && !strcmp(&(name[size - 6]), ".class")) {
UserClassArray* array = bootstrapLoader->upcalls->ArrayOfByte;
ArrayUInt8* res =
(ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator);
int ok = archive.readFile(res, file);
if (!ok) return;
memcpy(realName, name, size);
realName[size - 6] = 0;
const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName);
Class* cl = bootstrapLoader->constructClass(utf8, res);
if (cl == ClassArray::SuperArray) M->compileRT = true;
classes.push_back(cl);
} else if (size > 4 && (!strcmp(&name[size - 4], ".jar") ||
!strcmp(&name[size - 4], ".zip"))) {
UserClassArray* array = bootstrapLoader->upcalls->ArrayOfByte;
ArrayUInt8* res =
(ArrayUInt8*)array->doNew(file->ucsize, bootstrapLoader->allocator);
int ok = archive.readFile(res, file);
if (!ok) return;
extractFiles(res, M, bootstrapLoader, classes);
}
}
}
static const char* name;
void mainCompilerStart(JavaThread* th) {
Jnjvm* vm = th->getJVM();
JnjvmBootstrapLoader* bootstrapLoader = vm->bootstrapLoader;
JavaAOTCompiler* M = (JavaAOTCompiler*)bootstrapLoader->getCompiler();
JavaJITCompiler* Comp = 0;
if (!M->clinits->empty()) {
Comp = JavaJITCompiler::CreateCompiler("JIT");
Comp->EmitFunctionName = true;
bootstrapLoader->setCompiler(Comp);
bootstrapLoader->analyseClasspathEnv(vm->classpath);
} else {
bootstrapLoader->analyseClasspathEnv(vm->classpath);
bootstrapLoader->upcalls->initialiseClasspath(bootstrapLoader);
}
uint32 size = strlen(name);
if (size > 4 &&
(!strcmp(&name[size - 4], ".jar") || !strcmp(&name[size - 4], ".zip"))) {
std::vector<Class*> classes;
ArrayUInt8* bytes = Reader::openFile(bootstrapLoader, name);
if (!bytes) {
fprintf(stderr, "Can't find zip file.\n");
goto end;
}
extractFiles(bytes, M, bootstrapLoader, classes);
// First resolve everyone so that there can not be unknown references in
// constant pools.
for (std::vector<Class*>::iterator i = classes.begin(),
e = classes.end(); i != e; ++i) {
Class* cl = *i;
cl->resolveClass();
cl->setOwnerClass(JavaThread::get());
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
LLVMMethodInfo* LMI = M->getMethodInfo(&cl->virtualMethods[i]);
LMI->getMethod();
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
LLVMMethodInfo* LMI = M->getMethodInfo(&cl->staticMethods[i]);
LMI->getMethod();
}
}
if (!M->clinits->empty()) {
vm->loadBootstrap();
for (std::vector<std::string>::iterator i = M->clinits->begin(),
e = M->clinits->end(); i != e; ++i) {
if (i->at(i->length() - 1) == '*') {
for (std::vector<Class*>::iterator ii = classes.begin(),
ee = classes.end(); ii != ee; ++ii) {
Class* cl = *ii;
if (!strncmp(UTF8Buffer(cl->name).cString(), i->c_str(),
i->length() - 1)) {
TRY {
cl->asClass()->initialiseClass(vm);
} CATCH {
fprintf(stderr, "Error when initializing %s\n",
UTF8Buffer(cl->name).cString());
abort();
} END_CATCH;
}
}
} else {
const UTF8* name = bootstrapLoader->asciizConstructUTF8(i->c_str());
CommonClass* cl = bootstrapLoader->lookupClass(name);
if (cl && cl->isClass()) {
TRY {
cl->asClass()->initialiseClass(vm);
} CATCH {
fprintf(stderr, "Error when initializing %s\n",
UTF8Buffer(cl->name).cString());
abort();
} END_CATCH;
} else {
fprintf(stderr, "Class %s does not exist or is an array class.\n",
i->c_str());
}
}
}
bootstrapLoader->setCompiler(M);
}
for (std::vector<Class*>::iterator i = classes.begin(), e = classes.end();
i != e; ++i) {
Class* cl = *i;
cl->setOwnerClass(JavaThread::get());
}
for (std::vector<Class*>::iterator i = classes.begin(), e = classes.end();
i != e; ++i) {
Class* cl = *i;
M->compileClass(cl);
}
} else {
char* realName = (char*)alloca(size + 1);
if (size > 6 && !strcmp(&name[size - 6], ".class")) {
memcpy(realName, name, size - 6);
realName[size - 6] = 0;
} else {
memcpy(realName, name, size + 1);
}
const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName);
UserClass* cl = bootstrapLoader->loadName(utf8, true, true);
if (!M->clinits->empty()) {
vm->loadBootstrap();
cl->initialiseClass(vm);
bootstrapLoader->setCompiler(M);
}
cl->setOwnerClass(JavaThread::get());
cl->resolveInnerOuterClasses();
for (uint32 i = 0; i < cl->nbInnerClasses; ++i) {
cl->innerClasses[i]->setOwnerClass(JavaThread::get());
M->compileClass(cl->innerClasses[i]);
}
M->compileClass(cl);
}
if (M->compileRT) {
// Make sure that if we compile RT, the native classes are emitted.
M->getNativeClass(bootstrapLoader->upcalls->OfVoid);
M->getNativeClass(bootstrapLoader->upcalls->OfBool);
M->getNativeClass(bootstrapLoader->upcalls->OfByte);
M->getNativeClass(bootstrapLoader->upcalls->OfChar);
M->getNativeClass(bootstrapLoader->upcalls->OfShort);
M->getNativeClass(bootstrapLoader->upcalls->OfInt);
M->getNativeClass(bootstrapLoader->upcalls->OfFloat);
M->getNativeClass(bootstrapLoader->upcalls->OfLong);
M->getNativeClass(bootstrapLoader->upcalls->OfDouble);
// Also do not allow inling of some functions.
#define SET_INLINE(NAME) { \
const UTF8* name = bootstrapLoader->asciizConstructUTF8(NAME); \
Class* cl = (Class*)bootstrapLoader->lookupClass(name); \
if (cl) M->setNoInline(cl); }
SET_INLINE("java/util/concurrent/atomic/AtomicReferenceFieldUpdater")
SET_INLINE("java/util/concurrent/atomic/AtomicReferenceFieldUpdater"
"$AtomicReferenceFieldUpdaterImpl")
SET_INLINE("java/util/concurrent/atomic/AtomicIntegerFieldUpdater")
SET_INLINE("java/util/concurrent/atomic/AtomicIntegerFieldUpdater"
"$AtomicIntegerFieldUpdaterImpl")
SET_INLINE("java/util/concurrent/atomic/AtomicLongFieldUpdater")
SET_INLINE("java/util/concurrent/atomic/AtomicLongFieldUpdater"
"$CASUpdater")
SET_INLINE("java/util/concurrent/atomic/AtomicLongFieldUpdater"
"$LockedUpdater")
#undef SET_INLINE
}
M->CreateStaticInitializer();
end:
vm->threadSystem.nonDaemonLock.lock();
--(vm->threadSystem.nonDaemonThreads);
if (vm->threadSystem.nonDaemonThreads == 0)
vm->threadSystem.nonDaemonVar.signal();
vm->threadSystem.nonDaemonLock.unlock();
}
void JavaAOTCompiler::compileFile(Jnjvm* vm, const char* n) {
name = n;
JavaThread* th = new JavaThread(0, 0, vm);
vm->setMainThread(th);
th->start((void (*)(mvm::Thread*))mainCompilerStart);
vm->waitForExit();
}
/// compileAllStubs - Compile all the native -> Java stubs.
/// TODO: Once LLVM supports va_arg, enable AP.
///
void JavaAOTCompiler::compileAllStubs(Signdef* sign) {
sign->getStaticCallBuf();
// getStaticCallAP();
sign->getVirtualCallBuf();
// getVirtualCallAP();
}
void JavaAOTCompiler::generateMain(const char* name, bool jit) {
// Type Definitions
std::vector<const Type*> FuncArgs;
FuncArgs.push_back(Type::getInt32Ty(getLLVMContext()));
FuncArgs.push_back(PointerType::getUnqual(JavaIntrinsics.ptrType));
FunctionType* FuncTy = FunctionType::get(Type::getInt32Ty(getLLVMContext()),
FuncArgs, false);
Function* MainFunc = Function::Create(FuncTy, GlobalValue::ExternalLinkage,
"main", TheModule);
BasicBlock* currentBlock = BasicBlock::Create(getLLVMContext(), "enter",
MainFunc);
GlobalVariable* GvarArrayStr = new GlobalVariable(
*TheModule, ArrayType::get(Type::getInt8Ty(getLLVMContext()),
strlen(name) + 1),
true, GlobalValue::InternalLinkage, 0, "mainClass");
Constant* NameArray = ConstantArray::get(getLLVMContext(), name, true);
GvarArrayStr->setInitializer(NameArray);
Value* Indices[2] = { JavaIntrinsics.constantZero,
JavaIntrinsics.constantZero };
Value* ArgName = ConstantExpr::getGetElementPtr(GvarArrayStr, Indices, 2);
Function::arg_iterator FuncVals = MainFunc->arg_begin();
Value* Argc = FuncVals++;
Value* Argv = FuncVals++;
Value* Args[3] = { Argc, Argv, ArgName };
FuncArgs.push_back(Args[2]->getType());
FuncTy = FunctionType::get(Type::getInt32Ty(getLLVMContext()), FuncArgs, false);
Function* CalledFunc =
Function::Create(FuncTy, GlobalValue::ExternalLinkage,
jit ? "StartJnjvmWithJIT" : "StartJnjvmWithoutJIT",
TheModule);
Value* res = CallInst::Create(CalledFunc, Args, Args + 3, "", currentBlock);
ReturnInst::Create(getLLVMContext(), res, currentBlock);
}
// Use a FakeFunction to return from loadMethod, so that the compiler thinks
// the method is defined by J3.
extern "C" void __JavaAOTFakeFunction__() {}
void* JavaAOTCompiler::loadMethod(void* handle, const char* symbol) {
Function* F = mvm::MvmModule::globalModule->getFunction(symbol);
if (F) {
return (void*)(uintptr_t)__JavaAOTFakeFunction__;
}
return JavaCompiler::loadMethod(handle, symbol);
}
#ifdef WITH_MMTK
#include <set>
extern std::set<gc*> __InternalSet__;
CommonClass* JavaAOTCompiler::getUniqueBaseClass(CommonClass* cl) {
std::set<gc*>::iterator I = __InternalSet__.begin();
std::set<gc*>::iterator E = __InternalSet__.end();
CommonClass* currentClass = 0;
for (; I != E; ++I) {
JavaObject* obj = (JavaObject*)(*I);
if (!VMClassLoader::isVMClassLoader(obj) && obj->instanceOf(cl)) {
if (currentClass) {
if (obj->getClass() != currentClass) {
return 0;
}
} else {
currentClass = obj->getClass();
}
}
}
return currentClass;
}
#else
CommonClass* JavaAOTCompiler::getUniqueBaseClass(CommonClass* cl) {
return 0;
}
#endif