interface-related bugfixes

This commit is contained in:
Joel Dice 2007-07-04 20:25:25 -06:00
parent c3320c2c97
commit d2ef4dabc4
2 changed files with 115 additions and 51 deletions

View File

@ -79,13 +79,6 @@
(object name)
(object spec))
(type interface
(uint32_t id)
(object name)
(object supers)
(object methodTable)
(object staticTable))
(type pair
(object first)
(object second))

View File

@ -458,6 +458,21 @@ hashMapInsert(Thread* t, object map, object key, object value,
set(t, arrayBody(t, array, index), n);
}
inline bool
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
set(t, tripleSecond(t, n), value);
return false;
}
}
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
@ -1398,9 +1413,7 @@ instanceOf(Thread* t, object class_, object o)
return false;
}
if (objectClass(t, class_)
== arrayBody(t, t->vm->types, Machine::InterfaceType))
{
if (classFlags(t, class_) & ACC_INTERFACE) {
for (object oc = objectClass(t, o); oc; oc = classSuper(t, oc)) {
object itable = classInterfaceTable(t, oc);
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
@ -1644,6 +1657,28 @@ parsePool(Thread* t, Stream& s)
return pool;
}
void
addInterfaces(Thread* t, object class_, object map)
{
object table = classInterfaceTable(t, class_);
if (table) {
unsigned increment = 2;
if (classFlags(t, class_) & ACC_INTERFACE) {
increment = 1;
}
PROTECT(t, map);
PROTECT(t, table);
for (unsigned i = 0; i < arrayLength(t, table); i += increment) {
object interface = arrayBody(t, table, i);
object name = className(t, interface);
hashMapInsertOrReplace(t, map, name, interface, byteArrayHash,
byteArrayEqual);
}
}
}
void
parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
{
@ -1654,26 +1689,30 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, map);
if (classSuper(t, class_)) {
object superInterfaces = classInterfaceTable(t, classSuper(t, class_));
if (superInterfaces) {
PROTECT(t, superInterfaces);
for (unsigned i = 0; i < arrayLength(t, superInterfaces); i += 2) {
object name = interfaceName(t, arrayBody(t, superInterfaces, i));
hashMapInsert(t, map, name, name, byteArrayHash);
}
}
addInterfaces(t, classSuper(t, class_), map);
}
unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) {
object name = arrayBody(t, pool, s.read2() - 1);
hashMapInsert(t, map, name, name, byteArrayHash);
PROTECT(t, name);
object interface = resolveClass(t, name);
PROTECT(t, interface);
hashMapInsertOrReplace(t, map, name, interface, byteArrayHash,
byteArrayEqual);
addInterfaces(t, interface, map);
}
object interfaceTable = 0;
if (hashMapSize(t, map)) {
interfaceTable = makeArray(t, hashMapSize(t, map), true);
unsigned length = hashMapSize(t, map) ;
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
length *= 2;
}
interfaceTable = makeArray(t, length, true);
PROTECT(t, interfaceTable);
unsigned i = 0;
@ -1687,13 +1726,15 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
set(t, arrayBody(t, interfaceTable, i++), interface);
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
// we'll fill in this table in parseMethodTable():
object vtable = makeArray
(t, arrayLength(t, interfaceMethodTable(t, interface)), true);
(t, arrayLength(t, classVirtualTable(t, interface)), true);
set(t, arrayBody(t, interfaceTable, i++), vtable);
}
}
}
set(t, classInterfaceTable(t, class_), interfaceTable);
}
@ -2066,6 +2107,22 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
object superVirtualTable = 0;
PROTECT(t, superVirtualTable);
if (classFlags(t, class_) & ACC_INTERFACE) {
object itable = classInterfaceTable(t, class_);
if (itable) {
for (unsigned i = 0; i < arrayLength(t, itable); ++i) {
object vtable = classVirtualTable(t, arrayBody(t, itable, i));
for (unsigned j = 0; j < virtualCount; ++j) {
object method = arrayBody(t, vtable, j);
if (hashMapInsertOrReplace(t, virtualMap, method, method, methodHash,
methodEqual))
{
++ virtualCount;
}
}
}
}
} else {
if (classSuper(t, class_)) {
superVirtualTable = classVirtualTable(t, classSuper(t, class_));
}
@ -2077,6 +2134,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
hashMapInsert(t, virtualMap, method, method, methodHash);
}
}
}
object newVirtuals = makeList(t, 0, 0, 0);
PROTECT(t, newVirtuals);
@ -2179,9 +2237,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (virtualCount) {
// generate class vtable
unsigned i = 0;
object vtable = makeArray(t, virtualCount, false);
unsigned i = 0;
if (classFlags(t, class_) & ACC_INTERFACE) {
object it = hashMapIterator(t, virtualMap);
for (; it; it = hashMapIteratorNext(t, it)) {
object method = tripleFirst(t, hashMapIteratorNode(t, it));
set(t, arrayBody(t, vtable, i++), method);
}
} else {
if (superVirtualTable) {
for (; i < arrayLength(t, superVirtualTable); ++i) {
object method = arrayBody(t, superVirtualTable, i);
@ -2190,6 +2256,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
set(t, arrayBody(t, vtable, i), method);
}
}
}
for (object p = listFront(t, newVirtuals); p; p = pairSecond(t, p)) {
set(t, arrayBody(t, vtable, i++), pairFirst(t, p));
@ -2197,6 +2264,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
set(t, classVirtualTable(t, class_), vtable);
if ((classFlags(t, class_) & ACC_INTERFACE) == 0) {
// generate interface vtables
object itable = classInterfaceTable(t, class_);
@ -2204,12 +2272,13 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, itable);
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
object methodTable = interfaceMethodTable(t, arrayBody(t, itable, i));
object ivtable = classVirtualTable(t, arrayBody(t, itable, i));
object vtable = arrayBody(t, itable, i + 1);
for (unsigned j = 0; j < arrayLength(t, methodTable); ++j) {
object method = arrayBody(t, methodTable, j);
method = hashMapFind(t, virtualMap, method, methodHash, methodEqual);
for (unsigned j = 0; j < arrayLength(t, ivtable); ++j) {
object method = arrayBody(t, ivtable, j);
method = hashMapFind
(t, virtualMap, method, methodHash, methodEqual);
set(t, arrayBody(t, vtable, j), method);
}
@ -2217,6 +2286,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
}
}
}
}
object
parseClass(Thread* t, const uint8_t* data, unsigned size)
@ -2354,6 +2424,7 @@ resolveClass(Thread* t, object spec)
object bootstrapClass = hashMapFind
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
if (bootstrapClass) {
PROTECT(t, bootstrapClass);