diff --git a/makefile b/makefile index 68fd5152e6..8c9f6fe6e0 100644 --- a/makefile +++ b/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 diff --git a/src/constants.h b/src/constants.h index c72ec917df..1bce8dad33 100644 --- a/src/constants.h +++ b/src/constants.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; diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 3dda546ba0..79f6dedccd 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -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(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); } diff --git a/src/types.def b/src/types.def index 210293f515..e50ab1bd32 100644 --- a/src/types.def +++ b/src/types.def @@ -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)) diff --git a/src/vm.cpp b/src/vm.cpp index ae2827d607..617a840150 100644 --- a/src/vm.cpp +++ b/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 inline T& @@ -34,8 +35,6 @@ objectClass(object o) return cast(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(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(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(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(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;