blob: a3aeb6b5495cb9cbe12fc4a763cf678f132f93a9 [file] [log] [blame]
//===--- CLIRuntimeJIT.cpp - Runtime functions for the JIT compiled code --===//
//
// The vmkit project
//
// This file is distributed under the University Of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <cstdio>
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "mvm/JIT.h"
#include "mvm/Object.h"
#include "mvm/PrintBuffer.h"
#include "mvm/Threads/Locks.h"
#include "CLIString.h"
#include "MSCorlib.h"
#include "N3.h"
#include "VMArray.h"
#include "VMCache.h"
#include "VMClass.h"
#include "VMObject.h"
#include "VMThread.h"
#include "Assembly.h"
#include "mvm/GC/GC.h"
#include <cstdarg>
using namespace n3;
using namespace llvm;
extern "C" VMObject* initialiseClass(VMClass* cl) {
cl->clinitClass(NULL);
return cl->staticInstance;
}
extern "C" void n3ClassCastException() {
fflush(stdout);
assert(0 && "implement class cast exception");
}
extern "C" void n3NullPointerException() {
fflush(stdout);
assert(0 && "implement null pointer exception");
}
extern "C" void indexOutOfBounds() {
fflush(stdout);
assert(0 && "implement index out of bounds exception");
}
extern "C" VMObject* newString(const ArrayChar* utf8) {
N3 *vm = (N3*)VMThread::get()->getVM();
declare_gcroot(VMObject*, res) = vm->arrayToString(utf8);
return res;
}
extern "C" bool n3InstanceOf(VMObject* obj, VMCommonClass* cl) {
return VMObject::instanceOf(obj, cl);
}
extern "C" void* GetCppException() {
return VMThread::getCppException();
}
extern "C" void ThrowException(VMObject* obj) {
return VMThread::throwException(obj);
}
extern "C" VMObject* GetCLIException() {
declare_gcroot(VMObject*, res) = VMThread::getCLIException();
return res;
}
extern "C" bool CompareException(VMClass* cl) {
return VMThread::compareException(cl);
}
extern "C" void ClearException() {
return VMThread::get()->clearException();
}
static VMObject* doMultiNewIntern(VMClassArray* cl, uint32 dim, sint32* buf) {
if (dim <= 0) VMThread::get()->getVM()->error("Can't happen");
sint32 n = buf[0];
if (n < 0) VMThread::get()->getVM()->negativeArraySizeException(n);
declare_gcroot(VMArray*, res) = (VMArray*)cl->doNew(n);
if (dim > 1) {
VMCommonClass* base = cl->baseClass;
if (n > 0) {
for (sint32 i = 0; i < n; ++i) {
res->elements[i] = doMultiNewIntern((VMClassArray*)base, dim - 1, &(buf[1]));
}
}
for (uint32 i = 1; i < dim; ++i) {
if (buf[i] < 0) VMThread::get()->getVM()->negativeArraySizeException(buf[i]);
}
}
return res;
}
extern "C" VMObject* doMultiNew(VMClassArray* cl, ...) {
sint32* dimSizes = (sint32*)alloca(cl->dims * sizeof(sint32));
va_list ap;
va_start(ap, cl);
for (uint32 i = 0; i < cl->dims; ++i) {
dimSizes[i] = va_arg(ap, sint32);
}
va_end(ap);
return doMultiNewIntern(cl, cl->dims, dimSizes);
}
extern "C" CacheNode* n3VirtualLookup(CacheNode* cache, VMObject *obj) {
Enveloppe* enveloppe = cache->enveloppe;
VMCommonClass* ocl = obj->classOf;
VMMethod* orig = enveloppe->originalMethod;
CacheNode* rcache = 0;
CacheNode* tmp = enveloppe->firstCache;
CacheNode* last = tmp;
enveloppe->cacheLock->lock();
while (tmp) {
if (ocl == tmp->lastCible) {
rcache = tmp;
break;
} else {
last = tmp;
tmp = tmp->next;
}
}
if (!rcache) {
VMMethod* dmeth = ocl->lookupMethodDontThrow(orig->name,
orig->parameters,
false, true);
if (dmeth == 0) {
mvm::PrintBuffer _methAsciiz(orig->name);
mvm::PrintBuffer _nameAsciiz(orig->classDef->name);
mvm::PrintBuffer _nameSpaceAsciiz(orig->classDef->nameSpace);
const char* methAsciiz = _methAsciiz.cString();
const char* nameAsciiz = _nameAsciiz.cString();
const char* nameSpaceAsciiz = _nameSpaceAsciiz.cString();
char *buf = (char*)alloca(3 + strlen(methAsciiz) +
strlen(nameAsciiz) +
strlen(nameSpaceAsciiz));
sprintf(buf, "%s.%s.%s", nameSpaceAsciiz, nameAsciiz, methAsciiz);
const UTF8* newName = VMThread::get()->getVM()->asciizToUTF8(buf);
dmeth = ocl->lookupMethod(newName, orig->parameters, false, true);
}
if (cache->methPtr) {
rcache = CacheNode::allocate(orig->classDef->assembly->allocator);
rcache->enveloppe = enveloppe;
} else {
rcache = cache;
}
Function* func = dmeth->compiledPtr(NULL);
rcache->methPtr = mvm::MvmModule::executionEngine->getPointerToGlobal(func);
rcache->lastCible = (VMClass*)ocl;
rcache->box = (dmeth->classDef->super == MSCorlib::pValue);
}
if (enveloppe->firstCache != rcache) {
CacheNode *f = enveloppe->firstCache;
enveloppe->firstCache = rcache;
last->next = rcache->next;
rcache->next = f;
}
enveloppe->cacheLock->unlock();
return rcache;
}
extern "C" VMObject* newObject(VMClass* cl) {
declare_gcroot(VMObject*, res) = cl->doNew();
return res;
}
extern "C" VMObject* newArray(VMClassArray* cl, sint32 nb) {
declare_gcroot(VMObject*, res) = cl->doNew(nb);
return res;
}