blob: 177bed3e463079303400aed18dfee3f6fbc8e00d [file] [log] [blame]
//===-------- JavaClass.cpp - Java class representation -------------------===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define JNJVM_LOAD 0
#include <vector>
#include <string.h>
#include "mvm/JIT.h"
#include "debug.h"
#include "types.h"
#include "JavaArray.h"
#include "JavaCache.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaObject.h"
#include "JavaThread.h"
#include "JavaTypes.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "JnjvmModuleProvider.h"
#include "LockedMap.h"
#include "Reader.h"
using namespace jnjvm;
const UTF8* Attribut::codeAttribut = 0;
const UTF8* Attribut::exceptionsAttribut = 0;
const UTF8* Attribut::constantAttribut = 0;
const UTF8* Attribut::lineNumberTableAttribut = 0;
const UTF8* Attribut::innerClassesAttribut = 0;
const UTF8* Attribut::sourceFileAttribut = 0;
CommonClass* ClassArray::SuperArray;
Class** ClassArray::InterfacesArray;
Attribut::Attribut(const UTF8* name, uint32 length,
uint32 offset) {
this->start = offset;
this->nbb = length;
this->name = name;
}
Attribut* Class::lookupAttribut(const UTF8* key ) {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
if (cur->name->equals(key)) return cur;
}
return 0;
}
Attribut* JavaField::lookupAttribut(const UTF8* key ) {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
if (cur->name->equals(key)) return cur;
}
return 0;
}
Attribut* JavaMethod::lookupAttribut(const UTF8* key ) {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
if (cur->name->equals(key)) return cur;
}
return 0;
}
CommonClass::~CommonClass() {
classLoader->allocator.Deallocate(display);
}
CommonClass::CommonClass() {
display = 0;
virtualVT = 0;
nbVirtualFields = 0;
nbStaticFields = 0;
nbVirtualMethods = 0;
nbStaticMethods = 0;
nbInterfaces = 0;
access = 0;
}
Class::Class() : CommonClass() {
ctpInfo = 0;
staticVT = 0;
JInfo = 0;
outerClass = 0;
innerOuterResolved = false;
nbInnerClasses = 0;
}
Class::~Class() {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
cur->~Attribut();
classLoader->allocator.Deallocate(cur);
}
for (uint32 i = 0; i < nbStaticFields; ++i) {
JavaField* cur = &(staticFields[i]);
cur->~JavaField();
classLoader->allocator.Deallocate(cur);
}
for (uint32 i = 0; i < nbVirtualFields; ++i) {
JavaField* cur = &(virtualFields[i]);
cur->~JavaField();
classLoader->allocator.Deallocate(cur);
}
for (uint32 i = 0; i < nbVirtualMethods; ++i) {
JavaMethod* cur = &(virtualMethods[i]);
cur->~JavaMethod();
classLoader->allocator.Deallocate(cur);
}
for (uint32 i = 0; i < nbStaticMethods; ++i) {
JavaMethod* cur = &(staticMethods[i]);
cur->~JavaMethod();
classLoader->allocator.Deallocate(cur);
}
if (ctpInfo) {
ctpInfo->~JavaConstantPool();
classLoader->allocator.Deallocate(ctpInfo);
}
classLoader->allocator.Deallocate(staticVT);
// Currently, only regular classes have a heap allocated virtualVT.
// Array classes have a C++ allocated virtualVT and primitive classes
// do not have a virtualVT.
classLoader->allocator.Deallocate(virtualVT);
}
JavaField::~JavaField() {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
cur->~Attribut();
classDef->classLoader->allocator.Deallocate(cur);
}
}
JavaMethod::~JavaMethod() {
for (uint32 i = 0; i < nbAttributs; ++i) {
Attribut* cur = &(attributs[i]);
cur->~Attribut();
classDef->classLoader->allocator.Deallocate(cur);
}
for (uint32 i = 0; i < nbEnveloppes; ++i) {
Enveloppe* cur = &(enveloppes[i]);
cur->~Enveloppe();
classDef->classLoader->allocator.Deallocate(cur);
}
}
static void printClassNameIntern(const UTF8* name, unsigned int start,
unsigned int end, mvm::PrintBuffer* buf) {
uint16 first = name->elements[start];
if (first == I_TAB) {
unsigned int stepsEnd = start;
while (name->elements[stepsEnd] == I_TAB) stepsEnd++;
if (name->elements[stepsEnd] == I_REF) {
printClassNameIntern(name, (stepsEnd + 1),(end - 1), buf);
} else {
name->print(buf);
}
buf->write(" ");
for (uint32 i = start; i < stepsEnd; i++)
buf->write("[]");
} else {
char* tmp = (char*)(alloca(1 + (end - start)));
for (uint32 i = start; i < end; i++) {
short int cur = name->elements[i];
tmp[i - start] = (cur == '/' ? '.' : cur);
}
tmp[end - start] = 0;
buf->write(tmp);
}
}
void CommonClass::printClassName(const UTF8* name, mvm::PrintBuffer* buf) {
printClassNameIntern(name, 0, name->size, buf);
}
void CommonClass::print(mvm::PrintBuffer* buf) const {
buf->write("CommonClass<");
printClassName(name, buf);
buf->write(">");
}
UserClassPrimitive* CommonClass::toPrimitive(Jnjvm* vm) const {
if (this == vm->upcalls->voidClass) {
return vm->upcalls->OfVoid;
} else if (this == vm->upcalls->intClass) {
return vm->upcalls->OfInt;
} else if (this == vm->upcalls->shortClass) {
return vm->upcalls->OfShort;
} else if (this == vm->upcalls->charClass) {
return vm->upcalls->OfChar;
} else if (this == vm->upcalls->doubleClass) {
return vm->upcalls->OfDouble;
} else if (this == vm->upcalls->byteClass) {
return vm->upcalls->OfByte;
} else if (this == vm->upcalls->boolClass) {
return vm->upcalls->OfBool;
} else if (this == vm->upcalls->longClass) {
return vm->upcalls->OfLong;
} else if (this == vm->upcalls->floatClass) {
return vm->upcalls->OfFloat;
} else {
return 0;
}
}
UserClassPrimitive*
ClassPrimitive::byteIdToPrimitive(char id, Classpath* upcalls) {
switch (id) {
case I_FLOAT :
return upcalls->OfFloat;
case I_INT :
return upcalls->OfInt;
case I_SHORT :
return upcalls->OfShort;
case I_CHAR :
return upcalls->OfChar;
case I_DOUBLE :
return upcalls->OfDouble;
case I_BYTE :
return upcalls->OfByte;
case I_BOOL :
return upcalls->OfBool;
case I_LONG :
return upcalls->OfLong;
case I_VOID :
return upcalls->OfVoid;
default :
return 0;
}
}
CommonClass::CommonClass(JnjvmClassLoader* loader, const UTF8* n,
bool isArray) {
name = n;
virtualVT = 0;
status = loaded;
classLoader = loader;
array = isArray;
primitive = false;
nbVirtualMethods = 0;
nbStaticMethods = 0;
nbStaticFields = 0;
nbVirtualFields = 0;
nbInterfaces = 0;
interfaces = 0;
virtualMethods = 0;
staticMethods = 0;
virtualFields = 0;
staticFields = 0;
access = 0;
#if !defined(ISOLATE) && !defined(ISOLATE_SHARING)
this->delegatee = 0;
#endif
}
ClassPrimitive::ClassPrimitive(JnjvmClassLoader* loader, const UTF8* n,
uint32 nb) :
CommonClass(loader, n, false) {
display = (CommonClass**)loader->allocator.Allocate(sizeof(CommonClass*));
display[0] = this;
primitive = true;
status = ready;
access = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC;
virtualSize = nb;
}
Class::Class(JnjvmClassLoader* loader, const UTF8* n, ArrayUInt8* B) :
CommonClass(loader, n, false) {
bytes = B;
super = 0;
ctpInfo = 0;
JInfo = 0;
outerClass = 0;
innerOuterResolved = false;
display = 0;
nbInnerClasses = 0;
#if !defined(ISOLATE) && !defined(ISOLATE_SHARING)
_staticInstance = 0;
#endif
}
ClassArray::ClassArray(JnjvmClassLoader* loader, const UTF8* n,
UserCommonClass* base) :
CommonClass(loader, n, true) {
_baseClass = base;
super = ClassArray::SuperArray;
interfaces = ClassArray::InterfacesArray;
nbInterfaces = 2;
depth = 1;
display = (CommonClass**)loader->allocator.Allocate(2 * sizeof(CommonClass*));
display[0] = ClassArray::SuperArray;
display[1] = this;
access = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC;
if (base->isPrimitive()) {
virtualVT = JavaArray::VT;
} else {
virtualVT = ArrayObject::VT;
}
}
void Class::print(mvm::PrintBuffer* buf) const {
buf->write("Class<");
printClassName(name, buf);
buf->write(">");
}
void ClassArray::print(mvm::PrintBuffer* buf) const {
buf->write("ClassArray<");
printClassName(name, buf);
buf->write(">");
}
JavaArray* UserClassArray::doNew(sint32 n, Jnjvm* vm) {
if (n < 0)
vm->negativeArraySizeException(n);
else if (n > JavaArray::MaxArraySize)
vm->outOfMemoryError(n);
return doNew(n, vm->gcAllocator);
}
JavaArray* UserClassArray::doNew(sint32 n, mvm::Allocator& allocator) {
UserCommonClass* cl = baseClass();
assert(cl && virtualVT && "array class not resolved");
uint32 primSize = cl->isPrimitive() ? cl->virtualSize : sizeof(JavaObject*);
uint32 size = sizeof(JavaObject) + sizeof(sint32) + n * primSize;
JavaArray* res = (JavaArray*)allocator.allocateManagedObject(size,
virtualVT);
res->initialise(this);
res->size = n;
return res;
}
JavaArray* UserClassArray::doNew(sint32 n, mvm::BumpPtrAllocator& allocator) {
UserCommonClass* cl = baseClass();
assert(cl && virtualVT && "array class not resolved");
uint32 primSize = cl->isPrimitive() ? cl->virtualSize : sizeof(JavaObject*);
uint32 size = sizeof(JavaObject) + sizeof(sint32) + n * primSize;
JavaArray* res = (JavaArray*)allocator.Allocate(size);
((void**)res)[0] = virtualVT;
res->initialise(this);
res->size = n;
return res;
}
void* JavaMethod::compiledPtr() {
if (code != 0) return code;
else {
classDef->acquire();
if (code == 0) {
code =
classDef->classLoader->TheModuleProvider->materializeFunction(this);
}
classDef->release();
return code;
}
}
const char* JavaMethod::printString() const {
mvm::PrintBuffer *buf= mvm::PrintBuffer::alloc();
buf->write("JavaMethod<");
((JavaMethod*)this)->getSignature()->printWithSign(classDef, name, buf);
buf->write(">");
return buf->contents()->cString();
}
const char* JavaField::printString() const {
mvm::PrintBuffer *buf= mvm::PrintBuffer::alloc();
buf->write("JavaField<");
if (isStatic(access))
buf->write("static ");
else
buf->write("virtual ");
((JavaField*)this)->getSignature()->tPrintBuf(buf);
buf->write(" ");
classDef->print(buf);
buf->write("::");
name->print(buf);
buf->write(">");
return buf->contents()->cString();
}
JavaMethod* CommonClass::lookupMethodDontThrow(const UTF8* name,
const UTF8* type,
bool isStatic,
bool recurse,
Class** methodCl) {
JavaMethod* methods = 0;
uint32 nb = 0;
if (isStatic) {
methods = getStaticMethods();
nb = nbStaticMethods;
} else {
methods = getVirtualMethods();
nb = nbVirtualMethods;
}
for (uint32 i = 0; i < nb; ++i) {
JavaMethod& res = methods[i];
if (res.name->equals(name) && res.type->equals(type)) {
if (methodCl) *methodCl = (Class*)this;
return &res;
}
}
JavaMethod *cur = 0;
if (recurse) {
if (super) cur = super->lookupMethodDontThrow(name, type, isStatic,
recurse, methodCl);
if (cur) return cur;
if (isStatic) {
for (uint16 i = 0; i < nbInterfaces; ++i) {
Class* I = interfaces[i];
cur = I->lookupMethodDontThrow(name, type, isStatic, recurse,
methodCl);
if (cur) return cur;
}
}
}
return 0;
}
JavaMethod* CommonClass::lookupMethod(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
Class** methodCl) {
JavaMethod* res = lookupMethodDontThrow(name, type, isStatic, recurse,
methodCl);
if (!res) {
JavaThread::get()->isolate->noSuchMethodError(this, name);
}
return res;
}
JavaField*
CommonClass::lookupFieldDontThrow(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
CommonClass** definingClass) {
JavaField* fields = 0;
uint32 nb = 0;
if (isStatic) {
fields = getStaticFields();
nb = nbStaticFields;
} else {
fields = getVirtualFields();
nb = nbVirtualFields;
}
for (uint32 i = 0; i < nb; ++i) {
JavaField& res = fields[i];
if (res.name->equals(name) && res.type->equals(type)) {
if (definingClass) *definingClass = this;
return &res;
}
}
JavaField *cur = 0;
if (recurse) {
if (super) cur = super->lookupFieldDontThrow(name, type, isStatic,
recurse, definingClass);
if (cur) return cur;
if (isStatic) {
for (uint16 i = 0; i < nbInterfaces; ++i) {
Class* I = interfaces[i];
cur = I->lookupFieldDontThrow(name, type, isStatic, recurse,
definingClass);
if (cur) return cur;
}
}
}
return 0;
}
JavaField* CommonClass::lookupField(const UTF8* name, const UTF8* type,
bool isStatic, bool recurse,
CommonClass** definingClass) {
JavaField* res = lookupFieldDontThrow(name, type, isStatic, recurse,
definingClass);
if (!res) {
JavaThread::get()->isolate->noSuchFieldError(this, name);
}
return res;
}
JavaObject* UserClass::doNew(Jnjvm* vm) {
assert(this && "No class when allocating.");
assert((this->isReady() || classLoader->getModule()->isStaticCompiling())
&& "Uninitialized class when allocating.");
JavaObject* res =
(JavaObject*)vm->gcAllocator.allocateManagedObject(getVirtualSize(),
getVirtualVT());
res->classOf = this;
return res;
}
bool UserCommonClass::inheritName(const UTF8* Tname) {
if (getName()->equals(Tname)) {
return true;
} else if (isPrimitive()) {
return false;
} else if (super) {
if (getSuper()->inheritName(Tname)) return true;
}
for (uint32 i = 0; i < nbInterfaces; ++i) {
if (interfaces[i]->inheritName(Tname)) return true;
}
return false;
}
bool UserCommonClass::isOfTypeName(Jnjvm* vm, const UTF8* Tname) {
if (inheritName(Tname)) {
return true;
} else if (isArray()) {
UserCommonClass* curS = this;
uint32 prof = 0;
uint32 len = Tname->size;
bool res = true;
while (res && Tname->elements[prof] == I_TAB) {
UserCommonClass* cl = ((UserClassArray*)curS)->baseClass();
++prof;
cl->resolveClass();
res = curS->isArray() && cl && (prof < len);
curS = cl;
}
return (Tname->elements[prof] == I_REF) &&
(res && curS->inheritName(Tname->extract(vm, prof + 1, len - 1)));
} else {
return false;
}
}
bool UserCommonClass::implements(UserCommonClass* cl) {
if (this == cl) return true;
else {
for (uint16 i = 0; i < nbInterfaces; ++i) {
Class* I = interfaces[i];
if (I == cl) return true;
else if (I->implements(cl)) return true;
}
if (super) {
return super->implements(cl);
}
}
return false;
}
bool UserCommonClass::instantiationOfArray(UserClassArray* cl) {
if (this == cl) return true;
else {
if (isArray()) {
UserCommonClass* baseThis = ((UserClassArray*)this)->baseClass();
UserCommonClass* baseCl = ((UserClassArray*)cl)->baseClass();
if (baseThis->isInterface() && baseCl->isInterface()) {
return baseThis->implements(baseCl);
} else {
return baseThis->isAssignableFrom(baseCl);
}
}
}
return false;
}
bool UserCommonClass::subclassOf(UserCommonClass* cl) {
if (cl->depth <= depth) {
return display[cl->depth] == cl;
} else {
return false;
}
}
bool UserCommonClass::isAssignableFrom(UserCommonClass* cl) {
if (this == cl) {
return true;
} else if (cl->isInterface()) {
return this->implements(cl);
} else if (cl->isArray()) {
return this->instantiationOfArray((UserClassArray*)cl);
} else {
return this->subclassOf(cl);
}
}
void JavaField::InitField(JavaObject* obj, uint64 val) {
Typedef* type = getSignature();
if (!type->isPrimitive()) {
((sint32*)((uint64)obj + ptrOffset))[0] = (sint32)val;
return;
}
PrimitiveTypedef* prim = (PrimitiveTypedef*)type;
if (prim->isLong()) {
((sint64*)((uint64)obj + ptrOffset))[0] = val;
} else if (prim->isInt()) {
((sint32*)((uint64)obj + ptrOffset))[0] = (sint32)val;
} else if (prim->isChar()) {
((uint16*)((uint64)obj + ptrOffset))[0] = (uint16)val;
} else if (prim->isShort()) {
((sint16*)((uint64)obj + ptrOffset))[0] = (sint16)val;
} else if (prim->isByte()) {
((sint8*)((uint64)obj + ptrOffset))[0] = (sint8)val;
} else if (prim->isBool()) {
((uint8*)((uint64)obj + ptrOffset))[0] = (uint8)val;
} else {
// 0 value for everything else
((sint32*)((uint64)obj + ptrOffset))[0] = (sint32)val;
}
}
void JavaField::InitField(JavaObject* obj, JavaObject* val) {
((JavaObject**)((uint64)obj + ptrOffset))[0] = val;
}
void JavaField::InitField(JavaObject* obj, double val) {
((double*)((uint64)obj + ptrOffset))[0] = val;
}
void JavaField::InitField(JavaObject* obj, float val) {
((float*)((uint64)obj + ptrOffset))[0] = val;
}
void JavaField::initField(JavaObject* obj, Jnjvm* vm) {
const Typedef* type = getSignature();
Attribut* attribut = lookupAttribut(Attribut::constantAttribut);
if (!attribut) {
InitField(obj);
} else {
Reader reader(attribut, classDef->bytes);
JavaConstantPool * ctpInfo = classDef->ctpInfo;
uint16 idx = reader.readU2();
if (type->isPrimitive()) {
UserCommonClass* cl = type->assocClass(vm->bootstrapLoader);
if (cl == vm->upcalls->OfLong) {
InitField(obj, (uint64)ctpInfo->LongAt(idx));
} else if (cl == vm->upcalls->OfDouble) {
InitField(obj, ctpInfo->DoubleAt(idx));
} else if (cl == vm->upcalls->OfFloat) {
InitField(obj, ctpInfo->FloatAt(idx));
} else {
InitField(obj, (uint64)ctpInfo->IntegerAt(idx));
}
} else if (type->isReference()){
const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]);
InitField(obj, (JavaObject*)ctpInfo->resolveString(utf8, idx));
} else {
JavaThread::get()->isolate->
unknownError("unknown constant %s\n", type->printString());
}
}
}
JavaMethod* CommonClass::constructMethod(JavaMethod& method,
const UTF8* name,
const UTF8* type, uint32 access) {
method.name = name;
method.type = type;
method.classDef = (Class*)this;
method._signature = 0;
method.code = 0;
method.access = access;
method.canBeInlined = false;
method.offset = 0;
method.JInfo = 0;
method.enveloppes = 0;
return &method;
}
JavaField* CommonClass::constructField(JavaField& field,
const UTF8* name,
const UTF8* type, uint32 access) {
field.name = name;
field.type = type;
field.classDef = (Class*)this;
field._signature = 0;
field.ptrOffset = 0;
field.access = access;
field.JInfo = 0;
return &field;
}
void Class::readParents(Reader& reader) {
uint16 superEntry = reader.readU2();
const UTF8* superUTF8 = superEntry ?
ctpInfo->resolveClassName(superEntry) : 0;
uint16 nbI = reader.readU2();
// Use the super field to store the UTF8. since the field is never
// used before actually loading the super, this is harmless.
super = (Class*)superUTF8;
// Use the regular interface array to store the UTF8s. Since this array
// is never used before actually loading the interfaces, this is harmless.
interfaces = (Class**)
classLoader->allocator.Allocate(nbI * sizeof(Class*));
nbInterfaces = nbI;
for (int i = 0; i < nbI; i++)
interfaces[i] = (Class*)ctpInfo->resolveClassName(reader.readU2());
}
void UserClass::loadParents() {
const UTF8* superUTF8 = (const UTF8*)super;
if (superUTF8 == 0) {
depth = 0;
display = (CommonClass**)
classLoader->allocator.Allocate(sizeof(CommonClass*));
display[0] = this;
} else {
super = classLoader->loadName(superUTF8, true, true);
depth = super->depth + 1;
mvm::BumpPtrAllocator& allocator = classLoader->allocator;
display = (CommonClass**)
allocator.Allocate(sizeof(CommonClass*) * (depth + 1));
memcpy(display, super->display, depth * sizeof(UserCommonClass*));
display[depth] = this;
}
for (unsigned i = 0; i < nbInterfaces; i++)
interfaces[i] =
((UserClass*)classLoader->loadName((const UTF8*)interfaces[i],
true, true));
}
Attribut* Class::readAttributs(Reader& reader, uint16& size) {
uint16 nba = reader.readU2();
Attribut* attributs = new(classLoader->allocator) Attribut[nba];
for (int i = 0; i < nba; i++) {
const UTF8* attName = ctpInfo->UTF8At(reader.readU2());
uint32 attLen = reader.readU4();
Attribut& att = attributs[i];
att.start = reader.cursor;
att.nbb = attLen;
att.name = attName;
reader.seek(attLen, Reader::SeekCur);
}
size = nba;
return attributs;
}
void Class::readFields(Reader& reader) {
uint16 nbFields = reader.readU2();
virtualFields = new (classLoader->allocator) JavaField[nbFields];
staticFields = virtualFields + nbFields;
for (int i = 0; i < nbFields; i++) {
uint16 access = reader.readU2();
const UTF8* name = ctpInfo->UTF8At(reader.readU2());
const UTF8* type = ctpInfo->UTF8At(reader.readU2());
JavaField* field = 0;
if (isStatic(access)) {
--staticFields;
field = constructField(staticFields[0], name, type, access);
++nbStaticFields;
} else {
field = constructField(virtualFields[nbVirtualFields], name, type, access);
++nbVirtualFields;
}
field->attributs = readAttributs(reader, field->nbAttributs);
}
}
void Class::readMethods(Reader& reader) {
uint16 nbMethods = reader.readU2();
virtualMethods = new(classLoader->allocator) JavaMethod[nbMethods];
staticMethods = virtualMethods + nbMethods;
for (int i = 0; i < nbMethods; i++) {
uint16 access = reader.readU2();
const UTF8* name = ctpInfo->UTF8At(reader.readU2());
const UTF8* type = ctpInfo->UTF8At(reader.readU2());
JavaMethod* meth = 0;
if (isStatic(access)) {
--staticMethods;
meth = constructMethod(staticMethods[0], name, type, access);
++nbStaticMethods;
} else {
meth = constructMethod(virtualMethods[nbVirtualMethods], name, type, access);
++nbVirtualMethods;
}
meth->attributs = readAttributs(reader, meth->nbAttributs);
}
}
void Class::readClass() {
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "; ", 0);
PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "reading ", 0);
PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s\n", printString());
Reader reader(bytes);
uint32 magic = reader.readU4();
if (magic != Jnjvm::Magic) {
JavaThread::get()->isolate->classFormatError("bad magic number %p", magic);
}
/* uint16 minor = */ reader.readU2();
/* uint16 major = */ reader.readU2();
uint32 ctpSize = reader.readU2();
ctpInfo = new(classLoader->allocator, ctpSize) JavaConstantPool(this, reader,
ctpSize);
access = reader.readU2();
if (!isPublic(access)) access |= ACC_PRIVATE;
const UTF8* thisClassName =
ctpInfo->resolveClassName(reader.readU2());
if (!(thisClassName->equals(name))) {
JavaThread::get()->isolate->classFormatError(
"try to load %s and found class named %s",
printString(), thisClassName->printString());
}
readParents(reader);
readFields(reader);
readMethods(reader);
attributs = readAttributs(reader, nbAttributs);
}
#ifndef ISOLATE_SHARING
void CommonClass::resolveClass() {
if (status < resolved) {
acquire();
if (status >= resolved) {
release();
} else if (status == loaded) {
if (isArray()) {
ClassArray* arrayCl = (ClassArray*)this;
CommonClass* baseClass = arrayCl->baseClass();
baseClass->resolveClass();
status = resolved;
// Primitives are resolved at boot time
} else {
Class* cl = (Class*)this;
cl->readClass();
cl->status = classRead;
cl->release();
cl->loadParents();
cl->acquire();
cl->status = prepared;
classLoader->getModule()->resolveVirtualClass(cl);
cl->status = resolved;
}
release();
broadcastClass();
} else {
while (status < resolved) {
waitClass();
}
release();
}
}
}
#else
void CommonClass::resolveClass() {
assert(status >= resolved &&
"Asking to resolve a not resolved-class in a isolate environment");
}
#endif
void UserClass::resolveInnerOuterClasses() {
if (!innerOuterResolved) {
Attribut* attribut = lookupAttribut(Attribut::innerClassesAttribut);
if (attribut != 0) {
Reader reader(attribut, getBytes());
uint16 temp = 0;
uint16 nbi = reader.readU2();
for (uint16 i = 0; i < nbi; ++i) {
uint16 inner = reader.readU2();
uint16 outer = reader.readU2();
//uint16 innerName =
reader.readU2();
uint16 accessFlags = reader.readU2();
UserClass* clInner = (UserClass*)ctpInfo->loadClass(inner);
UserClass* clOuter = (UserClass*)ctpInfo->loadClass(outer);
if (clInner == this) {
outerClass = clOuter;
} else if (clOuter == this) {
if (!temp) {
innerClasses = (Class**)
classLoader->allocator.Allocate(nbi * sizeof(Class*));
}
clInner->setInnerAccess(accessFlags);
innerClasses[nbInnerClasses++] = clInner;
}
}
}
innerOuterResolved = true;
}
}
void CommonClass::getDeclaredConstructors(std::vector<JavaMethod*>& res,
bool publicOnly) {
for (uint32 i = 0; i < nbVirtualMethods; ++i) {
JavaMethod* meth = &virtualMethods[i];
bool pub = isPublic(meth->access);
if (meth->name->equals(classLoader->bootstrapLoader->initName) &&
(!publicOnly || pub)) {
res.push_back(meth);
}
}
}
void CommonClass::getDeclaredMethods(std::vector<JavaMethod*>& res,
bool publicOnly) {
for (uint32 i = 0; i < nbVirtualMethods; ++i) {
JavaMethod* meth = &virtualMethods[i];
bool pub = isPublic(meth->access);
if (!(meth->name->equals(classLoader->bootstrapLoader->initName)) &&
(!publicOnly || pub)) {
res.push_back(meth);
}
}
for (uint32 i = 0; i < nbStaticMethods; ++i) {
JavaMethod* meth = &staticMethods[i];
bool pub = isPublic(meth->access);
if (!(meth->name->equals(classLoader->bootstrapLoader->clinitName)) &&
(!publicOnly || pub)) {
res.push_back(meth);
}
}
}
void CommonClass::getDeclaredFields(std::vector<JavaField*>& res,
bool publicOnly) {
for (uint32 i = 0; i < nbVirtualFields; ++i) {
JavaField* field = &virtualFields[i];
if (!publicOnly || isPublic(field->access)) {
res.push_back(field);
}
}
for (uint32 i = 0; i < nbStaticFields; ++i) {
JavaField* field = &staticFields[i];
if (!publicOnly || isPublic(field->access)) {
res.push_back(field);
}
}
}
void Class::resolveStaticClass() {
classLoader->getModule()->resolveStaticClass((Class*)this);
}