From 7bd3ea1892e59caab72d923307b2c71c6bb3363d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 22 May 2012 13:53:32 -0600 Subject: [PATCH 1/7] add simple disassembler for debugging --- src/machine.cpp | 442 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 439 insertions(+), 3 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 4df244d536..fd4fed94c4 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -20,6 +20,8 @@ using namespace vm; namespace { +const bool DebugClassReader = false; + const unsigned NoByte = 0xFFFF; #ifdef USE_ATOMIC_OPERATIONS @@ -813,13 +815,22 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) switch (s.read1()) { case CONSTANT_Integer: case CONSTANT_Float: { - singletonValue(t, pool, i) = s.read4(); + uint32_t v = s.read4(); + singletonValue(t, pool, i) = v; + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = int/float 0x%x\n", i, v); + } } return 1; case CONSTANT_Long: case CONSTANT_Double: { uint64_t v = s.read8(); memcpy(&singletonValue(t, pool, i), &v, 8); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = long/double \n", i); + } } return 2; case CONSTANT_Utf8: { @@ -829,6 +840,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) value = internByteArray(t, value); } set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = utf8 %s\n", i, &byteArrayBody(t, value, 0)); + } } } return 1; @@ -839,6 +854,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object value = makeReference(t, 0, singletonObject(t, pool, si), 0); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = class \n", i); + } } } return 1; @@ -852,6 +871,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) (t, value, 0, cast(value, BytesPerWord) - 1); value = intern(t, value); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = string \n", i); + } } } return 1; @@ -867,6 +890,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object type = singletonObject(t, pool, ti); object value = makePair(t, name, type); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = nameAndType %s%s\n", i, &byteArrayBody(t, name, 0), &byteArrayBody(t, type, 0)); + } } } return 1; @@ -886,6 +913,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object value = makeReference (t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = method %s.%s%s\n", i, &byteArrayBody(t, class_, 0), &byteArrayBody(t, pairFirst(t, nameAndType), 0), &byteArrayBody(t, pairSecond(t, nameAndType), 0)); + } } } return 1; @@ -900,6 +931,10 @@ parsePool(Thread* t, Stream& s) object pool = makeSingletonOfSize(t, count + poolMaskSize(count)); PROTECT(t, pool); + if(DebugClassReader) { + fprintf(stderr, " const pool entries %d\n", count); + } + if (count) { uint32_t* index = static_cast(t->m->heap->allocate(count * 4)); @@ -1299,6 +1334,381 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) } } +uint16_t read16(uint8_t* code, unsigned& ip) { + uint16_t a = code[ip++]; + uint16_t b = code[ip++]; + return (a << 8) | b; +} + +uint32_t read32(uint8_t* code, unsigned& ip) { + uint32_t b = code[ip++]; + uint32_t a = code[ip++]; + uint32_t c = code[ip++]; + uint32_t d = code[ip++]; + return (a << 24) | (b << 16) | (c << 8) | d; +} + +void +disassembleCode(const char* prefix, uint8_t* code, unsigned length) +{ + unsigned ip = 0; + + while(ip < length) { + unsigned instr; + fprintf(stderr, "%s%x:\t", prefix, ip); + switch (instr = code[ip++]) { + case aaload: fprintf(stderr, "aaload\n"); break; + case aastore: fprintf(stderr, "aastore\n"); break; + + case aconst_null: fprintf(stderr, "aconst_null\n"); break; + + case aload: fprintf(stderr, "aload %02x\n", code[ip++]); break; + case aload_0: fprintf(stderr, "aload_0\n"); break; + case aload_1: fprintf(stderr, "aload_1\n"); break; + case aload_2: fprintf(stderr, "aload_2\n"); break; + case aload_3: fprintf(stderr, "aload_3\n"); break; + + case anewarray: fprintf(stderr, "anewarray %04x\n", read16(code, ip)); break; + case areturn: fprintf(stderr, "areturn\n"); break; + case arraylength: fprintf(stderr, "arraylength\n"); break; + + case astore: fprintf(stderr, "astore %02x\n", code[ip++]); break; + case astore_0: fprintf(stderr, "astore_0\n"); break; + case astore_1: fprintf(stderr, "astore_1\n"); break; + case astore_2: fprintf(stderr, "astore_2\n"); break; + case astore_3: fprintf(stderr, "astore_3\n"); break; + + + case athrow: fprintf(stderr, "athrow\n"); break; + case baload: fprintf(stderr, "baload\n"); break; + case bastore: fprintf(stderr, "bastore\n"); break; + + case bipush: fprintf(stderr, "bipush %02x\n", code[ip++]); break; + case caload: fprintf(stderr, "caload\n"); break; + case castore: fprintf(stderr, "castore\n"); break; + case checkcast: fprintf(stderr, "checkcast %04x\n", read16(code, ip)); break; + case d2f: fprintf(stderr, "d2f\n"); break; + case d2i: fprintf(stderr, "d2i\n"); break; + case d2l: fprintf(stderr, "d2l\n"); break; + case dadd: fprintf(stderr, "dadd\n"); break; + case daload: fprintf(stderr, "daload\n"); break; + case dastore: fprintf(stderr, "dastore\n"); break; + case dcmpg: fprintf(stderr, "dcmpg\n"); break; + case dcmpl: fprintf(stderr, "dcmpl\n"); break; + case dconst_0: fprintf(stderr, "dconst_0\n"); break; + case dconst_1: fprintf(stderr, "dconst_1\n"); break; + case ddiv: fprintf(stderr, "ddiv\n"); break; + case dmul: fprintf(stderr, "dmul\n"); break; + case dneg: fprintf(stderr, "dneg\n"); break; + case vm::drem: fprintf(stderr, "drem\n"); break; + case dsub: fprintf(stderr, "dsub\n"); break; + case dup: fprintf(stderr, "dup\n"); break; + case dup_x1: fprintf(stderr, "dup_x1\n"); break; + case dup_x2: fprintf(stderr, "dup_x2\n"); break; + case dup2: fprintf(stderr, "dup2\n"); break; + case dup2_x1: fprintf(stderr, "dup2_x1\n"); break; + case dup2_x2: fprintf(stderr, "dup2_x2\n"); break; + case f2d: fprintf(stderr, "f2d\n"); break; + case f2i: fprintf(stderr, "f2i\n"); break; + case f2l: fprintf(stderr, "f2l\n"); break; + case fadd: fprintf(stderr, "fadd\n"); break; + case faload: fprintf(stderr, "faload\n"); break; + case fastore: fprintf(stderr, "fastore\n"); break; + case fcmpg: fprintf(stderr, "fcmpg\n"); break; + case fcmpl: fprintf(stderr, "fcmpl\n"); break; + case fconst_0: fprintf(stderr, "fconst_0\n"); break; + case fconst_1: fprintf(stderr, "fconst_1\n"); break; + case fconst_2: fprintf(stderr, "fconst_2\n"); break; + case fdiv: fprintf(stderr, "fdiv\n"); break; + case fmul: fprintf(stderr, "fmul\n"); break; + case fneg: fprintf(stderr, "fneg\n"); break; + case frem: fprintf(stderr, "frem\n"); break; + case fsub: fprintf(stderr, "fsub\n"); break; + + case getfield: fprintf(stderr, "getfield %04x\n", read16(code, ip)); break; + case getstatic: fprintf(stderr, "getstatic %04x\n", read16(code, ip)); break; + case goto_: { + int16_t offset = read16(code, ip); + fprintf(stderr, "goto %04x\n", offset + ip - 3); + } break; + case goto_w: { + int32_t offset = read32(code, ip); + fprintf(stderr, "goto_w %08x\n", offset + ip - 5); + } break; + + case i2b: fprintf(stderr, "i2b\n"); break; + case i2c: fprintf(stderr, "i2c\n"); break; + case i2d: fprintf(stderr, "i2d\n"); break; + case i2f: fprintf(stderr, "i2f\n"); break; + case i2l: fprintf(stderr, "i2l\n"); break; + case i2s: fprintf(stderr, "i2s\n"); break; + case iadd: fprintf(stderr, "iadd\n"); break; + case iaload: fprintf(stderr, "iaload\n"); break; + case iand: fprintf(stderr, "iand\n"); break; + case iastore: fprintf(stderr, "iastore\n"); break; + case iconst_m1: fprintf(stderr, "iconst_m1\n"); break; + case iconst_0: fprintf(stderr, "iconst_0\n"); break; + case iconst_1: fprintf(stderr, "iconst_1\n"); break; + case iconst_2: fprintf(stderr, "iconst_2\n"); break; + case iconst_3: fprintf(stderr, "iconst_3\n"); break; + case iconst_4: fprintf(stderr, "iconst_4\n"); break; + case iconst_5: fprintf(stderr, "iconst_5\n"); break; + case idiv: fprintf(stderr, "idiv\n"); break; + + case if_acmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpeq %04x\n", offset + ip - 3); + } break; + case if_acmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpne %04x\n", offset + ip - 3); + } break; + case if_icmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpeq %04x\n", offset + ip - 3); + } break; + case if_icmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpne %04x\n", offset + ip - 3); + } break; + + case if_icmpgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpgt %04x\n", offset + ip - 3); + } break; + case if_icmpge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpge %04x\n", offset + ip - 3); + } break; + case if_icmplt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmplt %04x\n", offset + ip - 3); + } break; + case if_icmple: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmple %04x\n", offset + ip - 3); + } break; + + case ifeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifeq %04x\n", offset + ip - 3); + } break; + case ifne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifne %04x\n", offset + ip - 3); + } break; + case ifgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifgt %04x\n", offset + ip - 3); + } break; + case ifge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifge %04x\n", offset + ip - 3); + } break; + case iflt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "iflt %04x\n", offset + ip - 3); + } break; + case ifle: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifle %04x\n", offset + ip - 3); + } break; + + case ifnonnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnonnull %04x\n", offset + ip - 3); + } break; + case ifnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnull %04x\n", offset + ip - 3); + } break; + + case iinc: { + uint8_t a = code[ip++]; + uint8_t b = code[ip++]; + fprintf(stderr, "iinc %02x %02x\n", a, b); + } break; + + case iload: fprintf(stderr, "iload %02x\n", code[ip++]); break; + case fload: fprintf(stderr, "fload %02x\n", code[ip++]); break; + + case iload_0: fprintf(stderr, "iload_0\n"); break; + case fload_0: fprintf(stderr, "fload_0\n"); break; + case iload_1: fprintf(stderr, "iload_1\n"); break; + case fload_1: fprintf(stderr, "fload_1\n"); break; + + case iload_2: fprintf(stderr, "iload_2\n"); break; + case fload_2: fprintf(stderr, "fload_2\n"); break; + case iload_3: fprintf(stderr, "iload_3\n"); break; + case fload_3: fprintf(stderr, "fload_3\n"); break; + + case imul: fprintf(stderr, "imul\n"); break; + case ineg: fprintf(stderr, "ineg\n"); break; + + case instanceof: fprintf(stderr, "instanceof %04x\n", read16(code, ip)); break; + case invokeinterface: fprintf(stderr, "invokeinterface %04x\n", read16(code, ip)); break; + case invokespecial: fprintf(stderr, "invokespecial %04x\n", read16(code, ip)); break; + case invokestatic: fprintf(stderr, "invokestatic %04x\n", read16(code, ip)); break; + case invokevirtual: fprintf(stderr, "invokevirtual %04x\n", read16(code, ip)); break; + + case ior: fprintf(stderr, "ior\n"); break; + case irem: fprintf(stderr, "irem\n"); break; + case ireturn: fprintf(stderr, "ireturn\n"); break; + case freturn: fprintf(stderr, "freturn\n"); break; + case ishl: fprintf(stderr, "ishl\n"); break; + case ishr: fprintf(stderr, "ishr\n"); break; + + case istore: fprintf(stderr, "istore %02x\n", code[ip++]); break; + case fstore: fprintf(stderr, "fstore %02x\n", code[ip++]); break; + + case istore_0: fprintf(stderr, "istore_0\n"); break; + case fstore_0: fprintf(stderr, "fstore_0\n"); break; + case istore_1: fprintf(stderr, "istore_1\n"); break; + case fstore_1: fprintf(stderr, "fstore_1\n"); break; + case istore_2: fprintf(stderr, "istore_2\n"); break; + case fstore_2: fprintf(stderr, "fstore_2\n"); break; + case istore_3: fprintf(stderr, "istore_3\n"); break; + case fstore_3: fprintf(stderr, "fstore_3\n"); break; + + case isub: fprintf(stderr, "isub\n"); break; + case iushr: fprintf(stderr, "iushr\n"); break; + case ixor: fprintf(stderr, "ixor\n"); break; + + case jsr: fprintf(stderr, "jsr %04x\n", read16(code, ip)); break; + case jsr_w: fprintf(stderr, "jsr_w %08x\n", read32(code, ip)); break; + + case l2d: fprintf(stderr, "l2d\n"); break; + case l2f: fprintf(stderr, "l2f\n"); break; + case l2i: fprintf(stderr, "l2i\n"); break; + case ladd: fprintf(stderr, "ladd\n"); break; + case laload: fprintf(stderr, "laload\n"); break; + + case land: fprintf(stderr, "land\n"); break; + case lastore: fprintf(stderr, "lastore\n"); break; + + case lcmp: fprintf(stderr, "lcmp\n"); break; + case lconst_0: fprintf(stderr, "lconst_0\n"); break; + case lconst_1: fprintf(stderr, "lconst_1\n"); break; + + case ldc: fprintf(stderr, "ldc %04x\n", read16(code, ip)); break; + case ldc_w: fprintf(stderr, "ldc_w %08x\n", read32(code, ip)); break; + case ldc2_w: fprintf(stderr, "ldc2_w %04x\n", read16(code, ip)); break; + + case ldiv_: fprintf(stderr, "ldiv_\n"); break; + + case lload: fprintf(stderr, "lload %02x\n", code[ip++]); break; + case dload: fprintf(stderr, "dload %02x\n", code[ip++]); break; + + case lload_0: fprintf(stderr, "lload_0\n"); break; + case dload_0: fprintf(stderr, "dload_0\n"); break; + case lload_1: fprintf(stderr, "lload_1\n"); break; + case dload_1: fprintf(stderr, "dload_1\n"); break; + case lload_2: fprintf(stderr, "lload_2\n"); break; + case dload_2: fprintf(stderr, "dload_2\n"); break; + case lload_3: fprintf(stderr, "lload_3\n"); break; + case dload_3: fprintf(stderr, "dload_3\n"); break; + + case lmul: fprintf(stderr, "lmul\n"); break; + case lneg: fprintf(stderr, "lneg\n"); break; + + case lookupswitch: { + int32_t default_ = read32(code, ip); + int32_t pairCount = read32(code, ip); + fprintf(stderr, "lookupswitch default: %d pairCount: %d\n", default_, pairCount); + + for (int i = 0; i < pairCount; i++) { + int32_t k = read32(code, ip); + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %02x dest: %2x\n", prefix, k, d); + } + } break; + + case lor: fprintf(stderr, "lor\n"); break; + case lrem: fprintf(stderr, "lrem\n"); break; + case lreturn: fprintf(stderr, "lreturn\n"); break; + case dreturn: fprintf(stderr, "dreturn\n"); break; + case lshl: fprintf(stderr, "lshl\n"); break; + case lshr: fprintf(stderr, "lshr\n"); break; + + case lstore: fprintf(stderr, "lstore %02x\n", code[ip++]); break; + case dstore: fprintf(stderr, "dstore %02x\n", code[ip++]); break; + + case lstore_0: fprintf(stderr, "lstore_0\n"); break; + case dstore_0: fprintf(stderr, "dstore_0\n"); break; + case lstore_1: fprintf(stderr, "lstore_1\n"); break; + case dstore_1: fprintf(stderr, "dstore_1\n"); break; + case lstore_2: fprintf(stderr, "lstore_2\n"); break; + case dstore_2: fprintf(stderr, "dstore_2\n"); break; + case lstore_3: fprintf(stderr, "lstore_3\n"); break; + case dstore_3: fprintf(stderr, "dstore_3\n"); break; + + case lsub: fprintf(stderr, "lsub\n"); break; + case lushr: fprintf(stderr, "lushr\n"); break; + case lxor: fprintf(stderr, "lxor\n"); break; + + case monitorenter: fprintf(stderr, "monitorenter\n"); break; + case monitorexit: fprintf(stderr, "monitorexit\n"); break; + + case multianewarray: fprintf(stderr, "multianewarray %04x %02x\n", read16(code, ip), code[ip++]); break; + + case new_: fprintf(stderr, "new %04x\n", read16(code, ip)); break; + + case newarray: fprintf(stderr, "newarray %02x\n", code[ip++]); break; + + case nop: fprintf(stderr, "nop\n"); break; + case pop_: fprintf(stderr, "pop\n"); break; + case pop2: fprintf(stderr, "pop2\n"); break; + + case putfield: fprintf(stderr, "putfield %04x\n", read16(code, ip)); break; + case putstatic: fprintf(stderr, "putstatic %04x\n", read16(code, ip)); break; + + case ret: fprintf(stderr, "ret %02x\n", code[ip++]); break; + + case return_: fprintf(stderr, "return_\n"); break; + case saload: fprintf(stderr, "saload\n"); break; + case sastore: fprintf(stderr, "sastore\n"); break; + + case sipush: fprintf(stderr, "sipush %04x\n", read16(code, ip)); break; + + case swap: fprintf(stderr, "swap\n"); break; + + case tableswitch: { + int32_t default_ = read32(code, ip); + int32_t bottom = read32(code, ip); + int32_t top = read32(code, ip); + fprintf(stderr, "tableswitch default: %d bottom: %d top: %d\n", default_, bottom, top); + + for (int i = 0; i < top - bottom + 1; i++) { + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %d dest: %2x\n", prefix, i + bottom, d); + } + } break; + + case wide: { + switch (code[ip++]) { + case aload: fprintf(stderr, "wide aload %04x\n", read16(code, ip)); break; + + case astore: fprintf(stderr, "wide astore %04x\n", read16(code, ip)); break; + case iinc: fprintf(stderr, "wide iinc %04x %04x\n", read16(code, ip), read16(code, ip)); break; + case iload: fprintf(stderr, "wide iload %04x\n", read16(code, ip)); break; + case istore: fprintf(stderr, "wide istore %04x\n", read16(code, ip)); break; + case lload: fprintf(stderr, "wide lload %04x\n", read16(code, ip)); break; + case lstore: fprintf(stderr, "wide lstore %04x\n", read16(code, ip)); break; + case ret: fprintf(stderr, "wide ret %04x\n", read16(code, ip)); break; + + default: { + fprintf(stderr, "unknown wide instruction %02x %04x\n", instr, read16(code, ip)); + } + } + } break; + + default: { + fprintf(stderr, "unknown instruction %02x\n", instr); + } + } + } +} + object parseCode(Thread* t, Stream& s, object pool) { @@ -1308,10 +1718,18 @@ parseCode(Thread* t, Stream& s, object pool) unsigned maxLocals = s.read2(); unsigned length = s.read4(); + if(DebugClassReader) { + fprintf(stderr, " code: maxStack %d maxLocals %d length %d\n", maxStack, maxLocals, length); + } + object code = makeCode(t, pool, 0, 0, 0, 0, maxStack, maxLocals, length); s.read(&codeBody(t, code, 0), length); PROTECT(t, code); + if(DebugClassReader) { + disassembleCode(" ", &codeBody(t, code, 0), length); + } + unsigned ehtLength = s.read2(); if (ehtLength) { object eht = makeExceptionHandlerTable(t, ehtLength); @@ -1450,6 +1868,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, newVirtuals); unsigned count = s.read2(); + + if(DebugClassReader) { + fprintf(stderr, " method count %d\n", count); + } + if (count) { object methodTable = makeArray(t, count); PROTECT(t, methodTable); @@ -1465,6 +1888,12 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) unsigned name = s.read2(); unsigned spec = s.read2(); + if(DebugClassReader) { + fprintf(stderr, " method flags %d name %d spec %d '%s%s'\n", flags, name, spec, + &byteArrayBody(t, singletonObject(t, pool, name - 1), 0), + &byteArrayBody(t, singletonObject(t, pool, spec - 1), 0)); + } + addendum = 0; code = 0; @@ -3423,8 +3852,11 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, uint32_t magic = s.read4(); expect(t, magic == 0xCAFEBABE); - s.read2(); // minor version - s.read2(); // major version + unsigned minorVer = s.read2(); // minor version + unsigned majorVer = s.read2(); // major version + if(DebugClassReader) { + fprintf(stderr, "read class (minor %d major %d)\n", minorVer, majorVer); + } object pool = parsePool(t, s); PROTECT(t, pool); @@ -3468,6 +3900,10 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, & (ReferenceFlag | WeakReferenceFlag | HasFinalizerFlag | NeedInitFlag)); } + + if(DebugClassReader) { + fprintf(stderr, " flags %d name %d super %d\n", flags, name, super); + } parseInterfaceTable(t, s, class_, pool, throwType); From a5c9dd6f248c6e3254b562b0830a7bcead429eea Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 14:00:31 -0600 Subject: [PATCH 2/7] Fixing some issues with runtime annotations within avian. We were not properly converting dots to slashes internally for package names and we did not properly handle Method.getAnnotations and Method.getAnnotation(Class) on methods without any annotations. Added some tests to cover these cases. --- classpath/avian/VMMethod.java | 4 +++ classpath/java/lang/reflect/Method.java | 4 +-- classpath/java/lang/reflect/Proxy.java | 2 +- makefile | 5 ++- test/Annotations.java | 35 ++++++++----------- test/avian/testing/annotations/Color.java | 5 +++ test/avian/testing/annotations/Test.java | 9 +++++ test/avian/testing/annotations/TestEnum.java | 8 +++++ .../testing/annotations/TestInteger.java | 8 +++++ 9 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 test/avian/testing/annotations/Color.java create mode 100644 test/avian/testing/annotations/Test.java create mode 100644 test/avian/testing/annotations/TestEnum.java create mode 100644 test/avian/testing/annotations/TestInteger.java diff --git a/classpath/avian/VMMethod.java b/classpath/avian/VMMethod.java index e68d725242..843dd6012e 100644 --- a/classpath/avian/VMMethod.java +++ b/classpath/avian/VMMethod.java @@ -24,4 +24,8 @@ public class VMMethod { public MethodAddendum addendum; public VMClass class_; public Object code; + + public boolean hasAnnotations() { + return addendum != null && addendum.annotationTable != null; + } } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 2c0addfaae..f90ed311a5 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -170,7 +170,7 @@ public class Method extends AccessibleObject implements Member { } public T getAnnotation(Class class_) { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; @@ -183,7 +183,7 @@ public class Method extends AccessibleObject implements Member { } public Annotation[] getAnnotations() { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index 06805fc72c..cfc35a6077 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -358,7 +358,7 @@ public class Proxy { int[] interfaceIndexes = new int[interfaces.length]; for (int i = 0; i < interfaces.length; ++i) { interfaceIndexes[i] = ConstantPool.addClass - (pool, interfaces[i].getName()); + (pool, interfaces[i].getName().replace('.', '/')); } Map virtualMap = new HashMap(); diff --git a/makefile b/makefile index 86bc33e9b1..42ef1b95e7 100755 --- a/makefile +++ b/makefile @@ -685,7 +685,10 @@ vm-classes = \ avian/*.class \ avian/resource/*.class +test-support-sources = $(shell find $(test)/avian/ -name '*.java') test-sources = $(wildcard $(test)/*.java) +test-sources += $(test-support-sources) +test-support-classes = $(call java-classes, $(test-support-sources),$(test),$(test-build)) test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) test-dep = $(test-build).dep @@ -765,7 +768,7 @@ vg: build test: build $(library-path) /bin/sh $(test)/test.sh 2>/dev/null \ $(test-executable) $(mode) "$(test-flags)" \ - $(call class-names,$(test-build),$(test-classes)) \ + $(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \ $(continuation-tests) $(tail-tests) .PHONY: tarball diff --git a/test/Annotations.java b/test/Annotations.java index 17929065d1..c0234d21c0 100644 --- a/test/Annotations.java +++ b/test/Annotations.java @@ -1,7 +1,10 @@ -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; +import avian.testing.annotations.Color; +import avian.testing.annotations.Test; +import avian.testing.annotations.TestEnum; +import avian.testing.annotations.TestInteger; + public class Annotations { private static void expect(boolean v) { if (! v) throw new RuntimeException(); @@ -18,6 +21,12 @@ public class Annotations { .equals(Color.Red)); expect(((TestInteger) m.getAnnotation(TestInteger.class)).value() == 42); + + expect(m.getAnnotations().length == 3); + + Method noAnno = Annotations.class.getMethod("noAnnotation"); + expect(noAnno.getAnnotation(Test.class) == null); + expect(noAnno.getAnnotations().length == 0); } @Test("couscous") @@ -26,24 +35,8 @@ public class Annotations { public static void foo() { } - - @Retention(RetentionPolicy.RUNTIME) - private @interface Test { - public String value(); + + public static void noAnnotation() { + } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestEnum { - public Color value(); - } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestInteger { - public int value(); - } - - private static enum Color { - Red, Yellow, Blue - } - } diff --git a/test/avian/testing/annotations/Color.java b/test/avian/testing/annotations/Color.java new file mode 100644 index 0000000000..f054b0420a --- /dev/null +++ b/test/avian/testing/annotations/Color.java @@ -0,0 +1,5 @@ +package avian.testing.annotations; + +public enum Color { + Red, Yellow, Blue +} \ No newline at end of file diff --git a/test/avian/testing/annotations/Test.java b/test/avian/testing/annotations/Test.java new file mode 100644 index 0000000000..f9ba919647 --- /dev/null +++ b/test/avian/testing/annotations/Test.java @@ -0,0 +1,9 @@ +package avian.testing.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Test { + public String value(); +} diff --git a/test/avian/testing/annotations/TestEnum.java b/test/avian/testing/annotations/TestEnum.java new file mode 100644 index 0000000000..f8a252fd54 --- /dev/null +++ b/test/avian/testing/annotations/TestEnum.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestEnum { + public Color value(); +} \ No newline at end of file diff --git a/test/avian/testing/annotations/TestInteger.java b/test/avian/testing/annotations/TestInteger.java new file mode 100644 index 0000000000..b7ec78d0bc --- /dev/null +++ b/test/avian/testing/annotations/TestInteger.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestInteger { + public int value(); +} \ No newline at end of file From be869932d085db74bfa6829364a2c7eb94d26fac Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 15:18:42 -0600 Subject: [PATCH 3/7] Adding @Target and the associated ElementType enum for specifying the type an annotation is. --- .../java/lang/annotation/ElementType.java | 22 +++++++++++++++++++ classpath/java/lang/annotation/Target.java | 17 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 classpath/java/lang/annotation/ElementType.java create mode 100644 classpath/java/lang/annotation/Target.java diff --git a/classpath/java/lang/annotation/ElementType.java b/classpath/java/lang/annotation/ElementType.java new file mode 100644 index 0000000000..974fb10d64 --- /dev/null +++ b/classpath/java/lang/annotation/ElementType.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +public enum ElementType { + ANNOTATION_TYPE, + CONSTRUCTOR, + FIELD, + LOCAL_VARIABLE, + METHOD, + PACKAGE, + PARAMETER, + TYPE +} diff --git a/classpath/java/lang/annotation/Target.java b/classpath/java/lang/annotation/Target.java new file mode 100644 index 0000000000..8d2550343c --- /dev/null +++ b/classpath/java/lang/annotation/Target.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value=ElementType.ANNOTATION_TYPE) +public @interface Target { + public ElementType[] value(); +} From 97ffc5b15eeba27e0b80c1ef21031259f10ad364 Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 15:23:28 -0600 Subject: [PATCH 4/7] Adding java.util.Queue interface and java.util.AbstractQueue. --- classpath/java/util/AbstractQueue.java | 60 ++++++++++++++++++++++++++ classpath/java/util/Queue.java | 20 +++++++++ 2 files changed, 80 insertions(+) create mode 100644 classpath/java/util/AbstractQueue.java create mode 100644 classpath/java/util/Queue.java diff --git a/classpath/java/util/AbstractQueue.java b/classpath/java/util/AbstractQueue.java new file mode 100644 index 0000000000..19fa46aaa1 --- /dev/null +++ b/classpath/java/util/AbstractQueue.java @@ -0,0 +1,60 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractQueue extends AbstractCollection implements Queue { + + protected AbstractQueue() { + super(); + } + + public boolean add(T element) { + if (offer(element)) { + return true; + } else { + throw new IllegalStateException(); + } + } + + public boolean addAll(Collection collection) { + if (collection == null) { + throw new NullPointerException(); + } + + for (T element : collection) { + add(element); + } + + return true; + } + + public void clear() { + while (size() > 0) { + poll(); + } + } + + public T element() { + emptyCheck(); + return peek(); + } + + public T remove() { + emptyCheck(); + return poll(); + } + + private void emptyCheck() { + if (size() == 0) { + throw new NoSuchElementException(); + } + } +} diff --git a/classpath/java/util/Queue.java b/classpath/java/util/Queue.java new file mode 100644 index 0000000000..27855a7f61 --- /dev/null +++ b/classpath/java/util/Queue.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Queue extends Collection, Iterable { + public boolean add(T element); + public T element(); + public boolean offer(T element); + public T peek(); + public T poll(); + public T remove(); +} From 1f7b1a74e8532e2aa7cccccc1e9ad5faa3222473 Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 16:21:57 -0600 Subject: [PATCH 5/7] Adding java.util.SortedSet. --- classpath/java/util/SortedSet.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 classpath/java/util/SortedSet.java diff --git a/classpath/java/util/SortedSet.java b/classpath/java/util/SortedSet.java new file mode 100644 index 0000000000..1e1b2b923e --- /dev/null +++ b/classpath/java/util/SortedSet.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface SortedSet extends Collection, Iterable, Set { + public Comparator comparator(); + public T first(); + public SortedSet headSet(T toElement); + public T last(); + public SortedSet subSet(T fromElement, T toElement); + public SortedSet tailSet(T fromElement); +} From 20ee6604557c940dd155598e7225e5008ea2b544 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 22 May 2012 17:45:13 -0600 Subject: [PATCH 6/7] preserve classes needed for Unix filesystem access from ProGuard It seems that there are new classes loaded via reflection or JNI in OpenJDK needed for filesystem access, so we must tell ProGuard to retain them. --- openjdk.pro | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/openjdk.pro b/openjdk.pro index 953b5e205b..5a60ba1260 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -223,3 +223,21 @@ -keep class sun.util.resources.TimeZoneNames -keep class sun.text.resources.FormatData +# loaded via reflection from DefaultFileSystemProvider: +-keep class sun.nio.fs.LinuxFileSystemProvider +-keep class sun.nio.fs.BsdFileSystemProvider + +# loaded via JNI in UnixNativeDispatcher.c: +-keep class sun.nio.fs.UnixFileAttributes { + ; +} +-keep class sun.nio.fs.UnixFileStoreAttributes { + ; +} +-keep class sun.nio.fs.UnixMountEntry { + ; +} + +-keep class sun.nio.fs.UnixException { + UnixException(int); + } From 5d6899a8674cb86d297db518189823a120a97e45 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 24 May 2012 08:34:46 -0600 Subject: [PATCH 7/7] fix warning in disassembler code Apple's GCC is more picky about undefined ordering (and rightfully so)... --- src/machine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index fd4fed94c4..4c99de36de 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1649,7 +1649,10 @@ disassembleCode(const char* prefix, uint8_t* code, unsigned length) case monitorenter: fprintf(stderr, "monitorenter\n"); break; case monitorexit: fprintf(stderr, "monitorexit\n"); break; - case multianewarray: fprintf(stderr, "multianewarray %04x %02x\n", read16(code, ip), code[ip++]); break; + case multianewarray: { + unsigned type = read16(code, ip); + fprintf(stderr, "multianewarray %04x %02x\n", type, code[ip++]); + } break; case new_: fprintf(stderr, "new %04x\n", read16(code, ip)); break;