Index: src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java (revision 576831) +++ src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java (working copy) @@ -24,7 +24,7 @@ * */ public class AttrDefinitionBands extends BandSet { - + private int[] attributeDefinitionHeader; private String[] attributeDefinitionLayout; Index: src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (revision 576831) +++ src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (working copy) @@ -209,7 +209,7 @@ } public void add(AttributeLayout layout) { - layouts[layout.getContext()].put(Integer.valueOf(layout.getIndex()), layout); + layouts[layout.getContext()].put(new Integer(layout.getIndex()), layout); } public AttributeLayout getAttributeLayout(String name, int context) Index: src/main/java/org/apache/harmony/pack200/BcBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BcBands.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/BcBands.java (working copy) @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import org.apache.harmony.pack200.bytecode.ByteCode; import org.apache.harmony.pack200.bytecode.CodeAttribute; @@ -26,10 +27,11 @@ import org.apache.harmony.pack200.bytecode.CodeAttribute; /** - * + * Pack200 Bytecode bands */ public class BcBands extends BandSet { + // the bytecodes for each method in each class as they come (i.e. in their packed format) private byte[][][] methodByteCodePacked; /** @@ -61,12 +63,25 @@ ArrayList[][] methodAttributes = segment.getClassBands().getMethodAttributes(); String[][] methodDescr = segment.getClassBands().getMethodDescr(); + int bcCaseCountCount = 0; + int bcByteCount = 0; + int bcShortCount = 0; + int bcLocalCount = 0; + int bcLabelCount = 0; + int bcIntRefCount = 0; + int bcFloatRefCount = 0; + int bcLongRefCount = 0; + int bcDoubleRefCount = 0; int bcStringRefCount = 0; - int bcInitRefCount = 0; + int bcClassRefCount = 0; int bcFieldRefCount = 0; - int bcThisFieldCount = 0; int bcMethodRefCount = 0; int bcIMethodRefCount = 0; + int bcThisFieldCount = 0; + int bcSuperFieldCount = 0; + int bcThisMethodCount = 0; + int bcSuperMethodCount = 0; + int bcInitRefCount = 0; AttributeLayout abstractModifier = attributeDefinitionMap .getAttributeLayout(AttributeLayout.ACC_ABSTRACT, @@ -92,6 +107,11 @@ codeBytes.write(code); methodByteCodePacked[c][m] = codeBytes.toByteArray(); bcParsed += methodByteCodePacked[c][m].length; + int[] codes = new int[methodByteCodePacked[c][m].length]; + for (int i = 0; i < codes.length; i++) { + codes[i] = methodByteCodePacked[c][m][i] & 0xff; + } + System.out.println(Arrays.toString(codes)); for (int i = 0; i < methodByteCodePacked[c][m].length; i++) { int codePacked = 0xff & methodByteCodePacked[c][m][i]; // TODO a lot of this needs to be encapsulated in the @@ -103,9 +123,56 @@ // once they've been gotten. But that's for another // time. switch (codePacked) { + case 16: // bipush + case 188: // newarray + bcByteCount++; + break; + case 17: // sipush + bcShortCount++; + break; case 18: // (a)ldc + case 19: // aldc_w bcStringRefCount++; break; + case 234: // ildc + case 237: // ildc_w + bcIntRefCount++; + break; + case 235: // fldc + case 238: // fldc_w + bcFloatRefCount++; + break; + case 197: // multianewarray + bcByteCount++; + // fallthrough intended + case 233: // cldc + case 236: // cldc_w + case 187: // new + case 189: // anewarray + case 192: // checkcast + case 193: // instanceof + bcClassRefCount++; + break; + case 20: // lldc2_w + bcLongRefCount++; + break; + case 239: // dldc2_w + bcDoubleRefCount++; + break; + case 169: // ret + bcLocalCount++; + break; + case 167: // goto + case 168: // jsr + case 200: // goto_w + case 201: // jsr_w + bcLabelCount++; + break; + case 170: // tableswitch + case 171: // lookupswitch + bcCaseCountCount++; + bcLabelCount++; + break; case 178: // getstatic case 179: // putstatic case 180: // getfield @@ -124,15 +191,69 @@ case 203: // putstatic_this case 204: // getfield_this case 205: // putfield_this + case 209: // aload_0_getstatic_this + case 210: // aload_0_putstatic_this + case 211: // aload_0_putfield_this + case 212: // aload_0_putfield_this bcThisFieldCount++; break; - case 231: // invoke_special_init + case 206: // invokevirtual_this + case 207: // invokespecial_this + case 208: // invokestatic_this + case 213: // aload_0_invokevirtual_this + case 214: // aload_0_invokespecial_this + case 215: // aload_0_invokestatic_this + bcThisMethodCount++; + break; + case 216: // getstatic_super + case 217: // putstatic_super + case 218: // getfield_super + case 219: // putfield_super + case 223: // aload_0_getstatic_super + case 224: // aload_0_putstatic_super + case 225: // aload_0_getfield_super + case 226: // aload_0_putfield_super + bcSuperFieldCount++; + break; + case 220: // invokevirtual_super + case 221: // invokespecial_super + case 222: // invokestatic_super + case 227: // aload_0_invokevirtual_super + case 228: // aload_0_invokespecial_super + case 229: // aload_0_invokestatic_super + bcSuperMethodCount++; + break; + case 132: // iinc + bcLocalCount++; + bcByteCount++; + break; + case 196: // wide + int nextInstruction = 0xff & methodByteCodePacked[c][m][i+1]; + if (nextInstruction == 132) { // iinc + bcLocalCount += 2; + bcShortCount++; + } else if (endsWithLoad(nextInstruction) + || endsWithStore(nextInstruction) + || nextInstruction == 169) { + bcLocalCount += 2; + } else { + debug("Found unhandled " + ByteCode.getByteCode(nextInstruction)); + } + i++; + break; + case 230: // invokespecial_this_init + case 231: // invokespecial_super_init + case 232: // invokespecial_new_init bcInitRefCount++; break; - default: // unhandled specifically at this stage - debug("Found unhandled " - + ByteCode.getByteCode(codePacked)); + if(endsWithLoad(codePacked) || endsWithStore(codePacked)) { + bcLocalCount++; + } else if (startsWithIf(codePacked)) { + bcLabelCount++; + } else { + debug("Found unhandled " + ByteCode.getByteCode(codePacked)); + } } } } @@ -140,31 +261,50 @@ } // other bytecode bands debug("Parsed *bc_codes (" + bcParsed + ")"); - debug("unimplemented bc_case_count"); - debug("unimplemented bc_case_value"); - debug("unimplemented bc_byte"); - debug("unimplemented bc_short"); - debug("unimplemented bc_local"); - debug("unimplemented bc_label"); - debug("unimplemented bc_intref"); - debug("unimplemented bc_floatref"); - debug("unimplemented bc_longref"); - debug("unimplemented bc_doubleref"); - int[] bcStringRef = decodeBandInt("bc_stringref", in, Codec.DELTA5, - bcStringRefCount); - debug("unimplemented bc_classref"); - int[] bcFieldRef = decodeBandInt("bc_fieldref", in, Codec.DELTA5, - bcFieldRefCount); - int[] bcMethodRef = decodeBandInt("bc_methodref", in, Codec.UNSIGNED5, - bcMethodRefCount); - int[] bcIMethodRef = decodeBandInt("bc_imethodref", in, Codec.DELTA5, - bcIMethodRefCount); - int[] bcThisField = decodeBandInt("bc_thisfield", in, Codec.UNSIGNED5, - bcThisFieldCount); - debug("unimplemented bc_superfield"); - debug("unimplemented bc_thismethod"); - debug("unimplemented bc_supermethod"); - debug("unimplemented bc_initref"); + int[] bcCaseCount = decodeBandInt("bc_case_count", in, Codec.UNSIGNED5, bcCaseCountCount); + int[][] bcCaseValue = new int[bcCaseCount.length][]; + // TODO: Check for alternative codec. + for (int i = 0; i < bcCaseCount.length; i++) { + int numCases = bcCaseCount[i]; + bcCaseValue[i] = new int[numCases]; + int last = 0; + for (int j = 0; j < bcCaseValue[i].length; j++) { + bcCaseValue[i][j] = last = (int)Codec.DELTA5.decode(in, last); + } + } + int[] bcByte = decodeBandInt("bc_byte", in, Codec.BYTE1, bcByteCount); + int[] bcShort = decodeBandInt("bc_short", in, Codec.DELTA5, + bcShortCount); + int[] bcLocal = decodeBandInt("bc_local", in, Codec.UNSIGNED5, + bcLocalCount); + int[] bcLabel = decodeBandInt("bc_label", in, Codec.BRANCH5, + bcLabelCount); + int[] bcIntRef = decodeBandInt("bc_intref", in, Codec.DELTA5, + bcIntRefCount); + int[] bcFloatRef = decodeBandInt("bc_floatref", in, Codec.DELTA5, + bcFloatRefCount); + int[] bcLongRef = decodeBandInt("bc_longref", in, Codec.DELTA5, + bcLongRefCount); + int[] bcDoubleRef = decodeBandInt("bc_doubleref", in, Codec.DELTA5, + bcDoubleRefCount); + int[] bcStringRef = decodeBandInt("bc_stringref", in, Codec.DELTA5, + bcStringRefCount); + int[] bcClassRef = decodeBandInt("bc_classref", in, Codec.UNSIGNED5, + bcClassRefCount); + int[] bcFieldRef = decodeBandInt("bc_fieldref", in, Codec.DELTA5, + bcFieldRefCount); + int[] bcMethodRef = decodeBandInt("bc_methodref", in, Codec.UNSIGNED5, + bcMethodRefCount); + int[] bcIMethodRef = decodeBandInt("bc_imethodref", in, Codec.DELTA5, + bcIMethodRefCount); + int[] bcThisField = decodeBandInt("bc_thisfield", in, Codec.UNSIGNED5, + bcThisFieldCount); + int[] bcSuperField = decodeBandInt("bc_superfield", in, Codec.UNSIGNED5, + bcSuperFieldCount); + int[] bcThisMethod = decodeBandInt("bc_thismethod", in, Codec.UNSIGNED5, + bcThisMethodCount); + int[] bcSuperMethod = decodeBandInt("bc_supermethod", in, Codec.UNSIGNED5, + bcSuperMethodCount); int[] bcInitRef = decodeBandInt("bc_initref", in, Codec.UNSIGNED5, bcInitRefCount); debug("unimplemented bc_escref"); @@ -195,4 +335,20 @@ } + private boolean startsWithIf(int codePacked) { + return false; + } + + private boolean endsWithLoad(int codePacked) { + return (codePacked >= 21 && codePacked <= 25); + } + + private boolean endsWithStore(int codePacked) { + return (codePacked >= 54 && codePacked <= 58); + } + + public byte[][][] getMethodByteCodePacked() { + return methodByteCodePacked; + } + } Index: src/main/java/org/apache/harmony/pack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy) @@ -20,6 +20,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; import org.apache.harmony.pack200.bytecode.CPClass; import org.apache.harmony.pack200.bytecode.ConstantValueAttribute; @@ -26,7 +28,7 @@ import org.apache.harmony.pack200.bytecode.ExceptionsAttribute; /** - * + * */ public class ClassBands extends BandSet { @@ -41,7 +43,7 @@ private int[] classMethodCount; private String[] classSuper; - + private String[] classThis; private int[] codeHandlerCount; @@ -57,11 +59,11 @@ private String[][] fieldDescr; private long[][] fieldFlags; - + private int methodAttrCount; private ArrayList[][] methodAttributes; - + private String[][] methodDescr; private ExceptionsAttribute[][] methodExceptions; @@ -71,13 +73,16 @@ private AttributeLayoutMap attrMap; private CpBands cpBands; - + + private int codeAttrCount; + /** * @param header */ - public ClassBands(Segment segment){ + public ClassBands(Segment segment) { super(segment); - this.attrMap = segment.getAttrDefinitionBands().getAttributeDefinitionMap(); + this.attrMap = segment.getAttrDefinitionBands() + .getAttributeDefinitionMap(); this.cpBands = segment.getCpBands(); } @@ -96,8 +101,7 @@ * * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, - Pack200Exception { + public void unpack(InputStream in) throws IOException, Pack200Exception { int classCount = header.getClassCount(); classThis = parseReferences("class_this", in, Codec.DELTA5, classCount, cpBands.getCpClass()); @@ -141,8 +145,8 @@ "There are attribute flags, and I don't know what to do with them"); debug("unimplemented field_attr_indexes"); debug("unimplemented field_attr_calls"); - AttributeLayout layout = attrMap.getAttributeLayout( - "ConstantValue", AttributeLayout.CONTEXT_FIELD); + AttributeLayout layout = attrMap.getAttributeLayout("ConstantValue", + AttributeLayout.CONTEXT_FIELD); Codec codec = layout.getCodec(); fieldAttributes = new ArrayList[classCount][]; for (int i = 0; i < classCount; i++) { @@ -161,7 +165,8 @@ // be e.g. KIB or KIH if (type.equals("B") || type.equals("H")) type = "I"; - Object value = layout.getValue(result, type, cpBands.getConstantPool()); + Object value = layout.getValue(result, type, cpBands + .getConstantPool()); fieldAttributes[i][j] .add(new ConstantValueAttribute(value)); debug("Processed value " + value + " for ConstantValue"); @@ -168,8 +173,37 @@ } } } - debug("unimplemented field_Signature_RS"); - parseMetadataBands(AttributeLayout.CONTEXT_FIELD); + + layout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, + AttributeLayout.CONTEXT_FIELD); + codec = layout.getCodec(); +// fieldAttributes = new ArrayList[classCount][]; + for (int i = 0; i < classCount; i++) { +// fieldAttributes[i] = new ArrayList[fieldFlags[i].length]; + for (int j = 0; j < fieldFlags[i].length; j++) { +// fieldAttributes[i][j] = new ArrayList(); + long flag = fieldFlags[i][j]; + if (layout.matches(flag)) { + // we've got a value to read + long result = codec.decode(in); +// String desc = fieldDescr[i][j]; +// int colon = desc.indexOf(':'); +// // String name = desc.substring(0, colon); +// String type = desc.substring(colon + 1); +// // TODO Got to get better at this ... in any case, it should +// // be e.g. KIB or KIH +// if (type.equals("B") || type.equals("H")) +// type = "I"; +// Object value = layout.getValue(result, type, cpBands +// .getConstantPool()); +// fieldAttributes[i][j] +// .add(new ConstantValueAttribute(value)); + debug("Found a signature attribute: " + result); + } + } + } +// debug("unimplemented field_Signature_RS"); + parseFieldMetadataBands(); } private void parseMethodBands(InputStream in) throws IOException, @@ -203,9 +237,9 @@ } parseAttributeMethodExceptions(in); parseAttributeMethodSignature(in); - parseMetadataBands(AttributeLayout.CONTEXT_METHOD); + parseMethodMetadataBands(); } - + /** * @param in * @throws Pack200Exception @@ -215,8 +249,8 @@ throws Pack200Exception, IOException { // TODO Should refactor this stuff into the layout somehow int classCount = header.getClassCount(); - AttributeLayout layout = attrMap.getAttributeLayout( - "Exceptions", AttributeLayout.CONTEXT_METHOD); + AttributeLayout layout = attrMap.getAttributeLayout("Exceptions", + AttributeLayout.CONTEXT_METHOD); Codec codec = layout.getCodec(); methodExceptions = new ExceptionsAttribute[classCount][]; int[][] numExceptions = new int[classCount][]; @@ -235,20 +269,20 @@ long flag = methodFlags[i][j]; int n = numExceptions[i][j]; if (n > 0) { - CPClass[] exceptions = new CPClass[n]; - if (layout.matches(flag)) { - for (int k = 0; k < n; k++) { - long result = codec.decode(in); - exceptions[k] = new CPClass(cpBands.getCpClass()[(int) result]); - } - } - methodExceptions[i][j] = new ExceptionsAttribute(exceptions); - methodAttributes[i][j].add(methodExceptions[i][j]); - } + CPClass[] exceptions = new CPClass[n]; + if (layout.matches(flag)) { + for (int k = 0; k < n; k++) { + long result = codec.decode(in); + exceptions[k] = new CPClass( + cpBands.getCpClass()[(int) result]); + } + } + methodExceptions[i][j] = new ExceptionsAttribute(exceptions); + methodAttributes[i][j].add(methodExceptions[i][j]); + } } } } - /** * @param name @@ -258,12 +292,11 @@ private void parseAttributeUnknown(String name, int context, long[][] flags) throws Pack200Exception { debug("Parsing unknown attributes for " + name); - AttributeLayout layout = attrMap.getAttributeLayout( - name, context); - int count = SegmentUtils.countMatches(flags, layout); - if (count > 0) - throw new Error("We've got data for " + name - + " and we don't know what to do with it (yet)"); + AttributeLayout layout = attrMap.getAttributeLayout(name, context); + int count = SegmentUtils.countMatches(flags, layout); + if (count > 0) + throw new Error("We've got data for " + name + + " and we don't know what to do with it (yet)"); } /** @@ -294,8 +327,8 @@ debug("unimplemented class_attr_indexes"); debug("unimplemented class_attr_calls"); AttributeLayout layout = attrMap.getAttributeLayout( - AttributeLayout.ATTRIBUTE_SOURCE_FILE, - AttributeLayout.CONTEXT_CLASS); + AttributeLayout.ATTRIBUTE_SOURCE_FILE, + AttributeLayout.CONTEXT_CLASS); for (int i = 0; i < classCount; i++) { long flag = classFlags[i]; if (layout.matches(flag)) { @@ -303,7 +336,8 @@ // TODO File this as a sourcefile attribute and don't generate // everything below long result = layout.getCodec().decode(in); - Object value = layout.getValue(result, cpBands.getConstantPool()); + Object value = layout.getValue(result, cpBands + .getConstantPool()); debug("Processed value " + value + " for SourceFile"); } } @@ -310,7 +344,7 @@ debug("unimplemented class_EnclosingMethod_RC"); debug("unimplemented class_EnclosingMethod_RDN"); debug("unimplemented class_Signature_RS"); - parseMetadataBands(AttributeLayout.CONTEXT_CLASS); + parseClassMetadataBands(); debug("unimplemented class_InnerClasses_N"); debug("unimplemented class_InnerClasses_RC"); debug("unimplemented class_InnerClasses_F"); @@ -319,7 +353,6 @@ debug("unimplemented class_file_version_minor_H"); debug("unimplemented class_file_version_major_H"); } - private void parseCodeBands(InputStream in) throws Pack200Exception, IOException { @@ -370,49 +403,68 @@ throw new IllegalStateException("Shouldn't get here either"); } } - debug("unimplemented code_headers"); - debug("unimplemented code_max_stack"); - debug("unimplemented code_max_na_locals"); - debug("unimplemented code_hander_count"); - debug("unimplemented code_hander_start_P"); - debug("unimplemented code_hander_end_PO"); - debug("unimplemented code_hander_catch_PO"); - debug("unimplemented code_hander_class_RC"); - parseCodeAttrBands(in); + int codeFlagsCount = segment.getSegmentHeader().getOptions().hasAllCodeFlags() ? + codeBands : codeSpecialHeader; + parseCodeAttrBands(in, codeFlagsCount); } - - private void parseCodeAttrBands(InputStream in) { - debug("unimplemented code_flags"); + private void parseCodeAttrBands(InputStream in, int codeFlagsCount) throws IOException, Pack200Exception { + long[] codeFlags = parseFlags("code_flags", in, codeFlagsCount, Codec.UNSIGNED5, segment.getSegmentHeader().getOptions().hasCodeFlagsHi()); + for (int i = 0; i < codeFlagsCount; i++) { + long flag = codeFlags[i]; + if ((flag & (1 << 16)) != 0) + codeAttrCount++; + } + if (codeAttrCount > 0) + throw new Error( + "There are attribute flags, and I don't know what to do with them"); debug("unimplemented code_attr_count"); debug("unimplemented code_attr_indexes"); debug("unimplemented code_attr_calls"); - debug("unimplemented code_LineNumberTable_N"); - debug("unimplemented code_LineNumberTable_bci_P"); - debug("unimplemented code_LineNumberTable_line"); - String[] types = { "LocalVariableTable", "LocalVariableTypeTable" }; + + int lineNumberTableCount = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE, AttributeLayout.CONTEXT_CODE)); + int[] lineNumberTableN = decodeBandInt("code_LineNumberTable_N", in, Codec.UNSIGNED5, lineNumberTableCount); + int lineNumCount = arraySum(lineNumberTableN); + int[] lineNumberTableBciP = decodeBandInt("code_LineNumberTable_bci_P", in, Codec.BCI5, lineNumCount); + int[] lineNumberTableLine = decodeBandInt("code_LineNumberTable_line", in, Codec.UNSIGNED5, lineNumCount); + String[] types = { AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE, AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE }; for (int i = 0; i < types.length; i++) { String type = types[i]; - debug("unimplemented code_" + type + "_N"); - debug("unimplemented code_" + type + "_bci_P"); - debug("unimplemented code_" + type + "_span_O"); - debug("unimplemented code_" + type + "_name_RU"); - debug("unimplemented code_" + type + "_type_RS"); - debug("unimplemented code_" + type + "_slot"); + int lengthNBand = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(type, AttributeLayout.CONTEXT_CODE)); + int[] nBand = decodeBandInt("code_" + type + "_N", in, Codec.UNSIGNED5, lengthNBand); + int count = arraySum(nBand); + int[] bciP = decodeBandInt("code_" + type + "_bci_P", in, Codec.BCI5, count); + int[] spanO = decodeBandInt("code_" + type + "_span_O", in, Codec.BRANCH5, count); + String[] nameRU = parseReferences("code_" + type + "_name_RU", in, Codec.UNSIGNED5, count, cpBands.getCpUTF8()); + String[] typeRS = parseReferences("code_" + type + "_type_RS", in, Codec.UNSIGNED5, count, cpBands.getCpSignature()); + int[] slot = decodeBandInt("code_" + type + "_slot", in, Codec.UNSIGNED5, count); } } - private void parseMetadataBands(int context) throws Pack200Exception { - String[] RxA; - if (AttributeLayout.CONTEXT_METHOD == context) { - RxA = new String[] { "RVA", "RIA", "RVPA", "RIPA", "AD" }; - } else if (AttributeLayout.CONTEXT_FIELD == context - || AttributeLayout.CONTEXT_CLASS == context) { - RxA = new String[] { "RVA", "RIA" }; - } else { - throw new Pack200Exception("Unknown type of metadata unit " - + context); + private int arraySum(int[] array) { + int res = 0; + for (int i = 0; i < array.length; i++) { + res += array[i]; } + return res; + } + + private void parseFieldMetadataBands() throws Pack200Exception { + String[] RxA = new String[] { "RVA", "RIA" }; + + AttributeLayout rvaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_FIELD); + AttributeLayout riaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_FIELD); + + int rvaCount = SegmentUtils.countMatches(fieldFlags, rvaLayout); + int riaCount = SegmentUtils.countMatches(fieldFlags, riaLayout); + if (rvaCount > 0 || riaCount > 0) { + throw new Error("Field metadata not handled"); + } + // AttributeLayout layout = // map.get(RuntimeVisibleAnnotations,class/field/method as int) // foreachheader ... @@ -417,10 +469,115 @@ // map.get(RuntimeVisibleAnnotations,class/field/method as int) // foreachheader ... // if layout.matches(header[n] or whatever) - String contextName = (AttributeLayout.CONTEXT_METHOD == context ? "method" - : (AttributeLayout.CONTEXT_FIELD == context ? "field" - : (AttributeLayout.CONTEXT_CLASS == context ? "class" - : "unkowon"))); + String contextName = "field"; + for (int i = 0; i < RxA.length; i++) { + String rxa = RxA[i]; + if (rxa.indexOf("P") >= 0) { + debug("unimplemented " + contextName + "_" + rxa + "_param_NB"); + } + if (!rxa.equals("AD")) { + debug("unimplemented " + contextName + "_" + rxa + "_anno_N"); + debug("unimplemented " + contextName + "_" + rxa + "_type_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_pair_N"); + debug("unimplemented " + contextName + "_" + rxa + "_name_RU"); + } + debug("unimplemented " + contextName + "_" + rxa + "_T"); + debug("unimplemented " + contextName + "_" + rxa + "_caseI_KI"); + debug("unimplemented " + contextName + "_" + rxa + "_caseD_KD"); + debug("unimplemented " + contextName + "_" + rxa + "_caseF_KF"); + debug("unimplemented " + contextName + "_" + rxa + "_caseJ_KJ"); + debug("unimplemented " + contextName + "_" + rxa + "_casec_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_caseet_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_caseec_RU"); + debug("unimplemented " + contextName + "_" + rxa + "_cases_RU"); + debug("unimplemented " + contextName + "_" + rxa + "_casearray_N"); + debug("unimplemented " + contextName + "_" + rxa + "_nesttype_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_nestpair_N"); + debug("unimplemented " + contextName + "_" + rxa + "_nestname_RU"); + } + } + + private void parseMethodMetadataBands() throws Pack200Exception { + String[] RxA = new String[] { "RVA", "RIA", "RVPA", "RIPA", "AD" }; + int[] rxaCounts = new int[] { 0, 0, 0, 0, 0 }; + AttributeLayout rvaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout riaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout rvpaLayout = attrMap + .getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout ripaLayout = attrMap + .getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout adLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_ANNOTATION_DEFAULT, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout[] rxaLayouts = new AttributeLayout[] { rvaLayout, + riaLayout, rvpaLayout, ripaLayout, adLayout }; + + for (int i = 0; i < rxaLayouts.length; i++) { + rxaCounts[i] = SegmentUtils.countMatches(methodFlags, rxaLayouts[i]); + if (rxaCounts[i] > 0) { + throw new Error("Found method metadata"); + } + } + + // AttributeLayout layout = + // map.get(RuntimeVisibleAnnotations,class/field/method as int) + // foreachheader ... + // if layout.matches(header[n] or whatever) + String contextName = "method"; + for (int i = 0; i < RxA.length; i++) { + String rxa = RxA[i]; + if (rxa.indexOf("P") >= 0) { + debug("unimplemented " + contextName + "_" + rxa + "_param_NB"); + } + if (!rxa.equals("AD")) { + debug("unimplemented " + contextName + "_" + rxa + "_anno_N"); + debug("unimplemented " + contextName + "_" + rxa + "_type_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_pair_N"); + debug("unimplemented " + contextName + "_" + rxa + "_name_RU"); + } + debug("unimplemented " + contextName + "_" + rxa + "_T"); + debug("unimplemented " + contextName + "_" + rxa + "_caseI_KI"); + debug("unimplemented " + contextName + "_" + rxa + "_caseD_KD"); + debug("unimplemented " + contextName + "_" + rxa + "_caseF_KF"); + debug("unimplemented " + contextName + "_" + rxa + "_caseJ_KJ"); + debug("unimplemented " + contextName + "_" + rxa + "_casec_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_caseet_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_caseec_RU"); + debug("unimplemented " + contextName + "_" + rxa + "_cases_RU"); + debug("unimplemented " + contextName + "_" + rxa + "_casearray_N"); + debug("unimplemented " + contextName + "_" + rxa + "_nesttype_RS"); + debug("unimplemented " + contextName + "_" + rxa + "_nestpair_N"); + debug("unimplemented " + contextName + "_" + rxa + "_nestname_RU"); + } + } + + private void parseClassMetadataBands() throws Pack200Exception { + String[] RxA = new String[] { "RVA", "RIA" }; + + AttributeLayout rvaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_CLASS); + AttributeLayout riaLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, + AttributeLayout.CONTEXT_CLASS); + int rvaCount = SegmentUtils.countMatches(classFlags, rvaLayout); + int riaCount = SegmentUtils.countMatches(classFlags, riaLayout); + if (rvaCount > 0 || riaCount > 0) { + throw new Error("Class metadata not handled"); + } + // AttributeLayout layout = + // map.get(RuntimeVisibleAnnotations,class/field/method as int) + // foreachheader ... + // if layout.matches(header[n] or whatever) + String contextName = "class"; for (int i = 0; i < RxA.length; i++) { String rxa = RxA[i]; if (rxa.indexOf("P") >= 0) { Index: src/main/java/org/apache/harmony/pack200/Segment.java =================================================================== --- src/main/java/org/apache/harmony/pack200/Segment.java (revision 572724) +++ src/main/java/org/apache/harmony/pack200/Segment.java (working copy) @@ -357,7 +357,6 @@ return cpBands; } - protected FileBands getFileBands() { return fileBands; } @@ -362,12 +361,6 @@ return fileBands; } - - protected SegmentHeader getHeader() { - return header; - } - - protected IcBands getIcBands() { return icBands; } @@ -372,4 +365,4 @@ return icBands; } -} +} \ No newline at end of file Index: src/main/java/org/apache/harmony/pack200/bytecode/ByteCode.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/ByteCode.java (revision 572384) +++ src/main/java/org/apache/harmony/pack200/bytecode/ByteCode.java (working copy) @@ -240,11 +240,71 @@ byteCodeArray[203] = new ByteCode(203, "putstatic_this", new int[] { 179, 0, 0 }); byteCodeArray[204] = new ByteCode(204, "getfield_this", new int[] { - 180, 0, 0 }); - byteCodeArray[205] = new ByteCode(205, "putfield_this", new int[] { - 181, 0, 0 }); - byteCodeArray[231] = new ByteCode(231, "invokespecial_super_init", - new int[] { 183, 0, 0 }); + 180, 0, 0 }); + byteCodeArray[205] = new ByteCode(205, "putfield_this", new int[] { + 181, 0, 0 }); + byteCodeArray[206] = new ByteCode(206, "invokevirtual_this", new int[] { + 182, 0, 0 }); + byteCodeArray[207] = new ByteCode(207, "invokespecial_this", new int[] { + 183, 0, 0 }); + byteCodeArray[208] = new ByteCode(208, "invokestatic_this", new int[] { + 184, 0, 0 }); + byteCodeArray[209] = new ByteCode(209, "aload_0_getstatic_this", + new int[] { 41, 178, 0, 0 }); + byteCodeArray[210] = new ByteCode(210, "aload_0_putstatic_this", + new int[] { 41, 179, 0, 0 }); + byteCodeArray[211] = new ByteCode(211, "aload_0_getfield_this", + new int[] { 41, 180, 0, 0 }); + byteCodeArray[212] = new ByteCode(212, "aload_0_putfield_this", + new int[] { 41, 181, 0, 0 }); + byteCodeArray[213] = new ByteCode(213, "aload_0_invokevirtual_this", + new int[] { 41, 182, 0, 0 }); + byteCodeArray[214] = new ByteCode(214, "aload_0_invokespecial_this", + new int[] { 41, 183, 0, 0 }); + byteCodeArray[215] = new ByteCode(215, "aload_0_invokestatic_this", + new int[] { 41, 184, 0, 0 }); + byteCodeArray[216] = new ByteCode(216, "getstatic_super", new int[] { + 178, 0, 0 }); + byteCodeArray[217] = new ByteCode(217, "putstatic_super", new int[] { + 179, 0, 0 }); + byteCodeArray[218] = new ByteCode(218, "getfield_super", new int[] { + 180, 0, 0 }); + byteCodeArray[219] = new ByteCode(219, "putfield_super", new int[] { + 181, 0, 0 }); + byteCodeArray[220] = new ByteCode(220, "invokevirtual_super", + new int[] { 182, 0, 0 }); + byteCodeArray[221] = new ByteCode(221, "invokespecial_super", + new int[] { 183, 0, 0 }); + byteCodeArray[222] = new ByteCode(222, "invokestatic_super", new int[] { + 184, 0, 0 }); + byteCodeArray[223] = new ByteCode(223, "aload_0_getstatic_super", + new int[] { 41, 178, 0, 0 }); + byteCodeArray[224] = new ByteCode(224, "aload_0_putstatic_super", + new int[] { 41, 179, 0, 0 }); + byteCodeArray[225] = new ByteCode(225, "aload_0_getfield_super", + new int[] { 41, 180, 0, 0 }); + byteCodeArray[226] = new ByteCode(226, "aload_0_putfield_super", + new int[] { 41, 181, 0, 0 }); + byteCodeArray[227] = new ByteCode(227, "aload_0_invokevirtual_super", + new int[] { 41, 182, 0, 0 }); + byteCodeArray[228] = new ByteCode(228, "aload_0_invokespecial_super", + new int[] { 41, 183, 0, 0 }); + byteCodeArray[229] = new ByteCode(229, "aload_0_invokestatic_super", + new int[] { 41, 184, 0, 0 }); + byteCodeArray[230] = new ByteCode(230, "invokespecial_this_init", + new int[] { 183, 0, 0 }); + byteCodeArray[231] = new ByteCode(231, "invokespecial_super_init", + new int[] { 183, 0, 0 }); + byteCodeArray[232] = new ByteCode(232, "invokespecial_new_init", + new int[] { 184, 0, 0 }); + byteCodeArray[233] = new ByteCode(233, "cldc", new int[] { 18, 0 }); + byteCodeArray[234] = new ByteCode(234, "ildc", new int[] { 18, 0 }); + byteCodeArray[235] = new ByteCode(235, "fldc", new int[] { 18, 0 }); + byteCodeArray[236] = new ByteCode(236, "cldc_w", new int[] { 19, 0 }); + byteCodeArray[237] = new ByteCode(237, "ildc_w", new int[] { 19, 0 }); + byteCodeArray[238] = new ByteCode(238, "fldc_w", new int[] { 19, 0 }); + byteCodeArray[239] = new ByteCode(239, "dldc2_w", new int[] { 20, 0 }); + // Reserved bytecodes byteCodeArray[254] = new ByteCode(254, "impdep1"); byteCodeArray[255] = new ByteCode(255, "impdep2"); @@ -261,7 +321,7 @@ ByteCode byteCode = (ByteCode) byteCodes .get(new Integer(0xff & opcode)); if (byteCode == null) - throw new Error("Unknown bytecode"); + throw new Error("Unknown bytecode: " + opcode); return byteCode; } Index: src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java (revision 572384) +++ src/main/java/org/apache/harmony/pack200/bytecode/CodeAttribute.java (working copy) @@ -37,7 +37,7 @@ this.maxStack = maxStack; this.codeLength = 0; for (int i = 0; i < codePacked.length; i++) { - ByteCode byteCode = ByteCode.getByteCode(codePacked[i]); + ByteCode byteCode = ByteCode.getByteCode(codePacked[i] & 0xff); byteCodes.add(byteCode); this.codeLength += byteCode.getLength(); } Index: src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java (revision 572724) +++ src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java (working copy) @@ -34,13 +34,9 @@ private BandSet bandSet = new BandSet(new Segment()) { public void pack(OutputStream outputStream) { - // TODO Auto-generated method stub - } public void unpack(InputStream inputStream) throws IOException, Pack200Exception { - // TODO Auto-generated method stub - } }; Index: src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (revision 576831) +++ src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (working copy) @@ -16,10 +16,6 @@ */ package org.apache.harmony.pack200.tests; -// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5 -// NOTE: Do not extract strings as messages; this code is still a -// work-in-progress -// NOTE: Also, don't get rid of 'else' statements for the hell of it ... import org.apache.harmony.pack200.Segment; import junit.framework.TestCase; @@ -25,19 +21,15 @@ import junit.framework.TestCase; /** - * @author Alex Blewitt - * @version $Revision: $ + * Tests for org.apache.harmony.pack200.Segment, which is the main class for pack200. */ public class SegmentTest extends TestCase { -// Commented on request in HARMONY-2246 -// Will be uncommented later -// public void testHelloWorld() throws Exception { -// assertNotNull(Segment.parse(Segment.class -// .getResourceAsStream("/org/apache/harmony/pack200/tests/HelloWorld.pack"))); -// } - /** - * @throws Exception - */ + + public void testHelloWorld() throws Exception { + assertNotNull(Segment.parse(Segment.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/HelloWorld.pack"))); + } + public void testJustResources() throws Exception { assertNotNull(Segment .parse(Segment.class @@ -43,9 +35,7 @@ .parse(Segment.class .getResourceAsStream("/org/apache/harmony/pack200/tests/JustResources.pack"))); } - /** - * @throws Exception - */ + public void testJustResourcesGZip() throws Exception { assertNotNull(Segment .parse(Segment.class @@ -51,7 +41,7 @@ .parse(Segment.class .getResourceAsStream("/org/apache/harmony/pack200/tests/JustResources.pack.gz"))); } - + public void testInterfaceOnly() throws Exception { assertNotNull(Segment .parse(Segment.class @@ -58,4 +48,4 @@ .getResourceAsStream("/org/apache/harmony/pack200/tests/InterfaceOnly.pack"))); } -} +} \ No newline at end of file Index: src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java +++ src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.tests; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +import org.apache.harmony.pack200.AttrDefinitionBands; +import org.apache.harmony.pack200.AttributeLayoutMap; +import org.apache.harmony.pack200.BcBands; +import org.apache.harmony.pack200.ClassBands; +import org.apache.harmony.pack200.CpBands; +import org.apache.harmony.pack200.Pack200Exception; +import org.apache.harmony.pack200.Segment; +import org.apache.harmony.pack200.SegmentHeader; + +import junit.framework.TestCase; + +public class BcBandsTest extends TestCase { + + public class MockSegmentHeader extends SegmentHeader { + public int getClassCount() { + return 1; + } + } + + public class MockClassBands extends ClassBands { + public MockClassBands(Segment segment) { + super(segment); + } + + public long[][] getMethodFlags() { + return new long[][] {{0L}}; + } + + public int[] getCodeMaxStack() { + return new int[] {1}; + } + + public int[] getCodeMaxNALocals() { + return new int[] {1}; + } + + public String[][] getMethodDescr() { + return new String[][] {{"hello()"}}; + } + + public ArrayList[][] getMethodAttributes() { + return new ArrayList[][] {{new ArrayList()}}; + } + } + + public class MockAttributeDefinitionBands extends AttrDefinitionBands { + + public MockAttributeDefinitionBands(Segment segment) { + super(segment); + } + + public AttributeLayoutMap getAttributeDefinitionMap() { + try { + return new AttributeLayoutMap(); + } catch (Pack200Exception e) { + fail(e.getLocalizedMessage()); + } + return null; + } + + + + } + + public class MockSegment extends Segment { + protected AttrDefinitionBands getAttrDefinitionBands() { + return new MockAttributeDefinitionBands(this); + } + + protected CpBands getCpBands() { + return new CpBands(this); + } + + protected ClassBands getClassBands() { + return new MockClassBands(this); + } + + public SegmentHeader getSegmentHeader() { + return new MockSegmentHeader(); + } + } + + BcBands bcBands = new BcBands(new MockSegment()); + + /** + * Test with single bytecode instructions that mean all other + * bands apart from bc_codes will be empty. + * @throws IOException + * @throws Pack200Exception + */ + public void testSimple() throws IOException, Pack200Exception { + byte[] bytes = new byte[] {50, 50, (byte)255}; + InputStream in = new ByteArrayInputStream(bytes); + bcBands.unpack(in); + assertTrue(bcBands.getMethodByteCodePacked()[0][0].length == bytes.length - 1); + } + +}