blob: 3384cfc4ec5c72c178d2432356bbb20ad80306d9 [file] [log] [blame]
//===---------- Jnjvm.cpp - Java virtual machine description --------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// realpath
#include <limits.h>
#include <stdlib.h>
#include <float.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "debug.h"
#include "mvm/JIT.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "LockedMap.h"
#include "Reader.h"
#include "Zip.h"
using namespace jnjvm;
const char* Jnjvm::dirSeparator = "/";
const char* Jnjvm::envSeparator = ":";
const unsigned int Jnjvm::Magic = 0xcafebabe;
#define DECLARE_EXCEPTION(EXCP) \
const char* Jnjvm::EXCP = "java/lang/"#EXCP
#define DECLARE_REFLECT_EXCEPTION(EXCP) \
const char* Jnjvm::EXCP = "java/lang/reflect/"#EXCP
DECLARE_EXCEPTION(ArithmeticException);
DECLARE_REFLECT_EXCEPTION(InvocationTargetException);
DECLARE_EXCEPTION(ArrayStoreException);
DECLARE_EXCEPTION(ClassCastException);
DECLARE_EXCEPTION(IllegalMonitorStateException);
DECLARE_EXCEPTION(IllegalArgumentException);
DECLARE_EXCEPTION(InterruptedException);
DECLARE_EXCEPTION(IndexOutOfBoundsException);
DECLARE_EXCEPTION(ArrayIndexOutOfBoundsException);
DECLARE_EXCEPTION(NegativeArraySizeException);
DECLARE_EXCEPTION(NullPointerException);
DECLARE_EXCEPTION(SecurityException);
DECLARE_EXCEPTION(ClassFormatError);
DECLARE_EXCEPTION(ClassCircularityError);
DECLARE_EXCEPTION(NoClassDefFoundError);
DECLARE_EXCEPTION(UnsupportedClassVersionError);
DECLARE_EXCEPTION(NoSuchFieldError);
DECLARE_EXCEPTION(NoSuchMethodError);
DECLARE_EXCEPTION(InstantiationError);
DECLARE_EXCEPTION(IllegalAccessError);
DECLARE_EXCEPTION(IllegalAccessException);
DECLARE_EXCEPTION(VerifyError);
DECLARE_EXCEPTION(ExceptionInInitializerError);
DECLARE_EXCEPTION(LinkageError);
DECLARE_EXCEPTION(AbstractMethodError);
DECLARE_EXCEPTION(UnsatisfiedLinkError);
DECLARE_EXCEPTION(InternalError);
DECLARE_EXCEPTION(OutOfMemoryError);
DECLARE_EXCEPTION(StackOverflowError);
DECLARE_EXCEPTION(UnknownError);
DECLARE_EXCEPTION(ClassNotFoundException);
void Jnjvm::analyseClasspathEnv(const char* str) {
if (str != 0) {
unsigned int len = strlen(str);
char* buf = (char*)alloca(len + 1);
const char* cur = str;
int top = 0;
char* rp = 0;
char c = 1;
while (c != 0) {
while (((c = cur[top]) != 0) && c != envSeparator[0]) {
top++;
}
if (top != 0) {
memcpy(buf, cur, top);
buf[top] = 0;
rp = realpath(buf, rp);
if (rp != 0) {
struct stat st;
stat(rp, &st);
if ((st.st_mode & S_IFMT) == S_IFDIR) {
unsigned int len = strlen(rp);
char* temp = (char*)malloc(len + 2);
memcpy(temp, rp, len);
temp[len] = dirSeparator[0];
temp[len + 1] = 0;
bootClasspath.push_back(temp);
} else {
bootClasspath.push_back(rp);
}
}
}
cur = cur + top + 1;
top = 0;
}
}
}
void Jnjvm::readParents(Class* cl, Reader* reader) {
JavaCtpInfo* ctpInfo = cl->ctpInfo;
unsigned short int superEntry = reader->readU2();
const UTF8* super = superEntry ?
ctpInfo->resolveClassName(superEntry) : 0;
unsigned short int nbI = reader->readU2();
cl->superUTF8 = super;
for (int i = 0; i < nbI; i++)
cl->interfacesUTF8.push_back(ctpInfo->resolveClassName(reader->readU2()));
}
void Jnjvm::loadParents(Class* cl) {
const UTF8* super = cl->superUTF8;
int nbI = cl->interfacesUTF8.size();
JavaObject* classLoader = cl->classLoader;
if (super == 0) {
cl->depth = 0;
cl->display.push_back(cl);
} else {
cl->super = loadName(super, classLoader, true, false, true);
int depth = cl->super->depth;
cl->depth = depth + 1;
for (uint32 i = 0; i < cl->super->display.size(); ++i) {
cl->display.push_back(cl->super->display[i]);
}
cl->display.push_back(cl);
}
for (int i = 0; i < nbI; i++)
cl->interfaces.push_back((Class*)loadName(cl->interfacesUTF8[i],
classLoader, true, false, true));
}
void Jnjvm::readAttributs(Class* cl, Reader* reader,
std::vector<Attribut*>& attr) {
JavaCtpInfo* ctpInfo = cl->ctpInfo;
unsigned short int nba = reader->readU2();
for (int i = 0; i < nba; i++) {
const UTF8* attName = ctpInfo->UTF8At(reader->readU2());
unsigned int attLen = reader->readU4();
Attribut* att = Attribut::derive(attName, attLen, reader);
attr.push_back(att);
reader->seek(attLen, Reader::SeekCur);
}
}
void Jnjvm::readFields(Class* cl, Reader* reader) {
unsigned short int nbFields = reader->readU2();
JavaCtpInfo* ctpInfo = cl->ctpInfo;
for (int i = 0; i < nbFields; i++) {
unsigned short int access = reader->readU2();
const UTF8* name = ctpInfo->UTF8At(reader->readU2());
const UTF8* type = ctpInfo->UTF8At(reader->readU2());
JavaField* field = constructField(cl, name, type, access);
readAttributs(cl, reader, field->attributs);
if (isStatic(access)) {
cl->staticFields.push_back(field);
} else {
cl->virtualFields.push_back(field);
}
}
}
void Jnjvm::readMethods(Class* cl, Reader* reader) {
unsigned short int nbMethods = reader->readU2();
JavaCtpInfo* ctpInfo = cl->ctpInfo;
for (int i = 0; i < nbMethods; i++) {
unsigned short int access = reader->readU2();
const UTF8* name = ctpInfo->UTF8At(reader->readU2());
const UTF8* type = ctpInfo->UTF8At(reader->readU2());
JavaMethod* meth = constructMethod(cl, name, type, access);
readAttributs(cl, reader, meth->attributs);
if (isStatic(access)) {
cl->staticMethods.push_back(meth);
} else {
cl->virtualMethods.push_back(meth);
}
}
}
void Jnjvm::readClass(Class* cl) {
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "; ");
PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "reading ");
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s::%s\n", printString(),
cl->printString());
Reader* reader = Reader::allocateReader(cl->bytes);
uint32 magic = reader->readU4();
if (magic != Jnjvm::Magic) {
Jnjvm::error(ClassFormatError, "bad magic number %p", magic);
}
cl->minor = reader->readU2();
cl->major = reader->readU2();
JavaCtpInfo::read(this, cl, reader);
JavaCtpInfo* ctpInfo = cl->ctpInfo;
cl->access = reader->readU2();
const UTF8* thisClassName =
ctpInfo->resolveClassName(reader->readU2());
if (thisClassName != cl->name) {
error(ClassFormatError, "try to load %s and found class named %s",
cl->printString(), thisClassName->printString());
}
readParents(cl, reader);
readFields(cl, reader);
readMethods(cl, reader);
readAttributs(cl, reader, cl->attributs);
}
ArrayUInt8* Jnjvm::openName(const UTF8* utf8) {
char* asciiz = utf8->UTF8ToAsciiz();
uint32 alen = strlen(asciiz);
uint32 nbcp = bootClasspath.size();
uint32 idx = 0;
ArrayUInt8* res = 0;
while ((res == 0) && (idx < nbcp)) {
char* str = bootClasspath[idx];
unsigned int strLen = strlen(str);
char* buf = (char*)alloca(strLen + alen + 16);
if (str[strLen - 1] == dirSeparator[0]) {
sprintf(buf, "%s%s.class", str, asciiz);
res = Reader::openFile(buf);
} else {
sprintf(buf, "%s.class", asciiz);
res = Reader::openZip(str, buf);
}
idx++;
}
return res;
}
typedef void (*clinit_t)(void);
void Jnjvm::initialiseClass(CommonClass* cl) {
start:
if (!((Class*)cl)->isReady()) {
cl->aquire();
int status = cl->status;
#ifdef SINGLE_VM
if (status == ready) {
#else
if (((Class*)cl)->isReady()) {
#endif
cl->release();
} else if (status >= resolved && status != clinitParent && status != inClinit) {
cl->status = clinitParent;
cl->release();
if (cl->super) {
cl->super->initialiseClass();
}
for (uint32 i = 0; i < cl->interfaces.size(); i++) {
cl->interfaces[i]->initialiseClass();
}
cl->status = inClinit;
JavaMethod* meth = cl->lookupMethodDontThrow(clinitName, clinitType, true,
false);
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "; ");
PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "clinit ");
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s::%s\n", printString(),
cl->printString());
#ifndef SINGLE_VM
std::pair<uint8, JavaObject*>* val = 0;
if (this == bootstrapVM) {
JavaObject* staticVar = ((Class*)cl)->createStaticInstance();
val = new std::pair<uint8, JavaObject*>(0, staticVar);
JavaThread::get()->isolate->statics->hash((Class*)cl, val);
}
#endif
if (meth) {
JavaObject* exc = 0;
try{
clinit_t pred = (clinit_t)meth->compiledPtr();
pred();
} catch(...) {
exc = JavaThread::getJavaException();
assert(exc && "no exception?");
JavaThread::clearException();
}
if (exc) {
if (exc->classOf->isAssignableFrom(Classpath::newException)) {
JavaThread::get()->isolate->initializerError(exc);
} else {
JavaThread::throwException(exc);
}
}
}
cl->status = ready;
#ifndef SINGLE_VM
if (this == bootstrapVM) {
val->first = 1;
}
#endif
cl->broadcastClass();
} else if (status < resolved) {
cl->release();
unknownError("try to clinit a not-readed class...");
} else {
if (!cl->ownerClass()) {
while (status < ready) cl->waitClass();
cl->release();
goto start;
}
cl->release();
}
}
}
void Jnjvm::resolveClass(CommonClass* cl, bool doClinit) {
if (cl->status < resolved) {
cl->aquire();
int status = cl->status;
if (status >= resolved) {
cl->release();
} else if (status < loaded) {
cl->release();
unknownError("try to resolve a not-readed class");
} else if (status == loaded || cl->ownerClass()) {
if (cl->isArray) {
ClassArray* arrayCl = (ClassArray*)cl;
CommonClass* baseClass = arrayCl->baseClass();
baseClass->resolveClass(doClinit);
cl->access = cl->access | baseClass->access;
cl->status = resolved;
} else {
readClass((Class*)cl);
cl->status = readed;
cl->release();
loadParents((Class*)cl);
cl->aquire();
cl->status = prepared;
((Class*)cl)->resolveFields();
cl->status = resolved;
}
cl->release();
} else {
while (status < resolved) {
cl->waitClass();
}
cl->release();
}
}
if (doClinit) cl->initialiseClass();
}
CommonClass* Jnjvm::loadName(const UTF8* name, JavaObject* loader,
bool doResolve, bool doClinit, bool doThrow) {
CommonClass* cl = lookupClass(name, loader);
const UTF8* bootstrapName = name;
#ifndef SINGLE_VM
if (!loader) {
bootstrapName = bootstrapVM->readerConstructUTF8(name->elements,
name->size);
if (bootstrapName != name) {
JavaThread::get()->isolate->hashUTF8->replace(name, bootstrapName);
}
cl = lookupClass(bootstrapName, loader);
}
#endif
if (!cl || cl->status == hashed) {
if (!loader) { // I have to load it
ArrayUInt8* bytes = openName(name);
if (bytes) {
if (!cl) cl = bootstrapVM->constructClass(bootstrapName, loader);
if (cl->status == hashed) {
cl->aquire();
if (cl->status == hashed) {
cl->status = loaded;
((Class*)cl)->bytes = bytes;
}
cl->release();
}
} else {
cl = 0;
}
} else {
cl = loadInClassLoader(name->internalToJava(this, 0, name->size), loader);
}
}
if (!cl && doThrow) {
if (!memcmp(name->UTF8ToAsciiz(), NoClassDefFoundError,
strlen(NoClassDefFoundError))) {
unknownError("Unable to load NoClassDefFoundError");
}
Jnjvm::error(NoClassDefFoundError, "unable to load %s", name->printString());
}
if (cl && doResolve) cl->resolveClass(doClinit);
return cl;
}
void Jnjvm::errorWithExcp(const char* className, const JavaObject* excp) {
Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
CommonClass::jnjvmClassLoader,
true, true, true);
JavaObject* obj = (*cl)();
JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
"(Ljava/lang/Throwable;)V", ACC_VIRTUAL, obj, excp);
JavaThread::throwException(obj);
}
void Jnjvm::error(const char* className, const char* fmt, ...) {
char* tmp = (char*)alloca(4096);
Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
CommonClass::jnjvmClassLoader,
true, true, true);
va_list ap;
va_start(ap, fmt);
vsnprintf(tmp, 4096, fmt, ap);
va_end(ap);
JavaObject* obj = (*cl)();
JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
"(Ljava/lang/String;)V", ACC_VIRTUAL, obj,
this->asciizToStr(tmp));
JavaThread::throwException(obj);
}
void Jnjvm::verror(const char* className, const char* fmt, va_list ap) {
char* tmp = (char*)alloca(4096);
Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
CommonClass::jnjvmClassLoader,
true, true, true);
vsnprintf(tmp, 4096, fmt, ap);
va_end(ap);
JavaObject* obj = (*cl)();
JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
"(Ljava/lang/String;)V", ACC_VIRTUAL, obj,
this->asciizToStr(tmp));
JavaThread::throwException(obj);
}
void Jnjvm::arrayStoreException() {
error(ArrayStoreException, "");
}
void Jnjvm::indexOutOfBounds(const JavaObject* obj, sint32 entry) {
error(ArrayIndexOutOfBoundsException, "%d", entry);
}
void Jnjvm::negativeArraySizeException(sint32 size) {
error(NegativeArraySizeException, "%d", size);
}
void Jnjvm::nullPointerException(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char* val = va_arg(ap, char*);
va_end(ap);
error(NullPointerException, fmt, val);
}
void Jnjvm::illegalAccessException(const char* msg) {
error(IllegalAccessException, msg);
}
void Jnjvm::illegalMonitorStateException(const JavaObject* obj) {
error(IllegalMonitorStateException, "");
}
void Jnjvm::interruptedException(const JavaObject* obj) {
error(InterruptedException, "");
}
void Jnjvm::initializerError(const JavaObject* excp) {
errorWithExcp(ExceptionInInitializerError, excp);
}
void Jnjvm::invocationTargetException(const JavaObject* excp) {
errorWithExcp(InvocationTargetException, excp);
}
void Jnjvm::outOfMemoryError(sint32 n) {
error(OutOfMemoryError, "");
}
void Jnjvm::illegalArgumentExceptionForMethod(JavaMethod* meth,
CommonClass* required,
CommonClass* given) {
error(IllegalArgumentException, "for method %s", meth->printString());
}
void Jnjvm::illegalArgumentExceptionForField(JavaField* field,
CommonClass* required,
CommonClass* given) {
error(IllegalArgumentException, "for field %s", field->printString());
}
void Jnjvm::illegalArgumentException(const char* msg) {
error(IllegalArgumentException, msg);
}
void Jnjvm::classCastException(const char* msg) {
error(ClassCastException, msg);
}
void Jnjvm::unknownError(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
verror(UnknownError, fmt, ap);
}
CommonClass* Jnjvm::lookupClassFromUTF8(const UTF8* utf8, unsigned int start,
unsigned int len, JavaObject* loader,
bool doResolve, bool doClinit,
bool doThrow) {
uint32 origLen = len;
const UTF8* name = utf8->javaToInternal(this, start, len);
bool doLoop = true;
CommonClass* ret = 0;
if (len == 0) {
return 0;
} else if (name->at(0) == AssessorDesc::I_TAB) {
while (doLoop) {
if (len == 0) {
doLoop = false;
} else {
++start;
--len;
if (name->at(start) != AssessorDesc::I_TAB) {
if (name->at(start) == AssessorDesc::I_REF) {
uint32 size = (uint32)name->size;
if ((size == (start + 1)) || (size == (start + 2)) ||
(name->at(start + 1) == AssessorDesc::I_TAB) ||
(utf8->at(origLen - 1) != AssessorDesc::I_END_REF)) {
doLoop = false;
} else {
const UTF8* componentName = utf8->javaToInternal(this, start + 1,
len - 2);
if (loadName(componentName, loader, doResolve, doClinit,
doThrow)) {
ret = constructArray(name, loader);
if (doResolve) ret->resolveClass(doClinit);
doLoop = false;
} else {
doLoop = false;
}
}
} else {
uint16 cur = name->at(start);
if ((cur == AssessorDesc::I_BOOL || cur == AssessorDesc::I_BYTE ||
cur == AssessorDesc::I_CHAR || cur == AssessorDesc::I_SHORT ||
cur == AssessorDesc::I_INT || cur == AssessorDesc::I_FLOAT ||
cur == AssessorDesc::I_DOUBLE || cur == AssessorDesc::I_LONG)
&& ((uint32)name->size) == start + 1) {
ret = constructArray(name, loader);
ret->resolveClass(doClinit);
doLoop = false;
} else {
doLoop = false;
}
}
}
}
}
return ret;
} else {
return loadName(name, loader, doResolve, doClinit, doThrow);
}
}
CommonClass* Jnjvm::lookupClassFromJavaString(JavaString* str,
JavaObject* loader,
bool doResolve, bool doClinit,
bool doThrow) {
return lookupClassFromUTF8(str->value, str->offset, str->count, loader,
doResolve, doClinit, doThrow);
}
CommonClass* Jnjvm::lookupClass(const UTF8* utf8, JavaObject* loader) {
if (loader) {
#ifndef SERVICE_VM
ClassMap* map =
(ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!map) {
map = ClassMap::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
}
#else
ClassMap* map = 0;
ServiceDomain* vm =
(ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!vm) {
vm = ServiceDomain::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
}
map = vm->classes;
#endif
return map->lookup(utf8);
} else {
return bootstrapClasses->lookup(utf8);
}
}
static CommonClass* arrayDup(const UTF8*& name, Jnjvm *vm) {
ClassArray* cl = gc_new(ClassArray)();
cl->initialise(vm, true);
cl->name = name;
cl->classLoader = 0;
cl->_funcs = 0;
cl->_baseClass = 0;
cl->super = ClassArray::SuperArray;
cl->interfaces = ClassArray::InterfacesArray;
cl->virtualMethods = ClassArray::VirtualMethodsArray;
cl->staticMethods = ClassArray::StaticMethodsArray;
cl->virtualFields = ClassArray::VirtualFieldsArray;
cl->staticFields = ClassArray::StaticFieldsArray;
cl->depth = 1;
cl->display.push_back(ClassArray::SuperArray);
cl->display.push_back(cl);
cl->access = ACC_FINAL | ACC_ABSTRACT;
cl->status = loaded;
return cl;
}
ClassArray* Jnjvm::constructArray(const UTF8* name, JavaObject* loader) {
if (loader != 0)
loader = ClassArray::arrayLoader(this, name, loader, 1, name->size - 1);
if (loader) {
#ifndef SERVICE_VM
ClassMap* map =
(ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!map) {
map = ClassMap::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
}
ClassArray* res = (ClassArray*)map->lookupOrCreate(name, this, arrayDup);
#else
ClassMap* map = 0;
ServiceDomain* vm =
(ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!vm) {
vm = ServiceDomain::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
}
map = vm->classes;
ClassArray* res = (ClassArray*)map->lookupOrCreate(name, vm, arrayDup);
#endif
if (!res->classLoader) res->classLoader = loader;
return res;
} else {
return (ClassArray*)bootstrapClasses->lookupOrCreate(name, this, arrayDup);
}
}
static CommonClass* classDup(const UTF8*& name, Jnjvm *vm) {
Class* cl = gc_new(Class)();
cl->initialise(vm, false);
cl->name = name;
cl->classLoader = 0;
cl->bytes = 0;
cl->_staticInstance = 0;
cl->virtualInstance = 0;
cl->super = 0;
cl->ctpInfo = 0;
return cl;
}
Class* Jnjvm::constructClass(const UTF8* name, JavaObject* loader) {
if (loader) {
#ifndef SERVICE_VM
ClassMap* map =
(ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!map) {
map = ClassMap::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
}
Class* res = (Class*)map->lookupOrCreate(name, this, classDup);
#else
ClassMap* map = 0;
ServiceDomain* vm =
(ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
if (!vm) {
vm = ServiceDomain::allocate();
(*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
}
map = vm->classes;
Class* res = (Class*)map->lookupOrCreate(name, vm, classDup);
#endif
if (!res->classLoader) res->classLoader = loader;
return res;
} else {
return (Class*)bootstrapClasses->lookupOrCreate(name, this, classDup);
}
}
static JavaField* fieldDup(FieldCmp & cmp, Jnjvm *vm) {
JavaField* field = gc_new(JavaField)();
field->name = cmp.name;
field->type = cmp.type;
field->classDef = (Class*)cmp.classDef;
field->signature = vm->constructType(field->type);
field->ptrOffset = 0;
return field;
}
JavaField* Jnjvm::constructField(Class* cl, const UTF8* name, const UTF8* type,
uint32 access){
FieldCmp CC(name, cl, type);
JavaField* f = loadedFields->lookupOrCreate(CC, this, fieldDup);
f->access = access;
f->offset = 0;
return f;
}
JavaField* Jnjvm::lookupField(CommonClass* cl, const UTF8* name,
const UTF8* type) {
FieldCmp CC(name, cl, type);
JavaField* f = loadedFields->lookup(CC);
return f;
}
static JavaMethod* methodDup(FieldCmp & cmp, Jnjvm *vm) {
JavaMethod* method = gc_new(JavaMethod)();
method->name = cmp.name;
method->type = cmp.type;
method->classDef = (Class*)cmp.classDef;
method->signature = (Signdef*)vm->constructType(method->type);
method->methPtr = 0;
method->code = 0;
return method;
}
JavaMethod* Jnjvm::constructMethod(Class* cl, const UTF8* name,
const UTF8* type, uint32 access) {
FieldCmp CC(name, cl, type);
JavaMethod* f = loadedMethods->lookupOrCreate(CC, this, methodDup);
f->access = access;
return f;
}
const UTF8* Jnjvm::asciizConstructUTF8(const char* asciiz) {
#ifndef SINGLE_VM
if (this != bootstrapVM) {
const UTF8* existing = bootstrapVM->hashUTF8->lookupAsciiz(asciiz);
if (existing) return existing;
}
#endif
return hashUTF8->lookupOrCreateAsciiz(asciiz);
}
const UTF8* Jnjvm::readerConstructUTF8(const uint16* buf, uint32 size) {
#ifndef SINGLE_VM
if (this != bootstrapVM) {
const UTF8* existing = bootstrapVM->hashUTF8->lookupReader(buf, size);
if (existing) return existing;
}
#endif
return hashUTF8->lookupOrCreateReader(buf, size);
}
Typedef* Jnjvm::constructType(const UTF8* name) {
Typedef* res = javaTypes->lookup(name);
if (res == 0) {
res = Typedef::typeDup(name, this);
javaTypes->lock->lock();
Typedef* tmp = javaTypes->lookup(name);
if (tmp == 0) javaTypes->hash(name, res);
else res = tmp;
javaTypes->lock->unlock();
}
return res;
}
CommonClass* Jnjvm::loadInClassLoader(const UTF8* name, JavaObject* loader) {
JavaObject* obj = (JavaObject*)
Classpath::loadInClassLoader->invokeJavaObjectVirtual(loader, this->UTF8ToStr(name));
return (CommonClass*)((*Classpath::vmdataClass)(obj).PointerVal);
}
JavaString* Jnjvm::UTF8ToStr(const UTF8* utf8) {
#ifndef SINGLE_VM
if (this != bootstrapVM) {
JavaString* existing = bootstrapVM->hashStr->lookup(utf8);
if (existing) return existing;
}
#endif
JavaString* res = hashStr->lookupOrCreate(utf8, this, JavaString::stringDup);
return res;
}
JavaString* Jnjvm::asciizToStr(const char* asciiz) {
const UTF8* var = asciizConstructUTF8(asciiz);
return UTF8ToStr(var);
}
void Jnjvm::addProperty(char* key, char* value) {
postProperties.push_back(std::make_pair(key, value));
}
#ifdef SINGLE_VM
JavaObject* Jnjvm::getClassDelegatee(CommonClass* cl) {
if (!(cl->delegatee)) {
JavaObject* delegatee = (*Classpath::newClass)();
cl->delegatee = delegatee;
Classpath::initClass->invokeIntSpecial(delegatee, cl);
} else if (cl->delegatee->classOf != Classpath::newClass) {
JavaObject* pd = cl->delegatee;
JavaObject* delegatee = (*Classpath::newClass)();
cl->delegatee = delegatee;;
Classpath::initClassWithProtectionDomain->invokeIntSpecial(delegatee, cl, pd);
}
return cl->delegatee;
}
#else
JavaObject* Jnjvm::getClassDelegatee(CommonClass* cl) {
JavaObject* val = delegatees->lookup(cl);
if (!val) {
val = (*Classpath::newClass)();
delegatees->hash(cl, val);
Classpath::initClass->invokeIntSpecial(val, cl);
} else if (val->classOf != Classpath::newClass) {
JavaObject* pd = val;
val = (*Classpath::newClass)();
delegatees->hash(cl, val);
Classpath::initClassWithProtectionDomain->invokeIntSpecial(val, cl, pd);
}
return val;
}
#endif