blob: c7ebd7065af61da2c97490e24df8864835eea3f7 [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/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/IR/DataLayout.h"
#include "vmkit/UTF8.h"
#include "vmkit/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 "VMStaticInstance.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 precompile || (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;
}
}
void JavaAOTCompiler::AddInitializerToClass(GlobalVariable* varGV, CommonClass* classDef) {
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() && compileRT) {
Constant* C =
CreateConstantFromClassPrimitive(classDef->asPrimitiveClass());
varGV->setInitializer(C);
}
}
GlobalVariable* 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) {
llvm::Type* Ty = NULL;
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 (!precompile || classDef->isPrimitive()) {
AddInitializerToClass(varGV, classDef);
}
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) {
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::CreateConstantFromJavaConstantPool(JavaConstantPool* ctp) {
StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaConstantPoolType->getContainedType(0));
Module& Mod = *getLLVMModule();
std::vector<Constant*> Elemts;
// Class
Elemts.push_back(getNativeClass(ctp->classDef));
// ctpSize
Elemts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), ctp->ctpSize));
// ctpType
ArrayType* ATy = ArrayType::get(Type::getInt8Ty(getLLVMContext()), ctp->ctpSize);
std::vector<Constant*> Vals;
for (uint32 i = 0; i < ctp->ctpSize; ++i) {
Vals.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()), ctp->ctpType[i]));
}
Constant* Array = ConstantArray::get(ATy, Vals);
GlobalVariable* varGV = new GlobalVariable(Mod, Array->getType(), false,
GlobalValue::InternalLinkage,
Array, "");
Array = ConstantExpr::getBitCast(
varGV, PointerType::getUnqual(Type::getInt8Ty(getLLVMContext())));
Elemts.push_back(Array);
// ctpDef
ATy = ArrayType::get(Type::getInt32Ty(getLLVMContext()), ctp->ctpSize);
Vals.clear();
for (uint32 i = 0; i < ctp->ctpSize; ++i) {
Vals.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), ctp->ctpDef[i]));
}
Array = ConstantArray::get(ATy, Vals);
varGV = new GlobalVariable(Mod, Array->getType(), false,
GlobalValue::InternalLinkage,
Array, "");
Array = ConstantExpr::getBitCast(
varGV, PointerType::getUnqual(Type::getInt32Ty(getLLVMContext())));
Elemts.push_back(Array);
// ctpRes
Elemts.push_back(getResolvedConstantPool(ctp));
return ConstantStruct::get(STy, Elemts);
}
Constant* JavaAOTCompiler::getResolvedConstantPool(JavaConstantPool* ctp) {
resolved_constant_pool_iterator End = resolvedConstantPools.end();
resolved_constant_pool_iterator I = resolvedConstantPools.find(ctp);
if (I == End) {
Module& Mod = *getLLVMModule();
ArrayType* ATy = ArrayType::get(JavaIntrinsics.ptrType, ctp->ctpSize);
std::vector<Constant*> Vals;
for (uint32 i = 0; i < ctp->ctpSize; ++i) {
if (ctp->typeAt(i) == JavaConstantPool::ConstantUTF8) {
Vals.push_back(ConstantExpr::getBitCast(getUTF8(ctp->UTF8At(i)), JavaIntrinsics.ptrType));
} else if (ctp->typeAt(i) == JavaConstantPool::ConstantClass
&& (ctp->isClassLoaded(i) != NULL)) {
Vals.push_back(ConstantExpr::getBitCast(
getNativeClass(ctp->isClassLoaded(i)), JavaIntrinsics.ptrType));
} else {
Vals.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
}
}
Constant* Array = ConstantArray::get(ATy, Vals);
GlobalVariable* varGV = new GlobalVariable(Mod, Array->getType(), false,
GlobalValue::InternalLinkage,
Array, "");
Array = ConstantExpr::getBitCast(varGV, JavaIntrinsics.ResolvedConstantPoolType);
resolvedConstantPools.insert(std::make_pair(ctp, Array));
return Array;
} 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();
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) {
llvm_gcroot(str, 0);
assert(!useCooperativeGC());
string_iterator SI = strings.find(str);
if (SI != strings.end()) {
return SI->second;
} else {
assert(str && "No string given");
LLVMClassInfo* LCI = getClassInfo(JavaObject::getClass(str)->asClass());
llvm::Type* Ty = LCI->getVirtualType();
Module& Mod = *getLLVMModule();
const char* name = JavaString::strToAsciiz(str);
GlobalVariable* varGV =
new GlobalVariable(Mod, Ty->getContainedType(0), false,
GlobalValue::ExternalLinkage, 0, "str");
delete[] name;
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::getClassBytes(const UTF8* className, ClassBytes* bytes) {
class_bytes_iterator CI = classBytes.find(bytes);
if (CI != classBytes.end()) {
return CI->second;
}
std::vector<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Type::getInt8Ty(getLLVMContext()), bytes->size);
Elemts.push_back(Type::getInt32Ty(getLLVMContext()));
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMContext(), Elemts);
std::string name(UTF8Buffer(className).toCompileName("_bytes")->cString());
Constant* C = emitClassBytes ? CreateConstantFromClassBytes(bytes) : NULL;
GlobalVariable* varGV = new GlobalVariable(*getLLVMModule(), STy, false,
GlobalValue::ExternalLinkage,
C, name);
classBytes[bytes] = varGV;
return varGV;
}
Constant* JavaAOTCompiler::getStringPtr(JavaString** str) {
fprintf(stderr, "Implement me");
abort();
}
Constant* JavaAOTCompiler::getJavaClass(CommonClass* cl) {
return Constant::getNullValue(JavaIntrinsics.JavaObjectType);
}
Constant* JavaAOTCompiler::getJavaClassPtr(CommonClass* cl) {
// 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;
}
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) {
word_t* realObj = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(realObj, 0);
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)) {
realObj = (word_t*)obj;
word_t size = realObj[0];
ArrayType* ATy = ArrayType::get(JavaIntrinsics.JavaObjectType,
size + 1);
std::vector<Constant*> Vals;
for (uint32 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_gcroot(obj, 0);
assert(!useCooperativeGC());
llvm::GlobalVariable* varGV = 0;
final_object_iterator End = finalObjects.end();
final_object_iterator I = finalObjects.find(obj);
if (I == End) {
if (vmkit::Collector::begOf(obj)) {
Type* Ty = 0;
CommonClass* cl = JavaObject::getClass(obj);
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<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Ty, JavaArray::getSize(obj));
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) {
JavaObject* val = 0;
JavaString* obj = 0;
llvm_gcroot(val, 0);
llvm_gcroot(obj, 0);
LLVMClassInfo* LCI = getClassInfo(cl);
Type* Ty = LCI->getStaticType();
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);
Type* Ty = LAI.llvmType;
JavaAttribute* attribute = field.lookupAttribute(JavaAttribute::constantAttribute);
if (attribute == NULL) {
if ((cl->getStaticInstance() != NULL) && !useCooperativeGC()) {
if (type->isPrimitive()) {
const PrimitiveTypedef* prim = (const PrimitiveTypedef*)type;
if (prim->isBool() || prim->isByte()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt8Ty(getLLVMContext()),
field.getStaticInt8Field());
Elts.push_back(CI);
} else if (prim->isShort() || prim->isChar()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt16Ty(getLLVMContext()),
field.getStaticInt16Field());
Elts.push_back(CI);
} else if (prim->isInt()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt32Ty(getLLVMContext()),
field.getStaticInt32Field());
Elts.push_back(CI);
} else if (prim->isLong()) {
ConstantInt* CI = ConstantInt::get(
Type::getInt64Ty(getLLVMContext()),
field.getStaticLongField());
Elts.push_back(CI);
} else if (prim->isFloat()) {
Constant* CF = ConstantFP::get(
Type::getFloatTy(getLLVMContext()),
field.getStaticFloatField());
Elts.push_back(CF);
} else if (prim->isDouble()) {
Constant* CF = ConstantFP::get(
Type::getDoubleTy(getLLVMContext()),
field.getStaticDoubleField());
Elts.push_back(CF);
} else {
abort();
}
} else {
val = field.getStaticObjectField();
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(attribute, 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()) {
if (useCooperativeGC()) {
Elts.push_back(JavaIntrinsics.JavaObjectNullConstant);
} else {
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]);
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) {
static_instance_iterator End = staticInstances.end();
static_instance_iterator I = staticInstances.find(classDef);
if (I == End) {
LLVMClassInfo* LCI = getClassInfo(classDef);
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) {
ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
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 ((precompile && classDef->isPrimitive())
|| (!precompile && (isCompiling(classDef) || assumeCompiled))) {
varGV->setInitializer(CreateConstantFromVT(VT));
}
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());
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) {
assert(!useCooperativeGC());
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::CreateConstantFromJavaObject(JavaObject* obj) {
JavaObject* val = 0;
ArrayObject* array = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(val, 0);
llvm_gcroot(array, 0);
assert(!useCooperativeGC());
CommonClass* cl = JavaObject::getClass(obj);
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 {
array = (ArrayObject*)obj;
return CreateConstantFromObjectArray(array);
}
} else {
std::vector<Constant*> Elmts;
// JavaObject
Constant* CurConstant =
CreateConstantForBaseObject(JavaObject::getClass(obj));
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);
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.getInstanceInt8Field(obj));
TempElts.push_back(CI);
} else if (prim->isShort() || prim->isChar()) {
ConstantInt* CI = ConstantInt::get(Type::getInt16Ty(getLLVMContext()),
field.getInstanceInt16Field(obj));
TempElts.push_back(CI);
} else if (prim->isInt()) {
ConstantInt* CI = ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
field.getInstanceInt32Field(obj));
TempElts.push_back(CI);
} else if (prim->isLong()) {
ConstantInt* CI = ConstantInt::get(Type::getInt64Ty(getLLVMContext()),
field.getInstanceLongField(obj));
TempElts.push_back(CI);
} else if (prim->isFloat()) {
Constant* CF = ConstantFP::get(Type::getFloatTy(getLLVMContext()),
field.getInstanceFloatField(obj));
TempElts.push_back(CF);
} else if (prim->isDouble()) {
Constant* CF = ConstantFP::get(Type::getDoubleTy(getLLVMContext()),
field.getInstanceDoubleField(obj));
TempElts.push_back(CF);
} else {
abort();
}
} else {
val = field.getInstanceObjectField(obj);
if (val) {
JnjvmClassLoader* JCL = cl->classLoader;
CommonClass* FieldCl = field.getSignature()->assocClass(JCL);
Constant* C = getFinalObject(val, FieldCl);
TempElts.push_back(C);
} else {
llvm::Type* Ty = JavaIntrinsics.JavaObjectType;
TempElts.push_back(Constant::getNullValue(Ty));
}
}
}
CurConstant = ConstantStruct::get(STy, TempElts);
}
return CurConstant;
}
}
Constant* JavaAOTCompiler::CreateConstantFromJavaString(JavaString* str) {
llvm_gcroot(str, 0);
assert(!useCooperativeGC());
Class* cl = JavaObject::getClass(str)->asClass();
LLVMClassInfo* LCI = getClassInfo(cl);
StructType* STy =
dyn_cast<StructType>(LCI->getVirtualType()->getContainedType(0));
std::vector<Constant*> Elmts;
Elmts.push_back(CreateConstantForBaseObject(cl));
Constant* Array =
CreateConstantFromIntArray<ArrayUInt16>(JavaString::getValue(str),
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);
#ifndef USE_OPENJDK
// Classpath fields
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));
#else
// OpenJDK fields
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->offset));
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->count));
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()),
str->cachedHashCode));
#endif
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromAttribute(JavaAttribute& attribute) {
StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.AttributeType->getContainedType(0));
std::vector<Constant*> Elmts;
// name
Elmts.push_back(getUTF8(attribute.name));
// start
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), attribute.start));
// nbb
Elmts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), attribute.nbb));
return ConstantStruct::get(STy, Elmts);
}
Constant* JavaAOTCompiler::CreateConstantFromCommonClass(CommonClass* cl) {
StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.JavaCommonClassType->getContainedType(0));
Module& Mod = *getLLVMModule();
llvm::Type* TempTy = NULL;
std::vector<Constant*> CommonClassElts;
std::vector<Constant*> TempElmts;
// delegatee
ArrayType* ATy = dyn_cast<ArrayType>(STy->getContainedType(0));
assert(ATy && "Malformed type");
Constant* TCM[1] = { getJavaClass(cl) };
CommonClassElts.push_back(ConstantArray::get(ATy, TCM));
// access
CommonClassElts.push_back(ConstantInt::get(Type::getInt32Ty(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 {
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));
}
CommonClassElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// 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) {
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));
// attributes
if (field.nbAttributes) {
llvm::Type* AttrTy = JavaIntrinsics.AttributeType->getContainedType(0);
ArrayType* ATy = ArrayType::get(AttrTy, field.nbAttributes);
for (uint32 i = 0; i < field.nbAttributes; ++i) {
TempElts.push_back(CreateConstantFromAttribute(field.attributes[i]));
}
Constant* attributes = ConstantArray::get(ATy, TempElts);
TempElts.clear();
attributes = new GlobalVariable(*getLLVMModule(), ATy, true,
GlobalValue::InternalLinkage,
attributes, "");
attributes = ConstantExpr::getCast(Instruction::BitCast, attributes,
JavaIntrinsics.AttributeType);
FieldElts.push_back(attributes);
} else {
FieldElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributeType));
}
// nbAttributes
FieldElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), field.nbAttributes));
// 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) {
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));
// attributes
if (method.nbAttributes) {
llvm::Type* AttrTy = JavaIntrinsics.AttributeType->getContainedType(0);
ArrayType* ATy = ArrayType::get(AttrTy, method.nbAttributes);
for (uint32 i = 0; i < method.nbAttributes; ++i) {
TempElts.push_back(CreateConstantFromAttribute(method.attributes[i]));
}
Constant* attributes = ConstantArray::get(ATy, TempElts);
TempElts.clear();
attributes = new GlobalVariable(Mod, ATy, true,
GlobalValue::InternalLinkage,
attributes, "");
attributes = ConstantExpr::getCast(Instruction::BitCast, attributes,
JavaIntrinsics.AttributeType);
MethodElts.push_back(attributes);
} else {
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributeType));
}
// nbAttributes
MethodElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), method.nbAttributes));
// 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.isCustomizable));
// code
if (getMethodInfo(&method)->methodFunction == NULL) {
MethodElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
} else {
assert(!isAbstract(method.access));
Function* func = getMethod(&method, NULL);
MethodElts.push_back(ConstantExpr::getCast(Instruction::BitCast, func,
JavaIntrinsics.ptrType));
}
// offset
MethodElts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), method.offset));
return ConstantStruct::get(STy, MethodElts);
}
Constant* JavaAOTCompiler::CreateConstantFromClassPrimitive(ClassPrimitive* cl) {
llvm::Type* JCPTy =
JavaIntrinsics.JavaClassPrimitiveType->getContainedType(0);
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) {
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::CreateConstantFromClassMap(const vmkit::VmkitDenseMap<const UTF8*, CommonClass*>& map) {
StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.J3DenseMapType->getContainedType(0));
Module& Mod = *getLLVMModule();
std::vector<Constant*> elements;
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), map.NumBuckets));
Constant* buckets;
if (map.NumBuckets > 0) {
std::vector<Constant*> TempElts;
ArrayType* ATy = ArrayType::get(JavaIntrinsics.ptrType, map.NumBuckets * 2);
for (uint32 i = 0; i < map.NumBuckets; ++i) {
vmkit::VmkitPair<const UTF8*, CommonClass*> pair = map.Buckets[i];
if (pair.first == &vmkit::TombstoneKey) {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, UTF8TombstoneGV, JavaIntrinsics.ptrType));
TempElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
} else if (pair.first == &vmkit::EmptyKey) {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, UTF8EmptyGV, JavaIntrinsics.ptrType));
TempElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
} else {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, getUTF8(pair.first), JavaIntrinsics.ptrType));
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, getNativeClass(pair.second), JavaIntrinsics.ptrType));
}
}
buckets = ConstantArray::get(ATy, TempElts);
GlobalVariable* gv = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, buckets, "");
buckets = ConstantExpr::getCast(Instruction::BitCast, gv, JavaIntrinsics.ptrType);
} else {
buckets = Constant::getNullValue(JavaIntrinsics.ptrType);
}
elements.push_back(buckets);
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), map.NumEntries));
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), map.NumTombstones));
elements.push_back(ConstantInt::get(Type::getInt1Ty(getLLVMContext()), 1));
return new GlobalVariable(Mod, STy, false,
GlobalValue::ExternalLinkage,
ConstantStruct::get(STy, elements), "ClassMap");
}
Constant* JavaAOTCompiler::CreateConstantFromUTF8Map(const vmkit::VmkitDenseSet<vmkit::UTF8MapKey, const UTF8*>& set) {
StructType* STy =
dyn_cast<StructType>(JavaIntrinsics.J3DenseMapType->getContainedType(0));
Module& Mod = *getLLVMModule();
std::vector<Constant*> elements;
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), set.NumBuckets));
Constant* buckets;
if (set.NumBuckets > 0) {
std::vector<Constant*> TempElts;
ArrayType* ATy = ArrayType::get(JavaIntrinsics.ptrType, set.NumBuckets);
for (uint32 i = 0; i < set.NumBuckets; ++i) {
const UTF8* utf8 = set.Buckets[i];
if (utf8 == &vmkit::EmptyKey) {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, UTF8EmptyGV, JavaIntrinsics.ptrType));
} else if (utf8 == &vmkit::TombstoneKey) {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, UTF8TombstoneGV, JavaIntrinsics.ptrType));
} else {
TempElts.push_back(ConstantExpr::getCast(Instruction::BitCast, getUTF8(utf8), JavaIntrinsics.ptrType));
}
}
buckets = ConstantArray::get(ATy, TempElts);
GlobalVariable* gv = new GlobalVariable(Mod, ATy, false, GlobalValue::InternalLinkage, buckets, "");
buckets = ConstantExpr::getCast(Instruction::BitCast, gv, JavaIntrinsics.ptrType);
} else {
buckets = Constant::getNullValue(JavaIntrinsics.ptrType);
}
elements.push_back(buckets);
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), set.NumEntries));
elements.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), set.NumTombstones));
elements.push_back(ConstantInt::get(Type::getInt1Ty(getLLVMContext()), 1));
return new GlobalVariable(Mod, STy, false,
GlobalValue::ExternalLinkage,
ConstantStruct::get(STy, elements), "UTF8Map");
}
Constant* JavaAOTCompiler::CreateConstantFromClass(Class* cl) {
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
ArrayType* ATy = dyn_cast<ArrayType>(STy->getContainedType(3));
assert(ATy && "Malformed type");
StructType* TCMTy = dyn_cast<StructType>(ATy->getContainedType(0));
assert(TCMTy && "Malformed type");
TempElts.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()),
cl->getInitializationState()));
TempElts.push_back(ConstantInt::get(Type::getInt1Ty(getLLVMContext()),
cl->isReady() ? 1 : 0));
TempElts.push_back(getStaticInstance(cl));
Constant* CStr[1] = { ConstantStruct::get(TCMTy, TempElts) };
TempElts.clear();
ClassElts.push_back(ConstantArray::get(ATy, CStr));
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
ClassElts.push_back(ConstantExpr::getGetElementPtr(fields, nbVirtualFields));
// 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
ClassElts.push_back(ConstantExpr::getGetElementPtr(methods, nbVirtualMethods));
// nbStaticMethods
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbStaticMethods));
// ownerClass
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.ptrType));
// bytes
if (precompile) {
ClassElts.push_back(ConstantExpr::getBitCast(getClassBytes(cl->name, cl->bytes),
JavaIntrinsics.ClassBytesType));
} else {
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.ClassBytesType));
}
// ctpInfo
Constant* ctpInfo = CreateConstantFromJavaConstantPool(cl->ctpInfo);
Constant* varGV = new GlobalVariable(*getLLVMModule(), ctpInfo->getType(), false,
GlobalValue::InternalLinkage,
ctpInfo, "");
ClassElts.push_back(varGV);
// attributes
if (cl->nbAttributes) {
ATy = ArrayType::get(JavaIntrinsics.AttributeType->getContainedType(0),
cl->nbAttributes);
for (uint32 i = 0; i < cl->nbAttributes; ++i) {
TempElts.push_back(CreateConstantFromAttribute(cl->attributes[i]));
}
Constant* attributes = ConstantArray::get(ATy, TempElts);
TempElts.clear();
attributes = new GlobalVariable(*getLLVMModule(), ATy, true,
GlobalValue::InternalLinkage,
attributes, "");
attributes = ConstantExpr::getCast(Instruction::BitCast, attributes,
JavaIntrinsics.AttributeType);
ClassElts.push_back(attributes);
} else {
ClassElts.push_back(Constant::getNullValue(JavaIntrinsics.AttributeType));
}
// nbAttributes
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->nbAttributes));
// innerClasses
if (cl->nbInnerClasses) {
for (uint32 i = 0; i < cl->nbInnerClasses; ++i) {
TempElts.push_back(getNativeClass(cl->innerClasses[i]));
}
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 {
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));
// minJDKVersionMajor
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->minJDKVersionMajor));
// minJDKVersionMinor
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->minJDKVersionMinor));
// minJDKVersionBuild
ClassElts.push_back(ConstantInt::get(Type::getInt16Ty(getLLVMContext()), cl->minJDKVersionBuild));
return ConstantStruct::get(STy, ClassElts);
}
Constant* JavaAOTCompiler::CreateConstantFromClassBytes(ClassBytes* bytes) {
std::vector<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Type::getInt8Ty(getLLVMContext()), bytes->size);
Elemts.push_back(Type::getInt32Ty(getLLVMContext()));
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(ConstantInt::get(Type::getInt32Ty(getLLVMContext()), bytes->size));
std::vector<Constant*> Vals;
for (uint32 i = 0; i < bytes->size; ++i) {
Vals.push_back(ConstantInt::get(Type::getInt8Ty(getLLVMContext()), bytes->elements[i]));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
template<typename T>
Constant* JavaAOTCompiler::CreateConstantFromIntArray(const T* val, Type* Ty) {
assert(!useCooperativeGC());
std::vector<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Ty, T::getSize(val));
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(JavaObject::getClass(val)));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, T::getSize(val)));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < T::getSize(val); ++i) {
Vals.push_back(ConstantInt::get(Ty, (uint64)T::getElement(val, i)));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
template<typename T>
Constant* JavaAOTCompiler::CreateConstantFromFPArray(const T* val, Type* Ty) {
assert(!useCooperativeGC());
std::vector<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Ty, T::getSize(val));
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(JavaObject::getClass(val)));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType, T::getSize(val)));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < T::getSize(val); ++i) {
Vals.push_back(ConstantFP::get(Ty, (double)T::getElement(val, i)));
}
Cts.push_back(ConstantArray::get(ATy, Vals));
return ConstantStruct::get(STy, Cts);
}
Constant* JavaAOTCompiler::CreateConstantFromObjectArray(const ArrayObject* val) {
JavaObject* obj = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(val, 0);
assert(!useCooperativeGC());
std::vector<Type*> Elemts;
llvm::Type* Ty = JavaIntrinsics.JavaObjectType;
ArrayType* ATy = ArrayType::get(Ty, ArrayObject::getSize(val));
Elemts.push_back(JavaIntrinsics.JavaObjectType->getContainedType(0));
Elemts.push_back(JavaIntrinsics.pointerSizeType);
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMModule()->getContext(), Elemts);
std::vector<Constant*> Cts;
Cts.push_back(CreateConstantForBaseObject(JavaObject::getClass(val)));
Cts.push_back(ConstantInt::get(JavaIntrinsics.pointerSizeType,
ArrayObject::getSize(val)));
std::vector<Constant*> Vals;
for (sint32 i = 0; i < ArrayObject::getSize(val); ++i) {
obj = ArrayObject::getElement(val, i);
if (obj) {
Vals.push_back(getFinalObject(obj,
JavaObject::getClass(val)->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<Type*> Elemts;
ArrayType* ATy = ArrayType::get(Type::getInt16Ty(getLLVMContext()), val->size);
Elemts.push_back(JavaIntrinsics.UTF8SizeType);
Elemts.push_back(ATy);
StructType* STy = StructType::get(getLLVMModule()->getContext(),
Elemts);
std::vector<Constant*> Cts;
Cts.push_back(ConstantInt::get(JavaIntrinsics.UTF8SizeType, val->size));
ArrayRef<uint16_t> Vals(val->elements, val->size);
Cts.push_back(ConstantDataArray::get(getLLVMContext(), 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;
}
}
Function* JavaAOTCompiler::getMethodOrStub(JavaMethod* meth, Class* customizeFor) {
assert(!isStatic(meth->access));
LLVMMethodInfo* LMI = getMethodInfo(meth);
LLVMSignatureInfo* LSI = getSignatureInfo(meth->getSignature());
if (precompile) {
if (customizeFor != NULL) {
if (LMI->isCustomizable) {
if (LMI->customizedVersions[customizeFor] != NULL) {
// We have a customized version, get it.
return getMethod(meth, customizeFor);
} else {
// No customized version, even if there is an uncustomized version,
// we return the stub, so that we get a customized version at
// runtime.
return LSI->getVirtualStub();
}
} else {
// If we have created a method for it, we know the method is not customizable,
// and we can use the 'general' method.
if (LMI->methodFunction) {
return getMethod(meth, NULL);
} else {
// Otherwise, no method has been created for it.
return LSI->getVirtualStub();
}
}
} else {
// If we have created a method for it, take it.
if (LMI->methodFunction) {
return getMethod(meth, NULL);
} else {
// Otherwise, no method has been created for it.
return LSI->getVirtualStub();
}
}
} else {
// We're not precompiling, get the method.
return getMethod(meth, NULL);
}
}
Function* JavaAOTCompiler::getMethod(JavaMethod* meth, Class* customizeFor) {
Function* func = getMethodInfo(meth)->getMethod(customizeFor);
if (func->hasExternalWeakLinkage()) {
toCompile.push_back(std::make_pair(meth, customizeFor));
}
return func;
}
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;
Class* maybeCustomize = classDef->isClass() ? classDef->asClass() : NULL;
ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
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 = NULL;
if (VT->hasDestructor()) {
JavaMethod* meth = (JavaMethod*)(RealVT->destructor);
Finalizer = getMethodOrStub(meth, maybeCustomize);
} else {
Finalizer = EmptyDestructorFunction;
}
Elemts.push_back(ConstantExpr::getCast(Instruction::BitCast, Finalizer, PTy));
// Delete
Elemts.push_back(N);
// Tracer
Function* Tracer = 0;
if (classDef->isArray()) {
if (classDef->asArrayClass()->baseClass()->isPrimitive()) {
Tracer = JavaObjectTracer;
} else {
Tracer = ArrayObjectTracer;
}
} else if (classDef->isClass()) {
if (classDef->isSubclassOf(
classDef->classLoader->bootstrapLoader->upcalls->newReference)) {
Tracer = ReferenceObjectTracer;
} else {
Tracer = RegularObjectTracer;
}
}
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
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 {
// TODO: add a null element at the end to diagnose errors.
Class* cl = classDef->asClass();
assert(cl && "Not a class");
std::set<JavaMethod*> contents[InterfaceMethodTable::NumIndexes];
classDef->asClass()->fillIMT(contents);
ArrayType* ATy =
dyn_cast<ArrayType>(JavaIntrinsics.VTType->getContainedType(0));
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");
Function* func = getMethodOrStub(meth, maybeCustomize);
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");
Function* func = getMethodOrStub(methods[0], maybeCustomize);
IElemts.push_back(ConstantExpr::getBitCast(func, PTy));
} else {
uint32_t length = 2 * size;
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");
Function* func = getMethodOrStub(Cmeth, maybeCustomize);
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, JavaIntrinsics.pointerSizeType);
CI = ConstantExpr::getAdd(CI,
ConstantExpr::getIntegerCast(JavaIntrinsics.constantOne,
JavaIntrinsics.pointerSizeType,
false));
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];
// Primitive classes don't have methods--abstract or otherwise.
// (But we do have placeholders for j.l.Object methods in their VTs,
// so just emit NULL's here)
if (classDef->isPrimitive() || isAbstract(meth->access)) {
Elemts.push_back(Constant::getNullValue(PTy));
} else {
Function* F = getMethodOrStub(meth, maybeCustomize);
Elemts.push_back(ConstantExpr::getCast(Instruction::BitCast, F, PTy));
}
}
Constant* Array = ConstantArray::get(ATy, Elemts);
return Array;
}
JavaAOTCompiler::JavaAOTCompiler(
const std::string& ModuleID, bool compiling_garbage_collector) :
JavaLLVMCompiler(ModuleID, compiling_garbage_collector) {
std::string Error;
const Target* TheTarget(TargetRegistry::lookupTarget(
vmkit::VmkitModule::getHostTriple(), Error));
TargetOptions options;
options.NoFramePointerElim = true;
TargetMachine* TM = TheTarget->createTargetMachine(
vmkit::VmkitModule::getHostTriple(), "", "", options);
TheDataLayout = TM->getDataLayout();
TheModule->setDataLayout(TheDataLayout->getStringRepresentation());
TheModule->setTargetTriple(TM->getTargetTriple());
JavaIntrinsics.init(TheModule);
initialiseAssessorInfo();
generateStubs = true;
assumeCompiled = false;
compileRT = false;
precompile = false;
emitClassBytes = false;
std::vector<llvm::Type*> llvmArgs;
FunctionType* 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());
ArrayObjectTracer = Function::Create(FTy, GlobalValue::ExternalLinkage,
"ArrayObjectTracer", getLLVMModule());
RegularObjectTracer = Function::Create(FTy,
GlobalValue::ExternalLinkage,
"RegularObjectTracer",
getLLVMModule());
JavaObjectTracer = Function::Create(FTy, GlobalValue::ExternalLinkage,
"JavaObjectTracer", getLLVMModule());
ReferenceObjectTracer = Function::Create(FTy,
GlobalValue::ExternalLinkage,
"ReferenceObjectTracer",
getLLVMModule());
EmptyDestructorFunction = Function::Create(FTy,
GlobalValue::ExternalLinkage,
"EmptyDestructor",
getLLVMModule());
UTF8EmptyGV = new GlobalVariable(*getLLVMModule(),
JavaIntrinsics.UTF8Type->getContainedType(0),
false, GlobalValue::ExternalLinkage, NULL,
"EmptyKey");
UTF8TombstoneGV = new GlobalVariable(*getLLVMModule(),
JavaIntrinsics.UTF8Type->getContainedType(0),
false, GlobalValue::ExternalLinkage, NULL,
"TombstoneKey");
}
void JavaAOTCompiler::printStats() {
fprintf(stdout, "----------------- Info from the module -----------------\n");
fprintf(stdout, "Number of native classes : %llu\n",
(unsigned long long int) nativeClasses.size());
fprintf(stdout, "Number of Java classes : %llu\n",
(unsigned long long int) javaClasses.size());
fprintf(stdout, "Number of external array classes : %llu\n",
(unsigned long long int) arrayClasses.size());
fprintf(stdout, "Number of virtual tables : %llu\n",
(unsigned long long int) virtualTables.size());
fprintf(stdout, "Number of static instances : %llu\n",
(unsigned long long int) staticInstances.size());
fprintf(stdout, "Number of constant pools : %llu\n",
(unsigned long long int) resolvedConstantPools.size());
fprintf(stdout, "Number of strings : %llu\n",
(unsigned long long int) strings.size());
fprintf(stdout, "Number of native functions : %llu\n",
(unsigned long long int) nativeFunctions.size());
fprintf(stdout, "----------------- 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 += TheDataLayout->getTypeAllocSize(i->getType());
}
fprintf(stdout, "%lluB\n", (unsigned long long int)size);
}
void JavaAOTCompiler::CreateStaticInitializer() {
std::vector<llvm::Type*> llvmArgs;
llvmArgs.push_back(JavaIntrinsics.ptrType); // class loader
llvmArgs.push_back(JavaIntrinsics.JavaCommonClassType); // cl
FunctionType* FTy =
FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
Function* AddClass = Function::Create(FTy, GlobalValue::ExternalLinkage,
"vmjcAddPreCompiledClass",
getLLVMModule());
llvmArgs.clear();
llvmArgs.push_back(JavaIntrinsics.ptrType); // class loader.
FTy = FunctionType::get(Type::getVoidTy(getLLVMContext()), llvmArgs, false);
StaticInitializer = Function::Create(FTy, GlobalValue::InternalLinkage,
"Init", 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, ArrayRef<Value*>(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,
JavaIntrinsics.JavaCommonClassType);
CallInst::Create(AddClass, ArrayRef<Value*>(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, ArrayRef<Value*>(Args, 3), "", currentBlock);
}
ReturnInst::Create(getLLVMContext(), currentBlock);
}
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(word_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 = reinterpret_cast<word_t>(EmptyDestructor);
}
void JavaAOTCompiler::makeIMT(Class* cl) {
}
void JavaAOTCompiler::setMethod(Function* func, void* ptr, const char* name) {
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);
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, NULL);
if (generateStubs) compileAllStubs(meth.getSignature());
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
JavaMethod& meth = cl->staticMethods[i];
if (!isAbstract(meth.access)) parseFunction(&meth, NULL);
if (generateStubs) compileAllStubs(meth.getSignature());
}
}
void extractFiles(ClassBytes* bytes,
JavaAOTCompiler* M,
JnjvmBootstrapLoader* bootstrapLoader,
std::vector<Class*>& classes) {
ZipArchive archive(bytes, bootstrapLoader->allocator);
vmkit::BumpPtrAllocator allocator;
char* realName = (char*)allocator.Allocate(4096, "temp");
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")) {
memcpy(realName, name, size);
realName[size - 6] = 0;
const UTF8* utf8 = bootstrapLoader->asciizConstructUTF8(realName);
Class* cl = bootstrapLoader->loadName(utf8, true, false, NULL);
assert(cl && "Class not created");
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"))) {
ClassBytes* res = new (allocator, file->ucsize) ClassBytes(file->ucsize);
int ok = archive.readFile(res, file);
if (!ok) return;
extractFiles(res, M, bootstrapLoader, classes);
}
}
}
static const char* name;
extern "C" void UnreachableMagicMMTk() {
UNREACHABLE();
}
void mainCompilerStart(JavaThread* th) {
Jnjvm* vm = th->getJVM();
JnjvmBootstrapLoader* bootstrapLoader = vm->bootstrapLoader;
JavaAOTCompiler* M = (JavaAOTCompiler*)bootstrapLoader->getCompiler();
M->addJavaPasses();
bootstrapLoader->analyseClasspathEnv(vm->bootstrapLoader->bootClasspathEnv);
uint32 size = strlen(name);
if (size > 4 &&
(!strcmp(&name[size - 4], ".jar") || !strcmp(&name[size - 4], ".zip"))) {
bootstrapLoader->analyseClasspathEnv(name);
}
JavaJITCompiler* Comp = NULL;
if (!M->clinits->empty()) {
Comp = JavaJITCompiler::CreateCompiler("JIT");
Comp->EmitFunctionName = true;
if (!M->useCooperativeGC()) {
Comp->disableCooperativeGC();
}
bootstrapLoader->setCompiler(Comp);
bootstrapLoader->analyseClasspathEnv(vm->classpath);
} else {
bootstrapLoader->analyseClasspathEnv(vm->classpath);
bootstrapLoader->upcalls->initialiseClasspath(bootstrapLoader);
}
if (size > 4 &&
(!strcmp(&name[size - 4], ".jar") || !strcmp(&name[size - 4], ".zip"))) {
std::vector<Class*> classes;
ClassBytes* bytes = Reader::openFile(bootstrapLoader, name);
if (!bytes) {
fprintf(stderr, "Can't find zip file '%s'.\n", name);
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) {
if (!isAbstract(cl->virtualMethods[i].access)) {
M->getMethod(&cl->virtualMethods[i], NULL);
}
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
M->getMethod(&cl->staticMethods[i], NULL);
}
}
if (!M->clinits->empty()) {
vm->loadBootstrap();
// First, if we have the magic classes available, make sure we
// compile them so that we can call them directly and let
// LowerMagic lower them later on.
for (std::vector<Class*>::iterator ii = classes.begin(),
ee = classes.end(); ii != ee; ++ii) {
Class* cl = *ii;
static const std::string magic = "org/vmmagic";
static void* ptr = (void*)(word_t)UnreachableMagicMMTk;
if (!strncmp(UTF8Buffer(cl->name).cString(),
magic.c_str(),
magic.length() - 1)) {
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
if (!isAbstract(cl->virtualMethods[i].access)) {
Function* F = M->getMethod(&cl->virtualMethods[i], NULL);
M->setMethod(F, ptr, F->getName().data());
cl->virtualMethods[i].compiledPtr();
// Set native so that we don't try to inline it.
cl->virtualMethods[i].setNative();
}
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
Function* F = M->getMethod(&cl->staticMethods[i], NULL);
M->setMethod(F, ptr, F->getName().data());
cl->staticMethods[i].compiledPtr();
// Set native so that we don't try to inline it.
cl->staticMethods[i].setNative();
}
}
}
// Initialize all classes given with with the -with-clinit
// command line argument.
for (std::vector<std::string>::iterator i = M->clinits->begin(),
e = M->clinits->end(); i != e; ++i) {
Class* cl = NULL;
TRY {
if (i->at(i->length() - 1) == '*') {
for (std::vector<Class*>::iterator ii = classes.begin(),
ee = classes.end(); ii != ee; ++ii) {
cl = *ii;
if (!strncmp(UTF8Buffer(cl->name).cString(), i->c_str(),
i->length() - 1)) {
cl->initialiseClass(vm);
}
}
} else {
const UTF8* name = bootstrapLoader->asciizConstructUTF8(i->c_str());
CommonClass* cls = bootstrapLoader->lookupClass(name);
if (cls && cls->isClass()) {
cl = cls->asClass();
cl->initialiseClass(vm);
} else {
fprintf(stderr, "Class %s does not exist or is an array class.\n",
i->c_str());
}
}
} CATCH {
fprintf(stderr, "Error when initializing %s\n",
UTF8Buffer(cl->name).cString());
abort();
} END_CATCH;
}
bootstrapLoader->setCompiler(M);
}
// We don't want strings to be interned when AOT'ing, otherwise
// we would call Java code.
bootstrapLoader->upcalls->internString = NULL;
// Set the thread as the owner of the classes, so that it knows it
// has to compile them.
for (std::vector<Class*>::iterator i = classes.begin(), e = classes.end();
i != e; ++i) {
(*i)->setOwnerClass(JavaThread::get());
}
// Finally, compile all classes.
for (std::vector<Class*>::iterator i = classes.begin(), e = classes.end();
i != e; ++i) {
M->compileClass(*i);
}
} else {
vmkit::ThreadAllocator allocator;
char* realName = (char*)allocator.Allocate(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, NULL);
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);
}
M->CreateStaticInitializer();
end:
vm->threadSystem.leave();
}
void JavaAOTCompiler::compileFile(Jnjvm* vm, const char* n) {
name = n;
JavaThread* th = new JavaThread(vm);
vm->setMainThread(th);
th->start((void (*)(vmkit::Thread*))mainCompilerStart);
vm->waitForExit();
}
void JavaAOTCompiler::compileClassLoader(JnjvmBootstrapLoader* loader) {
JavaJITCompiler* jitCompiler = (JavaJITCompiler*)loader->getCompiler();
loader->setCompiler(this);
compileRT = true;
precompile = true;
addJavaPasses();
// Make sure that the native classes are emitted.
getNativeClass(loader->upcalls->OfVoid);
getNativeClass(loader->upcalls->OfBool);
getNativeClass(loader->upcalls->OfByte);
getNativeClass(loader->upcalls->OfChar);
getNativeClass(loader->upcalls->OfShort);
getNativeClass(loader->upcalls->OfInt);
getNativeClass(loader->upcalls->OfFloat);
getNativeClass(loader->upcalls->OfLong);
getNativeClass(loader->upcalls->OfDouble);
// First set all classes to resolved.
for (ClassMap::iterator i = loader->getClasses()->map.begin(),
e = loader->getClasses()->map.end(); i!= e; ++i) {
if (i->second->isClass()) {
if (i->second->asClass()->isResolved()) {
i->second->asClass()->setResolved();
} else {
i->second->asClass()->resolveClass();
}
}
}
for (method_info_iterator I = jitCompiler->method_infos.begin(),
E = jitCompiler->method_infos.end(); I != E; I++) {
if (!isAbstract(I->first->access)) {
LLVMMethodInfo* LMI = I->second;
if (LMI->methodFunction) {
parseFunction(I->first, NULL);
}
for (std::map<Class*, Function*>::iterator
CI = LMI->customizedVersions.begin(),
CE = LMI->customizedVersions.end(); CI != CE; CI++) {
parseFunction(I->first, CI->first);
}
}
}
while (!toCompile.empty()) {
JavaMethod* meth = toCompile.back().first;
Class* customizeFor = toCompile.back().second;
// parseFunction may introduce new functions to compile, so
// pop toCompile before calling parseFunction.
toCompile.pop_back();
parseFunction(meth, customizeFor);
}
// Make sure classes and arrays already referenced in constant pools
// are loaded.
for (ClassMap::iterator i = loader->getClasses()->map.begin(),
e = loader->getClasses()->map.end(); i!= e; ++i) {
if (i->second->isClass()) {
getResolvedConstantPool(i->second->asClass()->ctpInfo);
}
}
// Add all class and VT initializers.
for (ClassMap::iterator i = loader->getClasses()->map.begin(),
e = loader->getClasses()->map.end(); i!= e; ++i) {
AddInitializerToClass(getNativeClass(i->second), i->second);
JavaVirtualTable* VT = i->second->virtualVT;
GlobalVariable* gv =
dyn_cast<GlobalVariable>(getVirtualTable(VT)->getOperand(0));
gv->setInitializer(CreateConstantFromVT(VT));
}
assert(toCompile.size() == 0);
// Add used stubs to the image.
for (SignMap::iterator i = loader->javaSignatures->map.begin(),
e = loader->javaSignatures->map.end(); i != e; i++) {
Signdef* signature = i->second;
LLVMSignatureInfo* LSI = getSignatureInfo(signature);
if (signature->_staticCallBuf != 0) {
LSI->getStaticBuf();
}
if (signature->_virtualCallBuf != 0) {
LSI->getVirtualBuf();
}
if (signature->_staticCallAP != 0) {
LSI->getStaticAP();
}
if (signature->_virtualCallAP != 0) {
LSI->getVirtualAP();
}
if (signature->_virtualCallStub != 0) {
LSI->getVirtualStub();
}
if (signature->_specialCallStub != 0) {
LSI->getSpecialStub();
}
if (signature->_staticCallStub != 0) {
LSI->getStaticStub();
}
}
// Emit the stub for the main signature.
Signdef* mainSignature =
loader->constructSign(loader->asciizConstructUTF8("([Ljava/lang/String;)V"));
getSignatureInfo(mainSignature)->getStaticBuf();
// Emit the class map.
CreateConstantFromClassMap(loader->classes->map);
// Emit the UTF8 map.
CreateConstantFromUTF8Map(loader->hashUTF8->map);
// Check that we have compiled everything.
for (Module::iterator I = TheModule->begin(), E = TheModule->end();
I != E;
I++) {
assert(!I->hasExternalWeakLinkage());
}
}
void JavaAOTCompiler::generateClassBytes(JnjvmBootstrapLoader* loader) {
emitClassBytes = true;
// Add the bootstrap classes to the image.
for (std::vector<ZipArchive*>::iterator i = loader->bootArchives.begin(),
e = loader->bootArchives.end(); i != e; ++i) {
ZipArchive* archive = *i;
for (ZipArchive::table_iterator zi = archive->filetable.begin(),
ze = archive->filetable.end(); zi != ze; zi++) {
// Remove the '.class'.
const char* name = zi->first;
std::string str(name, strlen(name) - strlen(".class"));
ClassBytes* bytes = Reader::openZip(loader, archive, name);
getClassBytes(loader->asciizConstructUTF8(str.c_str()), bytes);
}
}
}
/// 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<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 = ConstantDataArray::getString(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, ArrayRef<Value*>(Args, 3), "", currentBlock);
ReturnInst::Create(getLLVMContext(), res, currentBlock);
}
// TODO: clean up to have a better interface with the fake GC.
#include <set>
extern std::set<gc*> __InternalSet__;
CommonClass* JavaAOTCompiler::getUniqueBaseClass(CommonClass* cl) {
JavaObject* obj = NULL;
llvm_gcroot(obj, 0);
std::set<gc*>::iterator I = __InternalSet__.begin();
std::set<gc*>::iterator E = __InternalSet__.end();
CommonClass* currentClass = 0;
for (; I != E; ++I) {
obj = (JavaObject*)(*I);
if (!VMClassLoader::isVMClassLoader(obj) &&
!VMStaticInstance::isVMStaticInstance(obj) &&
JavaObject::instanceOf(obj, cl)) {
if (currentClass != NULL) {
if (JavaObject::getClass(obj) != currentClass) {
return 0;
}
} else {
currentClass = JavaObject::getClass(obj);
}
}
}
return currentClass;
}