diff --git a/input/java/lang/Throwable.java b/input/java/lang/Throwable.java index 2623e96aeb..6ddb1cdfd7 100644 --- a/input/java/lang/Throwable.java +++ b/input/java/lang/Throwable.java @@ -3,4 +3,5 @@ package java.lang; public class Throwable { private String message; private Object trace; + private Throwable cause; } diff --git a/makefile b/makefile index e18a2397f3..1953bd27d9 100644 --- a/makefile +++ b/makefile @@ -36,7 +36,8 @@ generated-code = \ $(bld)/type-enums.cpp \ $(bld)/type-declarations.cpp \ $(bld)/type-constructors.cpp \ - $(bld)/type-initializations.cpp + $(bld)/type-initializations.cpp \ + $(bld)/type-java-initializations.cpp interpreter-depends = \ $(generated-code) \ $(src)/common.h \ diff --git a/src/system.h b/src/system.h index a33b0ead78..f899c7fa26 100644 --- a/src/system.h +++ b/src/system.h @@ -32,6 +32,7 @@ class System { virtual ~Library() { } virtual void* resolve(const char* function) = 0; virtual Library* next() = 0; + virtual void dispose() = 0; }; virtual ~System() { } @@ -63,6 +64,12 @@ abort(System* s) ::abort(); } +inline void +expect(System* s, bool v) +{ + if (UNLIKELY(not v)) abort(s); +} + #ifdef NDEBUG inline void assert(System*, bool) @@ -71,7 +78,7 @@ assert(System*, bool) inline void assert(System* s, bool v) { - if (UNLIKELY(not v)) abort(s); + expect(s, v); } #endif diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 9c35602feb..8ba1497cd6 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -278,19 +278,19 @@ memberHide(Object* o) class Type : public Object { public: const char* name; - const char* shortName; + const char* javaName; Object* super; List members; List subtypes; bool hideConstructor; static Type* make(Object::ObjectType type, const char* name, - const char* shortName) + const char* javaName) { Type* o = allocate(); o->type = type; o->name = name; - o->shortName = shortName; + o->javaName = javaName; o->super = 0; o->members.first = o->members.last = 0; o->subtypes.first = o->subtypes.last = 0; @@ -312,11 +312,11 @@ typeName(Object* o) } const char* -typeShortName(Object* o) +typeJavaName(Object* o) { switch (o->type) { case Object::Type: case Object::Pod: - return static_cast(o)->shortName; + return static_cast(o)->javaName; default: UNREACHABLE; @@ -878,13 +878,13 @@ parseType(Object::ObjectType type, Object* p, Object* declarations) { const char* name = string(car(p)); - const char* shortName = name; + const char* javaName = 0; if (cdr(p) and car(cdr(p))->type == Object::String) { p = cdr(p); - shortName = string(car(p)); + javaName = string(car(p)); } - Type* t = Type::make(type, name, shortName); + Type* t = Type::make(type, name, javaName); for (p = cdr(p); p; p = cdr(p)) { if (type == Object::Type) { @@ -931,7 +931,7 @@ void writeAccessorName(Output* out, Object* member, bool respectHide = false, bool unsafe = false) { - const char* owner = typeShortName(memberOwner(member)); + const char* owner = typeName(memberOwner(member)); out->write(owner); out->write(capitalize(memberName(member))); if (unsafe) { @@ -966,7 +966,7 @@ writeOffset(Output* out, Object* offset, bool allocationStyle = false) if (allocationStyle) { out->write("length"); } else { - out->write(typeShortName(memberOwner(o))); + out->write(typeName(memberOwner(o))); out->write(capitalize("length")); out->write("(o)"); } @@ -1480,17 +1480,33 @@ writeInitialization(Output* out, Object* type) out->write(" object mask = 0;\n"); } + if (typeJavaName(type)) { + if (typeObjectMask(type) != 1) { + out->write(" PROTECT(t, mask);\n"); + } + out->write(" object name = makeByteArray(t, \""); + out->write(typeJavaName(type)); + out->write("\");\n"); + } else { + out->write(" object name = 0;\n"); + } + out->write(" object class_ = makeClass"); out->write("(t, 0, "); out->write(typeFixedSize(type)); out->write(", "); out->write(typeArrayElementSize(type)); - out->write(", mask, 0, 0, 0, 0, 0, 0, 0, 0);\n"); + out->write(", mask, name, 0, 0, 0, 0, 0, 0, 0);\n"); out->write(" set(t, arrayBody(t, t->vm->types, Machine::"); out->write(capitalize(typeName(type))); out->write("Type), class_);\n"); + if (typeJavaName(type)) { + out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, "); + out->write("className(t, class_), class_, byteArrayHash);\n"); + } + out->write("}\n\n"); } @@ -1531,7 +1547,18 @@ writeInitializations(Output* out, Object* declarations) for (Object* p = declarations; p; p = cdr(p)) { Object* o = car(p); - if (o->type == Object::Type) { + if (o->type == Object::Type and typeJavaName(o) == 0) { + writeInitialization(out, o); + } + } +} + +void +writeJavaInitializations(Output* out, Object* declarations) +{ + for (Object* p = declarations; p; p = cdr(p)) { + Object* o = car(p); + if (o->type == Object::Type and typeJavaName(o)) { writeInitialization(out, o); } } @@ -1556,7 +1583,8 @@ main(int ac, char** av) and not equal(av[1], "enums") and not equal(av[1], "declarations") and not equal(av[1], "constructors") - and not equal(av[1], "initializations"))) + and not equal(av[1], "initializations") + and not equal(av[1], "java-initializations"))) { usageAndExit(av[0]); } @@ -1585,5 +1613,9 @@ main(int ac, char** av) writeInitializations(&out, declarations); } + if (ac == 1 or equal(av[1], "java-initializations")) { + writeJavaInitializations(&out, declarations); + } + return 0; } diff --git a/src/types.def b/src/types.def index 1bfe4990a5..dbd2e6c0f9 100644 --- a/src/types.def +++ b/src/types.def @@ -101,77 +101,6 @@ (uint32_t ip) (object next)) -(type thread - (object localMap) - (object exceptionHandler)) - -(type string - (object bytes) - (int32_t offset) - (int32_t length) - (int32_t hash)) - -(type throwable - (object message) - (object trace)) - -(type exception - (extends throwable)) - -(type runtimeException - (extends exception)) - -(type nullPointerException - (extends runtimeException)) - -(type arrayIndexOutOfBoundsException - (extends runtimeException)) - -(type negativeArrayStoreException - (extends runtimeException)) - -(type classCastException - (extends runtimeException)) - -(type classNotFoundException - (extends runtimeException)) - -(type error - (extends throwable)) - -(type stackOverflowError - (extends error)) - -(type noSuchFieldError - (extends error)) - -(type noSuchMethodError - (extends error)) - -(type byte - (int8_t value)) - -(type boolean - (int8_t value)) - -(type short - (int16_t value)) - -(type char - (uint16_t value)) - -(type int - (int32_t value)) - -(type long - (int64_t value)) - -(type float - (uint32_t value)) - -(type double - (uint64_t value)) - (type array (noassert array object body)) @@ -199,3 +128,88 @@ (type doubleArray (array uint64_t body)) + + +(type jobject java/lang/Object) + +(type string java/lang/String + (extends jobject) + (object bytes) + (int32_t offset) + (int32_t length) + (int32_t hash)) + +(type throwable java/lang/Throwable + (extends jobject) + (object message) + (object trace) + (object cause)) + +(type exception java/lang/Exception + (extends throwable)) + +(type runtimeException java/lang/RuntimeException + (extends exception)) + +(type nullPointerException java/lang/NullPointerException + (extends runtimeException)) + +(type arrayIndexOutOfBoundsException + java/lang/ArrayIndexOutOfBoundsException + (extends runtimeException)) + +(type negativeArrayStoreException java/lang/NegativeArrayStoreException + (extends runtimeException)) + +(type classCastException java/lang/ClassCastException + (extends runtimeException)) + +(type classNotFoundException java/lang/ClassNotFoundException + (extends runtimeException)) + +(type error java/lang/Error + (extends throwable)) + +(type stackOverflowError java/lang/StackOverflowError + (extends error)) + +(type noSuchFieldError java/lang/NoSuchFieldError + (extends error)) + +(type noSuchMethodError java/lang/NoSuchMethodError + (extends error)) + +(type unsatisfiedLinkError java/lang/UnsatisifiedLinkError + (extends error)) + +(type byte java/lang/Byte + (extends jobject) + (int8_t value)) + +(type boolean java/lang/Boolean + (extends jobject) + (int8_t value)) + +(type short java/lang/Short + (extends jobject) + (int16_t value)) + +(type char java/lang/Character + (extends jobject) + (uint16_t value)) + +(type int java/lang/Integer + (extends jobject) + (int32_t value)) + +(type long java/lang/Long + (extends jobject) + (int64_t value)) + +(type float java/lang/Float + (extends jobject) + (uint32_t value)) + +(type double java/lang/Double + (extends jobject) + (uint64_t value)) diff --git a/src/vm.cpp b/src/vm.cpp index 3c1fbaadbd..f934ffb43b 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -23,11 +23,13 @@ class Thread; void (*Initializer)(Thread*, object); void assert(Thread*, bool); +void expect(Thread*, bool); object resolveClass(Thread*, object); object allocate(Thread*, unsigned); object& arrayBodyUnsafe(Thread*, object, unsigned); void set(Thread*, object&, object); -object bootstrapInitializers(Thread*); +object makeByteArray(Thread*, const char*, ...); +unsigned objectSize(Thread* t, object o); object& objectClass(object o) @@ -71,7 +73,9 @@ class Machine { System::Monitor* stateLock; System::Monitor* heapLock; System::Monitor* classLock; + System::Library* libraries; object classMap; + object bootstrapClassMap; object types; bool unsafe; }; @@ -198,6 +202,12 @@ assert(Thread* t, bool v) assert(t->vm->system, v); } +inline void +expect(Thread* t, bool v) +{ + expect(t->vm->system, v); +} + Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): system(system), heap(heap), @@ -209,7 +219,9 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): stateLock(0), heapLock(0), classLock(0), + libraries(0), classMap(0), + bootstrapClassMap(0), types(0), unsafe(false) { @@ -227,12 +239,196 @@ Machine::dispose() stateLock->dispose(); heapLock->dispose(); classLock->dispose(); + libraries->dispose(); if (rootThread) { rootThread->dispose(); } } +uint32_t +hash(const int8_t* s, unsigned length) +{ + uint32_t h = 0; + for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i]; + return h; +} + +inline uint32_t +byteArrayHash(Thread* t, object array) +{ + return hash(&byteArrayBody(t, array, 0), byteArrayLength(t, array)); +} + +bool +byteArrayEqual(Thread* t, object a, object b) +{ + return a == b or + ((byteArrayLength(t, a) == byteArrayLength(t, b)) and + memcmp(&byteArrayBody(t, a, 0), &byteArrayBody(t, b, 0), + byteArrayLength(t, a)) == 0); +} + +bool +intArrayEqual(Thread* t, object a, object b) +{ + return a == b or + ((intArrayLength(t, a) == intArrayLength(t, b)) and + memcmp(&intArrayBody(t, a, 0), &intArrayBody(t, b, 0), + intArrayLength(t, a) * 4) == 0); +} + +inline uint32_t +methodHash(Thread* t, object method) +{ + return byteArrayHash(t, methodName(t, method)) + ^ byteArrayHash(t, methodSpec(t, method)); +} + +bool +methodEqual(Thread* t, object a, object b) +{ + return a == b or + (byteArrayEqual(t, methodName(t, a), methodName(t, b)) and + byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b))); +} + +object +hashMapFindNode(Thread* t, object map, object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + object array = hashMapArray(t, map); + if (array) { + unsigned index = hash(t, key) & (arrayLength(t, array) - 1); + object n = arrayBody(t, array, index); + while (n) { + if (equal(t, tripleFirst(t, n), key)) { + return n; + } + + n = tripleThird(t, n); + } + } + return 0; +} + +inline object +hashMapFind(Thread* t, object map, object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + object n = hashMapFindNode(t, map, key, hash, equal); + return (n ? tripleSecond(t, n) : 0); +} + +void +hashMapGrow(Thread* t, object map, uint32_t (*hash)(Thread*, object)) +{ + PROTECT(t, map); + + object oldArray = hashMapArray(t, map); + unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0); + PROTECT(t, oldArray); + + unsigned newLength = (oldLength ? oldLength * 2 : 32); + object newArray = makeArray(t, newLength, true); + + if (oldArray) { + for (unsigned i = 0; i < oldLength; ++i) { + object next; + for (object p = arrayBody(t, oldArray, i); p; p = next) { + next = tripleThird(t, p); + + object key = tripleFirst(t, p); + unsigned index = hash(t, key) & (newLength - 1); + object n = arrayBody(t, newArray, index); + + set(t, tripleThird(t, p), n); + set(t, arrayBody(t, newArray, index), p); + } + } + } + + set(t, hashMapArray(t, map), newArray); +} + +void +hashMapInsert(Thread* t, object map, object key, object value, + uint32_t (*hash)(Thread*, object)) +{ + object array = hashMapArray(t, map); + PROTECT(t, array); + + ++ hashMapSize(t, map); + + 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(t, key) & (arrayLength(t, array) - 1); + object n = arrayBody(t, array, index); + + n = makeTriple(t, key, value, n); + + 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) +{ + PROTECT(t, list); + + ++ listSize(t, list); + + object p = makePair(t, value, 0); + if (listFront(t, list)) { + set(t, pairSecond(t, listRear(t, list)), p); + } else { + set(t, listFront(t, list), p); + } + set(t, listRear(t, list), p); +} + Thread::Thread(Machine* m): vm(m), next(0), @@ -268,8 +464,9 @@ Thread::Thread(Machine* m): m->unsafe = false; m->classMap = makeHashMap(this, 0, 0); + m->bootstrapClassMap = makeHashMap(this, 0, 0); - m->bootstrapInitializers = bootstrapInitializers(this); +#include "type-java-initializations.cpp" } } @@ -326,6 +523,7 @@ collect(Machine* m, Heap::CollectionType type) virtual void visitRoots(Heap::Visitor* v) { v->visit(&(m->classMap)); + v->visit(&(m->bootstrapClassMap)); v->visit(&(m->types)); for (Thread* t = m->rootThread; t; t = t->next) { @@ -680,7 +878,7 @@ makeArrayIndexOutOfBoundsException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeArrayIndexOutOfBoundsException(t, message, trace); + return makeArrayIndexOutOfBoundsException(t, message, trace, 0); } object @@ -688,7 +886,7 @@ makeNegativeArrayStoreException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeNegativeArrayStoreException(t, message, trace); + return makeNegativeArrayStoreException(t, message, trace, 0); } object @@ -696,7 +894,7 @@ makeClassCastException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeClassCastException(t, message, trace); + return makeClassCastException(t, message, trace, 0); } object @@ -704,19 +902,19 @@ makeClassNotFoundException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeClassNotFoundException(t, message, trace); + return makeClassNotFoundException(t, message, trace, 0); } object makeNullPointerException(Thread* t) { - return makeNullPointerException(t, 0, makeTrace(t)); + return makeNullPointerException(t, 0, makeTrace(t), 0); } object makeStackOverflowError(Thread* t) { - return makeStackOverflowError(t, 0, makeTrace(t)); + return makeStackOverflowError(t, 0, makeTrace(t), 0); } object @@ -724,7 +922,7 @@ makeNoSuchFieldError(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeNoSuchFieldError(t, message, trace); + return makeNoSuchFieldError(t, message, trace, 0); } object @@ -732,7 +930,15 @@ makeNoSuchMethodError(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); - return makeNoSuchMethodError(t, message, trace); + return makeNoSuchMethodError(t, message, trace, 0); +} + +object +makeUnsatisfiedLinkError(Thread* t, object message) +{ + PROTECT(t, message); + object trace = makeTrace(t); + return makeUnsatisfiedLinkError(t, message, trace, 0); } inline bool @@ -743,7 +949,7 @@ isLongOrDouble(Thread* t, object o) } unsigned -fieldCode(unsigned javaCode) +fieldCode(Thread* t, unsigned javaCode) { switch (javaCode) { case 'B': @@ -821,7 +1027,7 @@ makePrimitive(Thread* t, unsigned code, uint64_t value) } unsigned -primitiveSize(unsigned code) +primitiveSize(Thread* t, unsigned code) { switch (code) { case ByteField: @@ -1043,179 +1249,6 @@ findMethodInClass(Thread* t, object class_, object reference) methodSpec, makeNoSuchMethodError); } -uint32_t -hash(const int8_t* s, unsigned length) -{ - uint32_t h = 0; - for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i]; - return h; -} - -inline uint32_t -byteArrayHash(Thread* t, object array) -{ - return hash(&byteArrayBody(t, array, 0), 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, 0), &byteArrayBody(t, b, 0)) == 0); -} - -inline uint32_t -methodHash(Thread* t, object method) -{ - return byteArrayHash(t, methodName(t, method)) - ^ byteArrayHash(t, methodSpec(t, method)); -} - -bool -methodEqual(Thread* t, object a, object b) -{ - return a == b or - (byteArrayEqual(t, methodName(t, a), methodName(t, b)) and - byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b))); -} - -object -hashMapFindNode(Thread* t, object map, object key, - uint32_t (*hash)(Thread*, object), - bool (*equal)(Thread*, object, object)) -{ - object array = hashMapArray(t, map); - if (array) { - unsigned index = hash(t, key) & (arrayLength(t, array) - 1); - object n = arrayBody(t, array, index); - while (n) { - if (equal(t, tripleFirst(t, n), key)) { - return n; - } - - n = tripleThird(t, n); - } - } - return 0; -} - -inline object -hashMapFind(Thread* t, object map, object key, - uint32_t (*hash)(Thread*, object), - bool (*equal)(Thread*, object, object)) -{ - object n = hashMapFindNode(t, map, key, hash, equal); - return (n ? tripleSecond(t, n) : 0); -} - -void -hashMapGrow(Thread* t, object map, uint32_t (*hash)(Thread*, object)) -{ - PROTECT(t, map); - - object oldArray = hashMapArray(t, map); - unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0); - PROTECT(t, oldArray); - - unsigned newLength = (oldLength ? oldLength * 2 : 32); - object newArray = makeArray(t, newLength, true); - - if (oldArray) { - for (unsigned i = 0; i < oldLength; ++i) { - object next; - for (object p = arrayBody(t, oldArray, i); p; p = next) { - next = tripleThird(t, p); - - object key = tripleFirst(t, p); - unsigned index = hash(t, key) & (newLength - 1); - object n = arrayBody(t, newArray, index); - - set(t, tripleThird(t, p), n); - set(t, arrayBody(t, newArray, index), p); - } - } - } - - set(t, hashMapArray(t, map), newArray); -} - -void -hashMapInsert(Thread* t, object map, object key, object value, - uint32_t (*hash)(Thread*, object)) -{ - object array = hashMapArray(t, map); - PROTECT(t, array); - - ++ hashMapSize(t, map); - - 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(t, key) & (arrayLength(t, array) - 1); - object n = arrayBody(t, array, index); - - n = makeTriple(t, key, value, n); - - 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) -{ - PROTECT(t, list); - - ++ listSize(t, list); - - object p = makePair(t, value, 0); - if (listFront(t, list)) { - set(t, pairSecond(t, listRear(t, list)), p); - } else { - set(t, listFront(t, list), p); - } - set(t, listRear(t, list), p); -} - object parsePool(Thread* t, Stream& s) { @@ -1398,7 +1431,7 @@ fieldSize(Thread* t, object field) if (code == ObjectField) { return BytesPerWord; } else { - return primitiveSize(code); + return primitiveSize(t, code); } } @@ -1431,28 +1464,28 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) s.skip(s.read4()); } - object value = makeField + object field = makeField (t, flags, 0, // offset - fieldCode(byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)), + fieldCode(t, byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)), arrayBody(t, pool, name - 1), arrayBody(t, pool, spec - 1), class_); if (flags & ACC_STATIC) { - fieldOffset(t, value) = staticOffset++; + fieldOffset(t, field) = staticOffset++; } else { unsigned excess = memberOffset % BytesPerWord; - if (excess and fieldCode(t, value) == ObjectField) { + if (excess and fieldCode(t, field) == ObjectField) { memberOffset += BytesPerWord - excess; } - fieldOffset(t, value) = memberOffset; - memberOffset += fieldSize(t, value); + fieldOffset(t, field) = memberOffset; + memberOffset += fieldSize(t, field); } - set(t, arrayBody(t, fieldTable, i), value); + set(t, arrayBody(t, fieldTable, i), field); } set(t, classFieldTable(t, class_), fieldTable); @@ -1552,14 +1585,23 @@ parameterCount(Thread* t, object spec) return count; } +object +makeJNIName(Thread* t, object method, bool decorate) +{ + // todo +} + void parseMethodTable(Thread* t, Stream& s, object class_, object pool) { PROTECT(t, class_); PROTECT(t, pool); - object map = makeHashMap(t, 0, 0); - PROTECT(t, map); + object virtualMap = makeHashMap(t, 0, 0); + PROTECT(t, virtualMap); + + object nativeMap = makeHashMap(t, 0, 0); + PROTECT(t, nativeMap); unsigned virtualCount = 0; @@ -1574,7 +1616,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) virtualCount = arrayLength(t, superVirtualTable); for (unsigned i = 0; i < virtualCount; ++i) { object method = arrayBody(t, superVirtualTable, i); - hashMapInsert(t, map, method, method, methodHash); + hashMapInsert(t, virtualMap, method, method, methodHash); } } @@ -1606,7 +1648,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } - object value = makeMethod + object method = makeMethod (t, flags, 0, // offset @@ -1615,29 +1657,51 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) arrayBody(t, pool, spec - 1), class_, code); - PROTECT(t, value); + PROTECT(t, method); if (flags & ACC_STATIC) { if (strcmp(reinterpret_cast(""), - &byteArrayBody(t, methodName(t, value), 0)) == 0) + &byteArrayBody(t, methodName(t, method), 0)) == 0) { - set(t, classInitializer(t, class_), value); + set(t, classInitializer(t, class_), method); } } else { - object p = hashMapFindNode(t, map, value, methodHash, methodEqual); + object p = hashMapFindNode + (t, virtualMap, method, methodHash, methodEqual); if (p) { - methodOffset(t, value) = methodOffset(t, tripleFirst(t, p)); + methodOffset(t, method) = methodOffset(t, tripleFirst(t, p)); - set(t, tripleSecond(t, p), value); + set(t, tripleSecond(t, p), method); } else { - methodOffset(t, value) = virtualCount++; + methodOffset(t, method) = virtualCount++; - listAppend(t, newVirtuals, value); + listAppend(t, newVirtuals, method); } } - set(t, arrayBody(t, methodTable, i), value); + if (flags & ACC_NATIVE) { + object p = hashMapFindNode + (t, nativeMap, method, methodHash, methodEqual); + + if (p == 0) { + hashMapInsert(t, virtualMap, method, method, methodHash); + } + } + + set(t, arrayBody(t, methodTable, i), method); + } + + for (unsigned i = 0; i < count; ++i) { + object method = arrayBody(t, methodTable, i); + + if (methodFlags(t, method) & ACC_NATIVE) { + object p = hashMapFindNode + (t, nativeMap, method, methodHash, methodEqual); + + object jniName = makeJNIName(t, method, p != 0); + set(t, methodCode(t, method), jniName); + } } set(t, classMethodTable(t, class_), methodTable); @@ -1652,7 +1716,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) if (superVirtualTable) { for (; i < arrayLength(t, superVirtualTable); ++i) { object method = arrayBody(t, superVirtualTable, i); - method = hashMapFind(t, map, method, methodHash, methodEqual); + method = hashMapFind(t, virtualMap, method, methodHash, methodEqual); set(t, arrayBody(t, vtable, i), method); } @@ -1676,7 +1740,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) for (unsigned j = 0; j < arrayLength(t, methodTable); ++j) { object method = arrayBody(t, methodTable, j); - method = hashMapFind(t, map, method, methodHash, methodEqual); + method = hashMapFind(t, virtualMap, method, methodHash, methodEqual); set(t, arrayBody(t, vtable, j), method); } @@ -1747,6 +1811,29 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) return class_; } +void +updateBootstrapClass(Thread* t, object bootstrapClass, object class_) +{ + expect(t, bootstrapClass != 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, (classObjectMask(t, bootstrapClass) == 0 + and classObjectMask(t, class_) == 0) + or intArrayEqual(t, classObjectMask(t, bootstrapClass), + classObjectMask(t, class_))); + + PROTECT(t, bootstrapClass); + PROTECT(t, class_); + + enter(t, Thread::ExclusiveState); + + memcpy(bootstrapClass, class_, objectSize(t, class_)); + + enter(t, Thread::ActiveState); +} + object resolveClass(Thread* t, object spec) { @@ -1772,10 +1859,13 @@ resolveClass(Thread* t, object spec) PROTECT(t, class_); - object initializer = hashMapFind - (t, t->vm->bootstrapInitializers, spec, byteArrayHash, byteArrayEqual); - if (initializer) { - static_cast(pointerValue(t, initializer))(t, class_); + object bootstrapClass = hashMapFind + (t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); + if (bootstrapClass) { + PROTECT(t, bootstrapClass); + + updateBootstrapClass(t, bootstrapClass, class_); + class_ = bootstrapClass; } hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); @@ -1854,7 +1944,7 @@ resolveNativeMethodData(Thread* t, object method) if (objectClass(methodCode(t, method)) == arrayBody(t, t->vm->types, Machine::ByteArrayType)) { - for (System::Library lib = t->vm->libraries; lib; lib = lib->next()) { + for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) { void* p = lib->resolve(reinterpret_cast (&byteArrayBody(t, methodCode(t, method), 0))); if (p) { @@ -1864,7 +1954,7 @@ resolveNativeMethodData(Thread* t, object method) p, 0, // argument table size 0, // return code - parameterCount, + methodParameterCount(t, method), false); unsigned argumentTableSize = 0; @@ -1873,7 +1963,7 @@ resolveNativeMethodData(Thread* t, object method) (&byteArrayBody(t, methodSpec(t, method), 0)); ++ s; // skip '(' while (*s and *s != ')') { - unsigned code = fieldCode(*s); + unsigned code = fieldCode(t, *s); nativeMethodDataParameterCodes(t, data, index++) = code; switch (*s) { @@ -1889,14 +1979,14 @@ resolveNativeMethodData(Thread* t, object method) break; default: - argumentTableSize += divide(primitiveSize(code), 4); + argumentTableSize += divide(primitiveSize(t, code), 4); ++ s; break; } } nativeMethodDataArgumentTableSize(t, data) = argumentTableSize; - nativeMethodReturnCode(t, data) = fieldCode(s[1]); + nativeMethodDataReturnCode(t, data) = fieldCode(t, s[1]); set(t, methodCode(t, method), data); return data; @@ -1909,28 +1999,6 @@ resolveNativeMethodData(Thread* t, object method) } } -void -bsiVM(Thread* t, object class_) -{ - // todo -} - -object -bootstrapInitializers(Thread* t) -{ - object map = makeHashMap(t, 0, 0); - PROTECT(t, map); - object key = 0; - PROTECT(t, key); - object value; - - key = makeByteArray(t, "vm/VM"); - value = makePointer(t, bsiVM); - hashMapInsert(t, map, key, value, hashByteArray); - - return map; -} - object run(Thread* t) { @@ -3291,83 +3359,83 @@ run(Thread* t) default: abort(t); } - invoke: - if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + sp - parameterCount - > Thread::StackSizeInWords)) - { - exception = makeStackOverflowError(t); - goto throw_; - } - - unsigned base = sp - parameterCount; - - if (methodFlags(t, code) & ACC_NATIVE) { - object data = resolveNativeMethodData(t, code); - if (UNLIKELY(data == 0)) { - object message = makeString - (t, "%s.%s:%s", - &byteArrayBody(t, className(t, methodClass(t, code)), 0), - &byteArrayBody(t, methodName(t, code), 0), - &byteArrayBody(t, methodSpec(t, code), 0)); - exception = makeUnsatifiedLinkError(t, message); - goto throw_; + invoke: { + if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + sp - parameterCount + > Thread::StackSizeInWords)) + { + exception = makeStackOverflowError(t); + goto throw_; } + + unsigned base = sp - parameterCount; - uint32_t* args[nativeMethodDataArgumentTableSize(t, data)]; - uint8_t sizes[parameterCount]; - unsigned offset = 0; - for (unsigned i = 0; i < parameterCount; ++i) { - unsigned code = nativeMethodDataParameterCodes(t, data); + if (methodFlags(t, code) & ACC_NATIVE) { + object data = resolveNativeMethodData(t, code); + if (UNLIKELY(data == 0)) { + object message = makeString + (t, "%s.%s:%s", + &byteArrayBody(t, className(t, methodClass(t, code)), 0), + &byteArrayBody(t, methodName(t, code), 0), + &byteArrayBody(t, methodSpec(t, code), 0)); + exception = makeUnsatisfiedLinkError(t, message); + goto throw_; + } - if (code == ObjectField) { - size[i] = 4; - args[offset++] = sp + i + 1; - } else { - size[i] = primitiveSize(code); - uint64_t v = primitiveValue(t, code, stack[sp + i]); - if (size[i] == 8) { - args[offset++] = v & 0xFFFFFFFF; - args[offset++] = v >> 32; + uint32_t args[nativeMethodDataArgumentTableSize(t, data)]; + uint8_t sizes[parameterCount]; + unsigned offset = 0; + for (unsigned i = 0; i < parameterCount; ++i) { + unsigned code = nativeMethodDataParameterCodes(t, data, i); + + if (code == ObjectField) { + sizes[i] = 4; + args[offset++] = sp + i + 1; } else { - args[offset++] = v; + sizes[i] = primitiveSize(t, code); + uint64_t v = primitiveValue(t, code, stack[sp + i]); + if (sizes[i] == 8) { + args[offset++] = static_cast(v & 0xFFFFFFFF); + args[offset++] = static_cast(v >> 32); + } else { + args[offset++] = v; + } } } - } - unsigned returnCode = nativeMethodDataReturnCode(t, data); - unsigned returnSize - = (code == ObjectField ? 4 : primitiveSize(returnCode)); + unsigned returnCode = nativeMethodDataReturnCode(t, data); + unsigned returnSize + = (returnCode == ObjectField ? 4 : primitiveSize(t, returnCode)); - uint64_t rv = t->vm->system->call(nativeMethodDataPointer(t, data), - parameterCount, - args, - sizes, - returnSize); + uint64_t rv = t->vm->system->call(nativeMethodDataPointer(t, data), + parameterCount, + args, + sizes, + returnSize); - sp = base; + sp = base; - if (returnCode == ObjectField) { - push(t, (rv == 0 ? 0 : stack[rv - 1])); + if (returnCode == ObjectField) { + push(t, (rv == 0 ? 0 : stack[rv - 1])); + } else { + push(t, makePrimitive(t, returnCode, rv)); + } } else { - push(t, makePrimitive(t, returnCode, rv)); + frameIp(t, frame) = ip; + ip = 0; + + frame = makeFrame(t, code, frame, 0, base, + codeMaxLocals(t, methodCode(t, code)), false); + code = methodCode(t, code); + + memcpy(&frameLocals(t, frame, 0), stack + base, + parameterCount * BytesPerWord); + + memset(&frameLocals(t, frame, 0) + parameterCount, 0, + (frameLength(t, frame) - parameterCount) * BytesPerWord); + + sp = base; } - } else { - frameIp(t, frame) = ip; - ip = 0; - - frame = makeFrame(t, code, frame, 0, base, - codeMaxLocals(t, methodCode(t, code)), false); - code = methodCode(t, code); - - memcpy(&frameLocals(t, frame, 0), stack + base, - parameterCount * BytesPerWord); - - memset(&frameLocals(t, frame, 0) + parameterCount, 0, - (frameLength(t, frame) - parameterCount) * BytesPerWord); - - sp = base; - } - goto loop; + } goto loop; throw_: for (; frame; frame = frameNext(t, frame)) { @@ -3394,26 +3462,28 @@ run(Thread* t) } } - if (t->thread) { - object method = threadExceptionHandler(t, t->thread); - code = methodCode(t, method); - frame = makeFrame(t, method, 0, 0, 0, codeMaxLocals(t, code), true); - sp = 0; - ip = 0; - push(t, exception); - exception = 0; - goto loop; - } else if (Debug) { - object p = 0; - object n = 0; - for (object trace = throwableTrace(t, exception); trace; trace = n) { - n = traceNext(t, trace); - set(t, traceNext(t, trace), p); - p = trace; + object p = 0; + object n = 0; + for (object trace = throwableTrace(t, exception); trace; trace = n) { + n = traceNext(t, trace); + set(t, traceNext(t, trace), p); + p = trace; + } + + for (object e = exception; e; e = throwableCause(t, e)) { + if (e == exception) { + fprintf(stderr, "uncaught exception: "); + } else { + fprintf(stderr, "caused by: "); } - fprintf(stderr, "uncaught exception: %s\n", &byteArrayBody - (t, stringBytes(t, throwableMessage(t, exception)), 0)); + fprintf(stderr, "%s", &byteArrayBody + (t, className(t, objectClass(exception)), 0)); + + if (throwableMessage(t, exception)) { + fprintf(stderr, ": %s\n", &byteArrayBody + (t, stringBytes(t, throwableMessage(t, exception)), 0)); + } for (; p; p = traceNext(t, p)) { fprintf(stderr, " at %s\n", &byteArrayBody @@ -3421,7 +3491,7 @@ run(Thread* t) } } - abort(t); + return 0; } void