finish support for inline vtables in class objects; convert constant pools from arrays to singletons to reduce memory footprint

This commit is contained in:
Joel Dice 2007-11-05 14:40:17 -07:00
parent f1bc2be9f9
commit fe0e542afe
9 changed files with 445 additions and 226 deletions

View File

@ -28,7 +28,7 @@ src = src
classpath = classpath classpath = classpath
test = test test = test
input = $(test-build)/References.class input = $(test-build)/List.class
build-cxx = g++ build-cxx = g++
build-cc = gcc build-cc = gcc

View File

@ -2051,36 +2051,33 @@ interpret(Thread* t)
index = codeReadInt16(t, code, ip); index = codeReadInt16(t, code, ip);
} }
object v = arrayBody(t, codePool(t, code), index - 1); object pool = codePool(t, code);
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::IntType) if (singletonIsObject(t, pool, index - 1)) {
or objectClass(t, v) == arrayBody(t, t->m->types, Machine::FloatType)) object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{ {
pushInt(t, intValue(t, v)); object class_ = resolveClassInPool(t, pool, index - 1);
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::StringType))
{
pushObject(t, v);
} else {
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_; if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_); pushObject(t, class_);
} else {
pushObject(t, v);
}
} else {
pushInt(t, singletonValue(t, pool, index - 1));
} }
} goto loop; } goto loop;
case ldc2_w: { case ldc2_w: {
uint16_t index = codeReadInt16(t, code, ip); uint16_t index = codeReadInt16(t, code, ip);
object v = arrayBody(t, codePool(t, code), index - 1); object pool = codePool(t, code);
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType) uint64_t v;
or objectClass(t, v) == arrayBody(t, t->m->types, Machine::DoubleType)) memcpy(&v, &singletonValue(t, pool, index - 1), 8);
{ pushLong(t, v);
pushLong(t, longValue(t, v));
} else {
abort(t);
}
} goto loop; } goto loop;
case ldiv_: { case ldiv_: {
@ -2863,15 +2860,45 @@ class MyProcessor: public Processor {
} }
virtual object virtual object
methodStub(vm::Thread*) makeMethod(vm::Thread* t,
uint8_t vmFlags,
uint8_t returnCode,
uint8_t parameterCount,
uint8_t parameterFootprint,
uint16_t flags,
uint16_t offset,
object name,
object spec,
object class_,
object code)
{ {
return 0; return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, name, spec, class_, code, 0);
} }
virtual object virtual object
nativeInvoker(vm::Thread*) makeClass(vm::Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t fixedSize,
uint16_t arrayElementSize,
object objectMask,
object name,
object super,
object interfaceTable,
object virtualTable,
object fieldTable,
object methodTable,
object staticTable,
object loader,
unsigned vtableLength UNUSED)
{ {
return 0; return vm::makeClass
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
methodTable, staticTable, loader, 0, false);
} }
virtual unsigned virtual unsigned

View File

@ -197,15 +197,15 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
} }
object object
findMethod(Thread* t, object class_, const char* name, const char* spec) findMethod(Thread* t, object c, const char* name, const char* spec)
{ {
ENTER(t, Thread::ActiveState); PROTECT(t, c);
object n = makeByteArray(t, "%s", name); object n = makeByteArray(t, "%s", name);
PROTECT(t, n); PROTECT(t, n);
object s = makeByteArray(t, "%s", spec); object s = makeByteArray(t, "%s", spec);
return vm::findMethod(t, class_, n, s); return vm::findMethod(t, c, n, s);
} }
jmethodID JNICALL jmethodID JNICALL

View File

@ -204,13 +204,8 @@ walk(Thread* t, Heap::Walker* w, object o)
} else if (classVmFlags(t, class_) & SingletonFlag) { } else if (classVmFlags(t, class_) & SingletonFlag) {
unsigned length = singletonLength(t, o); unsigned length = singletonLength(t, o);
if (length) { if (length) {
unsigned maskSize = ceiling(length + 2, BitsPerWord + 1); walk(t, w, singletonMask(t, o),
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0);
uint32_t mask[maskSize * (BytesPerWord / 4)];
memcpy(mask, &singletonBody(t, o, length - maskSize),
maskSize * BytesPerWord);
walk(t, w, mask, (length + 2) * BytesPerWord, 0, 0);
} else { } else {
w->visit(0); w->visit(0);
} }
@ -617,127 +612,151 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
return value; return value;
} }
object unsigned
parsePool(Thread* t, Stream& s) parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
{ {
unsigned poolCount = s.read2() - 1;
object pool = makeArray(t, poolCount, true);
PROTECT(t, pool); PROTECT(t, pool);
for (unsigned i = 0; i < poolCount; ++i) { s.setPosition(index[i]);
unsigned c = s.read1();
switch (c) {
case CONSTANT_Integer: {
object value = makeInt(t, s.read4());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
switch (s.read1()) {
case CONSTANT_Integer:
case CONSTANT_Float: { case CONSTANT_Float: {
object value = makeInt(t, s.readFloat()); singletonValue(t, pool, i) = s.read4();
set(t, pool, ArrayBody + (i * BytesPerWord), value); } return 1;
} break;
case CONSTANT_Long: {
object value = makeLong(t, s.read8());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
++i;
} break;
case CONSTANT_Long:
case CONSTANT_Double: { case CONSTANT_Double: {
object value = makeLong(t, s.readDouble()); uint64_t v = s.read8();
set(t, pool, ArrayBody + (i * BytesPerWord), value); memcpy(&singletonValue(t, pool, i), &v, 8);
++i; } return 2;
} break;
case CONSTANT_Utf8: { case CONSTANT_Utf8: {
if (singletonObject(t, pool, i) == 0) {
object value = parseUtf8(t, s, s.read2()); object value = parseUtf8(t, s, s.read2());
set(t, pool, ArrayBody + (i * BytesPerWord), value); set(t, pool, SingletonBody + (i * BytesPerWord), value);
} break; }
} return 1;
case CONSTANT_Class: { case CONSTANT_Class: {
object value = makeIntArray(t, 2, false); if (singletonObject(t, pool, i) == 0) {
intArrayBody(t, value, 0) = c; unsigned si = s.read2() - 1;
intArrayBody(t, value, 1) = s.read2(); parsePoolEntry(t, s, index, pool, si);
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break; object value = singletonObject(t, pool, si);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
case CONSTANT_String: { case CONSTANT_String: {
object value = makeIntArray(t, 2, false); if (singletonObject(t, pool, i) == 0) {
intArrayBody(t, value, 0) = c; unsigned si = s.read2() - 1;
intArrayBody(t, value, 1) = s.read2(); parsePoolEntry(t, s, index, pool, si);
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break; object value = singletonObject(t, pool, si);
value = makeString(t, value, 0, byteArrayLength(t, value) - 1, 0);
value = intern(t, value);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
case CONSTANT_NameAndType: { case CONSTANT_NameAndType: {
object value = makeIntArray(t, 3, false); if (singletonObject(t, pool, i) == 0) {
intArrayBody(t, value, 0) = c; unsigned ni = s.read2() - 1;
intArrayBody(t, value, 1) = s.read2(); unsigned ti = s.read2() - 1;
intArrayBody(t, value, 2) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value); parsePoolEntry(t, s, index, pool, ni);
} break; parsePoolEntry(t, s, index, pool, ti);
object name = singletonObject(t, pool, ni);
object type = singletonObject(t, pool, ti);
object value = makePair(t, name, type);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
case CONSTANT_Fieldref: case CONSTANT_Fieldref:
case CONSTANT_Methodref: case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: { case CONSTANT_InterfaceMethodref: {
object value = makeIntArray(t, 3, false); if (singletonObject(t, pool, i) == 0) {
intArrayBody(t, value, 0) = c; unsigned ci = s.read2() - 1;
intArrayBody(t, value, 1) = s.read2(); unsigned nti = s.read2() - 1;
intArrayBody(t, value, 2) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value); parsePoolEntry(t, s, index, pool, ci);
} break; parsePoolEntry(t, s, index, pool, nti);
object class_ = singletonObject(t, pool, ci);
object nameAndType = singletonObject(t, pool, nti);
object value = makeReference
(t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType));
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
default: abort(t);
}
}
object
parsePool(Thread* t, Stream& s)
{
unsigned count = s.read2() - 1;
object pool = makeSingleton(t, count);
if (count) {
uint32_t* index = static_cast<uint32_t*>
(t->m->system->allocate(count * 4));
for (unsigned i = 0; i < count; ++i) {
index[i] = s.position();
switch (s.read1()) {
case CONSTANT_Class:
case CONSTANT_String:
singletonMarkObject(t, pool, i);
s.skip(2);
break;
case CONSTANT_Integer:
case CONSTANT_Float:
s.skip(4);
break;
case CONSTANT_NameAndType:
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
singletonMarkObject(t, pool, i);
s.skip(4);
break;
case CONSTANT_Long:
case CONSTANT_Double:
s.skip(8);
++ i;
break;
case CONSTANT_Utf8:
singletonMarkObject(t, pool, i);
s.skip(s.read2());
break;
default: abort(t); default: abort(t);
} }
} }
for (unsigned i = 0; i < poolCount; ++i) { unsigned end = s.position();
object o = arrayBody(t, pool, i);
if (o and objectClass(t, o)
== arrayBody(t, t->m->types, Machine::IntArrayType))
{
switch (intArrayBody(t, o, 0)) {
case CONSTANT_Class: {
set(t, pool, ArrayBody + (i * BytesPerWord),
arrayBody(t, pool, intArrayBody(t, o, 1) - 1));
} break;
case CONSTANT_String: { PROTECT(t, pool);
object bytes = arrayBody(t, pool, intArrayBody(t, o, 1) - 1);
object value = makeString
(t, bytes, 0, byteArrayLength(t, bytes) - 1, 0);
value = intern(t, value);
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
case CONSTANT_NameAndType: { for (unsigned i = 0; i < count;) {
object name = arrayBody(t, pool, intArrayBody(t, o, 1) - 1); i += parsePoolEntry(t, s, index, pool, i);
object type = arrayBody(t, pool, intArrayBody(t, o, 2) - 1);
object value = makePair(t, name, type);
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
}
}
} }
for (unsigned i = 0; i < poolCount; ++i) { t->m->system->free(index);
object o = arrayBody(t, pool, i);
if (o and objectClass(t, o) s.setPosition(end);
== arrayBody(t, t->m->types, Machine::IntArrayType))
{
switch (intArrayBody(t, o, 0)) {
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: {
object c = arrayBody(t, pool, intArrayBody(t, o, 1) - 1);
object nameAndType = arrayBody(t, pool, intArrayBody(t, o, 2) - 1);
object value = makeReference
(t, c, pairFirst(t, nameAndType), pairSecond(t, nameAndType));
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
}
}
} }
return pool; return pool;
@ -780,7 +799,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
unsigned count = s.read2(); unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
object name = arrayBody(t, pool, s.read2() - 1); object name = singletonObject(t, pool, s.read2() - 1);
PROTECT(t, name); PROTECT(t, name);
object interface = resolveClass(t, name); object interface = resolveClass(t, name);
@ -861,31 +880,53 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
object value = 0; object value = 0;
PROTECT(t, value); PROTECT(t, value);
unsigned code = fieldCode
(t, byteArrayBody(t, singletonObject(t, pool, spec - 1), 0));
unsigned attributeCount = s.read2(); unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) { for (unsigned j = 0; j < attributeCount; ++j) {
object name = arrayBody(t, pool, s.read2() - 1); object name = singletonObject(t, pool, s.read2() - 1);
unsigned length = s.read4(); unsigned length = s.read4();
if (strcmp(reinterpret_cast<const int8_t*>("ConstantValue"), if (strcmp(reinterpret_cast<const int8_t*>("ConstantValue"),
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
value = arrayBody(t, pool, s.read2() - 1); switch (code) {
case ByteField:
case BooleanField:
case CharField:
case ShortField:
case IntField:
case FloatField:
value = makeInt(t, singletonValue(t, pool, s.read2() - 1));
break;
case LongField:
case DoubleField: {
uint64_t v;
memcpy(&v, &singletonValue(t, pool, s.read2() - 1), 8);
value = makeLong(t, v);
} break;
case ObjectField:
value = singletonObject(t, pool, s.read2() - 1);
break;
default: abort(t);
}
} else { } else {
s.skip(length); s.skip(length);
} }
} }
unsigned code = fieldCode
(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0));
object field = makeField object field = makeField
(t, (t,
0, // vm flags 0, // vm flags
code, code,
flags, flags,
0, // offset 0, // offset
arrayBody(t, pool, name - 1), singletonObject(t, pool, name - 1),
arrayBody(t, pool, spec - 1), singletonObject(t, pool, spec - 1),
class_); class_);
if (flags & ACC_STATIC) { if (flags & ACC_STATIC) {
@ -925,19 +966,11 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
if (staticCount) { if (staticCount) {
unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2), unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2),
BytesPerWord); BytesPerWord);
unsigned maskSize = ceiling(footprint + 2, BitsPerWord); object staticTable = makeSingleton(t, footprint);
object staticTable = makeSingleton(t, footprint + maskSize, false);
uint8_t* body = reinterpret_cast<uint8_t*> uint8_t* body = reinterpret_cast<uint8_t*>
(&singletonBody(t, staticTable, 0)); (&singletonBody(t, staticTable, 0));
uint32_t* mask = reinterpret_cast<uint32_t*>
(&singletonBody(t, staticTable, footprint));
memset(mask, 0, maskSize * BytesPerWord);
mask[0] |= 1;
for (unsigned i = 0, offset = 0; i < staticCount; ++i) { for (unsigned i = 0, offset = 0; i < staticCount; ++i) {
unsigned size = fieldSize(t, staticTypes[i]); unsigned size = fieldSize(t, staticTypes[i]);
unsigned excess = offset % size; unsigned excess = offset % size;
@ -979,8 +1012,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
} }
if (staticTypes[i] == ObjectField) { if (staticTypes[i] == ObjectField) {
unsigned index = (offset / BytesPerWord) + 2; singletonMarkObject(t, staticTable, offset / BytesPerWord);
mask[index / 32] |= static_cast<uint32_t>(1) << (index % 32);
} }
offset += size; offset += size;
@ -1064,7 +1096,7 @@ parseCode(Thread* t, Stream& s, object pool)
unsigned attributeCount = s.read2(); unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) { for (unsigned j = 0; j < attributeCount; ++j) {
object name = arrayBody(t, pool, s.read2() - 1); object name = singletonObject(t, pool, s.read2() - 1);
unsigned length = s.read4(); unsigned length = s.read4();
if (strcmp(reinterpret_cast<const int8_t*>("LineNumberTable"), if (strcmp(reinterpret_cast<const int8_t*>("LineNumberTable"),
@ -1181,7 +1213,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object code = 0; object code = 0;
unsigned attributeCount = s.read2(); unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) { for (unsigned j = 0; j < attributeCount; ++j) {
object name = arrayBody(t, pool, s.read2() - 1); object name = singletonObject(t, pool, s.read2() - 1);
unsigned length = s.read4(); unsigned length = s.read4();
if (strcmp(reinterpret_cast<const int8_t*>("Code"), if (strcmp(reinterpret_cast<const int8_t*>("Code"),
@ -1194,7 +1226,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
} }
const char* specString = reinterpret_cast<const char*> const char* specString = reinterpret_cast<const char*>
(&byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)); (&byteArrayBody(t, singletonObject(t, pool, spec - 1), 0));
unsigned parameterCount; unsigned parameterCount;
unsigned returnCode; unsigned returnCode;
@ -1203,25 +1235,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
unsigned parameterFootprint = t->m->processor->parameterFootprint unsigned parameterFootprint = t->m->processor->parameterFootprint
(t, specString, flags & ACC_STATIC); (t, specString, flags & ACC_STATIC);
object compiled; object method = t->m->processor->makeMethod
if (flags & ACC_NATIVE) { (t,
compiled = t->m->processor->nativeInvoker(t);
} else {
compiled = t->m->processor->methodStub(t);
}
object method = makeMethod(t,
0, // vm flags 0, // vm flags
returnCode, returnCode,
parameterCount, parameterCount,
parameterFootprint, parameterFootprint,
flags, flags,
0, // offset 0, // offset
arrayBody(t, pool, name - 1), singletonObject(t, pool, name - 1),
arrayBody(t, pool, spec - 1), singletonObject(t, pool, spec - 1),
class_, class_,
code, code);
compiled);
PROTECT(t, method); PROTECT(t, method);
if (methodVirtual(t, method)) { if (methodVirtual(t, method)) {
@ -1357,6 +1383,35 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
} }
} }
void
updateClassTables(Thread* t, object newClass, object oldClass)
{
object fieldTable = classFieldTable(t, newClass);
if (fieldTable) {
for (unsigned i = 0; i < arrayLength(t, fieldTable); ++i) {
set(t, arrayBody(t, fieldTable, i), FieldClass, newClass);
}
}
if (classFlags(t, newClass) & ACC_INTERFACE) {
object virtualTable = classVirtualTable(t, newClass);
if (virtualTable) {
for (unsigned i = 0; i < arrayLength(t, virtualTable); ++i) {
if (methodClass(t, arrayBody(t, virtualTable, i)) == oldClass) {
set(t, arrayBody(t, virtualTable, i), MethodClass, newClass);
}
}
}
} else {
object methodTable = classMethodTable(t, newClass);
if (methodTable) {
for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) {
set(t, arrayBody(t, methodTable, i), MethodClass, newClass);
}
}
}
}
void void
updateBootstrapClass(Thread* t, object bootstrapClass, object class_) updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
{ {
@ -1364,7 +1419,10 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
// verify that the classes have the same layout // verify that the classes have the same layout
expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_)); expect(t, classSuper(t, bootstrapClass) == classSuper(t, class_));
expect(t, classFixedSize(t, bootstrapClass) == classFixedSize(t, class_));
expect(t, bootstrapClass == arrayBody(t, t->m->types, Machine::ClassType)
or classFixedSize(t, bootstrapClass) == classFixedSize(t, class_));
expect(t, expect(t,
(classVmFlags(t, bootstrapClass) & ReferenceFlag) (classVmFlags(t, bootstrapClass) & ReferenceFlag)
or (classObjectMask(t, bootstrapClass) == 0 or (classObjectMask(t, bootstrapClass) == 0
@ -1388,19 +1446,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
set(t, bootstrapClass, ClassMethodTable, classMethodTable(t, class_)); set(t, bootstrapClass, ClassMethodTable, classMethodTable(t, class_));
set(t, bootstrapClass, ClassStaticTable, classStaticTable(t, class_)); set(t, bootstrapClass, ClassStaticTable, classStaticTable(t, class_));
object fieldTable = classFieldTable(t, class_); updateClassTables(t, bootstrapClass, class_);
if (fieldTable) {
for (unsigned i = 0; i < arrayLength(t, fieldTable); ++i) {
set(t, arrayBody(t, fieldTable, i), FieldClass, bootstrapClass);
}
}
object methodTable = classMethodTable(t, class_);
if (methodTable) {
for (unsigned i = 0; i < arrayLength(t, methodTable); ++i) {
set(t, arrayBody(t, methodTable, i), MethodClass, bootstrapClass);
}
}
} }
object object
@ -1408,7 +1454,10 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
object elementClass) object elementClass)
{ {
// todo: arrays should implement Cloneable and Serializable // todo: arrays should implement Cloneable and Serializable
return makeClass object vtable = classVirtualTable
(t, arrayBody(t, t->m->types, Machine::JobjectType));
return t->m->processor->makeClass
(t, (t,
0, 0,
0, 0,
@ -1419,11 +1468,12 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
spec, spec,
arrayBody(t, t->m->types, Machine::JobjectType), arrayBody(t, t->m->types, Machine::JobjectType),
0, 0,
classVirtualTable(t, arrayBody(t, t->m->types, Machine::JobjectType)), vtable,
0, 0,
0, 0,
elementClass, elementClass,
t->m->loader); t->m->loader,
arrayLength(t, vtable));
} }
object object
@ -1517,7 +1567,7 @@ invoke(Thread* t, const char* className, int argc, const char** argv)
void void
bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
unsigned fixedSize, unsigned arrayElementSize) unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength)
{ {
object mask; object mask;
if (objectMask) { if (objectMask) {
@ -1529,9 +1579,9 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0); object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0);
object class_ = makeClass object class_ = t->m->processor->makeClass
(t, 0, BootstrapFlag, 0, fixedSize, arrayElementSize, mask, 0, super, 0, 0, (t, 0, BootstrapFlag, 0, fixedSize, arrayElementSize, mask, 0, super, 0, 0,
0, 0, 0, t->m->loader); 0, 0, 0, t->m->loader, vtableLength);
set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_); set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_);
} }
@ -2517,7 +2567,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
public: public:
Client(Thread* t): t(t) { } Client(Thread* t): t(t) { }
virtual void NO_RETURN handleEOS() { virtual void NO_RETURN handleError() {
abort(t); abort(t);
} }
@ -2545,19 +2595,21 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
0, // fixed size 0, // fixed size
0, // array size 0, // array size
0, // object mask 0, // object mask
arrayBody(t, pool, name - 1), singletonObject(t, pool, name - 1),
0, // super 0, // super
0, // interfaces 0, // interfaces
0, // vtable 0, // vtable
0, // fields 0, // fields
0, // methods 0, // methods
0, // static table 0, // static table
t->m->loader); t->m->loader,
0, // vtable length
false);
PROTECT(t, class_); PROTECT(t, class_);
unsigned super = s.read2(); unsigned super = s.read2();
if (super) { if (super) {
object sc = resolveClass(t, arrayBody(t, pool, super - 1)); object sc = resolveClass(t, singletonObject(t, pool, super - 1));
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
set(t, class_, ClassSuper, sc); set(t, class_, ClassSuper, sc);
@ -2575,7 +2627,30 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
parseMethodTable(t, s, class_, pool); parseMethodTable(t, s, class_, pool);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return class_; object vtable = classVirtualTable(t, class_);
unsigned vtableLength = (vtable ? arrayLength(t, vtable) : 0);
object real = t->m->processor->makeClass
(t,
classFlags(t, class_),
classVmFlags(t, class_),
classArrayDimensions(t, class_),
classFixedSize(t, class_),
classArrayElementSize(t, class_),
classObjectMask(t, class_),
className(t, class_),
classSuper(t, class_),
classInterfaceTable(t, class_),
classVirtualTable(t, class_),
classFieldTable(t, class_),
classMethodTable(t, class_),
classStaticTable(t, class_),
classLoader(t, class_),
vtableLength);
updateClassTables(t, real, class_);
return real;
} }
object object
@ -2616,7 +2691,9 @@ resolveClass(Thread* t, object spec)
if (LIKELY(t->exception == 0)) { if (LIKELY(t->exception == 0)) {
if (Verbose) { if (Verbose) {
fprintf(stderr, "done parsing %s\n", &byteArrayBody(t, spec, 0)); fprintf(stderr, "done parsing %s: %p\n",
&byteArrayBody(t, spec, 0),
class_);
} }
object bootstrapClass = hashMapFind object bootstrapClass = hashMapFind

View File

@ -2188,6 +2188,79 @@ methodVirtual(Thread* t, object method)
and byteArrayBody(t, methodName(t, method), 0) != '<'; and byteArrayBody(t, methodName(t, method), 0) != '<';
} }
inline unsigned
singletonMaskSize(unsigned count)
{
if (count) {
return ceiling(count + 2, BitsPerWord);
}
return 0;
}
inline unsigned
singletonMaskSize(Thread* t, object singleton)
{
unsigned length = singletonLength(t, singleton);
if (length) {
return ceiling(length + 2, BitsPerWord + 1);
}
return 0;
}
inline unsigned
singletonCount(Thread* t, object singleton)
{
return singletonLength(t, singleton) - singletonMaskSize(t, singleton);
}
inline uint32_t*
singletonMask(Thread* t, object singleton)
{
assert(t, singletonLength(t, singleton));
return reinterpret_cast<uint32_t*>
(&singletonBody(t, singleton, singletonCount(t, singleton)));
}
inline void
singletonMarkObject(Thread* t, object singleton, unsigned index)
{
singletonMask(t, singleton)[(index + 2) / 32]
|= (static_cast<uint32_t>(1) << ((index + 2) % 32));
}
inline bool
singletonIsObject(Thread* t, object singleton, unsigned index)
{
assert(t, index < singletonCount(t, singleton));
return (singletonMask(t, singleton)[(index + 2) / 32]
& (static_cast<uint32_t>(1) << ((index + 2) % 32))) != 0;
}
inline object
singletonObject(Thread* t, object singleton, unsigned index)
{
assert(t, singletonIsObject(t, singleton, index));
return reinterpret_cast<object>(singletonBody(t, singleton, index));
}
inline uintptr_t&
singletonValue(Thread* t, object singleton, unsigned index)
{
assert(t, not singletonIsObject(t, singleton, index));
return singletonBody(t, singleton, index);
}
inline object
makeSingleton(Thread* t, unsigned count)
{
object o = makeSingleton(t, count + singletonMaskSize(count), true);
if (count) {
singletonMask(t, o)[0] = 1;
}
return o;
}
} // namespace vm } // namespace vm
#endif//MACHINE_H #endif//MACHINE_H

View File

@ -45,7 +45,7 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset)
inline object inline object
resolveClassInPool(Thread* t, object pool, unsigned index) resolveClassInPool(Thread* t, object pool, unsigned index)
{ {
object o = arrayBody(t, pool, index); object o = singletonObject(t, pool, index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType))
{ {
PROTECT(t, pool); PROTECT(t, pool);
@ -53,7 +53,7 @@ resolveClassInPool(Thread* t, object pool, unsigned index)
o = resolveClass(t, o); o = resolveClass(t, o);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
set(t, pool, ArrayBody + (index * BytesPerWord), o); set(t, pool, SingletonBody + (index * BytesPerWord), o);
} }
return o; return o;
} }
@ -63,7 +63,7 @@ resolve(Thread* t, object pool, unsigned index,
object (*find)(vm::Thread*, object, object, object), object (*find)(vm::Thread*, object, object, object),
object (*makeError)(vm::Thread*, object)) object (*makeError)(vm::Thread*, object))
{ {
object o = arrayBody(t, pool, index); object o = singletonObject(t, pool, index);
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
{ {
PROTECT(t, pool); PROTECT(t, pool);
@ -79,7 +79,7 @@ resolve(Thread* t, object pool, unsigned index,
find, makeError); find, makeError);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
set(t, pool, ArrayBody + (index * BytesPerWord), o); set(t, pool, SingletonBody + (index * BytesPerWord), o);
} }
return o; return o;

View File

@ -15,10 +15,35 @@ class Processor {
makeThread(Machine* m, object javaThread, Thread* parent) = 0; makeThread(Machine* m, object javaThread, Thread* parent) = 0;
virtual object virtual object
methodStub(Thread* t) = 0; makeMethod(Thread* t,
uint8_t vmFlags,
uint8_t returnCode,
uint8_t parameterCount,
uint8_t parameterFootprint,
uint16_t flags,
uint16_t offset,
object name,
object spec,
object class_,
object code) = 0;
virtual object virtual object
nativeInvoker(Thread* t) = 0; makeClass(Thread* t,
uint16_t flags,
uint8_t vmFlags,
uint8_t arrayDimensions,
uint16_t fixedSize,
uint16_t arrayElementSize,
object objectMask,
object name,
object super,
object interfaceTable,
object virtualTable,
object fieldTable,
object methodTable,
object staticTable,
object loader,
unsigned vtableLength) = 0;
virtual unsigned virtual unsigned
parameterFootprint(Thread* t, const char* spec, bool static_) = 0; parameterFootprint(Thread* t, const char* spec, bool static_) = 0;

View File

@ -10,27 +10,35 @@ class Stream {
class Client { class Client {
public: public:
virtual ~Client() { } virtual ~Client() { }
virtual void NO_RETURN handleEOS() = 0; virtual void NO_RETURN handleError() = 0;
}; };
Stream(Client* client, const uint8_t* data, unsigned size): Stream(Client* client, const uint8_t* data, unsigned size):
client(client), data(data), size(size), position(0) client(client), data(data), size(size), position_(0)
{ } { }
unsigned position() {
return position_;
}
void setPosition(unsigned p) {
position_ = p;
}
void skip(unsigned size) { void skip(unsigned size) {
if (size > this->size - position) { if (size > this->size - position_) {
client->handleEOS(); client->handleError();
} else { } else {
position += size; position_ += size;
} }
} }
void read(uint8_t* data, unsigned size) { void read(uint8_t* data, unsigned size) {
if (size > this->size - position) { if (size > this->size - position_) {
client->handleEOS(); client->handleError();
} else { } else {
memcpy(data, this->data + position, size); memcpy(data, this->data + position_, size);
position += size; position_ += size;
} }
} }
@ -70,7 +78,7 @@ class Stream {
Client* client; Client* client;
const uint8_t* data; const uint8_t* data;
unsigned size; unsigned size;
unsigned position; unsigned position_;
}; };
} // namespace vm } // namespace vm

View File

@ -1351,6 +1351,12 @@ parseJavaClass(Object* type, Stream* s, Object* declarations)
} }
} }
if (equal(typeJavaName(type), "java/lang/Class")) {
// add inline vtable
addMember(type, Array::make
(type, 0, "void*", "vtable", sizeOf("void*", 0)));
}
if (typeSuper(type)) { if (typeSuper(type)) {
for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) { for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) {
addMethod(type, car(p)); addMethod(type, car(p));
@ -2114,6 +2120,9 @@ writeInitialization(Output* out, Object* type)
out->write(", "); out->write(", ");
out->write(typeArrayElementSize(type)); out->write(typeArrayElementSize(type));
out->write(", ");
out->write(methodCount(type));
out->write(");\n"); out->write(");\n");
} }