From 95c4bff51b96926b049c28394b1bcb23172f970c Mon Sep 17 00:00:00 2001 From: Joel Dice <git@seibutsu.mailsnare.net> Date: Wed, 20 Jun 2007 19:38:02 -0600 Subject: [PATCH] lots of bugfixes --- makefile | 37 ++-- src/constants.h | 389 +++++++++++++++++++++-------------------- src/main.cpp | 29 ++- src/type-generator.cpp | 13 +- src/vm.cpp | 377 +++++++++++++++++++++++++-------------- 5 files changed, 498 insertions(+), 347 deletions(-) diff --git a/makefile b/makefile index cac6103639..80d08df336 100644 --- a/makefile +++ b/makefile @@ -8,6 +8,7 @@ cxx = g++ cc = gcc vg = nice valgrind --leak-check=full --num-callers=32 --db-attach=yes \ --freelist-vol=100000000 +javac = javac warnings = -Wall -Wextra -Werror -Wold-style-cast -Wunused-parameter \ -Winit-self -Wconversion @@ -51,7 +52,6 @@ interpreter-sources = \ $(src)/main.cpp interpreter-objects = $(call cpp-objects,$(interpreter-sources),$(src)) interpreter-cflags = $(slow) $(cflags) -input = Test generator-headers = \ $(src)/input.h \ @@ -74,32 +74,42 @@ fast-objects = $(patsubst $(bld)/%,$(bld)/fast-%,$(interpreter-objects)) fast-executable = $(bld)/fast-vm fast-cflags = $(fast) $(cflags) +input = $(bld)/classes/Test.class +input-depends = \ + $(bld)/classes/java/lang/Object.class \ + $(bld)/classes/java/lang/Class.class \ + $(bld)/classes/vm/VM.class + +gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:') + .PHONY: build build: $(executable) +$(input): $(input-depends) + .PHONY: run -run: $(executable) - $(<) $(input) +run: $(executable) $(input) + $(<) -cp $(bld)/classes $(call gen-run-arg,$(input)) .PHONY: debug -debug: $(executable) - gdb --args $(<) $(input) +debug: $(executable) $(input) + gdb --args $(<) -cp $(bld)/classes $(call gen-run-arg,$(input)) .PHONY: fast fast: $(fast-executable) ls -lh $(<) .PHONY: vg -vg: $(executable) - $(vg) $(<) $(input) +vg: $(executable) $(input) + $(vg) $(<) -cp $(bld)/classes $(call gen-run-arg,$(input)) .PHONY: test -test: $(test-executable) - $(vg) $(<) $(input) +test: $(test-executable) $(input) + $(vg) $(<) -cp $(bld)/classes $(call gen-run-arg,$(input)) .PHONY: stress -stress: $(stress-executable) - $(vg) $(<) $(input) +stress: $(stress-executable) $(input) + $(vg) $(<) -cp $(bld)/classes $(call gen-run-arg,$(input)) .PHONY: run-all run-all: $(executable) @@ -136,6 +146,11 @@ $(bld)/fast-vm.o: \ $(bld)/type-generator.o: \ $(generator-headers) +$(bld)/classes/%.class: $(inp)/%.java + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(javac) -bootclasspath $(inp) -classpath $(inp) -d $(bld)/classes $(<) + $(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp @echo "compiling $(@)" @mkdir -p $(dir $(@)) diff --git a/src/constants.h b/src/constants.h index 4307fc0598..def9058369 100644 --- a/src/constants.h +++ b/src/constants.h @@ -4,191 +4,210 @@ namespace vm { enum OpCode { - aaload, - aastore, - aconst_null, - aload, - aload_0, - aload_1, - aload_2, - aload_3, - anewarray, - areturn, - arraylength, - astore, - astore_0, - astore_1, - astore_2, - astore_3, - athrow, - baload, - bastore, - bipush, - breakpoint, - caload, - castore, - checkcast, - d2f, - d2i, - d2l, - dadd, - daload, - dastore, - dcmpg, - dcmpl, - dconst, - ddiv, - dload, - dmul, - dneg, - drem, - dreturn, - dstore, - dsub, - dup, - dup_x1, - dup_x2, - dup2, - dup2_x1, - dup2_x2, - f2d, - f2i, - f2l, - fadd, - faload, - fastore, - fcmpg, - fcmpl, - fconst, - fdiv, - fload, - fmul, - fneg, - frem, - freturn, - fstore, - fsub, - getfield, - getstatic, - goto_, - goto_w, - i2b, - i2c, - i2d, - i2f, - i2l, - i2s, - iadd, - iaload, - iand, - iastore, - iconst_0, - iconst_1, - iconst_2, - iconst_3, - iconst_4, - iconst_5, - idiv, - if_, - if_acmpeq, - if_acmpne, - if_icmpeq, - if_icmpne, - if_icmpgt, - if_icmpge, - if_icmplt, - if_icmple, - ifeq, - ifge, - ifgt, - ifle, - iflt, - ifne, - ifnonnull, - ifnull, - iinc, - iload, - iload_0, - iload_1, - iload_2, - iload_3, - impdep1, - impdep2, - imul, - ineg, - instanceof, - invokeinterface, - invokespecial, - invokestatic, - invokevirtual, - ior, - irem, - ireturn, - ishl, - ishr, - istore, - istore_0, - istore_1, - istore_2, - istore_3, - isub, - iushr, - ixor, - jsr, - jsr_w, - l2d, - l2f, - l2i, - ladd, - laload, - land, - lastore, - lcmp, - lconst_0, - lconst_1, - ldc, - ldc_w, - ldc2_w, - ldiv, - lload, - lload_0, - lload_1, - lload_2, - lload_3, - lmul, - lneg, - lookupswitch, - lor, - lrem, - lreturn, - lshl, - lshr, - lstore, - lstore_0, - lstore_1, - lstore_2, - lstore_3, - lsub, - lushr, - lxor, - monitorenter, - monitorexit, - multianewarray, - new_, - newarray, - nop, - pop, - pop2, - putfield, - putstatic, - ret, - return_, - saload, - sastore, - sipush, - swap, - tableswitch, - wide + aaload = 0x32, + aastore = 0x53, + aconst_null = 0x01, + aload = 0x19, + aload_0 = 0x2a, + aload_1 = 0x2b, + aload_2 = 0x2c, + aload_3 = 0x2d, + anewarray = 0xbd, + areturn = 0xb0, + arraylength = 0xbe, + astore = 0x3a, + astore_0 = 0x4b, + astore_1 = 0x4c, + astore_2 = 0x4d, + astore_3 = 0x4e, + athrow = 0xbf, + baload = 0x33, + bastore = 0x54, + bipush = 0x10, + breakpoint = 0xca, + caload = 0x34, + castore = 0x55, + checkcast = 0xc0, + d2f = 0x90, + d2i = 0x8e, + d2l = 0x8f, + dadd = 0x63, + daload = 0x31, + dastore = 0x52, + dcmpg = 0x98, + dcmpl = 0x97, + dconst_0 = 0x0e, + dconst_1 = 0x0f, + ddiv = 0x6f, + dload = 0x18, + dload_0 = 0x26, + dload_1 = 0x27, + dload_2 = 0x28, + dload_3 = 0x29, + dmul = 0x6b, + dneg = 0x77, + drem = 0x73, + dreturn = 0xaf, + dstore = 0x39, + dstore_0 = 0x47, + dstore_1 = 0x48, + dstore_2 = 0x49, + dstore_3 = 0x4a, + dsub = 0x67, + dup = 0x59, + dup_x1 = 0x5a, + dup_x2 = 0x5b, + dup2 = 0x5c, + dup2_x1 = 0x5d, + dup2_x2 = 0x5e, + f2d = 0x8d, + f2i = 0x8b, + f2l = 0x8c, + fadd = 0x62, + faload = 0x30, + fastore = 0x51, + fcmpg = 0x96, + fcmpl = 0x95, + fconst_0 = 0x0b, + fconst_1 = 0x0c, + fconst_2 = 0x0d, + fdiv = 0x6e, + fload = 0x17, + fload_0 = 0x22, + fload_1 = 0x23, + fload_2 = 0x24, + fload_3 = 0x25, + fmul = 0x6a, + fneg = 0x76, + frem = 0x72, + freturn = 0xae, + fstore = 0x38, + fstore_0 = 0x43, + fstore_1 = 0x44, + fstore_2 = 0x45, + fstore_3 = 0x46, + fsub = 0x66, + getfield = 0xb4, + getstatic = 0xb2, + goto_ = 0xa7, + goto_w = 0xc8, + i2b = 0x91, + i2c = 0x92, + i2d = 0x87, + i2f = 0x86, + i2l = 0x85, + i2s = 0x93, + iadd = 0x60, + iaload = 0x2e, + iand = 0x73, + iastore = 0x4f, + iconst_m1 = 0x02, + iconst_0 = 0x03, + iconst_1 = 0x04, + iconst_2 = 0x05, + iconst_3 = 0x06, + iconst_4 = 0x07, + iconst_5 = 0x08, + idiv = 0x6c, + if_acmpeq = 0xa5, + if_acmpne = 0xa6, + if_icmpeq = 0x9f, + if_icmpne = 0xa0, + if_icmpgt = 0xa1, + if_icmpge = 0xa2, + if_icmplt = 0xa3, + if_icmple = 0xa4, + ifeq = 0x99, + ifge = 0x9c, + ifgt = 0x9d, + ifle = 0x9e, + iflt = 0x9b, + ifne = 0x9a, + ifnonnull = 0xc7, + ifnull = 0xc6, + iinc = 0x84, + iload = 0x15, + iload_0 = 0x1a, + iload_1 = 0x1b, + iload_2 = 0x1c, + iload_3 = 0x1d, + impdep1 = 0xfe, + impdep2 = 0xff, + imul = 0x68, + ineg = 0x74, + instanceof = 0xc1, + invokeinterface = 0xb9, + invokespecial = 0xb7, + invokestatic = 0xb8, + invokevirtual = 0xb6, + ior = 0x80, + irem = 0x70, + ireturn = 0xac, + ishl = 0x78, + ishr = 0x7a, + istore = 0x36, + istore_0 = 0x3b, + istore_1 = 0x3c, + istore_2 = 0x3d, + istore_3 = 0x3e, + isub = 0x64, + iushr = 0x7c, + ixor = 0x82, + jsr = 0xa8, + jsr_w = 0xc9, + l2d = 0x8a, + l2f = 0x89, + l2i = 0x88, + ladd = 0x61, + laload = 0x2f, + land = 0x7f, + lastore = 0x50, + lcmp = 0x94, + lconst_0 = 0x09, + lconst_1 = 0x0a, + ldc = 0x12, + ldc_w = 0x13, + ldc2_w = 0x14, + ldiv = 0x6d, + lload = 0x16, + lload_0 = 0x1e, + lload_1 = 0x1f, + lload_2 = 0x20, + lload_3 = 0x21, + lmul = 0x69, + lneg = 0x75, + lookupswitch = 0xab, + lor = 0x81, + lrem = 0x71, + lreturn = 0xad, + lshl = 0x79, + lshr = 0x7b, + lstore = 0x37, + lstore_0 = 0x3f, + lstore_1 = 0x40, + lstore_2 = 0x41, + lstore_3 = 0x42, + lsub = 0x65, + lushr = 0x7d, + lxor = 0x83, + monitorenter = 0xc2, + monitorexit = 0xc3, + multianewarray = 0xc5, + new_ = 0xbb, + newarray = 0xbc, + nop = 0x00, + pop = 0x57, + pop2 = 0x58, + putfield = 0xb5, + putstatic = 0xb3, + ret = 0xa9, + return_ = 0xb1, + saload = 0x35, + sastore = 0x56, + sipush = 0x11, + swap = 0x5f, + tableswitch = 0xaa, + wide = 0xc4 }; enum TypeCode { diff --git a/src/main.cpp b/src/main.cpp index 8679a28c65..49d07dec4c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,13 +42,19 @@ class System: public vm::System { if (up == 0) abort(); *up = *size; + count += *up; + return up + 1; } virtual void free(const void* p) { if (p) { const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1; + if (count < *up) { + abort(); + } count -= *up; + ::free(const_cast<uintptr_t*>(up)); } } @@ -71,15 +77,18 @@ class System: public vm::System { }; const char* -append(vm::System* s, const char* a, const char* b, const char* c) +append(vm::System* s, const char* a, const char* b, const char* c, + const char* d) { unsigned al = strlen(a); unsigned bl = strlen(b); unsigned cl = strlen(c); - char* p = static_cast<char*>(s->allocate(al + bl + cl + 1)); + unsigned dl = strlen(d); + char* p = static_cast<char*>(s->allocate(al + bl + cl + dl + 1)); memcpy(p, a, al); memcpy(p + al, b, bl); - memcpy(p + al + bl, c, cl + 1); + memcpy(p + al + bl, c, cl); + memcpy(p + al + bl + cl, d, dl + 1); return p; } @@ -92,7 +101,8 @@ class ClassFinder: public vm::ClassFinder { class Data: public vm::ClassFinder::Data { public: - Data(uint8_t* start, size_t length): + Data(vm::System* system, uint8_t* start, size_t length): + system(system), start_(start), length_(length) { } @@ -109,18 +119,22 @@ class ClassFinder: public vm::ClassFinder { if (start_) { munmap(start_, length_); } + system->free(this); } + vm::System* system; uint8_t* start_; size_t length_; }; virtual Data* find(const char* className) { - Data* d = new (system->allocate(sizeof(Data))) Data(0, 0); + Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0); for (const char** p = path; *p; ++p) { - const char* file = append(system, *p, "/", className); + const char* file = append(system, *p, "/", className, ".class"); int fd = open(file, O_RDONLY); + system->free(file); + if (fd != -1) { struct stat s; int r = fstat(fd, &s); @@ -133,7 +147,6 @@ class ClassFinder: public vm::ClassFinder { } } } - system->free(file); } system->free(d); @@ -183,7 +196,7 @@ parsePath(vm::System* s, const char* path) unsigned i = 0; for (Tokenizer t(path, ':'); t.hasMore(); ++i) { Tokenizer::Token token(t.next()); - char* p = static_cast<char*>(s->allocate(token.length)); + char* p = static_cast<char*>(s->allocate(token.length + 1)); memcpy(p, token.s, token.length); p[token.length] = 0; v[i] = p; diff --git a/src/type-generator.cpp b/src/type-generator.cpp index a030ad529a..4b7f6ec8d1 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1492,19 +1492,14 @@ writeInitializations(Output* out, Object* declarations) out->write("t->vm->types = allocate(t, pad(("); out->write(count); - out->write(" * "); - out->write(sizeof(void*)); - out->write(") + 4 + "); - out->write(sizeof(void*)); - out->write("));\n"); + out->write(" * sizeof(void*)) + 4 + sizeof(void*)));\n"); out->write("objectClass(t->vm->types) = 0;\n"); out->write("arrayLength(t, t->vm->types) = "); out->write(count); out->write(";\n"); - - out->write("t->vm->types = makeArray(t, "); - out->write(typeCount(declarations)); - out->write(");\n\n"); + out->write("memset(&arrayBody(t, t->vm->types, 0), 0, "); + out->write(count); + out->write(" * sizeof(void*));\n\n"); for (Object* p = declarations; p; p = cdr(p)) { Object* o = car(p); diff --git a/src/vm.cpp b/src/vm.cpp index 21f6695d4f..f3a37f024a 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -16,6 +16,8 @@ using namespace vm; namespace { +static const bool Debug = true; + class Thread; void assert(Thread*, bool); @@ -291,6 +293,8 @@ collect(Machine* m, Heap::CollectionType type) Machine* m; } it(m); + fprintf(stderr, "collection time!\n"); + m->heap->collect(type, &it); } @@ -759,18 +763,19 @@ find(Thread* t, object class_, object table, object reference, object n = referenceName(t, reference); object s = referenceSpec(t, reference); for (unsigned i = 0; i < arrayLength(t, table); ++i) { - object field = arrayBody(t, table, i); - if (strcmp(&byteArrayBody(t, name(t, field), 0), + object o = arrayBody(t, table, i); + + if (strcmp(&byteArrayBody(t, name(t, o), 0), &byteArrayBody(t, n, 0)) == 0 and - strcmp(&byteArrayBody(t, spec(t, field), 0), + strcmp(&byteArrayBody(t, spec(t, o), 0), &byteArrayBody(t, s, 0)) == 0) { - return field; + return o; } } object message = makeString - (t, "%s (%s) not found in %s", + (t, "%s:%s not found in %s", &byteArrayBody(t, n, 0), &byteArrayBody(t, s, 0), &byteArrayBody(t, className(t, class_), 0)); @@ -966,6 +971,126 @@ listAppend(Thread* t, object list, object value) set(t, listRear(t, list), p); } +object +parsePool(Thread* t, Stream& s) +{ + unsigned poolCount = s.read2() - 1; + object pool = makeArray(t, poolCount); + PROTECT(t, pool); + + for (unsigned i = 0; i < poolCount; ++i) { + unsigned c = s.read1(); + + switch (c) { + case CONSTANT_Integer: { + object value = makeInt(t, s.read4()); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Float: { + object value = makeFloat(t, s.readFloat()); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Long: { + object value = makeLong(t, s.read8()); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Double: { + object value = makeLong(t, s.readDouble()); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Utf8: { + unsigned length = s.read2(); + object value = makeByteArray(t, length + 1); + s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, value, 0)), length); + byteArrayBody(t, value, length) = 0; + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Class: { + object value = makeIntArray(t, 2); + intArrayBody(t, value, 0) = c; + intArrayBody(t, value, 1) = s.read2(); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_String: { + object value = makeIntArray(t, 2); + intArrayBody(t, value, 0) = c; + intArrayBody(t, value, 1) = s.read2(); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_NameAndType: { + object value = makeIntArray(t, 3); + intArrayBody(t, value, 0) = c; + intArrayBody(t, value, 1) = s.read2(); + intArrayBody(t, value, 2) = s.read2(); + set(t, arrayBody(t, pool, i), value); + } break; + + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: { + object value = makeIntArray(t, 3); + intArrayBody(t, value, 0) = c; + intArrayBody(t, value, 1) = s.read2(); + intArrayBody(t, value, 2) = s.read2(); + set(t, arrayBody(t, pool, i), value); + } break; + + default: abort(t); + } + } + + for (unsigned i = 0; i < poolCount; ++i) { + object o = arrayBody(t, pool, i); + if (objectClass(o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) { + switch (intArrayBody(t, o, 0)) { + case CONSTANT_Class: { + set(t, arrayBody(t, pool, i), + 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), 0); + set(t, arrayBody(t, pool, i), 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, arrayBody(t, pool, i), value); + } break; + } + } + } + + for (unsigned i = 0; i < poolCount; ++i) { + object o = arrayBody(t, pool, i); + if (objectClass(o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) { + switch (intArrayBody(t, o, 0)) { + 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, arrayBody(t, pool, i), value); + } break; + } + } + } + + return pool; +} + void parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) { @@ -975,17 +1100,21 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) object map = makeHashMap(t, 0, 0); PROTECT(t, map); - object superInterfaces = classInterfaceTable(t, classSuper(t, class_)); - PROTECT(t, superInterfaces); + 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); + for (unsigned i = 0; i < arrayLength(t, superInterfaces); i += 2) { + object name = interfaceName(t, arrayBody(t, superInterfaces, i)); + hashMapInsert(t, map, name, name, byteArrayHash); + } + } } unsigned count = s.read2(); for (unsigned i = 0; i < count; ++i) { - object name = arrayBody(t, pool, s.read2()); + object name = arrayBody(t, pool, s.read2() - 1); hashMapInsert(t, map, name, name, byteArrayHash); } @@ -1060,8 +1189,13 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) unsigned count = s.read2(); if (count) { - unsigned memberOffset - = classFixedSize(t, classSuper(t, class_)) * BytesPerWord; + fprintf(stderr, "%d fields\n", count); + + unsigned memberOffset = BytesPerWord; + if (classSuper(t, class_)) { + memberOffset= classFixedSize(t, classSuper(t, class_)) * BytesPerWord; + } + unsigned staticOffset = 0; object fieldTable = makeArray(t, count); @@ -1081,8 +1215,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) object value = makeField(t, flags, 0, // offset - arrayBody(t, pool, name), - arrayBody(t, pool, spec), + arrayBody(t, pool, name - 1), + arrayBody(t, pool, spec - 1), class_); if (flags & ACC_STATIC) { @@ -1185,14 +1319,18 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) unsigned virtualCount = 0; - object superVirtualTable = classVirtualTable(t, classSuper(t, class_)); + object superVirtualTable = 0; PROTECT(t, superVirtualTable); + if (classSuper(t, class_)) { + superVirtualTable = classVirtualTable(t, classSuper(t, class_)); + } + if (superVirtualTable) { virtualCount = arrayLength(t, superVirtualTable); for (unsigned i = 0; i < virtualCount; ++i) { object method = arrayBody(t, superVirtualTable, i); - hashMapInsert(t, map, method, method, byteArrayHash); + hashMapInsert(t, map, method, method, methodHash); } } @@ -1212,7 +1350,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()); + object name = arrayBody(t, pool, s.read2() - 1); unsigned length = s.read4(); if (strcmp(reinterpret_cast<const int8_t*>("Code"), @@ -1224,14 +1362,15 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } - object value = makeMethod(t, - flags, - 0, // offset - parameterCount(t, arrayBody(t, pool, spec)), - arrayBody(t, pool, name), - arrayBody(t, pool, spec), - class_, - code); + object value = makeMethod + (t, + flags, + 0, // offset + parameterCount(t, arrayBody(t, pool, spec - 1)), + arrayBody(t, pool, name - 1), + arrayBody(t, pool, spec - 1), + class_, + code); PROTECT(t, value); if (flags & ACC_STATIC) { @@ -1265,18 +1404,18 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) object vtable = makeArray(t, virtualCount); + unsigned i = 0; if (superVirtualTable) { - unsigned i = 0; for (; i < arrayLength(t, superVirtualTable); ++i) { object method = arrayBody(t, superVirtualTable, i); method = hashMapFind(t, map, method, methodHash, methodEqual); 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)); - } + for (object p = listFront(t, newVirtuals); p; p = pairSecond(t, p)) { + set(t, arrayBody(t, vtable, i++), pairFirst(t, p)); } set(t, classVirtualTable(t, class_), vtable); @@ -1284,17 +1423,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) // generate interface vtables object itable = classInterfaceTable(t, class_); - PROTECT(t, itable); + if (itable) { + PROTECT(t, itable); - for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { - object methodTable = interfaceMethodTable(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, map, method, methodHash, methodEqual); - - set(t, arrayBody(t, vtable, j), method); + for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { + object methodTable = interfaceMethodTable(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, map, method, methodHash, methodEqual); + + set(t, arrayBody(t, vtable, j), method); + } } } } @@ -1322,70 +1463,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) s.read2(); // minor version s.read2(); // major version - unsigned poolCount = s.read2(); - object pool = makeArray(t, poolCount); - PROTECT(t, pool); - - for (unsigned i = 0; i < poolCount; ++i) { - switch (s.read1()) { - case CONSTANT_Class: { - set(t, arrayBody(t, pool, i), arrayBody(t, pool, s.read2())); - } break; - - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: { - object c = arrayBody(t, pool, s.read2()); - object nameAndType = arrayBody(t, pool, s.read2()); - object value = makeReference - (t, c, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_String: { - object bytes = arrayBody(t, pool, s.read2()); - object value = makeString(t, bytes, 0, byteArrayLength(t, bytes), 0); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_Integer: { - object value = makeInt(t, s.read4()); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_Float: { - object value = makeFloat(t, s.readFloat()); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_Long: { - object value = makeLong(t, s.read8()); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_Double: { - object value = makeLong(t, s.readDouble()); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_NameAndType: { - object name = arrayBody(t, pool, s.read2()); - object type = arrayBody(t, pool, s.read2()); - object value = makePair(t, name, type); - set(t, arrayBody(t, pool, i), value); - } break; - - case CONSTANT_Utf8: { - unsigned length = s.read2(); - object value = makeByteArray(t, length + 1); - s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, value, 0)), length); - byteArrayBody(t, value, length) = 0; - set(t, arrayBody(t, pool, i), value); - } break; - - default: abort(t); - } - } + object pool = parsePool(t, s); unsigned flags = s.read2(); unsigned name = s.read2(); @@ -1395,7 +1473,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) 0, // fixed size 0, // array size 0, // object mask - arrayBody(t, pool, name), + arrayBody(t, pool, name - 1), 0, // super 0, // interfaces 0, // vtable @@ -1405,10 +1483,13 @@ parseClass(Thread* t, const uint8_t* data, unsigned size) 0); // initializer PROTECT(t, class_); - object super = resolveClass(t, arrayBody(t, pool, s.read2())); - if (UNLIKELY(t->exception)) return 0; + unsigned super = s.read2(); + if (super) { + object sc = resolveClass(t, arrayBody(t, pool, super - 1)); + if (UNLIKELY(t->exception)) return 0; - set(t, classSuper(t, class_), super); + set(t, classSuper(t, class_), sc); + } parseInterfaceTable(t, s, class_, pool); if (UNLIKELY(t->exception)) return 0; @@ -1435,10 +1516,16 @@ resolveClass(Thread* t, object spec) (reinterpret_cast<const char*>(&byteArrayBody(t, spec, 0))); if (data) { + fprintf(stderr, "parsing %s\n", &byteArrayBody + (t, spec, 0)); + // parse class file class_ = parseClass(t, data->start(), data->length()); data->dispose(); + fprintf(stderr, "done parsing %s\n", &byteArrayBody + (t, className(t, class_), 0)); + PROTECT(t, class_); hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash); @@ -1614,7 +1701,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object class_ = resolveClass(t, codePool(t, code), index); + object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object array = makeObjectArray(t, class_, c); @@ -1804,7 +1891,7 @@ run(Thread* t) if (stack[sp - 1]) { uint16_t index = (index1 << 8) | index2; - object class_ = resolveClass(t, codePool(t, code), index); + object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; if (not instanceOf(t, class_, stack[sp - 1])) { @@ -1915,7 +2002,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object field = resolveField(t, codePool(t, code), index); + object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; push(t, getField(t, instance, field)); @@ -1930,7 +2017,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object field = resolveField(t, codePool(t, code), index); + object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object clinit = classInitializer(t, fieldClass(t, field)); @@ -2288,7 +2375,7 @@ run(Thread* t) if (stack[sp - 1]) { uint16_t index = (index1 << 8) | index2; - object class_ = resolveClass(t, codePool(t, code), index); + object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; if (instanceOf(t, class_, stack[sp - 1])) { @@ -2308,7 +2395,7 @@ run(Thread* t) ip += 2; - object method = resolveMethod(t, codePool(t, code), index); + object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; parameterCount = methodParameterCount(t, method); @@ -2328,7 +2415,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object method = resolveMethod(t, codePool(t, code), index); + object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; parameterCount = methodParameterCount(t, method); @@ -2353,7 +2440,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object method = resolveMethod(t, codePool(t, code), index); + object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object clinit = classInitializer(t, methodClass(t, method)); @@ -2374,7 +2461,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object method = resolveMethod(t, codePool(t, code), index); + object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; parameterCount = methodParameterCount(t, method); @@ -2539,7 +2626,7 @@ run(Thread* t) } goto loop; case ldc: { - push(t, arrayBody(t, codePool(t, code), codeBody(t, code, ip++))); + push(t, arrayBody(t, codePool(t, code), codeBody(t, code, ip++) - 1)); } goto loop; case ldc_w: @@ -2547,7 +2634,7 @@ run(Thread* t) uint8_t index1 = codeBody(t, code, ip++); uint8_t index2 = codeBody(t, code, ip++); - push(t, arrayBody(t, codePool(t, code), (index1 << 8) | index2)); + push(t, arrayBody(t, codePool(t, code), ((index1 << 8) | index2) - 1)); } goto loop; case vm::ldiv: { @@ -2625,7 +2712,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object class_ = resolveClass(t, codePool(t, code), index); + object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object clinit = classInitializer(t, class_); @@ -2727,7 +2814,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object field = resolveField(t, codePool(t, code), index); + object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object value = pop(t); @@ -2743,7 +2830,7 @@ run(Thread* t) uint8_t index2 = codeBody(t, code, ip++); uint16_t index = (index1 << 8) | index2; - object field = resolveField(t, codePool(t, code), index); + object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; object clinit = classInitializer(t, fieldClass(t, field)); @@ -2906,11 +2993,13 @@ run(Thread* t) if (eht) { for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); - uint16_t catchType = exceptionHandlerCatchType(eh); + object catchType = + arrayBody(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1); + if (catchType == 0 or - instanceOf(t, - arrayBody(t, codePool(t, code), catchType), - exception)) + (objectClass(catchType) + == arrayBody(t, t->vm->types, Machine::ClassType) and + instanceOf(t, catchType, exception))) { sp = frameStackBase(t, frame); ip = exceptionHandlerIp(eh); @@ -2922,14 +3011,34 @@ run(Thread* t) } } - object method = threadExceptionHandler(t, t->thread); - code = methodCode(t, method); - frame = makeFrame(t, method, 0, 0, 0, codeMaxLocals(t, code)); - sp = 0; - ip = 0; - push(t, exception); - exception = 0; - goto loop; + if (t->thread) { + object method = threadExceptionHandler(t, t->thread); + code = methodCode(t, method); + frame = makeFrame(t, method, 0, 0, 0, codeMaxLocals(t, code)); + 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; + } + + fprintf(stderr, "uncaught exception: %s\n", &byteArrayBody + (t, stringBytes(t, throwableMessage(t, exception)), 0)); + + for (; p; p = traceNext(t, p)) { + fprintf(stderr, " at %s\n", &byteArrayBody + (t, methodName(t, traceMethod(t, p)), 0)); + } + } + + abort(t); } void