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
test = test
input = $(test-build)/References.class
input = $(test-build)/List.class
build-cxx = g++
build-cc = gcc

View File

@ -2051,36 +2051,33 @@ interpret(Thread* 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::IntType)
or objectClass(t, v) == arrayBody(t, t->m->types, Machine::FloatType))
{
pushInt(t, intValue(t, v));
} else if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::StringType))
{
pushObject(t, v);
if (singletonIsObject(t, pool, index - 1)) {
object v = singletonObject(t, pool, index - 1);
if (objectClass(t, v)
== arrayBody(t, t->m->types, Machine::ByteArrayType))
{
object class_ = resolveClassInPool(t, pool, index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_);
} else {
pushObject(t, v);
}
} else {
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(exception)) goto throw_;
pushObject(t, class_);
pushInt(t, singletonValue(t, pool, index - 1));
}
} goto loop;
case ldc2_w: {
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)
or objectClass(t, v) == arrayBody(t, t->m->types, Machine::DoubleType))
{
pushLong(t, longValue(t, v));
} else {
abort(t);
}
uint64_t v;
memcpy(&v, &singletonValue(t, pool, index - 1), 8);
pushLong(t, v);
} goto loop;
case ldiv_: {
@ -2863,15 +2860,45 @@ class MyProcessor: public Processor {
}
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
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

View File

@ -197,15 +197,15 @@ IsInstanceOf(Thread* t, jobject o, jclass c)
}
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);
PROTECT(t, n);
object s = makeByteArray(t, "%s", spec);
return vm::findMethod(t, class_, n, s);
return vm::findMethod(t, c, n, s);
}
jmethodID JNICALL

View File

@ -204,13 +204,8 @@ walk(Thread* t, Heap::Walker* w, object o)
} else if (classVmFlags(t, class_) & SingletonFlag) {
unsigned length = singletonLength(t, o);
if (length) {
unsigned maskSize = ceiling(length + 2, BitsPerWord + 1);
uint32_t mask[maskSize * (BytesPerWord / 4)];
memcpy(mask, &singletonBody(t, o, length - maskSize),
maskSize * BytesPerWord);
walk(t, w, mask, (length + 2) * BytesPerWord, 0, 0);
walk(t, w, singletonMask(t, o),
(singletonCount(t, o) + 2) * BytesPerWord, 0, 0);
} else {
w->visit(0);
}
@ -617,127 +612,151 @@ parseUtf8(Thread* t, Stream& s, unsigned length)
return value;
}
unsigned
parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i)
{
PROTECT(t, pool);
s.setPosition(index[i]);
switch (s.read1()) {
case CONSTANT_Integer:
case CONSTANT_Float: {
singletonValue(t, pool, i) = s.read4();
} return 1;
case CONSTANT_Long:
case CONSTANT_Double: {
uint64_t v = s.read8();
memcpy(&singletonValue(t, pool, i), &v, 8);
} return 2;
case CONSTANT_Utf8: {
if (singletonObject(t, pool, i) == 0) {
object value = parseUtf8(t, s, s.read2());
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
case CONSTANT_Class: {
if (singletonObject(t, pool, i) == 0) {
unsigned si = s.read2() - 1;
parsePoolEntry(t, s, index, pool, si);
object value = singletonObject(t, pool, si);
set(t, pool, SingletonBody + (i * BytesPerWord), value);
}
} return 1;
case CONSTANT_String: {
if (singletonObject(t, pool, i) == 0) {
unsigned si = s.read2() - 1;
parsePoolEntry(t, s, index, pool, si);
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: {
if (singletonObject(t, pool, i) == 0) {
unsigned ni = s.read2() - 1;
unsigned ti = s.read2() - 1;
parsePoolEntry(t, s, index, pool, ni);
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_Methodref:
case CONSTANT_InterfaceMethodref: {
if (singletonObject(t, pool, i) == 0) {
unsigned ci = s.read2() - 1;
unsigned nti = s.read2() - 1;
parsePoolEntry(t, s, index, pool, ci);
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 poolCount = s.read2() - 1;
object pool = makeArray(t, poolCount, true);
unsigned count = s.read2() - 1;
PROTECT(t, pool);
object pool = makeSingleton(t, count);
for (unsigned i = 0; i < poolCount; ++i) {
unsigned c = s.read1();
if (count) {
uint32_t* index = static_cast<uint32_t*>
(t->m->system->allocate(count * 4));
switch (c) {
case CONSTANT_Integer: {
object value = makeInt(t, s.read4());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
for (unsigned i = 0; i < count; ++i) {
index[i] = s.position();
case CONSTANT_Float: {
object value = makeInt(t, s.readFloat());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
switch (s.read1()) {
case CONSTANT_Class:
case CONSTANT_String:
singletonMarkObject(t, pool, i);
s.skip(2);
break;
case CONSTANT_Long: {
object value = makeLong(t, s.read8());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
++i;
} break;
case CONSTANT_Integer:
case CONSTANT_Float:
s.skip(4);
break;
case CONSTANT_Double: {
object value = makeLong(t, s.readDouble());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
++i;
} break;
case CONSTANT_Utf8: {
object value = parseUtf8(t, s, s.read2());
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
case CONSTANT_Class: {
object value = makeIntArray(t, 2, false);
intArrayBody(t, value, 0) = c;
intArrayBody(t, value, 1) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
case CONSTANT_String: {
object value = makeIntArray(t, 2, false);
intArrayBody(t, value, 0) = c;
intArrayBody(t, value, 1) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
case CONSTANT_NameAndType: {
object value = makeIntArray(t, 3, false);
intArrayBody(t, value, 0) = c;
intArrayBody(t, value, 1) = s.read2();
intArrayBody(t, value, 2) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: {
object value = makeIntArray(t, 3, false);
intArrayBody(t, value, 0) = c;
intArrayBody(t, value, 1) = s.read2();
intArrayBody(t, value, 2) = s.read2();
set(t, pool, ArrayBody + (i * BytesPerWord), value);
} break;
default: abort(t);
}
}
for (unsigned i = 0; i < poolCount; ++i) {
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: {
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: {
object name = arrayBody(t, pool, intArrayBody(t, o, 1) - 1);
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) {
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_NameAndType:
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;
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);
}
}
unsigned end = s.position();
PROTECT(t, pool);
for (unsigned i = 0; i < count;) {
i += parsePoolEntry(t, s, index, pool, i);
}
t->m->system->free(index);
s.setPosition(end);
}
return pool;
@ -780,7 +799,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
unsigned count = s.read2();
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);
object interface = resolveClass(t, name);
@ -861,31 +880,53 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
object value = 0;
PROTECT(t, value);
unsigned code = fieldCode
(t, byteArrayBody(t, singletonObject(t, pool, spec - 1), 0));
unsigned attributeCount = s.read2();
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();
if (strcmp(reinterpret_cast<const int8_t*>("ConstantValue"),
&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 {
s.skip(length);
}
}
unsigned code = fieldCode
(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0));
object field = makeField
(t,
0, // vm flags
code,
flags,
0, // offset
arrayBody(t, pool, name - 1),
arrayBody(t, pool, spec - 1),
singletonObject(t, pool, name - 1),
singletonObject(t, pool, spec - 1),
class_);
if (flags & ACC_STATIC) {
@ -925,19 +966,11 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
if (staticCount) {
unsigned footprint = ceiling(staticOffset - (BytesPerWord * 2),
BytesPerWord);
unsigned maskSize = ceiling(footprint + 2, BitsPerWord);
object staticTable = makeSingleton(t, footprint + maskSize, false);
object staticTable = makeSingleton(t, footprint);
uint8_t* body = reinterpret_cast<uint8_t*>
(&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) {
unsigned size = fieldSize(t, staticTypes[i]);
unsigned excess = offset % size;
@ -979,8 +1012,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
}
if (staticTypes[i] == ObjectField) {
unsigned index = (offset / BytesPerWord) + 2;
mask[index / 32] |= static_cast<uint32_t>(1) << (index % 32);
singletonMarkObject(t, staticTable, offset / BytesPerWord);
}
offset += size;
@ -1064,7 +1096,7 @@ parseCode(Thread* t, Stream& s, object pool)
unsigned attributeCount = s.read2();
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();
if (strcmp(reinterpret_cast<const int8_t*>("LineNumberTable"),
@ -1181,7 +1213,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object code = 0;
unsigned attributeCount = s.read2();
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();
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*>
(&byteArrayBody(t, arrayBody(t, pool, spec - 1), 0));
(&byteArrayBody(t, singletonObject(t, pool, spec - 1), 0));
unsigned parameterCount;
unsigned returnCode;
@ -1203,25 +1235,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
unsigned parameterFootprint = t->m->processor->parameterFootprint
(t, specString, flags & ACC_STATIC);
object compiled;
if (flags & ACC_NATIVE) {
compiled = t->m->processor->nativeInvoker(t);
} else {
compiled = t->m->processor->methodStub(t);
}
object method = t->m->processor->makeMethod
(t,
0, // vm flags
returnCode,
parameterCount,
parameterFootprint,
flags,
0, // offset
singletonObject(t, pool, name - 1),
singletonObject(t, pool, spec - 1),
class_,
code);
object method = makeMethod(t,
0, // vm flags
returnCode,
parameterCount,
parameterFootprint,
flags,
0, // offset
arrayBody(t, pool, name - 1),
arrayBody(t, pool, spec - 1),
class_,
code,
compiled);
PROTECT(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
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
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,
(classVmFlags(t, bootstrapClass) & ReferenceFlag)
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, ClassStaticTable, classStaticTable(t, class_));
object fieldTable = classFieldTable(t, 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);
}
}
updateClassTables(t, bootstrapClass, class_);
}
object
@ -1408,7 +1454,10 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
object elementClass)
{
// 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,
0,
0,
@ -1419,11 +1468,12 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
spec,
arrayBody(t, t->m->types, Machine::JobjectType),
0,
classVirtualTable(t, arrayBody(t, t->m->types, Machine::JobjectType)),
vtable,
0,
0,
elementClass,
t->m->loader);
t->m->loader,
arrayLength(t, vtable));
}
object
@ -1517,7 +1567,7 @@ invoke(Thread* t, const char* className, int argc, const char** argv)
void
bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask,
unsigned fixedSize, unsigned arrayElementSize)
unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength)
{
object mask;
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 class_ = makeClass
object class_ = t->m->processor->makeClass
(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_);
}
@ -2517,7 +2567,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
public:
Client(Thread* t): t(t) { }
virtual void NO_RETURN handleEOS() {
virtual void NO_RETURN handleError() {
abort(t);
}
@ -2545,19 +2595,21 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
0, // fixed size
0, // array size
0, // object mask
arrayBody(t, pool, name - 1),
singletonObject(t, pool, name - 1),
0, // super
0, // interfaces
0, // vtable
0, // fields
0, // methods
0, // static table
t->m->loader);
t->m->loader,
0, // vtable length
false);
PROTECT(t, class_);
unsigned super = s.read2();
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;
set(t, class_, ClassSuper, sc);
@ -2575,7 +2627,30 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
parseMethodTable(t, s, class_, pool);
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
@ -2616,7 +2691,9 @@ resolveClass(Thread* t, object spec)
if (LIKELY(t->exception == 0)) {
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

View File

@ -2188,6 +2188,79 @@ methodVirtual(Thread* t, object method)
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
#endif//MACHINE_H

View File

@ -45,7 +45,7 @@ resolveClassInObject(Thread* t, object container, unsigned classOffset)
inline object
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))
{
PROTECT(t, pool);
@ -53,7 +53,7 @@ resolveClassInPool(Thread* t, object pool, unsigned index)
o = resolveClass(t, o);
if (UNLIKELY(t->exception)) return 0;
set(t, pool, ArrayBody + (index * BytesPerWord), o);
set(t, pool, SingletonBody + (index * BytesPerWord), o);
}
return o;
}
@ -63,7 +63,7 @@ resolve(Thread* t, object pool, unsigned index,
object (*find)(vm::Thread*, object, object, 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))
{
PROTECT(t, pool);
@ -79,7 +79,7 @@ resolve(Thread* t, object pool, unsigned index,
find, makeError);
if (UNLIKELY(t->exception)) return 0;
set(t, pool, ArrayBody + (index * BytesPerWord), o);
set(t, pool, SingletonBody + (index * BytesPerWord), o);
}
return o;

View File

@ -15,10 +15,35 @@ class Processor {
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
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
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
parameterFootprint(Thread* t, const char* spec, bool static_) = 0;

View File

@ -10,27 +10,35 @@ class Stream {
class Client {
public:
virtual ~Client() { }
virtual void NO_RETURN handleEOS() = 0;
virtual void NO_RETURN handleError() = 0;
};
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) {
if (size > this->size - position) {
client->handleEOS();
if (size > this->size - position_) {
client->handleError();
} else {
position += size;
position_ += size;
}
}
void read(uint8_t* data, unsigned size) {
if (size > this->size - position) {
client->handleEOS();
if (size > this->size - position_) {
client->handleError();
} else {
memcpy(data, this->data + position, size);
position += size;
memcpy(data, this->data + position_, size);
position_ += size;
}
}
@ -70,7 +78,7 @@ class Stream {
Client* client;
const uint8_t* data;
unsigned size;
unsigned position;
unsigned position_;
};
} // 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)) {
for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) {
addMethod(type, car(p));
@ -2114,6 +2120,9 @@ writeInitialization(Output* out, Object* type)
out->write(", ");
out->write(typeArrayElementSize(type));
out->write(", ");
out->write(methodCount(type));
out->write(");\n");
}