mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +00:00
clean up sketch of parseClass() and friends; etc.
This commit is contained in:
parent
f99425d944
commit
1cb866aac1
2
makefile
2
makefile
@ -33,8 +33,6 @@ stdcpp-cflags = $(fast) $(cflags)
|
||||
|
||||
type-headers = \
|
||||
$(bld)/type-header.h \
|
||||
$(bld)/type-enums.h \
|
||||
$(bld)/type-enum-cases.h \
|
||||
$(bld)/type-declarations.h \
|
||||
$(bld)/type-constructors.h \
|
||||
$(bld)/type-primary-inits.h
|
||||
|
@ -215,8 +215,13 @@ enum Constant {
|
||||
};
|
||||
|
||||
const unsigned ACC_PUBLIC = 1 << 0;
|
||||
const unsigned ACC_PRIVATE = 1 << 1;
|
||||
const unsigned ACC_PROTECTED = 1 << 2;
|
||||
const unsigned ACC_STATIC = 1 << 3;
|
||||
const unsigned ACC_FINAL = 1 << 4;
|
||||
const unsigned ACC_SUPER = 1 << 5;
|
||||
const unsigned ACC_VOLATILE = 1 << 6;
|
||||
const unsigned ACC_TRANSIENT = 1 << 7;
|
||||
const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
|
||||
|
@ -992,9 +992,9 @@ writeSubtypeAssertions(Output* out, Object* o)
|
||||
{
|
||||
for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
|
||||
Object* st = car(p);
|
||||
out->write(" or typeOf(o) == ");
|
||||
out->write(capitalize(typeName(st)));
|
||||
out->write("Type");
|
||||
out->write(" or objectClass(o) == t->vm->");
|
||||
out->write(typeName(st));
|
||||
out->write("Class");
|
||||
writeSubtypeAssertions(out, st);
|
||||
}
|
||||
}
|
||||
@ -1027,9 +1027,9 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
out->write(") {\n");
|
||||
|
||||
if (not unsafe and memberOwner(member)->type == Object::Type) {
|
||||
out->write(" assert(t, objectClass(o) == 0 or typeOf(o) == ");
|
||||
out->write(capitalize(::typeName(memberOwner(member))));
|
||||
out->write("Type");
|
||||
out->write(" assert(t, objectClass(o) == 0 or objectClass(o) == t->vm->");
|
||||
out->write(::typeName(memberOwner(member)));
|
||||
out->write("Class");
|
||||
writeSubtypeAssertions(out, memberOwner(member));
|
||||
out->write(");\n");
|
||||
}
|
||||
@ -1328,65 +1328,6 @@ writeConstructors(Output* out, Object* declarations)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeEnums(Output* out, Object* declarations)
|
||||
{
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
switch (o->type) {
|
||||
case Object::Type: {
|
||||
out->write(capitalize(typeName(o)));
|
||||
out->write("Type,\n");
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
lispStyle(const char* s)
|
||||
{
|
||||
unsigned length = 0;
|
||||
for (const char* p = s; *p; ++p) {
|
||||
if (*p >= 'A' and *p <= 'Z') ++ length;
|
||||
++ length;
|
||||
}
|
||||
|
||||
char* n = static_cast<char*>(malloc(length + 1));
|
||||
assert(n);
|
||||
char* np = n;
|
||||
for (const char* p = s; *p; ++p) {
|
||||
if (*p >= 'A' and *p <= 'Z') {
|
||||
*(np++) = '-';
|
||||
*(np++) = 'a' + (*p - 'A');
|
||||
} else {
|
||||
*(np++) = *p;
|
||||
}
|
||||
}
|
||||
*np = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
writeEnumCases(Output* out, Object* declarations)
|
||||
{
|
||||
for (Object* p = declarations; p; p = cdr(p)) {
|
||||
Object* o = car(p);
|
||||
switch (o->type) {
|
||||
case Object::Type: {
|
||||
out->write("case ");
|
||||
out->write(capitalize(typeName(o)));
|
||||
out->write("Type: return \"");
|
||||
out->write(lispStyle(typeName(o)));
|
||||
out->write("\";\n");
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeDeclarations(Output* out, Object* declarations)
|
||||
{
|
||||
@ -1551,8 +1492,7 @@ void
|
||||
usageAndExit(const char* command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s {header,enums,enum-cases,declarations,constructors,"
|
||||
"primary-inits}\n",
|
||||
"usage: %s {header,declarations,constructors,primary-inits}\n",
|
||||
command);
|
||||
exit(-1);
|
||||
}
|
||||
@ -1565,8 +1505,6 @@ main(int ac, char** av)
|
||||
if ((ac != 1 and ac != 2)
|
||||
or (ac == 2
|
||||
and not equal(av[1], "header")
|
||||
and not equal(av[1], "enums")
|
||||
and not equal(av[1], "enum-cases")
|
||||
and not equal(av[1], "declarations")
|
||||
and not equal(av[1], "constructors")
|
||||
and not equal(av[1], "primary-inits")))
|
||||
@ -1586,14 +1524,6 @@ main(int ac, char** av)
|
||||
writeConstructorDeclarations(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "enums")) {
|
||||
writeEnums(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "enum-cases")) {
|
||||
writeEnumCases(&out, declarations);
|
||||
}
|
||||
|
||||
if (ac == 1 or equal(av[1], "declarations")) {
|
||||
writeDeclarations(&out, declarations);
|
||||
}
|
||||
|
@ -73,11 +73,16 @@
|
||||
(object third))
|
||||
|
||||
(type hashMap
|
||||
(object size)
|
||||
(uint32_t size)
|
||||
(object array))
|
||||
|
||||
(type hashMapIterator
|
||||
(object map)
|
||||
(object node)
|
||||
(unsigned index))
|
||||
|
||||
(type list
|
||||
(object size)
|
||||
(uint32_t size)
|
||||
(object front)
|
||||
(object rear))
|
||||
|
||||
@ -137,7 +142,7 @@
|
||||
(int8_t value))
|
||||
|
||||
(type boolean
|
||||
(int8_t byte))
|
||||
(int8_t value))
|
||||
|
||||
(type short
|
||||
(int16_t value))
|
||||
|
189
src/vm.cpp
189
src/vm.cpp
@ -19,7 +19,8 @@ typedef unsigned Type;
|
||||
|
||||
class Thread;
|
||||
|
||||
void assert(Thread* t, bool v);
|
||||
void assert(Thread*, bool);
|
||||
object resolveClass(Thread*, object);
|
||||
|
||||
template <class T>
|
||||
inline T&
|
||||
@ -34,8 +35,6 @@ objectClass(object o)
|
||||
return cast<object>(o, 0);
|
||||
}
|
||||
|
||||
#include "type-header.h"
|
||||
|
||||
class Machine {
|
||||
public:
|
||||
System* sys;
|
||||
@ -45,11 +44,12 @@ class Machine {
|
||||
Thread* exclusive;
|
||||
unsigned activeCount;
|
||||
unsigned liveCount;
|
||||
unsigned nextClassId;
|
||||
System::Monitor* stateLock;
|
||||
System::Monitor* heapLock;
|
||||
System::Monitor* classLock;
|
||||
object classMap;
|
||||
|
||||
#include "type-declarations.h"
|
||||
};
|
||||
|
||||
class Thread {
|
||||
@ -97,6 +97,8 @@ class Thread {
|
||||
Protector* protector;
|
||||
};
|
||||
|
||||
#include "type-header.h"
|
||||
|
||||
void enter(Thread* t, Thread::State state);
|
||||
|
||||
class MonitorResource {
|
||||
@ -148,7 +150,6 @@ init(Machine* m, System* sys, Heap* heap, ClassFinder* classFinder)
|
||||
m->sys = sys;
|
||||
m->heap = heap;
|
||||
m->classFinder = classFinder;
|
||||
m->nextClassId = OtherType + 1;
|
||||
|
||||
if (not sys->success(sys->make(&(m->stateLock))) or
|
||||
not sys->success(sys->make(&(m->heapLock))) or
|
||||
@ -497,7 +498,7 @@ isLongOrDouble(Thread* t, object o)
|
||||
inline object
|
||||
getField(Thread* t, object instance, object field)
|
||||
{
|
||||
switch (arrayBody(t, fieldSpec(t, field))[0]) {
|
||||
switch (byteArrayBody(t, fieldSpec(t, field))[0]) {
|
||||
case 'B':
|
||||
return makeByte(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
||||
case 'C':
|
||||
@ -525,7 +526,7 @@ getField(Thread* t, object instance, object field)
|
||||
inline void
|
||||
setField(Thread* t, object o, object field, object value)
|
||||
{
|
||||
switch (arrayBody(t, fieldSpec(t, field))[0]) {
|
||||
switch (byteArrayBody(t, fieldSpec(t, field))[0]) {
|
||||
case 'B':
|
||||
cast<int8_t>(o, fieldOffset(t, field)) = byteValue(t, value);
|
||||
break;
|
||||
@ -709,6 +710,14 @@ byteArrayHash(Thread* t, object array)
|
||||
return hash(byteArrayBody(t, array), byteArrayLength(t, array) - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
byteArrayEqual(Thread* t, object a, object b)
|
||||
{
|
||||
return a == b or
|
||||
((byteArrayLength(t, a) == byteArrayLength(t, b)) and
|
||||
strcmp(byteArrayBody(t, a), byteArrayBody(t, b)) == 0);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
methodHash(Thread* t, object method)
|
||||
{
|
||||
@ -717,11 +726,11 @@ methodHash(Thread* t, object method)
|
||||
}
|
||||
|
||||
bool
|
||||
byteArrayEqual(Thread* t, object a, object b)
|
||||
methodEqual(Thread* t, object a, object b)
|
||||
{
|
||||
return a == b or
|
||||
((byteArrayLength(t, a) == byteArrayLength(t, b)) and
|
||||
strcmp(byteArrayBody(t, a), byteArrayBody(t, b)) == 0);
|
||||
(byteArrayEqual(t, methodName(t, a), methodName(t, b)) and
|
||||
byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b)));
|
||||
}
|
||||
|
||||
object
|
||||
@ -764,10 +773,10 @@ hashMapGrow(Thread* t, object map, uint32_t (*hash)(Thread*, object))
|
||||
|
||||
unsigned newLength = (oldLength ? oldLength * 2 : 32);
|
||||
object newArray = makeArray(t, newLength);
|
||||
memset(arrayBody(t, newArray), o, newLength * sizeof(object));
|
||||
memset(arrayBody(t, newArray), 0, newLength * sizeof(object));
|
||||
|
||||
if (oldArray) {
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
for (unsigned i = 0; i < oldLength; ++i) {
|
||||
object next;
|
||||
for (object p = arrayBody(t, oldArray)[i]; p; p = next) {
|
||||
next = tripleThird(t, p);
|
||||
@ -789,19 +798,21 @@ void
|
||||
hashMapInsert(Thread* t, object map, object key, object value,
|
||||
uint32_t (*hash)(Thread*, object))
|
||||
{
|
||||
PROTECT(t, map);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
PROTECT(t, array);
|
||||
|
||||
++ hashMapSize(t, map);
|
||||
|
||||
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
|
||||
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
|
||||
PROTECT(t, map);
|
||||
PROTECT(t, key);
|
||||
PROTECT(t, value);
|
||||
|
||||
hashMapGrow(t, map, hash);
|
||||
array = hashMapArray(t, map);
|
||||
}
|
||||
|
||||
unsigned index = hash & (arrayLength(t, array) - 1);
|
||||
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
|
||||
object n = arrayBody(t, array)[index];
|
||||
|
||||
n = makeTriple(t, key, value, n);
|
||||
@ -809,6 +820,40 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
set(t, arrayBody(t, array)[index], n);
|
||||
}
|
||||
|
||||
object
|
||||
hashMapIterator(Thread* t, object map)
|
||||
{
|
||||
object array = hashMapArray(t, map);
|
||||
if (array) {
|
||||
for (unsigned i = 0; i < arrayLength(t, array); ++i) {
|
||||
if (arrayBody(t, array)[i]) {
|
||||
return makeHashMapIterator(t, map, arrayBody(t, array)[i], i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
object
|
||||
hashMapIteratorNext(Thread* t, object it)
|
||||
{
|
||||
object map = hashMapIteratorMap(t, it);
|
||||
object node = hashMapIteratorNode(t, it);
|
||||
unsigned index = hashMapIteratorIndex(t, it);
|
||||
|
||||
if (tripleThird(t, node)) {
|
||||
return makeHashMapIterator(t, map, tripleThird(t, node), index + 1);
|
||||
} else {
|
||||
object array = hashMapArray(t, map);
|
||||
for (unsigned i = index; i < arrayLength(t, array); ++i) {
|
||||
if (arrayBody(t, array)[i]) {
|
||||
return makeHashMapIterator(t, map, arrayBody(t, array)[i], i + 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
listAppend(Thread* t, object list, object value)
|
||||
{
|
||||
@ -854,18 +899,19 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
||||
PROTECT(t, interfaceTable);
|
||||
|
||||
unsigned i = 0;
|
||||
object it = hmIterator(t, map);
|
||||
object it = hashMapIterator(t, map);
|
||||
PROTECT(t, it);
|
||||
|
||||
for (; it; it = hmIteratorNext(t, it)) {
|
||||
object interface = resolveClass(t, hmIteratorKey(t, it));
|
||||
for (; it; it = hashMapIteratorNext(t, it)) {
|
||||
object interface = resolveClass
|
||||
(t, tripleFirst(t, hashMapIteratorNode(t, it)));
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
set(t, arrayBody(t, interfaceTable)[i++], interface);
|
||||
|
||||
// we'll fill in this table in parseMethodTable():
|
||||
object vtable = makeArray
|
||||
(t, arraySize(t, interfaceMethodTable(t, interface)));
|
||||
(t, arrayLength(t, interfaceMethodTable(t, interface)));
|
||||
set(t, arrayBody(t, interfaceTable)[i++], vtable);
|
||||
}
|
||||
}
|
||||
@ -873,6 +919,43 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
||||
set(t, classInterfaceTable(t, class_), interfaceTable);
|
||||
}
|
||||
|
||||
bool
|
||||
isReferenceField(Thread* t, object field)
|
||||
{
|
||||
switch (byteArrayBody(t, fieldSpec(t, field))[0]) {
|
||||
case 'L':
|
||||
case '[':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
fieldSize(Thread* t, object field)
|
||||
{
|
||||
switch (byteArrayBody(t, fieldSpec(t, field))[0]) {
|
||||
case 'B':
|
||||
return 1;
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'Z':
|
||||
return 2;
|
||||
case 'D':
|
||||
case 'J':
|
||||
return 8;
|
||||
case 'F':
|
||||
case 'I':
|
||||
return 4;
|
||||
case 'L':
|
||||
case '[':
|
||||
return sizeof(void*);
|
||||
|
||||
default: abort(t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
||||
{
|
||||
@ -947,11 +1030,11 @@ parseCode(Thread* t, Stream& s, object pool)
|
||||
|
||||
object eht = makeExceptionHandlerTable(t, ehtLength);
|
||||
for (unsigned i = 0; i < ehtLength; ++i) {
|
||||
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht) + i;
|
||||
eh->start = s.read2();
|
||||
eh->end = s.read2();
|
||||
eh->ip = s.read2();
|
||||
eh->catchType = s.read2();
|
||||
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
||||
exceptionHandlerStart(eh) = s.read2();
|
||||
exceptionHandlerEnd(eh) = s.read2();
|
||||
exceptionHandlerIp(eh) = s.read2();
|
||||
exceptionHandlerCatchType(eh) = s.read2();
|
||||
}
|
||||
|
||||
set(t, codeExceptionHandlerTable(t, code), eht);
|
||||
@ -964,8 +1047,36 @@ parseCode(Thread* t, Stream& s, object pool)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
parameterCount(Thread* t, object spec)
|
||||
{
|
||||
unsigned count = 0;
|
||||
const char* s = reinterpret_cast<const char*>(byteArrayBody(t, spec));
|
||||
++ s; // skip '('
|
||||
while (*s and *s != ')') {
|
||||
switch (*s) {
|
||||
case 'L':
|
||||
while (*s and *s != ';') ++ s;
|
||||
++ s;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
while (*s == '[') ++ s;
|
||||
break;
|
||||
|
||||
default:
|
||||
++ s;
|
||||
break;
|
||||
}
|
||||
|
||||
++ count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
parseMemberTable(Thread* t, Stream& s, object class_, object pool)
|
||||
parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||
{
|
||||
PROTECT(t, class_);
|
||||
PROTECT(t, pool);
|
||||
@ -975,7 +1086,7 @@ parseMemberTable(Thread* t, Stream& s, object class_, object pool)
|
||||
|
||||
unsigned virtualCount = 0;
|
||||
|
||||
object superVirtualTable = classVirtualTable(t, super);
|
||||
object superVirtualTable = classVirtualTable(t, classSuper(t, class_));
|
||||
PROTECT(t, superVirtualTable);
|
||||
|
||||
if (superVirtualTable) {
|
||||
@ -1017,7 +1128,7 @@ parseMemberTable(Thread* t, Stream& s, object class_, object pool)
|
||||
object value = makeMethod(t,
|
||||
flags,
|
||||
0, // offset
|
||||
parameterCount(arrayBody(t, pool)[spec]),
|
||||
parameterCount(t, arrayBody(t, pool)[spec]),
|
||||
arrayBody(t, pool)[name],
|
||||
arrayBody(t, pool)[spec],
|
||||
class_,
|
||||
@ -1031,17 +1142,16 @@ parseMemberTable(Thread* t, Stream& s, object class_, object pool)
|
||||
set(t, classInitializer(t, class_), value);
|
||||
}
|
||||
} else {
|
||||
object p = hashMapFindNode(t, map, method, methodHash, methodEqual);
|
||||
object p = hashMapFindNode(t, map, value, methodHash, methodEqual);
|
||||
|
||||
if (p) {
|
||||
methodOffset(t, value) = methodOffset(t, tripleFirst(t, p));
|
||||
|
||||
set(t, tripleSecond(t, p), value);
|
||||
} else {
|
||||
methodOffset(t, value) = offset++;
|
||||
methodOffset(t, value) = virtualCount++;
|
||||
|
||||
listAppend(t, newVirtuals, value);
|
||||
++ virtualCount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1168,8 +1278,9 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
||||
|
||||
case CONSTANT_Utf8: {
|
||||
unsigned length = s.read2();
|
||||
object value = makeByteArray(t, length);
|
||||
object value = makeByteArray(t, length + 1);
|
||||
s.read(reinterpret_cast<uint8_t*>(byteArrayBody(t, value)), length);
|
||||
byteArrayBody(t, value)[length] = 0;
|
||||
set(t, arrayBody(t, pool)[i], value);
|
||||
} break;
|
||||
|
||||
@ -1181,18 +1292,18 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
||||
unsigned name = s.read2();
|
||||
|
||||
object class_ = makeClass(t,
|
||||
t->vm->nextClassId++,
|
||||
flags,
|
||||
0, // fixed size
|
||||
0, // array size
|
||||
0, // object mask
|
||||
flags,
|
||||
arrayBody(t, pool)[name],
|
||||
0, // super
|
||||
0, // interfaces
|
||||
0, // vtable
|
||||
0, // fields
|
||||
0, // methods
|
||||
0, // static table
|
||||
0); // initializers
|
||||
0); // initializer
|
||||
PROTECT(t, class_);
|
||||
|
||||
object super = resolveClass(t, arrayBody(t, pool)[s.read2()]);
|
||||
@ -2144,9 +2255,9 @@ run(Thread* t)
|
||||
object method = resolveMethod(t, codePool(t, code), index);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
object clinit = classInitializer(t, fieldClass(t, field));
|
||||
object clinit = classInitializer(t, methodClass(t, method));
|
||||
if (clinit) {
|
||||
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
||||
set(t, classInitializer(t, methodClass(t, method)), 0);
|
||||
code = clinit;
|
||||
ip -= 3;
|
||||
parameterCount = 0;
|
||||
@ -2416,9 +2527,9 @@ run(Thread* t)
|
||||
object class_ = resolveClass(t, codePool(t, code), index);
|
||||
if (UNLIKELY(exception)) goto throw_;
|
||||
|
||||
object clinit = classInitializer(t, fieldClass(t, field));
|
||||
object clinit = classInitializer(t, class_);
|
||||
if (clinit) {
|
||||
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
||||
set(t, classInitializer(t, class_), 0);
|
||||
code = clinit;
|
||||
ip -= 3;
|
||||
parameterCount = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user