blob: 79611b26f16265f1021f0732475c90d040e84543 [file] [log] [blame]
//===------------ VMClass.cpp - CLI class representation ------------------===//
//
// N3
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdarg.h>
#include <vector>
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "N3Debug.h"
#include "types.h"
#include "mvm/JIT.h"
#include "mvm/PrintBuffer.h"
#include "mvm/Threads/Locks.h"
#include "Assembly.h"
#include "CLIAccess.h"
#include "CLIJit.h"
#include "MSCorlib.h"
#include "N3.h"
#include "VMArray.h"
#include "VMClass.h"
#include "VMThread.h"
using namespace n3;
void VMCommonClass::print(mvm::PrintBuffer* buf) const {
buf->write("CLIType<");
nameSpace->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}
void VMCommonClass::aquire() {
lockVar->lock();
}
void VMCommonClass::release() {
lockVar->unlock();
}
void VMCommonClass::waitClass() {
condVar->wait(lockVar);
}
void VMCommonClass::broadcastClass() {
condVar->broadcast();
}
bool VMCommonClass::ownerClass() {
return lockVar->selfOwner();
}
void VMClass::print(mvm::PrintBuffer* buf) const {
buf->write("CLIType<");
nameSpace->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}
void VMClassArray::print(mvm::PrintBuffer* buf) const {
buf->write("CLITypeArray<");
nameSpace->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}
void VMClassPointer::print(mvm::PrintBuffer* buf) const {
buf->write("CLITypePointer<");
nameSpace->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}
void VMMethod::print(mvm::PrintBuffer* buf) const {
buf->write("CLIMethod<");
classDef->nameSpace->print(buf);
buf->write(".");
classDef->name->print(buf);
buf->write("::");
name->print(buf);
buf->write("(");
std::vector<VMCommonClass*>::iterator i = ((VMMethod*)this)->parameters.begin();
std::vector<VMCommonClass*>::iterator e = ((VMMethod*)this)->parameters.end();
++i;
if (i != e) {
while (true) {
(*i)->nameSpace->print(buf);
buf->write(".");
(*i)->name->print(buf);
++i;
if (i == e) break;
else buf->write(" ,");
}
}
buf->write(")");
buf->write(">");
}
void VMGenericMethod::print(mvm::PrintBuffer* buf) const {
buf->write("CLIGenericMethod<");
classDef->nameSpace->print(buf);
buf->write(".");
classDef->name->print(buf);
buf->write("::");
name->print(buf);
buf->write("(");
std::vector<VMCommonClass*>::iterator i = ((VMMethod*)this)->parameters.begin();
std::vector<VMCommonClass*>::iterator e = ((VMMethod*)this)->parameters.end();
++i;
if (i != e) {
while (true) {
(*i)->nameSpace->print(buf);
buf->write(".");
(*i)->name->print(buf);
++i;
if (i == e) break;
else buf->write(" ,");
}
}
buf->write(")");
buf->write(">");
}
void VMField::print(mvm::PrintBuffer* buf) const {
buf->write("CLIField<");
classDef->nameSpace->print(buf);
buf->write(".");
classDef->name->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}
void Param::print(mvm::PrintBuffer* buf) const {
buf->write("CLIParam<");
name->print(buf);
buf->write(">");
}
void Property::print(mvm::PrintBuffer* buf) const {
buf->write("Property def with name <");
name->print(buf);
buf->write(">");
}
void VMCommonClass::initialise(N3* vm, bool isArray) {
this->lockVar = new mvm::LockRecursive();
this->condVar = new mvm::Cond();
this->ooo_delegatee = 0;
this->status = hashed;
this->vm = vm;
this->isArray = isArray;
this->isPointer = false;
this->isPrimitive = false;
this->naturalType = llvm::OpaqueType::get(llvm::getGlobalContext());
}
const UTF8* VMClassArray::constructArrayName(const UTF8* name, uint32 dims) {
mvm::PrintBuffer _asciiz(name);
const char* asciiz = _asciiz.cString();
char* res = (char*)alloca(strlen(asciiz) + (dims * 2) + 1);
sprintf(res, asciiz);
for (uint32 i = 0; i < dims; ++i) {
sprintf(res, "%s[]", res);
}
return VMThread::get()->getVM()->asciizToUTF8(res);
}
const UTF8* VMClassPointer::constructPointerName(const UTF8* name, uint32 dims) {
mvm::PrintBuffer _asciiz(name);
const char* asciiz = _asciiz.cString();
char* res = (char*)alloca(strlen(asciiz) + (dims * 2) + 1);
sprintf(res, asciiz);
for (uint32 i = 0; i < dims; ++i) {
sprintf(res, "%s*", res);
}
return VMThread::get()->getVM()->asciizToUTF8(res);
}
void VMCommonClass::loadParents(VMGenericClass* genClass, VMGenericMethod* genMethod) {
if ((0xffff & superToken) == 0) {
depth = 0;
display.push_back(this);
} else {
super = assembly->loadType((N3*)vm, superToken, true, false, false, true, genClass, genMethod);
depth = super->depth + 1;
for (uint32 i = 0; i < super->display.size(); ++i) {
display.push_back(super->display[i]);
}
display.push_back(this);
}
for (std::vector<uint32>::iterator i = interfacesToken.begin(),
e = interfacesToken.end(); i!= e; ++i) {
interfaces.push_back((VMClass*)assembly->loadType((N3*)vm, (*i), true,
false, false, true, genClass, genMethod));
}
}
typedef void (*clinit_t)(void);
void VMCommonClass::clinitClass(VMGenericMethod* genMethod) {
// printf("----- clinit: %s\n", mvm::PrintBuffer::objectToString(this));
VMCommonClass* cl = this;
if (cl->status < ready) {
cl->aquire();
int status = cl->status;
if (status == ready) {
cl->release();
} else if (status == static_resolved) {
cl->status = clinitParent;
cl->release();
if (cl->super) {
cl->super->resolveStatic(true, genMethod);
}
for (uint32 i = 0; i < cl->interfaces.size(); i++) {
cl->interfaces[i]->resolveStatic(true, genMethod);
}
cl->status = inClinit;
resolveVT();
std::vector<VMCommonClass*> args;
args.push_back(MSCorlib::pVoid);
VMMethod* meth = cl->lookupMethodDontThrow(N3::clinitName, args,
true, false);
PRINT_DEBUG(N3_LOAD, 0, COLOR_NORMAL, "%s", "; ");
PRINT_DEBUG(N3_LOAD, 0, LIGHT_GREEN, "%s", "clinit ");
PRINT_DEBUG(N3_LOAD, 0, COLOR_NORMAL, "%s::%s\n", mvm::PrintBuffer(this).cString(),
mvm::PrintBuffer(cl).cString());
if (meth) {
llvm::Function* pred = meth->compiledPtr(genMethod);
clinit_t res = (clinit_t)
(intptr_t)mvm::MvmModule::executionEngine->getPointerToGlobal(pred);
res();
}
cl->status = ready;
cl->broadcastClass();
} else if (status < static_resolved) {
cl->release();
VMThread::get()->getVM()->unknownError("try to clinit a not-readed class...");
} else {
if (!cl->ownerClass()) {
while (status < ready) cl->waitClass();
}
cl->release();
}
}
}
void VMClass::resolveStaticFields(VMGenericMethod* genMethod) {
VMClass* cl = this;
std::vector<const llvm::Type*> fields;
fields.push_back(VMObject::llvmType->getContainedType(0));
uint64 offset = 0;
for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
e = cl->staticFields.end(); i!= e; ++i) {
// preincrement because 0 is VMObject
(*i)->offset = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), ++offset);
}
for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
e = cl->staticFields.end(); i!= e; ++i) {
(*i)->signature->resolveType(false, false, genMethod);
fields.push_back((*i)->signature->naturalType);
}
cl->staticType = llvm::PointerType::getUnqual(llvm::StructType::get(vm->LLVMModule->getContext(), fields, false));
N3VirtualTable* VT = CLIJit::makeVT(cl, true);
uint64 size = mvm::MvmModule::getTypeSize(cl->staticType->getContainedType(0));
cl->staticInstance = (VMObject*)gc::operator new(size, VT);
VMObject::initialise(cl->staticInstance, cl);
for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
e = cl->staticFields.end(); i!= e; ++i) {
(*i)->initField(cl->staticInstance);
}
}
void VMClass::unifyTypes(VMGenericClass* genClass, VMGenericMethod* genMethod) {
llvm::PATypeHolder PA = naturalType;
for (std::vector<VMField*>::iterator i = virtualFields.begin(),
e = virtualFields.end(); i!= e; ++i) {
(*i)->signature->resolveVirtual(genClass, genMethod);
}
naturalType = PA.get();
}
void VMClass::resolveVirtualFields(VMGenericClass* genClass, VMGenericMethod* genMethod) {
const llvm::Type* ResultTy = 0;
if (hasExplicitLayout(flags)) {
explicitLayoutSize = assembly->getExplicitLayout(token);
ResultTy = llvm::IntegerType::get(llvm::getGlobalContext(), explicitLayoutSize);
} else if (super != 0) {
if (super == MSCorlib::pValue) {
uint32 size = virtualFields.size();
if (size == 1) {
virtualFields[0]->offset = VMThread::get()->getVM()->module->constantZero;
ResultTy = virtualFields[0]->signature->naturalType;
} else if (size == 0) {
ResultTy = llvm::Type::getVoidTy(llvm::getGlobalContext());
} else {
std::vector<const llvm::Type*> Elts;
uint32 offset = -1;
for (std::vector<VMField*>::iterator i = virtualFields.begin(),
e = virtualFields.end(); i!= e; ++i) {
(*i)->offset = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), ++offset);
const llvm::Type* type = (*i)->signature->naturalType;
Elts.push_back(type);
}
ResultTy = llvm::StructType::get(vm->LLVMModule->getContext(), Elts);
}
} else if (super == MSCorlib::pEnum) {
ResultTy = llvm::Type::getInt32Ty(llvm::getGlobalContext()); // TODO find max
} else {
std::vector<const llvm::Type*> Elts;
Elts.push_back(super->naturalType->getContainedType(0));
uint32 offset = 0;
for (std::vector<VMField*>::iterator i = virtualFields.begin(),
e = virtualFields.end(); i!= e; ++i) {
(*i)->offset = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), ++offset);
const llvm::Type* type = (*i)->signature->naturalType;
Elts.push_back(type);
}
ResultTy = llvm::PointerType::getUnqual(llvm::StructType::get(vm->LLVMModule->getContext(), Elts));
}
} else {
ResultTy = VMObject::llvmType;
}
if (naturalType->isAbstract()) {
const llvm::OpaqueType *OldTy =
llvm::dyn_cast_or_null<llvm::OpaqueType>(this->naturalType);
if (OldTy) {
const_cast<llvm::OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
}
naturalType = ResultTy;
}
unifyTypes(genClass, genMethod);
if (super == MSCorlib::pValue) {
std::vector<const llvm::Type*> Elts;
Elts.push_back(VMObject::llvmType->getContainedType(0));
for (std::vector<VMField*>::iterator i = virtualFields.begin(),
e = virtualFields.end(); i!= e; ++i) {
Elts.push_back((*i)->signature->naturalType);
}
virtualType = llvm::PointerType::getUnqual(llvm::StructType::get(vm->LLVMModule->getContext(), Elts));
} else {
virtualType = naturalType;
}
}
void VMClassArray::makeType() {
std::vector<const llvm::Type*> arrayFields;
arrayFields.push_back(VMObject::llvmType->getContainedType(0));
arrayFields.push_back(llvm::Type::getInt32Ty(llvm::getGlobalContext()));
arrayFields.push_back(llvm::ArrayType::get(baseClass->naturalType, 0));
const llvm::Type* type = llvm::PointerType::getUnqual(llvm::StructType::get(vm->LLVMModule->getContext(), arrayFields, false));
((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(type);
naturalType = type;
virtualType = naturalType;
}
void VMClassPointer::makeType() {
const llvm::Type* type = (baseClass->naturalType == llvm::Type::getVoidTy(llvm::getGlobalContext())) ? llvm::Type::getInt8Ty(llvm::getGlobalContext()) : baseClass->naturalType;
const llvm::Type* pType = llvm::PointerType::getUnqual(type);
((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(pType);
naturalType = pType;
}
void VMCommonClass::resolveVirtual(VMGenericClass* genClass, VMGenericMethod *genMethod) {
// printf("Resolve virtual: %s\n", mvm::PrintBuffer::objectToString(this));
VMCommonClass* cl = this;
if (cl->status < virtual_resolved) {
cl->aquire();
int status = cl->status;
if (status >= virtual_resolved) {
cl->release();
} else if (status < loaded) {
cl->release();
VMThread::get()->getVM()->unknownError("try to resolve a not-readed class");
} else if (status == loaded) {
if (cl->isArray) {
VMClassArray* arrayCl = (VMClassArray*)cl;
VMCommonClass* baseClass = arrayCl->baseClass;
// printf("Resolveing base class: %s\n", mvm::PrintBuffer::objectToString(baseClass));
baseClass->resolveType(false, false, genMethod);
// printf("Resolveing base class: %s done\n", mvm::PrintBuffer::objectToString(baseClass));
arrayCl->makeType();
cl->status = virtual_resolved;
} else if (cl->isPointer) {
VMClassPointer* pointerCl = (VMClassPointer*)cl;
VMCommonClass* baseClass = pointerCl->baseClass;
baseClass->resolveType(false, false, genMethod);
pointerCl->makeType();
cl->status = virtual_resolved;
} else {
cl->release();
cl->loadParents(genClass, genMethod);
cl->aquire();
cl->status = prepared;
assembly->readClass(cl, genMethod);
cl->status = readed;
((VMClass*)cl)->resolveVirtualFields(genClass, genMethod);
cl->status = virtual_resolved;
}
cl->release();
} else {
if (!(cl->ownerClass())) {
while (status < virtual_resolved) {
cl->waitClass();
}
}
cl->release();
}
}
}
void VMCommonClass::resolveVT() {
VMCommonClass* cl = this;
if (cl->isArray) {
VMClassArray* arrayCl = (VMClassArray*)cl;
arrayCl->baseClass->resolveVT();
// printf("Making vt of %s\n", mvm::PrintBuffer(this).cString());
arrayCl->arrayVT = CLIJit::makeArrayVT(arrayCl);
} else if (cl->isPointer) {
} else {
VMClass* cl = (VMClass*)this;
if (super)
super->resolveVT();
// We check for virtual instance because the string class has a
// bigger size than the class declares.
if (super != MSCorlib::pEnum && !cl->virtualInstance) {
cl->vtSize = super ? ((VMClass*)super)->vtSize : sizeof(N3VirtualTable) / sizeof(uintptr_t);
for (std::vector<VMMethod*>::iterator i = virtualMethods.begin(),
e = virtualMethods.end(); i!= e; ++i) {
(*i)->offsetInVt = cl->vtSize++;
}
// printf("Making vt of %s with %d elements\n", mvm::PrintBuffer(this).cString(), cl->vtSize);
N3VirtualTable* VT = CLIJit::makeVT(cl, false);
uint64 size = mvm::MvmModule::getTypeSize(cl->virtualType->getContainedType(0));
cl->virtualInstance = (VMObject*)gc::operator new(size, VT);
VMObject::initialise(cl->virtualInstance, cl);
for (std::vector<VMField*>::iterator i = cl->virtualFields.begin(),
e = cl->virtualFields.end(); i!= e; ++i) {
(*i)->initField(cl->virtualInstance);
}
}
}
}
void VMCommonClass::resolveType(bool stat, bool clinit, VMGenericMethod* genMethod) {
// printf("Resolve type: %s %d %d\n", mvm::PrintBuffer::objectToString(this), stat, clinit);
resolveVirtual(static_cast<VMGenericClass*>(this), genMethod);
if (stat) resolveStatic(clinit, genMethod);
}
void VMCommonClass::resolveStatic(bool clinit, VMGenericMethod* genMethod) {
// printf("Resolve static: %s %d\n", mvm::PrintBuffer::objectToString(this), clinit);
VMCommonClass* cl = this;
if (cl->status < static_resolved) {
cl->aquire();
int status = cl->status;
if (status >= static_resolved) {
cl->release();
} else if (status < virtual_resolved) {
cl->release();
// printf("Will throw an exception: %s....\n", mvm::PrintBuffer::objectToString(this));
// ((char *)0)[0] = 22;
VMThread::get()->getVM()->unknownError("try to resolve static of a not virtual-resolved class");
} else if (status == virtual_resolved) {
if (cl->isArray) {
VMClassArray* arrayCl = (VMClassArray*)cl;
VMCommonClass* baseClass = arrayCl->baseClass;
baseClass->resolveStatic(false, genMethod);
cl->status = static_resolved;
} else if (cl->isPointer) {
VMClassPointer* pointerCl = (VMClassPointer*)cl;
VMCommonClass* baseClass = pointerCl->baseClass;
baseClass->resolveStatic(false, genMethod);
cl->status = static_resolved;
} else {
((VMClass*)cl)->resolveStaticFields(genMethod);
cl->status = static_resolved;
}
cl->release();
} else {
if (!(cl->ownerClass())) {
while (status < static_resolved) {
cl->waitClass();
}
}
cl->release();
}
}
if (clinit) cl->clinitClass(genMethod);
}
VMMethod* VMCommonClass::lookupMethodDontThrow(const UTF8* name,
std::vector<VMCommonClass*>& args,
bool isStatic, bool recurse) {
std::vector<VMMethod*>* meths = (isStatic? &staticMethods :
&virtualMethods);
VMMethod *cur, *res = 0;
int i = 0;
int nbm = meths->size();
while (!res && i < nbm) {
cur = meths->at(i);
if (cur->name == name && cur->signatureEquals(args)) {
return cur;
}
++i;
}
if (recurse) {
if (super) res = super->lookupMethodDontThrow(name, args, isStatic,
recurse);
if (!res && isStatic) {
int nbi = interfaces.size();
i = 0;
while (res == 0 && i < nbi) {
res = interfaces[i]->lookupMethodDontThrow(name, args, isStatic,
recurse);
++i;
}
}
}
return res;
}
VMMethod* VMCommonClass::lookupMethod(const UTF8* name,
std::vector<VMCommonClass*>& args,
bool isStatic, bool recurse) {
VMMethod* res = lookupMethodDontThrow(name, args, isStatic, recurse);
if (!res) {
VMThread::get()->getVM()->error(N3::MissingMethodException,
"unable to find %s in %s",
mvm::PrintBuffer(name).cString(), mvm::PrintBuffer(this).cString());
}
return res;
}
VMField* VMCommonClass::lookupFieldDontThrow(const UTF8* name,
VMCommonClass* type,
bool isStatic, bool recurse) {
std::vector<VMField*>* fields = (isStatic? &staticFields : &virtualFields);
VMField *cur, *res = 0;
int i = 0;
int nbm = fields->size();
while (!res && i < nbm) {
cur = fields->at(i);
if (cur->name == name && cur->signature == type) {
return cur;
}
++i;
}
if (recurse) {
if (super) res = super->lookupFieldDontThrow(name, type, isStatic,
recurse);
if (!res && isStatic) {
int nbi = interfaces.size();
i = 0;
while (res == 0 && i < nbi) {
res = interfaces[i]->lookupFieldDontThrow(name, type, isStatic,
recurse);
++i;
}
}
}
return res;
}
VMField* VMCommonClass::lookupField(const UTF8* name, VMCommonClass* type,
bool isStatic, bool recurse) {
VMField* res = lookupFieldDontThrow(name, type, isStatic, recurse);
if (!res) {
VMThread::get()->getVM()->error(N3::MissingFieldException,
"unable to find %s in %s",
mvm::PrintBuffer(name).cString(), mvm::PrintBuffer(this).cString());
}
return res;
}
VMObject* VMClass::initialiseObject(VMObject* obj) {
uint64 size = mvm::MvmModule::getTypeSize(virtualType->getContainedType(0));
memcpy(obj, virtualInstance, size);
return obj;
}
VMObject* VMClass::doNew() {
if (status < inClinit) resolveType(true, true, NULL);
uint64 size = mvm::MvmModule::getTypeSize(virtualType->getContainedType(0));
declare_gcroot(VMObject*, res) = (VMObject*)gc::operator new(size, VMObject::getN3VirtualTable(virtualInstance));
memcpy(res, virtualInstance, size);
return res;
}
VMObject* VMClassArray::doNew(uint32 nb) {
if (status < inClinit) resolveType(true, true, NULL);
uint64 size = mvm::MvmModule::getTypeSize(baseClass->naturalType);
declare_gcroot(VMArray*, res) = (VMArray*)gc::operator new(size * nb + sizeof(VMObject) + sizeof(sint32), arrayVT);
memset(res->elements, 0, size * nb);
VMObject::initialise(res, this);
res->size = nb;
return res;
}
static void disassembleStruct(std::vector<const llvm::Type*> &args,
const llvm::Type* arg) {
const llvm::StructType* STy = llvm::dyn_cast<llvm::StructType>(arg);
for (llvm::StructType::element_iterator I = STy->element_begin(),
E = STy->element_end(); I != E; ++I) {
if ((*I)->isSingleValueType()) {
args.push_back(*I);
} else {
disassembleStruct(args, *I);
}
}
}
const llvm::FunctionType* VMMethod::resolveSignature(
std::vector<VMCommonClass*> & parameters, bool isVirt,
bool& structRet, VMGenericMethod* genMethod) {
const llvm::Type* ret;
std::vector<const llvm::Type*> args;
std::vector<VMCommonClass*>::iterator i = parameters.begin(),
e = parameters.end();
if ((*i)->naturalType->isAbstract()) {
(*i)->resolveType(false, false, genMethod);
}
ret = (*i)->naturalType;
++i;
if (isVirt) {
VMCommonClass* cur = (*i);
++i;
if (cur->naturalType->isAbstract()) {
cur->resolveType(false, false, genMethod);
}
if (cur->super != MSCorlib::pValue && cur->super != MSCorlib::pEnum) {
args.push_back(cur->naturalType);
} else {
args.push_back(llvm::PointerType::getUnqual(cur->naturalType));
}
}
for ( ; i!= e; ++i) {
VMCommonClass* cur = (*i);
if (cur->naturalType->isAbstract()) {
cur->resolveType(false, false, genMethod);
}
if (cur->naturalType->isSingleValueType()) {
args.push_back(cur->naturalType);
} else {
args.push_back(llvm::PointerType::getUnqual(cur->naturalType));
}
}
if (!(ret->isSingleValueType()) && ret != llvm::Type::getVoidTy(llvm::getGlobalContext())) {
args.push_back(llvm::PointerType::getUnqual(ret));
ret = llvm::Type::getVoidTy(llvm::getGlobalContext());
structRet = true;
} else {
structRet = false;
}
return llvm::FunctionType::get(ret, args, false);
}
const llvm::FunctionType* VMMethod::getSignature(VMGenericMethod* genMethod) {
if (!_signature) {
_signature = resolveSignature(parameters, !isStatic(flags), structReturn, genMethod);
}
return _signature;
}
const llvm::FunctionType* Property::getSignature(VMGenericMethod* genMethod) {
if (!_signature) {
bool structReturn = false;
_signature = VMMethod::resolveSignature(parameters, virt, structReturn, genMethod);
}
return _signature;
}
bool VMCommonClass::implements(VMCommonClass* cl) {
if (this == cl) return true;
else {
for (uint32 i = 0; i < interfaces.size(); i++) {
VMCommonClass* cur = interfaces[i];
if (cur == cl) return true;
else if (cur->implements(cl)) return true;
}
if (super) {
return super->implements(cl);
}
}
return false;
}
bool VMCommonClass::instantiationOfArray(VMCommonClass* cl) {
if (this == cl) return true;
else {
if (isArray && cl->isArray) {
VMCommonClass* baseThis = ((VMClassArray*)this)->baseClass;
VMCommonClass* baseCl = ((VMClassArray*)cl)->baseClass;
if (isInterface(baseThis->flags) && isInterface(baseCl->flags)) {
return baseThis->implements(baseCl);
} else {
return baseThis->isAssignableFrom(baseCl);
}
}
}
return false;
}
bool VMCommonClass::subclassOf(VMCommonClass* cl) {
if (cl->depth < display.size()) {
return display[cl->depth] == cl;
} else {
return false;
}
}
bool VMCommonClass::isAssignableFrom(VMCommonClass* cl) {
if (this == cl) {
return true;
} else if (isInterface(cl->flags)) {
return this->implements(cl);
} else if (cl->isArray) {
return this->instantiationOfArray(cl);
} else if (cl->isPointer){
VMThread::get()->getVM()->error("implement me");
return false;
} else {
return this->subclassOf(cl);
}
}
VMMethod *VMMethod::compileToNative(VMGenericMethod* genMethod) {
if(!code) {
if (classDef->status < ready)
classDef->resolveType(true, true, NULL);
llvm::Function *methPtr = compiledPtr(genMethod);
void* res =
mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(methPtr);
if (res == 0) {
classDef->aquire();
res =
mvm::MvmModule::executionEngine->getPointerToGlobalIfAvailable(methPtr);
if (res == 0) {
CLIJit::compile(classDef, this);
void* res = mvm::MvmModule::executionEngine->getPointerToGlobal(methPtr);
code = res;
N3* vm = VMThread::get()->getVM();
// vm->addMethodInFunctionMap(this, res);
}
classDef->release();
classDef->resolveStatic(true, NULL);
}
}
return this;
}
bool VMMethod::signatureEquals(std::vector<VMCommonClass*>& args) {
bool stat = isStatic(flags);
if (args.size() != parameters.size()) return false;
else {
std::vector<VMCommonClass*>::iterator i = parameters.begin(),
a = args.begin(), e = args.end();
if ((*i) != (*a)) return false;
++i; ++a;
if (!stat) {
++i; ++a;
}
for( ; a != e; ++i, ++a) {
if ((*i) != (*a)) return false;
}
}
return true;
}
bool VMMethod::signatureEqualsGeneric(std::vector<VMCommonClass*> & args) {
bool stat = isStatic(flags);
if (args.size() != parameters.size())
return false;
else {
std::vector<VMCommonClass*>::iterator i = parameters.begin(), a =
args.begin(), e = args.end();
// dummy classes for generic arguments have a NULL assembly field
// check whether both i and a point to a dummy class
if (((*i)->assembly == NULL && (*a)->assembly != NULL) ||
((*i)->assembly != NULL && (*a)->assembly == NULL))
return false;
// dummy classes for generic arguments contain the
// argument number in the token field
// signature is only equal if the argument number matches
if ((*i)->assembly == NULL && (*a)->assembly == NULL) {
if ((*i)->token != (*a)->token) {
return false;
}
}
if ((*i) != (*a))
return false;
++i;
++a;
if (!stat) {
++i;
++a;
}
for (; a != e; ++i, ++a) {
// dummy classes for generic arguments have a NULL assembly field
// check whether both i and a point to a dummy class
if (((*i)->assembly == NULL && (*a)->assembly != NULL) ||
((*i)->assembly != NULL && (*a)->assembly == NULL))
return false;
// dummy classes for generic arguments contain the
// argument number in the token field
// signature is only equal if the argument number matches
if ((*i)->assembly == NULL && (*a)->assembly == NULL) {
if ((*i)->token != (*a)->token) {
return false;
} else {
continue;
}
}
if ((*i) != (*a))
return false;
}
}
return true;
}
void VMGenericClass::print(mvm::PrintBuffer* buf) const {
buf->write("GenCLIType<");
nameSpace->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
}