Author: sjanuary Date: Fri Jun 12 08:35:08 2009 New Revision: 784030 URL: http://svn.apache.org/viewvc?rev=784030&view=rev Log: Pack200 - support for -E option (different effort compression algorithms) Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java (with props) Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BHSDCodec.java Fri Jun 12 08:35:08 2009 @@ -204,14 +204,14 @@ return cardinality; } - public long decode(InputStream in) throws IOException, Pack200Exception { + public int decode(InputStream in) throws IOException, Pack200Exception { if (d != 0) throw new Pack200Exception( "Delta encoding used without passing in last value; this is a coding error"); return decode(in, 0); } - public long decode(InputStream in, long last) throws IOException, + public int decode(InputStream in, long last) throws IOException, Pack200Exception { int n = 0; long z = 0; @@ -219,6 +219,7 @@ do { x = in.read(); + lastBandLength ++; z += x * powers[n]; n++; } while (x >= l && n < b); @@ -252,7 +253,39 @@ // } if (isDelta()) z += last; - return z; + return (int)z; + } + + public int[] decodeInts(int n, InputStream in) throws IOException, + Pack200Exception { + int[] band = super.decodeInts(n, in); + if (isDelta()) { + for (int i = 0; i < band.length; i++) { + while (band[i] > largest) { + band[i] -= cardinality; + } + while (band[i] < smallest) { + band[i] += cardinality; + } + } + } + return band; + } + + public int[] decodeInts(int n, InputStream in, int firstValue) + throws IOException, Pack200Exception { + int[] band = super.decodeInts(n, in, firstValue); + if (isDelta()) { + for (int i = 0; i < band.length; i++) { + while (band[i] > largest) { + band[i] -= cardinality; + } + while (band[i] < smallest) { + band[i] += cardinality; + } + } + } + return band; } // private long cast32(long u) { @@ -269,19 +302,19 @@ * @return true if the encoding can encode this value */ public boolean encodes(long value) { - return (value >= smallest && value <= largest); + return value >= smallest && value <= largest; } - public byte[] encode(long value, long last) throws Pack200Exception { - if (isDelta()) { - value -= last; + public byte[] encode(int value, int last) throws Pack200Exception { + if(!encodes(value)) { + throw new Pack200Exception("The codec " + toString() + + " does not encode the value " + value); } - // TODO: Do we need this? this implementation isn't right because of integer overflow... -// if (!encodes(value)) { -// throw new Pack200Exception("The codec " + toString() -// + " does not encode the value " + value); -// } + long z = value; + if (isDelta()) { + z -= last; + } if (isSigned()) { if(z < Integer.MIN_VALUE) { z += 4294967296L; @@ -301,12 +334,16 @@ if (z < 0) { // Need to use integer overflow here to represent negatives. if(cardinality < 4294967296L) { - z+= cardinality; + z += cardinality; } else { z += 4294967296L; // this value is equal to (1 << 32). } } } + if (z < 0) { + throw new Pack200Exception("unable to encode"); + } + List byteList = new ArrayList(); for (int n = 0; n < b; n++) { long byteN; @@ -331,7 +368,7 @@ return bytes; } - public byte[] encode(long value) throws Pack200Exception { + public byte[] encode(int value) throws Pack200Exception { return encode(value, 0); } @@ -393,19 +430,16 @@ private long calculateSmallest() { long result; - if (d == 1) { - BHSDCodec bh0 = new BHSDCodec(b, h); - return bh0.smallest(); - } else if (isSigned()) { - result = -cardinality() / (1 << s); - } else { - if (cardinality > Integer.MAX_VALUE) { + if (d == 1 || !isSigned()) { + if (cardinality >= 4294967296L) { // 2^32 result = Integer.MIN_VALUE; } else { result = 0; } + } else { + result = Math.max(Integer.MIN_VALUE, -cardinality() / (1 << s)); } - return Math.max(Integer.MIN_VALUE, result); + return result; } /** Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java Fri Jun 12 08:35:08 2009 @@ -18,13 +18,26 @@ import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; public abstract class BandSet { - private final int effort; protected final SegmentHeader segmentHeader; + private final int effort; + + // Minimum size of band for each effort level where we consider alternative codecs + // Note: these values have been tuned - please test carefully if changing them + private final int[] effortThresholds = new int[] {0, 0, 1000, 500, 100, 100, 100, 100, 100, 0}; + + private long[] canonicalLargest; + private long[] canonicalSmallest; public BandSet(int effort, SegmentHeader header) { this.effort = effort; @@ -42,25 +55,36 @@ } public byte[] encodeBandInt(String name, int[] ints, BHSDCodec defaultCodec) throws Pack200Exception { - if(effort > 1 && (ints.length > 99 || effort == 9)) { - Codec betterCodec = lookForBetterCodec(name, ints, defaultCodec); + byte[] encodedBand = null; + if(effort > 1 && (ints.length >= effortThresholds[effort])) { + BandAnalysisResults results = analyseBand(name, ints, defaultCodec); + Codec betterCodec = results.betterCodec; + encodedBand = results.encodedBand; if(betterCodec != null) { if(betterCodec instanceof BHSDCodec) { int[] specifierBand = CodecEncoding.getSpecifier(betterCodec, defaultCodec); int specifier = specifierBand[0]; - if(specifierBand.length > 0) { + if(specifierBand.length > 1) { for (int i = 1; i < specifierBand.length; i++) { segmentHeader.appendBandCodingSpecifier(specifierBand[i]); } } + if(defaultCodec.isSigned()) { + specifier = -1 -specifier; + } else { + specifier = specifier + defaultCodec.getL(); + } byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier}); - byte[] rest = betterCodec.encode(ints); - byte[] band = new byte[specifierEncoded.length + rest.length]; + byte[] band = new byte[specifierEncoded.length + encodedBand.length]; System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length); - System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length); + System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length); return band; } else if (betterCodec instanceof PopulationCodec) { - + int[] extraSpecifierInfo = results.extraMetadata; + for (int i = 0; i < extraSpecifierInfo.length; i++) { + segmentHeader.appendBandCodingSpecifier(extraSpecifierInfo[i]); + } + return encodedBand; } else if (betterCodec instanceof RunCodec) { } @@ -69,37 +93,201 @@ // If we get here then we've decided to use the default codec. if(ints.length > 0) { -// System.out.println("encoding " + name + ", size = " + ints.length); + if(encodedBand == null) { + encodedBand = defaultCodec.encode(ints); + } int first = ints[0]; if(defaultCodec.getB() != 1) { if (defaultCodec.isSigned() && first >= -256 && first <= -1) { int specifier = -1 - CodecEncoding.getSpecifierForDefaultCodec(defaultCodec); byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier}); - byte[] rest = defaultCodec.encode(ints); - byte[] band = new byte[specifierEncoded.length + rest.length]; + byte[] band = new byte[specifierEncoded.length + encodedBand.length]; System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length); - System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length); + System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length); return band; } else if (!defaultCodec.isSigned() && first >= defaultCodec.getL() && first <= defaultCodec.getL() + 255) { int specifier = CodecEncoding.getSpecifierForDefaultCodec(defaultCodec) + defaultCodec.getL(); byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier}); - byte[] rest = defaultCodec.encode(ints); - byte[] band = new byte[specifierEncoded.length + rest.length]; + byte[] band = new byte[specifierEncoded.length + encodedBand.length]; System.arraycopy(specifierEncoded, 0, band, 0, specifierEncoded.length); - System.arraycopy(rest, 0, band, specifierEncoded.length, rest.length); + System.arraycopy(encodedBand, 0, band, specifierEncoded.length, encodedBand.length); return band; } } - return defaultCodec.encode(ints); + return encodedBand; } return new byte[0]; } - private Codec lookForBetterCodec(String name, int[] ints, - BHSDCodec defaultCodec) { - // TODO Auto-generated method stub - return null; + private BandAnalysisResults analyseBand(String name, int[] band, + BHSDCodec defaultCodec) throws Pack200Exception { + + BandAnalysisResults results = new BandAnalysisResults(); + + if(canonicalLargest == null) { + canonicalLargest = new long[116]; + canonicalSmallest = new long[116]; + for (int i = 1; i < canonicalLargest.length; i++) { + canonicalLargest[i] = CodecEncoding.getCanonicalCodec(i).largest(); + canonicalSmallest[i] = CodecEncoding.getCanonicalCodec(i).smallest(); + } + } + BandData bandData = new BandData(band); + + // Check that there is a reasonable saving to be made + byte[] encoded = defaultCodec.encode(band); + results.encodedBand = encoded; + + // Note: these values have been tuned - please test carefully if changing them + if(encoded.length <= band.length + 23 - 2*effort) { // TODO: tweak + return results; + } + + // Check if we can use BYTE1 as that's a 1:1 mapping if we can + if(!bandData.anyNegatives() && bandData.largest <= Codec.BYTE1.largest()) { + results.encodedBand = Codec.BYTE1.encode(band) ; + results.betterCodec = Codec.BYTE1; + return results; + } + + // Consider a population codec (but can't be nested) + if(effort > 3 && !name.equals("POPULATION")) { + int numDistinctValues = bandData.numDistinctValues(); + float distinctValuesAsProportion = (float)numDistinctValues / (float)band.length; + + // Note: these values have been tuned - please test carefully if changing them + if(numDistinctValues < 100 || distinctValuesAsProportion < 0.02 || (effort > 6 && distinctValuesAsProportion < 0.04)) { // TODO: tweak + encodeWithPopulationCodec(name, band, defaultCodec, bandData, results); + if(timeToStop(results)) { + return results; + } + } + } + + List codecFamiliesToTry = new ArrayList(); + + // See if the deltas are mainly small increments + if(bandData.mainlyPositiveDeltas() && bandData.mainlySmallDeltas()) { + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs2); + } + + if (bandData.wellCorrelated()) { // Try delta encodings + if (bandData.mainlyPositiveDeltas()) { + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs5); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2); + } else { + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs2); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs5); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs2); + } + } else { + if (bandData.anyNegatives()) { + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaSignedCodecs2); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs2); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaSignedCodecs5); + } else { + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5); + codecFamiliesToTry.add(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs1); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs3); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs4); + codecFamiliesToTry.add(CanonicalCodecFamilies.deltaUnsignedCodecs5); + } + } + if(name.equalsIgnoreCase("cpint")) { + System.out.print(""); + } + + for (Iterator iterator = codecFamiliesToTry.iterator(); iterator + .hasNext();) { + BHSDCodec[] family = (BHSDCodec[]) iterator.next(); + tryCodecs(name, band, defaultCodec, bandData, results, encoded, + family); + if (timeToStop(results)) { + break; + } + } + + return results; + } + + + private boolean timeToStop(BandAnalysisResults results) { + // if tried more than effort number of codecs for this band then return + // Note: these values have been tuned - please test carefully if changing them + if(effort > 6) { + return results.numCodecsTried >= effort * 2; + } + return results.numCodecsTried >= effort; + // May want to also check how much we've saved if performance needs improving, e.g. saved more than effort*2 % + // || (float)results.saved/(float)results.encodedBand.length > (float)effort * 2/100; + } + + private void tryCodecs(String name, int[] band, BHSDCodec defaultCodec, BandData bandData, + BandAnalysisResults results, byte[] encoded, + BHSDCodec[] potentialCodecs) throws Pack200Exception { + for (int i = 0; i < potentialCodecs.length; i++) { + BHSDCodec potential = potentialCodecs[i]; + if(potential.equals(defaultCodec)) { + return; // don't try codecs with greater cardinality in the same 'family' as the default codec as there won't be any savings + } + if (potential.isDelta()) { + if (potential.largest() >= bandData.largestDelta + && potential.smallest() <= bandData.smallestDelta + && potential.largest() >= bandData.largest + && potential.smallest() <= bandData.smallest) { + // TODO: can represent some negative deltas with overflow + byte[] encoded2 = potential.encode(band); + results.numCodecsTried++; + results.codecsTried.add(potential); + byte[] specifierEncoded = defaultCodec.encode(CodecEncoding + .getSpecifier(potential, null)); + int saved = encoded.length - encoded2.length + - specifierEncoded.length; + if (saved > results.saved) { + results.betterCodec = potential; + results.encodedBand = encoded2; + results.saved = saved; + } + } + } else if (potential.largest() >= bandData.largest + && potential.smallest() <= bandData.smallest) { + byte[] encoded2 = potential.encode(band); + results.numCodecsTried++; + results.codecsTried.add(potential); + byte[] specifierEncoded = defaultCodec.encode(CodecEncoding + .getSpecifier(potential, null)); + int saved = encoded.length - encoded2.length + - specifierEncoded.length; + if (saved > results.saved) { + results.betterCodec = potential; + results.encodedBand = encoded2; + results.saved = saved; + } + } + if(timeToStop(results)) { + return; + } + } } public boolean isPredictableSourceFileName(String className, String sourceFileName) { @@ -113,6 +301,201 @@ return className.equals(sourceFileName); } +// This could be useful if further enhancements are done but is not currently used +// +// private void encodeWithRunCodec(String name, int[] band, int index, +// BHSDCodec defaultCodec, BandData bandData, +// BandAnalysisResults results) throws Pack200Exception { +// int[] firstBand = new int[index]; +// int[] secondBand = new int[band.length - index]; +// System.arraycopy(band, 0, firstBand, 0, index); +// System.arraycopy(band, index, secondBand, 0, secondBand.length); +// BandAnalysisResults firstResults = analyseBand(name + "A", firstBand, defaultCodec); +// BandAnalysisResults secondResults = analyseBand(name + "B", secondBand, defaultCodec); +// int specifier = 117; +// byte[] specifierEncoded = defaultCodec.encode(new int[] {specifier}); +// int totalLength = firstResults.encodedBand.length + secondResults.encodedBand.length + specifierEncoded.length + 4; // TODO actual +// if(totalLength < results.encodedBand.length) { +// System.out.println("using run codec"); +// results.saved += results.encodedBand.length - totalLength; +// byte[] encodedBand = new byte[specifierEncoded.length + firstResults.encodedBand.length + secondResults.encodedBand.length]; +// System.arraycopy(specifierEncoded, 0, encodedBand, 0, specifierEncoded.length); +// System.arraycopy(firstResults.encodedBand, 0, encodedBand, specifierEncoded.length, firstResults.encodedBand.length); +// System.arraycopy(secondResults.encodedBand, 0, encodedBand, specifierEncoded.length + firstResults.encodedBand.length, secondResults.encodedBand.length); +// results.encodedBand = encodedBand; +// results.betterCodec = new RunCodec(index, firstResults.betterCodec, secondResults.betterCodec); +// } +// } + + private void encodeWithPopulationCodec(String name, int[] band, + BHSDCodec defaultCodec, BandData bandData, BandAnalysisResults results) throws Pack200Exception { + results.numCodecsTried += 3; // quite a bit more effort to try this codec + final Map distinctValues = bandData.distinctValues; + + List favoured = new ArrayList(); + for (Iterator iterator = distinctValues.keySet().iterator(); iterator + .hasNext();) { + Integer value = (Integer) iterator.next(); + Integer count = (Integer) distinctValues.get(value); + if(count.intValue() > 2 || distinctValues.size() < 256) { // TODO: tweak + favoured.add(value); + } + } + + // Sort the favoured list with the most commonly occurring first + if(distinctValues.size() > 255) { + Collections.sort(favoured, new Comparator() { + public int compare(Object arg0, Object arg1) { + return ((Integer)distinctValues.get(arg1)).compareTo((Integer)distinctValues.get(arg0)); + } + }); + } + + IntList unfavoured = new IntList(); + Map favouredToIndex = new HashMap(); + for (int i = 0; i < favoured.size(); i++) { + Integer value = (Integer) favoured.get(i); + favouredToIndex.put(value, new Integer(i)); + } + + int[] tokens = new int[band.length]; + for (int i = 0; i < band.length; i++) { + Integer favouredIndex = (Integer)favouredToIndex.get(new Integer(band[i])); + if(favouredIndex == null) { + tokens[i] = 0; + unfavoured.add(band[i]); + } else { + tokens[i] = favouredIndex.intValue() + 1; + } + } + favoured.add(favoured.get(favoured.size() - 1)); // repeat last value + int[] favouredBand = listToArray(favoured); + int[] unfavouredBand = unfavoured.toArray(); + + // Analyse the three bands to get the best codec + BandAnalysisResults favouredResults = analyseBand("POPULATION", favouredBand, defaultCodec); + BandAnalysisResults unfavouredResults = analyseBand("POPULATION", unfavouredBand, defaultCodec); + + int tdefL = 0; + int l = 0; + Codec tokenCodec = null; + byte[] tokensEncoded; + int k = favoured.size() - 1; + if(k < 256) { + tdefL = 1; + tokensEncoded = Codec.BYTE1.encode(tokens); + } else { + BandAnalysisResults tokenResults = analyseBand("POPULATION", tokens, defaultCodec); + tokenCodec = tokenResults.betterCodec; + tokensEncoded = tokenResults.encodedBand; + if(tokenCodec == null) { + tokenCodec = defaultCodec; + } + l = ((BHSDCodec) tokenCodec).getL(); + int h = ((BHSDCodec) tokenCodec).getH(); + int s = ((BHSDCodec) tokenCodec).getS(); + int b = ((BHSDCodec) tokenCodec).getB(); + int d = ((BHSDCodec) tokenCodec).isDelta() ? 1 : 0; + if(s == 0 && d == 0) { + boolean canUseTDefL = true; + if(b > 1) { + BHSDCodec oneLowerB = new BHSDCodec(b-1, h); + if(oneLowerB.largest() >= k) { + canUseTDefL = false; + } + } + if(canUseTDefL) { + switch (l) { + case 4: + tdefL = 1; + break; + case 8: + tdefL = 2; + break; + case 16: + tdefL = 3; + break; + case 32: + tdefL = 4; + break; + case 64: + tdefL = 5; + break; + case 128: + tdefL = 6; + break; + case 192: + tdefL = 7; + break; + case 224: + tdefL = 8; + break; + case 240: + tdefL = 9; + break; + case 248: + tdefL = 10; + break; + case 252: + tdefL = 11; + break; + } + } + } + } + + byte[] favouredEncoded = favouredResults.encodedBand; + byte[] unfavouredEncoded = unfavouredResults.encodedBand; + Codec favouredCodec = favouredResults.betterCodec; + Codec unfavouredCodec = unfavouredResults.betterCodec; + + int specifier = 141 + (favouredCodec == null ? 1 : 0) + (4 * tdefL) + (unfavouredCodec == null ? 2 : 0); + IntList extraBandMetadata = new IntList(3); + if(favouredCodec != null) { + int[] specifiers = CodecEncoding.getSpecifier(favouredCodec, null); + for (int i = 0; i < specifiers.length; i++) { + extraBandMetadata.add(specifiers[i]); + } + } + if(tdefL == 0) { + int[] specifiers = CodecEncoding.getSpecifier(tokenCodec, null); + for (int i = 0; i < specifiers.length; i++) { + extraBandMetadata.add(specifiers[i]); + } + } + if(unfavouredCodec != null) { + int[] specifiers = CodecEncoding.getSpecifier(unfavouredCodec, null); + for (int i = 0; i < specifiers.length; i++) { + extraBandMetadata.add(specifiers[i]); + } + } + int[] extraMetadata = extraBandMetadata.toArray(); + byte[] extraMetadataEncoded = Codec.UNSIGNED5.encode(extraMetadata); + if(defaultCodec.isSigned()) { + specifier = -1 -specifier; + } else { + specifier = specifier + defaultCodec.getL(); + } + byte[] firstValueEncoded = defaultCodec.encode(new int[] {specifier}); + int totalBandLength = firstValueEncoded.length + favouredEncoded.length + tokensEncoded.length + unfavouredEncoded.length; + + if(totalBandLength + extraMetadataEncoded.length < results.encodedBand.length) { + results.saved += results.encodedBand.length - (totalBandLength + extraMetadataEncoded.length); + byte[] encodedBand = new byte[totalBandLength]; + System.arraycopy(firstValueEncoded, 0, encodedBand, 0, firstValueEncoded.length); + System.arraycopy(favouredEncoded, 0, encodedBand, firstValueEncoded.length, favouredEncoded.length); + System.arraycopy(tokensEncoded, 0, encodedBand, firstValueEncoded.length + favouredEncoded.length, tokensEncoded.length); + System.arraycopy(unfavouredEncoded, 0, encodedBand, firstValueEncoded.length + favouredEncoded.length + tokensEncoded.length, unfavouredEncoded.length); + results.encodedBand = encodedBand; + results.extraMetadata = extraMetadata; + if(l != 0) { + results.betterCodec = new PopulationCodec(favouredCodec, l, unfavouredCodec); + } else { + results.betterCodec = new PopulationCodec(favouredCodec, tokenCodec, unfavouredCodec); + } + } + } + protected byte[] encodeFlags(String name, long[] flags, BHSDCodec loCodec, BHSDCodec hiCodec, boolean haveHiFlags) throws Pack200Exception { if(!haveHiFlags) { @@ -199,4 +582,112 @@ return flatArray; } + /** + * BandData represents information about a band, e.g. largest value etc + * and is used in the heuristics that calculate whether an alternative + * Codec could make the encoded band smaller. + */ + public class BandData { + + private final int[] band; + private int smallest = Integer.MAX_VALUE; + private int largest = Integer.MIN_VALUE; + private int smallestDelta; + private int largestDelta; + + private int deltaIsAscending = 0; + private int smallDeltaCount = 0; + + private double averageAbsoluteDelta = 0; + private double averageAbsoluteValue = 0; + + private Map distinctValues; + + public BandData(int[] band) { + this.band = band; + Integer one = new Integer(1); + for (int i = 0; i < band.length; i++) { + if(band[i] < smallest) { + smallest = band[i]; + } + if(band[i] > largest) { + largest = band[i]; + } + if(i != 0) { + int delta = band[i] - band[i - 1]; + if(delta < smallestDelta) { + smallestDelta = delta; + } + if(delta > largestDelta) { + largestDelta = delta; + } + if(delta >= 0) { + deltaIsAscending++; + } + averageAbsoluteDelta += (double)Math.abs(delta)/(double)(band.length - 1); + if(Math.abs(delta) < 256) { + smallDeltaCount++; + } + } else { + smallestDelta = band[0]; + largestDelta = band[0]; + } + averageAbsoluteValue += (double)Math.abs(band[i])/(double)band.length; + if(effort > 3) { // do calculations needed to consider population codec + if(distinctValues == null) { + distinctValues = new HashMap(); + } + Integer value = new Integer(band[i]); + Integer count = (Integer) distinctValues.get(value); + if(count == null) { + count = one; + } else { + count = new Integer(count.intValue() + 1); + } + distinctValues.put(value, count); + } + } + } + + public boolean mainlySmallDeltas() { + // Note: the value below has been tuned - please test carefully if changing it + return (float)smallDeltaCount/(float)band.length > 0.7F; + } + public boolean wellCorrelated() { + // Note: the value below has been tuned - please test carefully if changing it + return averageAbsoluteDelta * 3.1 < averageAbsoluteValue; + } + + public boolean mainlyPositiveDeltas() { + // Note: the value below has been tuned - please test carefully if changing it + return (float)deltaIsAscending/(float)band.length > 0.95F; + } + + public boolean anyNegatives() { + return smallest < 0; + } + + public int numDistinctValues() { + if(distinctValues == null) { + return band.length; + } + return distinctValues.size(); + } + + } + + public class BandAnalysisResults { + + private final List codecsTried = new ArrayList(effort); + + private int numCodecsTried = 0; + private int saved = 0; + + private int[] extraMetadata; + + private byte[] encodedBand; + private Codec betterCodec; + + } + } Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java?rev=784030&view=auto ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java (added) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java Fri Jun 12 08:35:08 2009 @@ -0,0 +1,210 @@ +/* + * 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; + +/** + * Sets of codecs that share characteristics. Mainly used for different effort + * compression heuristics in BandSet. + */ +public class CanonicalCodecFamilies { + + // Families of codecs for bands of positive integers that do not correlate + // well (i.e. would not benefit from delta encoding) + + public static BHSDCodec[] nonDeltaUnsignedCodecs1 = new BHSDCodec[] { + // (1,256) is a special case and is considered separately so shouldn't be included here +// CodecEncoding.getCanonicalCodec(1), // (1,256) + CodecEncoding.getCanonicalCodec(5), // (2,256) + CodecEncoding.getCanonicalCodec(9), // (3,256) + CodecEncoding.getCanonicalCodec(13) // (4,256) + }; + + public static BHSDCodec[] nonDeltaUnsignedCodecs2 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(17), // (5,4) + CodecEncoding.getCanonicalCodec(20), // (5,16) + CodecEncoding.getCanonicalCodec(23), // (5,32) + CodecEncoding.getCanonicalCodec(26), // (5,64) + CodecEncoding.getCanonicalCodec(29) // (5,128) + }; + + public static BHSDCodec[] nonDeltaUnsignedCodecs3 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(47), // (2,192) + CodecEncoding.getCanonicalCodec(48), // (2,224) + CodecEncoding.getCanonicalCodec(49), // (2,240) + CodecEncoding.getCanonicalCodec(50), // (2,248) + CodecEncoding.getCanonicalCodec(51) // (2,252) + }; + + public static BHSDCodec[] nonDeltaUnsignedCodecs4 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(70), // (3,192) + CodecEncoding.getCanonicalCodec(71), // (3,224) + CodecEncoding.getCanonicalCodec(72), // (3,240) + CodecEncoding.getCanonicalCodec(73), // (3,248) + CodecEncoding.getCanonicalCodec(74) // (3,252) + }; + + public static BHSDCodec[] nonDeltaUnsignedCodecs5 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(93), // (4,192) + CodecEncoding.getCanonicalCodec(94), // (4,224) + CodecEncoding.getCanonicalCodec(95), // (4,240) + CodecEncoding.getCanonicalCodec(96), // (4,248) + CodecEncoding.getCanonicalCodec(97) // (4,252) + }; + + // Families of codecs for bands of positive integers that do correlate well + // and would benefit from delta encoding + + public static BHSDCodec[] deltaUnsignedCodecs1 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(3), // (1,256,0,1) + CodecEncoding.getCanonicalCodec(7), // (2,256,0,1) + CodecEncoding.getCanonicalCodec(11), // (3,256,0,1) + CodecEncoding.getCanonicalCodec(15) // (4,256,0,1) + }; + + public static BHSDCodec[] deltaUnsignedCodecs2 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(32), // (5,4,0,1) + CodecEncoding.getCanonicalCodec(35), // (5,16,0,1) + CodecEncoding.getCanonicalCodec(38), // (5,32,0,1) + CodecEncoding.getCanonicalCodec(41), // (5,64,0,1) + CodecEncoding.getCanonicalCodec(44) // (5,128,0,1) + }; + + public static BHSDCodec[] deltaUnsignedCodecs3 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(52), // (2,8,0,1) + CodecEncoding.getCanonicalCodec(54), // (2,16,0,1) + CodecEncoding.getCanonicalCodec(56), // (2,32,0,1) + CodecEncoding.getCanonicalCodec(58), // (2,64,0,1) + CodecEncoding.getCanonicalCodec(60), // (2,128,0,1) + CodecEncoding.getCanonicalCodec(62), // (2,192,0,1) + CodecEncoding.getCanonicalCodec(64), // (2,224,0,1) + CodecEncoding.getCanonicalCodec(66), // (2,240,0,1) + CodecEncoding.getCanonicalCodec(68) // (2,248,0,1) + }; + + public static BHSDCodec[] deltaUnsignedCodecs4 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(75), // (3,8,0,1) + CodecEncoding.getCanonicalCodec(77), // (3,16,0,1) + CodecEncoding.getCanonicalCodec(79), // (3,32,0,1) + CodecEncoding.getCanonicalCodec(81), // (3,64,0,1) + CodecEncoding.getCanonicalCodec(83), // (3,128,0,1) + CodecEncoding.getCanonicalCodec(85), // (3,192,0,1) + CodecEncoding.getCanonicalCodec(87), // (3,224,0,1) + CodecEncoding.getCanonicalCodec(89), // (3,240,0,1) + CodecEncoding.getCanonicalCodec(91) // (3,248,0,1) + }; + + public static BHSDCodec[] deltaUnsignedCodecs5 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(98), // (4,8,0,1) + CodecEncoding.getCanonicalCodec(100), // (4,16,0,1) + CodecEncoding.getCanonicalCodec(102), // (4,32,0,1) + CodecEncoding.getCanonicalCodec(104), // (4,64,0,1) + CodecEncoding.getCanonicalCodec(106), // (4,128,0,1) + CodecEncoding.getCanonicalCodec(108), // (4,192,0,1) + CodecEncoding.getCanonicalCodec(110), // (4,224,0,1) + CodecEncoding.getCanonicalCodec(112), // (4,240,0,1) + CodecEncoding.getCanonicalCodec(114) // (4,248,0,1) + }; + + // Families of codecs for bands containing positive and negative integers + // that do correlate well (i.e. delta encoding is used) + + public static BHSDCodec[] deltaSignedCodecs1 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(4), // (1,256,1,1) + CodecEncoding.getCanonicalCodec(8), // (2,256,1,1) + CodecEncoding.getCanonicalCodec(12), // (3,256,1,1) + CodecEncoding.getCanonicalCodec(16) // (4,256,1,1) + }; + + public static BHSDCodec[] deltaSignedCodecs2 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(33), // (5,4,1,1) + CodecEncoding.getCanonicalCodec(36), // (5,16,1,1) + CodecEncoding.getCanonicalCodec(39), // (5,32,1,1) + CodecEncoding.getCanonicalCodec(42), // (5,64,1,1) + CodecEncoding.getCanonicalCodec(45) // (5,128,1,1) + }; + + public static BHSDCodec[] deltaSignedCodecs3 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(53), // (2,8,1,1) + CodecEncoding.getCanonicalCodec(55), // (2,16,1,1) + CodecEncoding.getCanonicalCodec(57), // (2,32,1,1) + CodecEncoding.getCanonicalCodec(59), // (2,64,1,1) + CodecEncoding.getCanonicalCodec(61), // (2,128,1,1) + CodecEncoding.getCanonicalCodec(63), // (2,192,1,1) + CodecEncoding.getCanonicalCodec(65), // (2,224,1,1) + CodecEncoding.getCanonicalCodec(67), // (2,240,1,1) + CodecEncoding.getCanonicalCodec(69) // (2,248,1,1) + }; + + public static BHSDCodec[] deltaSignedCodecs4 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(76), // (3,8,1,1) + CodecEncoding.getCanonicalCodec(78), // (3,16,1,1) + CodecEncoding.getCanonicalCodec(80), // (3,32,1,1) + CodecEncoding.getCanonicalCodec(82), // (3,64,1,1) + CodecEncoding.getCanonicalCodec(84), // (3,128,1,1) + CodecEncoding.getCanonicalCodec(86), // (3,192,1,1) + CodecEncoding.getCanonicalCodec(88), // (3,224,1,1) + CodecEncoding.getCanonicalCodec(90), // (3,240,1,1) + CodecEncoding.getCanonicalCodec(92) // (3,248,1,1) + }; + + public static BHSDCodec[] deltaSignedCodecs5 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(99), // (4,8,1,1) + CodecEncoding.getCanonicalCodec(101), // (4,16,1,1) + CodecEncoding.getCanonicalCodec(103), // (4,32,1,1) + CodecEncoding.getCanonicalCodec(105), // (4,64,1,1) + CodecEncoding.getCanonicalCodec(107), // (4,128,1,1) + CodecEncoding.getCanonicalCodec(109), // (4,192,1,1) + CodecEncoding.getCanonicalCodec(111), // (4,224,1,1) + CodecEncoding.getCanonicalCodec(113), // (4,240,1,1) + CodecEncoding.getCanonicalCodec(115) // (4,248,1,1) + }; + + public static BHSDCodec[] deltaDoubleSignedCodecs1 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(34), // (5,4,2,1) + CodecEncoding.getCanonicalCodec(37), // (5,16,2,1) + CodecEncoding.getCanonicalCodec(40), // (5,32,2,1) + CodecEncoding.getCanonicalCodec(43), // (5,64,2,1) + CodecEncoding.getCanonicalCodec(46) // (5,128,2,1) + }; + + // Families of codecs for bands containing positive and negative values that + // do not correlate well (i.e. delta encoding is not used) + + public static BHSDCodec[] nonDeltaSignedCodecs1 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(2), // (1,256,1) + CodecEncoding.getCanonicalCodec(6), // (2,256,1) + CodecEncoding.getCanonicalCodec(10), // (3,256,1) + CodecEncoding.getCanonicalCodec(14) // (4,256,1) + }; + + public static BHSDCodec[] nonDeltaSignedCodecs2 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(18), // (5,4,1) + CodecEncoding.getCanonicalCodec(21), // (5,16,1) + CodecEncoding.getCanonicalCodec(24), // (5,32,1) + CodecEncoding.getCanonicalCodec(27), // (5,64,1) + CodecEncoding.getCanonicalCodec(30) // (5,128,1) + }; + + public static BHSDCodec[] nonDeltaDoubleSignedCodecs1 = new BHSDCodec[] { + CodecEncoding.getCanonicalCodec(19), // (5,4,2) + CodecEncoding.getCanonicalCodec(22), // (5,16,2) + CodecEncoding.getCanonicalCodec(25), // (5,32,2) + CodecEncoding.getCanonicalCodec(28), // (5,64,2) + CodecEncoding.getCanonicalCodec(31) // (5,128,2) + }; + +} Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CanonicalCodecFamilies.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Codec.java Fri Jun 12 08:35:08 2009 @@ -85,6 +85,8 @@ */ public static final BHSDCodec UNSIGNED5 = new BHSDCodec(5, 64); + public int lastBandLength; + /** * Decode a sequence of bytes from the given input stream, returning the * value as a long. Note that this method can only be applied for non-delta @@ -99,7 +101,7 @@ * @throws Pack200Exception * if the encoding is a delta encoding */ - public abstract long decode(InputStream in) throws IOException, + public abstract int decode(InputStream in) throws IOException, Pack200Exception; /** @@ -112,7 +114,7 @@ * @return the encoded bytes * @throws Pack200Exception */ - public abstract byte[] encode(long value, long last) + public abstract byte[] encode(int value, int last) throws Pack200Exception; /** @@ -124,7 +126,7 @@ * @return the encoded bytes * @throws Pack200Exception */ - public abstract byte[] encode(long value) throws Pack200Exception; + public abstract byte[] encode(int value) throws Pack200Exception; /** * Decode a sequence of bytes from the given input stream, returning the @@ -154,7 +156,7 @@ * if there is a problem decoding the value or that the value is * invalid */ - public abstract long decode(InputStream in, long last) throws IOException, + public abstract int decode(InputStream in, long last) throws IOException, Pack200Exception; /** @@ -168,36 +170,6 @@ * the number of values to decode * @param in * the input stream to read from - * @return an array of long values corresponding to values - * decoded - * @throws IOException - * if there is a problem reading from the underlying input - * stream - * @throws Pack200Exception - * if there is a problem decoding the value or that the value is - * invalid - */ - public long[] decode(int n, InputStream in) throws IOException, - Pack200Exception { - long result[] = new long[n]; - long last = 0; - for (int i = 0; i < n; i++) { - result[i] = last = decode(in, last); - } - return result; - } - - /** - * Decodes a sequence of n values from in. - * This should probably be used in most cases, since some codecs (such as - * - * @{link PopCodec}) only work when the number of values to be read is - * known. - * - * @param n - * the number of values to decode - * @param in - * the input stream to read from * @return an array of int values corresponding to values * decoded * @throws IOException @@ -209,38 +181,10 @@ */ public int[] decodeInts(int n, InputStream in) throws IOException, Pack200Exception { + lastBandLength = 0; int result[] = new int[n]; int last = 0; for (int i = 0; i < n; i++) { - result[i] = last = (int) decode(in, last); - } - return result; - } - - /** - * Decodes a sequence of n values from in. - * - * @param n - * the number of values to decode - * @param in - * the input stream to read from - * @param firstValue - * the first value in the band if it has already been read - * @return an array of long values corresponding to values - * decoded, with firstValue as the first value in the array. - * @throws IOException - * if there is a problem reading from the underlying input - * stream - * @throws Pack200Exception - * if there is a problem decoding the value or that the value is - * invalid - */ - public long[] decode(int n, InputStream in, long firstValue) - throws IOException, Pack200Exception { - long result[] = new long[n + 1]; - result[0] = firstValue; - long last = firstValue; - for (int i = 1; i < n + 1; i++) { result[i] = last = decode(in, last); } return result; @@ -270,7 +214,7 @@ result[0] = firstValue; int last = firstValue; for (int i = 1; i < n + 1; i++) { - result[i] = last = (int) decode(in, last); + result[i] = last = decode(in, last); } return result; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CodecEncoding.java Fri Jun 12 08:35:08 2009 @@ -34,7 +34,7 @@ * one of the standard encodings. The following values are defined in the * Pack200 specification, and this array cannot be changed. */ - private static final Codec[] canonicalCodec = { null, + private static final BHSDCodec[] canonicalCodec = { null, new BHSDCodec(1, 256), new BHSDCodec(1, 256, 1), new BHSDCodec(1, 256, 0, 1), new BHSDCodec(1, 256, 1, 1), new BHSDCodec(2, 256), new BHSDCodec(2, 256, 1), @@ -292,7 +292,7 @@ int fDef = favouredCodec.equals(defaultForBand) ? 1 : 0; int uDef = unfavouredCodec.equals(defaultForBand) ? 1 : 0; int tDefL = 0; - long[] favoured = populationCodec.getFavoured(); + int[] favoured = populationCodec.getFavoured(); if(favoured != null) { int k = favoured.length; if(tokenCodec == Codec.BYTE1) { @@ -334,4 +334,8 @@ return null; } + + public static BHSDCodec getCanonicalCodec(int i) { + return canonicalCodec[i]; + } } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java Fri Jun 12 08:35:08 2009 @@ -93,9 +93,9 @@ writeCpClass(out); writeCpSignature(out); writeCpDescr(out); - writeCpMethodOrField(cp_Field, out); - writeCpMethodOrField(cp_Method, out); - writeCpMethodOrField(cp_Imethod, out); + writeCpMethodOrField(cp_Field, out, "cp_Field"); + writeCpMethodOrField(cp_Method, out, "cp_Method"); + writeCpMethodOrField(cp_Imethod, out, "cp_Imethod"); } private void writeCpUtf8(OutputStream out) throws IOException, @@ -175,7 +175,7 @@ cpInt[i] = integer.getInt(); i++; } - out.write(encodeBandInt("cpInt", cpInt, Codec.UDELTA5)); + out.write(encodeBandInt("cp_Int", cpInt, Codec.UDELTA5)); } private void writeCpFloat(OutputStream out) throws IOException, @@ -187,7 +187,7 @@ cpFloat[i] = Float.floatToIntBits(fl.getFloat()); i++; } - out.write(encodeBandInt("cpFloat", cpFloat, Codec.UDELTA5)); + out.write(encodeBandInt("cp_Float", cpFloat, Codec.UDELTA5)); } private void writeCpLong(OutputStream out) throws IOException, @@ -278,11 +278,11 @@ cpDescrType[i] = nameAndType.getTypeIndex(); i++; } - out.write(encodeBandInt("cpDescrName", cpDescrName, Codec.DELTA5)); - out.write(encodeBandInt("cpDescrType", cpDescrType, Codec.UDELTA5)); + out.write(encodeBandInt("cp_Descr_Name", cpDescrName, Codec.DELTA5)); + out.write(encodeBandInt("cp_Descr_Type", cpDescrType, Codec.UDELTA5)); } - private void writeCpMethodOrField(Set cp, OutputStream out) + private void writeCpMethodOrField(Set cp, OutputStream out, String name) throws IOException, Pack200Exception { int[] cp_methodOrField_class = new int[cp.size()]; int[] cp_methodOrField_desc = new int[cp.size()]; @@ -293,9 +293,9 @@ cp_methodOrField_desc[i] = mOrF.getDescIndex(); i++; } - out.write(encodeBandInt("cp_methodOrField_class", + out.write(encodeBandInt(name + "_class", cp_methodOrField_class, Codec.DELTA5)); - out.write(encodeBandInt("cp_methodOrField_desc", cp_methodOrField_desc, + out.write(encodeBandInt(name + "_desc", cp_methodOrField_desc, Codec.UDELTA5)); } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java Fri Jun 12 08:35:08 2009 @@ -104,7 +104,7 @@ int index = 0; for (int i = 0; i < bytes.length; i++) { for (int j = 0; j < bytes[i].length; j++) { - band[index++] = bytes[i][j]; + band[index++] = bytes[i][j] & 0xFF; } } return band; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/PopulationCodec.java Fri Jun 12 08:35:08 2009 @@ -22,7 +22,7 @@ /** * A PopulationCodec is a Codec that is well suited to encoding data that shows - * statistical or repetetive patterns, containign for example a few numbers + * statistical or repetitive patterns, containing for example a few numbers * which are repeated a lot throughout the set, but not necessarily * sequentially. */ @@ -32,12 +32,12 @@ private Codec tokenCodec; private final Codec unvafouredCodec; private int l; - private long[] favoured; + private int[] favoured; - public PopulationCodec(Codec favouredCodec, Codec tableCodec, + public PopulationCodec(Codec favouredCodec, Codec tokenCodec, Codec unvafouredCodec) { this.favouredCodec = favouredCodec; - this.tokenCodec = tableCodec; + this.tokenCodec = tokenCodec; this.unvafouredCodec = unvafouredCodec; } @@ -49,26 +49,27 @@ this.unvafouredCodec = unvafouredCodec; } - public long decode(InputStream in) throws IOException, Pack200Exception { + public int decode(InputStream in) throws IOException, Pack200Exception { throw new Pack200Exception( "Population encoding does not work unless the number of elements are known"); } - public long decode(InputStream in, long last) throws IOException, + public int decode(InputStream in, long last) throws IOException, Pack200Exception { throw new Pack200Exception( "Population encoding does not work unless the number of elements are known"); } - public long[] decode(int n, InputStream in) throws IOException, + public int[] decodeInts(int n, InputStream in) throws IOException, Pack200Exception { - favoured = new long[n]; // there must be <= n values, but probably a lot + lastBandLength = 0; + favoured = new int[n]; // there must be <= n values, but probably a lot // less - long result[]; + int result[]; // read table of favorites first - long smallest = Long.MAX_VALUE; - long last = 0; - long value = 0; + int smallest = Integer.MAX_VALUE; + int last = 0; + int value = 0; int k = -1; while (true) { value = favouredCodec.decode(in, last); @@ -83,6 +84,7 @@ } last = value; } + lastBandLength += k; // if tokenCodec needs to be derived from the T, L and K values if (tokenCodec == null) { if (k < 256) { @@ -102,12 +104,14 @@ } } // read favorites - result = tokenCodec.decode(n, in); + lastBandLength += n; + result = tokenCodec.decodeInts(n, in); // read unfavorites last = 0; for (int i = 0; i < n; i++) { - int index = (int) result[i]; + int index = result[i]; if (index == 0) { + lastBandLength++; result[i] = last = unvafouredCodec.decode(in, last); } else { result[i] = favoured[index - 1]; @@ -116,17 +120,7 @@ return result; } - public int[] decodeInts(int n, InputStream in) throws IOException, - Pack200Exception { - long[] result = decode(n, in); - int[] intRes = new int[result.length]; - for (int i = 0; i < intRes.length; i++) { - intRes[i] = (int) result[i]; - } - return intRes; - } - - public long[] getFavoured() { + public int[] getFavoured() { return favoured; } @@ -138,14 +132,23 @@ return unvafouredCodec; } - public byte[] encode(long value, long last) throws Pack200Exception { - // TODO Auto-generated method stub - return null; + public byte[] encode(int value, int last) throws Pack200Exception { + throw new Pack200Exception( + "Population encoding does not work unless the number of elements are known"); } - public byte[] encode(long value) throws Pack200Exception { - // TODO Auto-generated method stub - return null; + public byte[] encode(int value) throws Pack200Exception { + throw new Pack200Exception( + "Population encoding does not work unless the number of elements are known"); + } + + public byte[] encode(int[] favoured, int[] tokens, int[] unfavoured) throws Pack200Exception { + byte[] favouredEncoded = favouredCodec.encode(favoured); + byte[] tokensEncoded = tokenCodec.encode(tokens); + byte[] unfavouredEncoded = unvafouredCodec.encode(unfavoured); + byte[] band = new byte[favouredEncoded.length + tokensEncoded.length + unfavouredEncoded.length]; + + return band; } public Codec getTokenCodec() { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/RunCodec.java Fri Jun 12 08:35:08 2009 @@ -31,7 +31,7 @@ private int k; private final Codec aCodec; private final Codec bCodec; - private long last; + private int last; public RunCodec(int k, Codec aCodec, Codec bCodec) throws Pack200Exception { if (k <= 0) @@ -44,14 +44,14 @@ this.bCodec = bCodec; } - public long decode(InputStream in) throws IOException, Pack200Exception { + public int decode(InputStream in) throws IOException, Pack200Exception { return decode(in, this.last); } - public long decode(InputStream in, long last) throws IOException, + public int decode(InputStream in, long last) throws IOException, Pack200Exception { if (--k >= 0) { - long value = aCodec.decode(in, this.last); + int value = aCodec.decode(in, this.last); this.last = (k == 0 ? 0 : value); return normalise(aCodec, value); } else { @@ -60,7 +60,7 @@ } } - private long normalise(Codec codecUsed, long value) { + private int normalise(Codec codecUsed, int value) { if (codecUsed instanceof BHSDCodec && ((BHSDCodec) codecUsed).isDelta()) { BHSDCodec bhsd = (BHSDCodec) codecUsed; long cardinality = bhsd.cardinality(); @@ -83,6 +83,7 @@ normalise(bValues, bCodec); System.arraycopy(aValues, 0, band, 0, k); System.arraycopy(bValues, 0, band, k, n - k); + lastBandLength = aCodec.lastBandLength + bCodec.lastBandLength; return band; } @@ -100,7 +101,7 @@ } } else if (codecUsed instanceof PopulationCodec) { PopulationCodec popCodec = (PopulationCodec) codecUsed; - long[] favoured = (long[]) popCodec.getFavoured().clone(); + int[] favoured = (int[]) popCodec.getFavoured().clone(); Arrays.sort(favoured); for (int i = 0; i < band.length; i++) { boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1; @@ -126,12 +127,12 @@ + "]"; } - public byte[] encode(long value, long last) throws Pack200Exception { + public byte[] encode(int value, int last) throws Pack200Exception { // TODO Auto-generated method stub return null; } - public byte[] encode(long value) throws Pack200Exception { + public byte[] encode(int value) throws Pack200Exception { // TODO Auto-generated method stub return null; } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java Fri Jun 12 08:35:08 2009 @@ -16,6 +16,7 @@ */ package org.apache.harmony.pack200; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -70,13 +71,19 @@ bcBands.finaliseBands(); fileBands.finaliseBands(); + // Temporary fix because we have to encode the other bands before + // segmentHeader, but probably not very good performance + ByteArrayOutputStream tempStream = new ByteArrayOutputStream(); + + cpBands.pack(tempStream); + attributeDefinitionBands.pack(tempStream); + icBands.pack(tempStream); + classBands.pack(tempStream); + bcBands.pack(tempStream); + fileBands.pack(tempStream); + segmentHeader.pack(out); - cpBands.pack(out); - attributeDefinitionBands.pack(out); - icBands.pack(out); - classBands.pack(out); - bcBands.pack(out); - fileBands.pack(out); + tempStream.writeTo(out); } private void processClasses(List classes) { @@ -166,7 +173,7 @@ public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) { - // TODO Auto-generated method stub + // TODO: Java 6 - implement support for this } Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/BandSet.java Fri Jun 12 08:35:08 2009 @@ -108,20 +108,14 @@ // First element should not be discarded band = codec.decodeInts(count - 1, in, first); } - if (codecUsed instanceof BHSDCodec && ((BHSDCodec) codecUsed).isDelta()) { - BHSDCodec bhsd = (BHSDCodec) codecUsed; - long cardinality = bhsd.cardinality(); - for (int i = 0; i < band.length; i++) { - while (band[i] > bhsd.largest()) { - band[i] -= cardinality; - } - while (band[i] < bhsd.smallest()) { - band[i] += cardinality; - } - } - } else if (codecUsed instanceof PopulationCodec) { + // Useful for debugging -E options: + //if(!codecUsed.equals(codec)) { + // int bytes = codecUsed.lastBandLength; + // System.out.println(count + " " + name + " encoded with " + codecUsed + " " + bytes); + //} + if (codecUsed instanceof PopulationCodec) { PopulationCodec popCodec = (PopulationCodec) codecUsed; - long[] favoured = (long[]) popCodec.getFavoured().clone(); + int[] favoured = (int[]) popCodec.getFavoured().clone(); Arrays.sort(favoured); for (int i = 0; i < band.length; i++) { boolean favouredValue = Arrays.binarySearch(favoured, band[i]) > -1; Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/unpack200/SegmentHeader.java Fri Jun 12 08:35:08 2009 @@ -103,16 +103,16 @@ public void read(InputStream in) throws IOException, Pack200Exception, Error, Pack200Exception { - long word[] = decodeScalar("archive_magic_word", in, Codec.BYTE1, + int word[] = decodeScalar("archive_magic_word", in, Codec.BYTE1, magic.length); for (int m = 0; m < magic.length; m++) if (word[m] != magic[m]) throw new Error("Bad header"); - setArchiveMinorVersion((int) decodeScalar("archive_minver", in, + setArchiveMinorVersion(decodeScalar("archive_minver", in, Codec.UNSIGNED5)); - setArchiveMajorVersion((int) decodeScalar("archive_majver", in, + setArchiveMajorVersion(decodeScalar("archive_majver", in, Codec.UNSIGNED5)); - options = new SegmentOptions((int) decodeScalar("archive_options", in, + options = new SegmentOptions(decodeScalar("archive_options", in, Codec.UNSIGNED5)); parseArchiveFileCounts(in); parseArchiveSpecialCounts(in); @@ -290,7 +290,7 @@ Codec.UNSIGNED5)); setArchiveModtime(decodeScalar("archive_modtime", in, Codec.UNSIGNED5)); - numberOfFiles = (int) decodeScalar("file_count", in, + numberOfFiles = decodeScalar("file_count", in, Codec.UNSIGNED5); } } @@ -298,7 +298,7 @@ private void parseArchiveSpecialCounts(InputStream in) throws IOException, Pack200Exception { if (getOptions().hasSpecialFormats()) { - bandHeadersSize = (int) decodeScalar("band_headers_size", in, + bandHeadersSize = decodeScalar("band_headers_size", in, Codec.UNSIGNED5); setAttributeDefinitionCount(decodeScalar("attr_definition_count", in, Codec.UNSIGNED5)); @@ -307,37 +307,37 @@ private void parseClassCounts(InputStream in) throws IOException, Pack200Exception { - innerClassCount = (int) decodeScalar("ic_count", in, Codec.UNSIGNED5); - defaultClassMinorVersion = (int) decodeScalar("default_class_minver", + innerClassCount = decodeScalar("ic_count", in, Codec.UNSIGNED5); + defaultClassMinorVersion = decodeScalar("default_class_minver", in, Codec.UNSIGNED5); - defaultClassMajorVersion = (int) decodeScalar("default_class_majver", + defaultClassMajorVersion = decodeScalar("default_class_majver", in, Codec.UNSIGNED5); - classCount = (int) decodeScalar("class_count", in, Codec.UNSIGNED5); + classCount = decodeScalar("class_count", in, Codec.UNSIGNED5); } private void parseCpCounts(InputStream in) throws IOException, Pack200Exception { - cpUTF8Count = (int) decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5); + cpUTF8Count = decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5); if (getOptions().hasCPNumberCounts()) { - cpIntCount = (int) decodeScalar("cp_Int_count", in, Codec.UNSIGNED5); - cpFloatCount = (int) decodeScalar("cp_Float_count", in, + cpIntCount = decodeScalar("cp_Int_count", in, Codec.UNSIGNED5); + cpFloatCount = decodeScalar("cp_Float_count", in, Codec.UNSIGNED5); - cpLongCount = (int) decodeScalar("cp_Long_count", in, + cpLongCount = decodeScalar("cp_Long_count", in, Codec.UNSIGNED5); - cpDoubleCount = (int) decodeScalar("cp_Double_count", in, + cpDoubleCount = decodeScalar("cp_Double_count", in, Codec.UNSIGNED5); } - cpStringCount = (int) decodeScalar("cp_String_count", in, + cpStringCount = decodeScalar("cp_String_count", in, Codec.UNSIGNED5); - cpClassCount = (int) decodeScalar("cp_Class_count", in, Codec.UNSIGNED5); - cpSignatureCount = (int) decodeScalar("cp_Signature_count", in, + cpClassCount = decodeScalar("cp_Class_count", in, Codec.UNSIGNED5); + cpSignatureCount = decodeScalar("cp_Signature_count", in, Codec.UNSIGNED5); - cpDescriptorCount = (int) decodeScalar("cp_Descr_count", in, + cpDescriptorCount = decodeScalar("cp_Descr_count", in, Codec.UNSIGNED5); - cpFieldCount = (int) decodeScalar("cp_Field_count", in, Codec.UNSIGNED5); - cpMethodCount = (int) decodeScalar("cp_Method_count", in, + cpFieldCount = decodeScalar("cp_Field_count", in, Codec.UNSIGNED5); + cpMethodCount = decodeScalar("cp_Method_count", in, Codec.UNSIGNED5); - cpIMethodCount = (int) decodeScalar("cp_Imethod_count", in, + cpIMethodCount = decodeScalar("cp_Imethod_count", in, Codec.UNSIGNED5); } @@ -360,11 +360,11 @@ * if there is a problem decoding the value or that the value is * invalid */ - private long[] decodeScalar(String name, InputStream in, BHSDCodec codec, + private int[] decodeScalar(String name, InputStream in, BHSDCodec codec, int n) throws IOException, Pack200Exception { segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " (" + n + ")"); - return codec.decode(n, in); + return codec.decodeInts(n, in); } /** @@ -386,9 +386,9 @@ * if there is a problem decoding the value or that the value is * invalid */ - private long decodeScalar(String name, InputStream in, BHSDCodec codec) + private int decodeScalar(String name, InputStream in, BHSDCodec codec) throws IOException, Pack200Exception { - long ret = codec.decode(in); + int ret = codec.decode(in); segment .log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " as " + ret); Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java Fri Jun 12 08:35:08 2009 @@ -42,9 +42,13 @@ // range of the codec long largest = codec.largest(); long smallest = codec.isSigned() ? codec.smallest() : 0; + if(smallest < Integer.MIN_VALUE) smallest = Integer.MIN_VALUE; long difference = (largest - smallest) / 4; for (long j = smallest; j <= largest; j += difference) { - byte[] encoded = codec.encode(j, 0); + if(j > Integer.MAX_VALUE) { + break; + } + byte[] encoded = codec.encode((int)j, 0); long decoded = 0; try { decoded = codec.decode( Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/CodecTest.java Fri Jun 12 08:35:08 2009 @@ -23,6 +23,7 @@ import junit.framework.TestCase; import org.apache.harmony.pack200.BHSDCodec; +import org.apache.harmony.pack200.CanonicalCodecFamilies; import org.apache.harmony.pack200.Codec; import org.apache.harmony.pack200.Pack200Exception; import org.apache.harmony.pack200.RunCodec; @@ -203,8 +204,6 @@ (byte) 255, (byte) 191 }, 51130559, 0); decode(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192, (byte) 192, 0 }, 51130560, 0); - decode(Codec.UNSIGNED5, new byte[] { (byte) 255, (byte) 252, - (byte) 252, (byte) 252, (byte) 252 }, 0xFFFFFFFFL, 0); decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192 }); decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192 }); decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, @@ -212,6 +211,27 @@ decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192, (byte) 192 }); } + public void testCodecFamilies() { + checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs1); + checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs2); + checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs3); + checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs4); + checkAscendingCardinalities(CanonicalCodecFamilies.nonDeltaUnsignedCodecs5); + checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs1); + checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs2); + checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs3); + checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs4); + checkAscendingCardinalities(CanonicalCodecFamilies.deltaUnsignedCodecs5); + } + + private void checkAscendingCardinalities(BHSDCodec[] family) { + for (int i = 1; i < family.length; i++) { + BHSDCodec previous = family[i-1]; + BHSDCodec codec = family[i]; + assertTrue(codec.largest() >= previous.largest()); + assertTrue(codec.smallest() <= previous.smallest()); + } + } private void decodeFail(final Codec codec, final byte[] data) throws IOException, Pack200Exception { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java Fri Jun 12 08:35:08 2009 @@ -55,7 +55,7 @@ throws IOException, Pack200Exception { InputStream in = new ByteArrayInputStream(data); - long[] result = new PopulationCodec(codec, codec, codec).decode( + int[] result = new PopulationCodec(codec, codec, codec).decodeInts( expectedResult.length, in); assertEquals(expectedResult.length, result.length); for (int i = 0; i < expectedResult.length; i++) { Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java?rev=784030&r1=784029&r2=784030&view=diff ============================================================================== --- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java (original) +++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/unpack200/tests/ClassBandsTest.java Fri Jun 12 08:35:08 2009 @@ -92,8 +92,8 @@ byte[] classThis = Codec.DELTA5.encode(1, 0); byte[] classSuper = Codec.DELTA5.encode(2, 0); byte[] classInterfaceCount = Codec.DELTA5.encode(2, 0); - byte[] classInterfaceRef1 = encodeBandLong( - new long[] { 3, 4 }, Codec.DELTA5); + byte[] classInterfaceRef1 = encodeBandInt( + new int[] { 3, 4 }, Codec.DELTA5); byte[] classFieldCount = Codec.DELTA5.encode(0, 0); byte[] classMethodCount = Codec.DELTA5.encode(0, 0); byte[] classFlags = Codec.UNSIGNED5.encode(0, 0); @@ -132,10 +132,10 @@ byte[] classInterfaceCount = Codec.DELTA5.encode(0, 0); byte[] classFieldCount = Codec.DELTA5.encode(0, 0); byte[] classMethodCount = Codec.DELTA5.encode(3, 0); - byte[] methodDescr = encodeBandLong(new long[] { 0, 1, 2 }, + byte[] methodDescr = encodeBandInt(new int[] { 0, 1, 2 }, Codec.MDELTA5); - byte[] methodFlagsLo = encodeBandLong( - new long[] { 0, 0, 0 }, Codec.UNSIGNED5); + byte[] methodFlagsLo = encodeBandInt( + new int[] { 0, 0, 0 }, Codec.UNSIGNED5); byte[] classFlags = Codec.UNSIGNED5.encode(0, 0); byte[][] allArrays = new byte[][] { classThis, classSuper, classInterfaceCount, classFieldCount, classMethodCount, @@ -166,7 +166,7 @@ cpDescriptor = null; } - public byte[] encodeBandLong(long[] data, BHSDCodec codec) + public byte[] encodeBandInt(int[] data, BHSDCodec codec) throws IOException, Pack200Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int i = 0; i < data.length; i++) {