blob: a22f80ab0c1822c113a1ed9f92d188431af5fb82 [file] [log] [blame]
//===--- IsolateCommonClass.cpp - User visible classes with isolates -------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "IsolateSharedLoader.h"
#include "JavaAllocator.h"
#include "JavaClass.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "JnjvmModule.h"
using namespace jnjvm;
UserCommonClass::UserCommonClass() {
this->lockVar = mvm::Lock::allocRecursive();
this->condVar = mvm::Cond::allocCond();
this->status = loaded;
}
UserClass::UserClass(JnjvmClassLoader* JCL, const UTF8* name,
ArrayUInt8* bytes) {
Class* cl = JnjvmSharedLoader::sharedLoader->constructSharedClass(name,
bytes);
if (!cl) {
cl = allocator_new(JCL->allocator, Class)(JCL, name, bytes);
}
classDef = cl;
classLoader = JCL;
delegatee = 0;
staticInstance = 0;
ctpInfo = 0;
}
UserClassArray::UserClassArray(JnjvmClassLoader* JCL, const UTF8* name) {
ClassArray* cl = JnjvmSharedLoader::sharedLoader->constructSharedClassArray(name);
if (!cl) {
cl = allocator_new(JCL->allocator, ClassArray)(JCL, name);
}
classDef = cl;
classLoader = JCL;
delegatee = 0;
_baseClass = 0;
_funcs = 0;
super = JCL->bootstrapLoader->SuperArray;
interfaces = JCL->bootstrapLoader->InterfacesArray;
depth = 1;
display = (UserCommonClass**)malloc(2 * sizeof(UserCommonClass*));
display[0] = super;
display[1] = this;
}
UserClassPrimitive::UserClassPrimitive(JnjvmClassLoader* JCL, const UTF8* name,
uint32 nb) {
ClassPrimitive* cl =
JnjvmSharedLoader::sharedLoader->constructSharedClassPrimitive(name, nb);
if (!cl) {
cl = new ClassPrimitive(JCL, name, nb);
}
classDef = cl;
classLoader = JCL;
delegatee = 0;
display = (UserCommonClass**)malloc(sizeof(UserCommonClass*));
display[0] = this;
virtualSize = nb;
status = ready;
}
void UserCommonClass::resolveClass() {
if (status < resolved) {
acquire();
if (status >= resolved) {
release();
} else if (status == loaded) {
if (isArray()) {
UserClassArray* arrayCl = (UserClassArray*)this;
UserCommonClass* baseClass = arrayCl->baseClass();
baseClass->resolveClass();
status = resolved;
} else {
UserClass* cl = (UserClass*)this;
Class* def = (Class*)classDef;
if (classDef->status < resolved) {
classDef->acquire();
if (classDef->status == loaded) {
def->readClass();
def->status = classRead;
status = classRead;
cl->ctpInfo =
new(classLoader->allocator, def->ctpInfo->ctpSize) UserConstantPool(cl);
cl->loadParents();
if (cl->super)
def->super = cl->super->classDef;
for (std::vector<UserClass*>::iterator i = interfaces.begin(),
e = interfaces.end(); i != e; ++i) {
def->interfaces.push_back((Class*)((*i)->classDef));
}
def->status = prepared;
status = prepared;
def->classLoader->TheModule->resolveVirtualClass(def);
virtualSize = def->virtualSize;
uint64 vtSize = def->virtualTableSize * sizeof(void*);
virtualVT = (VirtualTable*)malloc(2 * vtSize);
memcpy((void*)((uint64)virtualVT + vtSize), def->virtualVT, vtSize);
if (super) {
memcpy(virtualVT, (void*)((uint64)super->virtualVT - vtSize),
vtSize);
}
virtualVT = (VirtualTable*)((uint64)virtualVT + vtSize);
for (CommonClass::method_iterator i = def->virtualMethods.begin(),
e = def->virtualMethods.end(); i != e; ++i) {
if (i->second->offset > 0) {
((void**)virtualVT)[-(i->second->offset)] = ctpInfo;
}
}
def->status = resolved;
status = resolved;
classDef->broadcastClass();
} else {
while (classDef->status < resolved) {
classDef->waitClass();
}
}
classDef->release();
} else {
cl->ctpInfo =
new(classLoader->allocator, def->ctpInfo->ctpSize) UserConstantPool(cl);
release();
status = classRead,
cl->loadParents();
status = resolved;
broadcastClass();
}
}
release();
} else {
while (status < resolved) {
waitClass();
}
release();
}
}
}
UserClass* UserCommonClass::lookupClassFromMethod(JavaMethod* meth) {
UserClass* res = 0;
lookupMethodDontThrow(meth->name, meth->type,
isStatic(meth->access), true, res);
return res;
}
UserCommonClass* UserCommonClass::getUserClass(CommonClass* cl) {
fprintf(stderr, "implement me");
abort();
return 0;
}
UserCommonClass* UserConstantPool::isClassLoaded(uint32 entry) {
JavaConstantPool* ctpInfo = getSharedPool();
if (! ((entry > 0) && (entry < ctpInfo->ctpSize) &&
ctpInfo->typeAt(entry) == JavaConstantPool::ConstantClass)) {
JavaThread::get()->isolate->classFormatError(
"bad constant pool number for class at entry %d", entry);
}
return (UserCommonClass*)ctpRes[entry];
}
UserCommonClass* UserConstantPool::loadClass(uint32 index) {
UserCommonClass* temp = isClassLoaded(index);
if (!temp) {
JavaConstantPool* ctpInfo = getSharedPool();
JnjvmClassLoader* loader = getClass()->classLoader;
const UTF8* name = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
if (name->elements[0] == AssessorDesc::I_TAB) {
temp = loader->constructArray(name);
temp->resolveClass();
} else {
// Put into ctpRes because there is only one representation of the class
temp = loader->loadName(name, true, false);
}
ctpRes[index] = temp;
ctpInfo->ctpRes[index] = temp->classDef;
}
return temp;
}
void UserConstantPool::resolveMethod(uint32 index, UserCommonClass*& cl,
const UTF8*& utf8, Signdef*& sign) {
JavaConstantPool* ctpInfo = getSharedPool();
sint32 entry = ctpInfo->ctpDef[index];
sint32 ntIndex = entry & 0xFFFF;
sign = (Signdef*)ctpInfo->ctpRes[ntIndex];
assert(sign && "No cached signature after JITting");
utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[ntIndex] >> 16);
cl = loadClass(entry >> 16);
assert(cl && cl->isResolved() && "No resolved class when resolving method");
}
void UserConstantPool::resolveField(uint32 index, UserCommonClass*& cl,
const UTF8*& utf8, Typedef*& sign) {
JavaConstantPool* ctpInfo = getSharedPool();
sint32 entry = ctpInfo->ctpDef[index];
sint32 ntIndex = entry & 0xFFFF;
sign = (Typedef*)ctpInfo->ctpRes[ntIndex];
assert(sign && "No cached Typedef after JITting");
utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[ntIndex] >> 16);
cl = loadClass(entry >> 16);
assert(cl && cl->isResolved() && "No resolved class when resolving field");
}
void* UserConstantPool::operator new(size_t sz, JavaAllocator* alloc,
uint32 size){
return alloc->allocateObject(sz + size * sizeof(void*), VT);
}
UserClassPrimitive* AssessorDesc::getPrimitiveClass() const {
Jnjvm* vm = JavaThread::get()->isolate;
if (numId > VOID_ID && numId < ARRAY_ID) {
UserClassArray* arrayCl = vm->arrayClasses[numId];
UserClassPrimitive* cl = (UserClassPrimitive*)arrayCl->_baseClass;
assert(cl && "Primitive array class does not have a primitive.");
return cl;
} else if (numId == VOID_ID) {
return vm->upcalls->OfVoid;
}
return 0;
}
UserClassArray* AssessorDesc::getArrayClass() const {
Jnjvm* vm = JavaThread::get()->isolate;
UserClassArray* arrayCl = vm->arrayClasses[numId];
return arrayCl;
}
JavaMethod* UserCommonClass::lookupMethodDontThrow(const UTF8* name,
const UTF8* type,
bool isStatic,
bool recurse,
UserClass*& methodCl) {
CommonClass::FieldCmp CC(name, type);
CommonClass::method_map* map = isStatic ? getStaticMethods() :
getVirtualMethods();
CommonClass::method_iterator End = map->end();
CommonClass::method_iterator I = map->find(CC);
if (I != End) {
methodCl = (UserClass*)this;
return I->second;
}
JavaMethod *cur = 0;
if (recurse) {
if (super) cur = super->lookupMethodDontThrow(name, type, isStatic,
recurse, methodCl);
if (cur) return cur;
if (isStatic) {
std::vector<UserClass*>* interfaces = getInterfaces();
for (std::vector<UserClass*>::iterator i = interfaces->begin(),
e = interfaces->end(); i!= e; i++) {
cur = (*i)->lookupMethodDontThrow(name, type, isStatic, recurse,
methodCl);
if (cur) return cur;
}
}
}
return 0;
}
JavaMethod* UserCommonClass::lookupMethod(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
UserClass*& methodCl) {
JavaMethod* res = lookupMethodDontThrow(name, type, isStatic, recurse,
methodCl);
if (!res) {
JavaThread::get()->isolate->noSuchMethodError(this->classDef, name);
}
return res;
}
JavaField*
UserCommonClass::lookupFieldDontThrow(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
UserCommonClass*& definingClass) {
CommonClass::FieldCmp CC(name, type);
CommonClass::field_map* map = isStatic ? getStaticFields() :
getVirtualFields();
CommonClass::field_iterator End = map->end();
CommonClass::field_iterator I = map->find(CC);
if (I != End) {
definingClass = this;
return I->second;
}
JavaField *cur = 0;
if (recurse) {
if (super) cur = super->lookupFieldDontThrow(name, type, isStatic,
recurse, definingClass);
if (cur) return cur;
if (isStatic) {
std::vector<UserClass*>* interfaces = getInterfaces();
for (std::vector<UserClass*>::iterator i = interfaces->begin(),
e = interfaces->end(); i!= e; i++) {
cur = (*i)->lookupFieldDontThrow(name, type, isStatic, recurse,
definingClass);
if (cur) return cur;
}
}
}
return 0;
}
JavaField* UserCommonClass::lookupField(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
UserCommonClass*& definingClass) {
JavaField* res = lookupFieldDontThrow(name, type, isStatic, recurse,
definingClass);
if (!res) {
JavaThread::get()->isolate->noSuchFieldError(this->classDef, name);
}
return res;
}
void UserConstantPool::print(mvm::PrintBuffer* buf) const {
buf->write("User constant pool of <");
getClass()->classDef->print(buf);
buf->write(">");
}
void UserCommonClass::print(mvm::PrintBuffer* buf) const {
buf->write("User class of <");
classDef->print(buf);
buf->write(">");
}