blob: 7c4378d26d3bf1113f9e92d5cecf733adee961b5 [file] [log] [blame]
//===---- JavaMetaJIT.cpp - Functions for Java internal objects -----------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <string.h>
#include <llvm/Type.h>
#include <llvm/Support/CFG.h>
#include <llvm/Module.h>
#include <llvm/Constants.h>
#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Instructions.h>
#include <llvm/ModuleProvider.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/PassManager.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Target/TargetOptions.h>
#include <llvm/CodeGen/MachineCodeEmitter.h>
#include <llvm/CodeGen/MachineBasicBlock.h>
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include <llvm/Transforms/IPO.h>
#include "mvm/JIT.h"
#include "mvm/Method.h"
#include "debug.h"
#include "JavaArray.h"
#include "JavaCache.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaObject.h"
#include "JavaJIT.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "JnjvmModuleProvider.h"
#include "NativeUtil.h"
#include "Reader.h"
#include "Zip.h"
#include <iostream>
using namespace jnjvm;
using namespace llvm;
#ifndef SINGLE_VM
GlobalVariable* Class::staticVar(llvm::Module* compilingModule) {
if (!_staticVar) {
aquire();
if (!_staticVar) {
if (isolate == Jnjvm::bootstrapVM) {
_staticVar = llvmVar(compilingModule);
release();
return _staticVar;
} else {
isolate->protectModule->lock();
_staticVar = new GlobalVariable(JavaObject::llvmType, false,
GlobalValue::ExternalLinkage,
JavaJIT::constantJavaObjectNull, "",
isolate->module);
isolate->protectModule->unlock();
// TODO: put an initializer in here
void* ptr = mvm::jit::executionEngine->getPointerToGlobal(_staticVar);
GenericValue Val = GenericValue((void*)staticInstance());
llvm::GenericValue * Ptr = (llvm::GenericValue*)ptr;
mvm::jit::executionEngine->StoreValueToMemory(Val, Ptr, staticType);
}
}
release();
}
return _staticVar;
}
#else
GlobalVariable* Class::staticVar(llvm::Module* compilingModule) {
if (!_staticVar) {
aquire();
if (!_staticVar) {
JavaObject* obj = staticInstance();
mvm::jit::protectConstants();//->lock();
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (obj)),
JavaObject::llvmType);
mvm::jit::unprotectConstants();//->unlock();
isolate->protectModule->lock();
_staticVar = new GlobalVariable(JavaObject::llvmType, true,
GlobalValue::ExternalLinkage,
cons, "",
isolate->module);
isolate->protectModule->unlock();
}
release();
}
return _staticVar;
}
#endif
GlobalVariable* CommonClass::llvmVar(llvm::Module* compilingModule) {
if (!_llvmVar) {
aquire();
if (!_llvmVar) {
#ifndef SINGLE_VM
if (compilingModule == Jnjvm::bootstrapVM->module && isArray && isolate != Jnjvm::bootstrapVM) {
// We know the array class can belong to bootstrap
_llvmVar = Jnjvm::bootstrapVM->constructArray(this->name, 0)->llvmVar(compilingModule);
release();
return _llvmVar;
}
#endif
const Type* pty = mvm::jit::ptrType;
mvm::jit::protectConstants();//->lock();
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
pty);
mvm::jit::unprotectConstants();//->unlock();
isolate->protectModule->lock();
_llvmVar = new GlobalVariable(pty, true,
GlobalValue::ExternalLinkage,
cons, "",
isolate->module);
isolate->protectModule->unlock();
}
release();
}
return _llvmVar;
}
#ifdef SINGLE_VM
GlobalVariable* CommonClass::llvmDelegatee() {
if (!_llvmDelegatee) {
aquire();
if (!_llvmDelegatee) {
const Type* pty = JavaObject::llvmType;
JavaObject* obj = getClassDelegatee();
mvm::jit::protectConstants();//->lock();
Constant* cons =
ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (obj)),
pty);
mvm::jit::unprotectConstants();//->unlock();
isolate->protectModule->lock();
_llvmDelegatee = new GlobalVariable(pty, true,
GlobalValue::ExternalLinkage,
cons, "",
isolate->module);
isolate->protectModule->unlock();
}
release();
}
return _llvmDelegatee;
}
#endif
ConstantInt* JavaObject::classOffset() {
return mvm::jit::constantOne;
}
ConstantInt* JavaArray::sizeOffset() {
return mvm::jit::constantOne;
}
ConstantInt* JavaArray::elementsOffset() {
return mvm::jit::constantTwo;
}
void JavaJIT::invokeOnceVoid(Jnjvm* vm, JavaObject* loader,
char const* className, char const* func,
char const* sign, int access, ...) {
CommonClass* cl = vm->loadName(vm->asciizConstructUTF8(className), loader,
true, true, true);
bool stat = access == ACC_STATIC ? true : false;
JavaMethod* method = cl->lookupMethod(vm->asciizConstructUTF8(func),
vm->asciizConstructUTF8(sign), stat,
true);
va_list ap;
va_start(ap, access);
if (stat) {
method->invokeIntStaticAP(ap);
} else {
JavaObject* obj = va_arg(ap, JavaObject*);
method->invokeIntSpecialAP(obj, ap);
}
va_end(ap);
}
VirtualTable* JavaJIT::makeVT(Class* cl, bool stat) {
const Type* type = stat ? cl->staticType : cl->virtualType;
std::vector<JavaField*> &fields = stat ? cl->staticFields : cl->virtualFields;
cl->isolate->protectModule->lock();
Function* func = new Function(markAndTraceLLVMType,
GlobalValue::ExternalLinkage,
"markAndTraceObject",
cl->isolate->module);
cl->isolate->protectModule->unlock();
Constant* zero = mvm::jit::constantZero;
Argument* arg = func->arg_begin();
BasicBlock* block = new BasicBlock("", func);
llvm::Value* realArg = new BitCastInst(arg, type, "", block);
if (stat || cl->super == 0) {
new CallInst(javaObjectTracerLLVM, arg, "", block);
} else {
new CallInst(((Class*)cl->super)->virtualTracer, arg, "", block);
}
for (std::vector<JavaField*>::iterator i = fields.begin(),
e = fields.end(); i!= e; ++i) {
if ((*i)->signature->funcs->doTrace) {
std::vector<Value*> args; //size = 2
args.push_back(zero);
args.push_back((*i)->offset);
Value* ptr = new GetElementPtrInst(realArg, args.begin(), args.end(), "",
block);
Value* val = new LoadInst(ptr, "", block);
Value* valCast = new BitCastInst(val, JavaObject::llvmType, "", block);
new CallInst(markAndTraceLLVM, valCast, "", block);
}
}
new ReturnInst(block);
VirtualTable * res = malloc(VT_SIZE);
memcpy(res, JavaObject::VT, VT_SIZE);
void* codePtr = mvm::jit::executionEngine->getPointerToGlobal(func);
((void**)res)[VT_TRACER_OFFSET] = codePtr;
if (!stat) {
cl->virtualTracer = func;
cl->codeVirtualTracer = (mvm::Code*)((unsigned*)codePtr - 1);
} else {
cl->staticTracer = func;
cl->codeStaticTracer = (mvm::Code*)((unsigned*)codePtr - 1);
}
return res;
}
static void _initField(JavaField* field) {
ConstantInt* offset = field->offset;
const TargetData* targetData = mvm::jit::executionEngine->getTargetData();
bool stat = isStatic(field->access);
const Type* clType = stat ? field->classDef->staticType :
field->classDef->virtualType;
const StructLayout* sl =
targetData->getStructLayout((StructType*)(clType->getContainedType(0)));
uint64 ptrOffset = sl->getElementOffset(offset->getZExtValue());
field->ptrOffset = ptrOffset;
}
void JavaJIT::initField(JavaField* field, JavaObject* obj, uint64 val) {
_initField(field);
const AssessorDesc* funcs = field->signature->funcs;
if (funcs == AssessorDesc::dLong) {
((sint64*)((uint64)obj + field->ptrOffset))[0] = val;
} else if (funcs == AssessorDesc::dInt) {
((sint32*)((uint64)obj + field->ptrOffset))[0] = (sint32)val;
} else if (funcs == AssessorDesc::dChar) {
((uint16*)((uint64)obj + field->ptrOffset))[0] = (uint16)val;
} else if (funcs == AssessorDesc::dShort) {
((sint16*)((uint64)obj + field->ptrOffset))[0] = (sint16)val;
} else if (funcs == AssessorDesc::dByte) {
((sint8*)((uint64)obj + field->ptrOffset))[0] = (sint8)val;
} else if (funcs == AssessorDesc::dBool) {
((uint8*)((uint64)obj + field->ptrOffset))[0] = (uint8)val;
} else {
// 0 value for everything else
((sint32*)((uint64)obj + field->ptrOffset))[0] = (sint32)val;
}
}
void JavaJIT::initField(JavaField* field, JavaObject* obj, JavaObject* val) {
_initField(field);
((JavaObject**)((uint64)obj + field->ptrOffset))[0] = val;
}
void JavaJIT::initField(JavaField* field, JavaObject* obj, double val) {
_initField(field);
((double*)((uint64)obj + field->ptrOffset))[0] = val;
}
void JavaJIT::initField(JavaField* field, JavaObject* obj, float val) {
_initField(field);
((float*)((uint64)obj + field->ptrOffset))[0] = val;
}
JavaObject* Class::operator()() {
if (!isReady())
isolate->loadName(name, classLoader, true, true, true);
return doNew();
}
void JavaField::operator()(JavaObject* obj, float val) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) obj = classDef->staticInstance();
void* ptr = (void*)((uint64)obj + ptrOffset);
if (signature->funcs->llvmType == Type::FloatTy) {
((float*)ptr)[0] = val;
} else {
JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
}
}
void JavaField::operator()(JavaObject* obj, double val) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) obj = classDef->staticInstance();
void* ptr = (void*)((uint64)obj + ptrOffset);
if (signature->funcs->llvmType == Type::DoubleTy) {
((double*)ptr)[0] = val;
} else {
JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
}
}
void JavaField::operator()(JavaObject* obj, sint64 val) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) obj = classDef->staticInstance();
void* ptr = (void*)((uint64)obj + ptrOffset);
if (signature->funcs == AssessorDesc::dLong) {
((uint64*)ptr)[0] = val;
} else {
JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
}
}
void JavaField::operator()(JavaObject* obj, uint32 val) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) obj = classDef->staticInstance();
void* ptr = (void*)((uint64)obj + ptrOffset);
if (signature->funcs == AssessorDesc::dInt) {
((sint32*)ptr)[0] = (sint32)val;
} else if (signature->funcs == AssessorDesc::dShort) {
((sint16*)ptr)[0] = (sint16)val;
} else if (signature->funcs == AssessorDesc::dByte) {
((sint8*)ptr)[0] = (sint8)val;
} else if (signature->funcs == AssessorDesc::dBool) {
((uint8*)ptr)[0] = (uint8)val;
} else if (signature->funcs == AssessorDesc::dChar) {
((uint16*)ptr)[0] = (uint16)val;
} else {
JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
}
}
void JavaField::operator()(JavaObject* obj, JavaObject* val) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) obj = classDef->staticInstance();
void* ptr = (void*)((uint64)obj + ptrOffset);
if (signature->funcs->llvmType == JavaObject::llvmType) {
((JavaObject**)ptr)[0] = val;
} else {
JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
}
}
GenericValue JavaField::operator()(JavaObject* obj) {
if (!classDef->isReady())
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
bool stat = isStatic(access);
if (stat) {
if (obj != 0) {
// Assignment to a static var
void* ptr = (void*)((uint64)(classDef->staticInstance()) + ptrOffset);
((JavaObject**)ptr)[0] = obj;
return GenericValue(0);
} else {
// Get a static var
obj = classDef->staticInstance();
}
}
assert(obj && "getting a field from a null value");
void* ptr = (void*)((uint64)obj + ptrOffset);
const Type* type = signature->funcs->llvmType;
if (type == Type::Int8Ty) {
GenericValue gv;
gv.IntVal = APInt(8, ((uint8*)ptr)[0]);
return gv;
} else if (type == Type::Int16Ty) {
GenericValue gv;
gv.IntVal = APInt(16, ((uint16*)ptr)[0]);
return gv;
} else if (type == Type::Int32Ty) {
GenericValue gv;
gv.IntVal = APInt(32, ((uint32*)ptr)[0]);
return gv;
} else if (type == Type::Int64Ty) {
GenericValue gv;
gv.IntVal = APInt(64, ((uint64*)ptr)[0]);
return gv;
} else if (type == Type::DoubleTy) {
GenericValue gv;
gv.DoubleVal = ((double*)ptr)[0];
return gv;
} else if (type == Type::FloatTy) {
GenericValue gv;
gv.FloatVal = ((float*)ptr)[0];
return gv;
} else if (type == JavaObject::llvmType) {
GenericValue gv(((JavaObject**)ptr)[0]);
return gv;
} else {
assert(0 && "Unknown type!");
return GenericValue(0);
}
}
#define readArgs(buf, signature, ap) \
for (std::vector<Typedef*>::iterator i = signature->args.begin(), \
e = signature->args.end(); i!= e; i++) { \
const AssessorDesc* funcs = (*i)->funcs; \
if (funcs == AssessorDesc::dLong) { \
((sint64*)buf)[0] = va_arg(ap, sint64); \
buf += 2; \
} else if (funcs == AssessorDesc::dInt) { \
((sint32*)buf)[0] = va_arg(ap, sint32); \
buf++; \
} else if (funcs == AssessorDesc::dChar) { \
((uint32*)buf)[0] = va_arg(ap, uint32); \
buf++; \
} else if (funcs == AssessorDesc::dShort) { \
((uint32*)buf)[0] = va_arg(ap, uint32); \
buf++; \
} else if (funcs == AssessorDesc::dByte) { \
((uint32*)buf)[0] = va_arg(ap, uint32); \
buf++; \
} else if (funcs == AssessorDesc::dBool) { \
((uint32*)buf)[0] = va_arg(ap, uint32); \
buf++; \
} else if (funcs == AssessorDesc::dFloat) { \
((float*)buf)[0] = (float)va_arg(ap, double); \
buf++; \
} else if (funcs == AssessorDesc::dDouble) { \
((double*)buf)[0] = va_arg(ap, double); \
buf += 2; \
} else if (funcs == AssessorDesc::dRef || funcs == AssessorDesc::dTab) { \
((JavaObject**)buf)[0] = va_arg(ap, JavaObject*); \
buf++; \
} else { \
assert(0 && "Should not be here"); \
} \
} \
#if 1//defined(__PPC__) && !defined(__MACH__)
#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
\
TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(JavaObject* obj, va_list ap) { \
if (!classDef->isReady()) \
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true); \
\
verifyNull(obj); \
JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true); \
\
void** buf = (void**)alloca(meth->signature->args.size() * sizeof(uint64)); \
void* _buf = (void*)buf; \
readArgs(buf, signature, ap); \
void* func = meth->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, _buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(JavaObject* obj, va_list ap) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
void** buf = (void**)alloca(this->signature->args.size() * sizeof(uint64)); \
void* _buf = (void*)buf; \
readArgs(buf, signature, ap); \
void* func = this->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, _buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(va_list ap) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
void** buf = (void**)alloca(this->signature->args.size() * sizeof(uint64)); \
void* _buf = (void*)buf; \
readArgs(buf, signature, ap); \
void* func = this->compiledPtr();\
return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, _buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(JavaObject* obj, void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true);\
\
void* func = meth->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(JavaObject* obj, void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Virtual(JavaObject* obj, ...) { \
va_list ap;\
va_start(ap, obj);\
TYPE res = invoke##TYPE_NAME##VirtualAP(obj, ap);\
va_end(ap); \
return res; \
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Special(JavaObject* obj, ...) {\
va_list ap;\
va_start(ap, obj);\
TYPE res = invoke##TYPE_NAME##SpecialAP(obj, ap);\
va_end(ap); \
return res; \
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Static(...) {\
va_list ap;\
va_start(ap, this);\
TYPE res = invoke##TYPE_NAME##StaticAP(ap);\
va_end(ap); \
return res; \
}\
#else
#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
\
TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(JavaObject* obj, va_list ap) { \
if (!classDef->isReady()) \
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true); \
\
verifyNull(obj); \
JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true); \
\
void* func = meth->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_AP)signature->virtualCallAP())(func, obj, ap);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(JavaObject* obj, va_list ap) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_AP)signature->virtualCallAP())(func, obj, ap);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(va_list ap) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_STATIC_AP)signature->staticCallAP())(func, ap);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(JavaObject* obj, void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true);\
\
void* func = meth->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(JavaObject* obj, void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
verifyNull(obj);\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(void* buf) {\
if (!classDef->isReady())\
classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
\
void* func = this->compiledPtr();\
return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, buf);\
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Virtual(JavaObject* obj, ...) { \
va_list ap;\
va_start(ap, obj);\
TYPE res = invoke##TYPE_NAME##VirtualAP(obj, ap);\
va_end(ap); \
return res; \
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Special(JavaObject* obj, ...) {\
va_list ap;\
va_start(ap, obj);\
TYPE res = invoke##TYPE_NAME##SpecialAP(obj, ap);\
va_end(ap); \
return res; \
}\
\
TYPE JavaMethod::invoke##TYPE_NAME##Static(...) {\
va_list ap;\
va_start(ap, this);\
TYPE res = invoke##TYPE_NAME##StaticAP(ap);\
va_end(ap); \
return res; \
}\
#endif
typedef uint32 (*uint32_virtual_ap)(void*, JavaObject*, va_list);
typedef sint64 (*sint64_virtual_ap)(void*, JavaObject*, va_list);
typedef float (*float_virtual_ap)(void*, JavaObject*, va_list);
typedef double (*double_virtual_ap)(void*, JavaObject*, va_list);
typedef JavaObject* (*object_virtual_ap)(void*, JavaObject*, va_list);
typedef uint32 (*uint32_static_ap)(void*, va_list);
typedef sint64 (*sint64_static_ap)(void*, va_list);
typedef float (*float_static_ap)(void*, va_list);
typedef double (*double_static_ap)(void*, va_list);
typedef JavaObject* (*object_static_ap)(void*, va_list);
typedef uint32 (*uint32_virtual_buf)(void*, JavaObject*, void*);
typedef sint64 (*sint64_virtual_buf)(void*, JavaObject*, void*);
typedef float (*float_virtual_buf)(void*, JavaObject*, void*);
typedef double (*double_virtual_buf)(void*, JavaObject*, void*);
typedef JavaObject* (*object_virtual_buf)(void*, JavaObject*, void*);
typedef uint32 (*uint32_static_buf)(void*, void*);
typedef sint64 (*sint64_static_buf)(void*, void*);
typedef float (*float_static_buf)(void*, void*);
typedef double (*double_static_buf)(void*, void*);
typedef JavaObject* (*object_static_buf)(void*, void*);
INVOKE(uint32, Int, uint32_virtual_ap, uint32_static_ap, uint32_virtual_buf, uint32_static_buf)
INVOKE(sint64, Long, sint64_virtual_ap, sint64_static_ap, sint64_virtual_buf, sint64_static_buf)
INVOKE(float, Float, float_virtual_ap, float_static_ap, float_virtual_buf, float_static_buf)
INVOKE(double, Double, double_virtual_ap, double_static_ap, double_virtual_buf, double_static_buf)
INVOKE(JavaObject*, JavaObject, object_virtual_ap, object_static_ap, object_virtual_buf, object_static_buf)
#undef INVOKE
GenericValue JavaObject::operator()(JavaField* field) {
return (*field)(this);
}
void JavaObject::operator()(JavaField* field, float val) {
return (*field)(this, val);
}
void JavaObject::operator()(JavaField* field, double val) {
return (*field)(this, val);
}
void JavaObject::operator()(JavaField* field, uint32 val) {
return (*field)(this, val);
}
void JavaObject::operator()(JavaField* field, sint64 val) {
return (*field)(this, val);
}
void JavaObject::operator()(JavaField* field, JavaObject* val) {
return (*field)(this, val);
}
void JavaField::operator()(float val) {
JavaField * field = this;
return (*field)(classDef->virtualInstance, val);
}
void JavaField::operator()(double val) {
JavaField * field = this;
return (*field)(classDef->virtualInstance, val);
}
void JavaField::operator()(sint64 val) {
JavaField * field = this;
return (*field)(classDef->virtualInstance, val);
}
void JavaField::operator()(uint32 val) {
JavaField * field = this;
return (*field)(classDef->virtualInstance, val);
}
Function* Signdef::createFunctionCallBuf(bool virt) {
ConstantInt* CI = mvm::jit::constantZero;
std::vector<Value*> Args;
isolate->protectModule->lock();
Function* res = new llvm::Function(virt ? virtualBufType : staticBufType,
GlobalValue::ExternalLinkage,
this->printString(),
isolate->module);
isolate->protectModule->unlock();
BasicBlock* currentBlock = new BasicBlock("enter", res);
Function::arg_iterator i = res->arg_begin();
Value *obj, *ptr, *func;
func = i;
++i;
if (virt) {
obj = i;
++i;
Args.push_back(obj);
}
ptr = i;
for (std::vector<Typedef*>::iterator i = args.begin(),
e = args.end(); i!= e; ++i) {
const AssessorDesc* funcs = (*i)->funcs;
ptr = new GetElementPtrInst(ptr, CI, "", currentBlock);
Value* val = new BitCastInst(ptr, funcs->llvmTypePtr, "", currentBlock);
Value* arg = new LoadInst(val, "", currentBlock);
Args.push_back(arg);
if (funcs == AssessorDesc::dLong || funcs == AssessorDesc::dDouble) {
CI = mvm::jit::constantTwo;
} else {
CI = mvm::jit::constantOne;
}
}
Value* val = new CallInst(func, Args.begin(), Args.end(), "", currentBlock);
if (ret->funcs != AssessorDesc::dVoid)
new ReturnInst(val, currentBlock);
else
new ReturnInst(currentBlock);
return res;
}
Function* Signdef::createFunctionCallAP(bool virt) {
std::vector<Value*> Args;
isolate->protectModule->lock();
Function* res = new llvm::Function(virt ? virtualBufType : staticBufType,
GlobalValue::ExternalLinkage,
this->printString(),
isolate->module);
isolate->protectModule->unlock();
BasicBlock* currentBlock = new BasicBlock("enter", res);
Function::arg_iterator i = res->arg_begin();
Value *obj, *ap, *func;
func = i;
++i;
if (virt) {
obj = i;
Args.push_back(obj);
++i;
}
ap = i;
for (std::vector<Typedef*>::iterator i = args.begin(),
e = args.end(); i!= e; i++) {
Args.push_back(new VAArgInst(ap, (*i)->funcs->llvmType, "", currentBlock));
}
Value* val = new CallInst(func, Args.begin(), Args.end(), "", currentBlock);
if (ret->funcs != AssessorDesc::dVoid)
new ReturnInst(val, currentBlock);
else
new ReturnInst(currentBlock);
return res;
}
void Signdef::createFuncPtrsCalls() {
assert(0 && "do not call me");
Function* virtBuf = createFunctionCallBuf(true);
Function* statBuf = createFunctionCallBuf(false);
Function* virtAP = createFunctionCallAP(true);
Function* statAP = createFunctionCallAP(false);
_staticCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statBuf);
_virtualCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtBuf);
_staticCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statAP);
_virtualCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtAP);
}
void* Signdef::staticCallBuf() {
if (!_staticCallBuf) {
Function* statBuf = createFunctionCallBuf(false);
_staticCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statBuf);
}
return _staticCallBuf;
}
void* Signdef::virtualCallBuf() {
if (!_virtualCallBuf) {
Function* virtBuf = createFunctionCallBuf(true);
_virtualCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtBuf);
}
return _virtualCallBuf;
}
void* Signdef::staticCallAP() {
if (!_staticCallAP) {
Function* statAP = createFunctionCallAP(false);
_staticCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statAP);
}
return _staticCallAP;
}
void* Signdef::virtualCallAP() {
if (!_virtualCallAP) {
Function* virtAP = createFunctionCallAP(true);
_virtualCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtAP);
}
return _virtualCallAP;
}