You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sj...@apache.org on 2008/11/19 17:36:11 UTC

svn commit: r719007 - /harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/

Author: sjanuary
Date: Wed Nov 19 08:36:11 2008
New Revision: 719007

URL: http://svn.apache.org/viewvc?rev=719007&view=rev
Log:
Ongoing pack200 development

Modified:
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java
    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/BcBands.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPClass.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPSignature.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.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/IcBands.java
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java Wed Nov 19 08:36:11 2008
@@ -30,6 +30,11 @@
  */
 public class AttributeDefinitionBands extends BandSet {
 
+    public static final int CONTEXT_CLASS = 0;
+    public static final int CONTEXT_CODE = 3;
+    public static final int CONTEXT_FIELD = 1;
+    public static final int CONTEXT_METHOD = 2;
+
     private final Map layouts = new HashMap();
 
     private final SegmentHeader segmentHeader;
@@ -42,18 +47,22 @@
     private final List attributeDefinitions = new ArrayList();
 
     private final CpBands cpBands;
+    private final Segment segment;
 
-    public AttributeDefinitionBands(SegmentHeader segmentHeader, CpBands cpBands) {
-        this.segmentHeader = segmentHeader;
-        this.cpBands = cpBands;
+    public AttributeDefinitionBands(Segment segment) {
+        this.segmentHeader = segment.getSegmentHeader();
+        this.cpBands = segment.getCpBands();
+        this.segment = segment;
     }
 
     public void finaliseBands() {
+        addSyntheticDefinitions();
         segmentHeader.setAttribute_definition_count(classAttributes.keySet()
                 .size()
                 + methodAttributes.keySet().size()
                 + fieldAttributes.keySet().size()
-                + codeAttributes.keySet().size());
+                + codeAttributes.keySet().size()
+                + attributeDefinitions.size());
         if (classAttributes.keySet().size() > 7) {
             segmentHeader.setHave_class_flags_hi(true);
         }
@@ -73,31 +82,31 @@
         if(classAttributes.size() > 7) {
             availableClassIndices = addHighIndices(availableClassIndices);
         }
-        addAttributeDefinitions(classAttributes, availableClassIndices, 0);
+        addAttributeDefinitions(classAttributes, availableClassIndices, CONTEXT_CLASS);
         int[] availableMethodIndices = new int[] {26, 27, 28, 29, 30, 31};
         if(methodAttributes.size() > 6) {
             availableMethodIndices = addHighIndices(availableMethodIndices);
         }
-        addAttributeDefinitions(methodAttributes, availableMethodIndices, 0);
+        addAttributeDefinitions(methodAttributes, availableMethodIndices, CONTEXT_METHOD);
         int[] availableFieldIndices = new int[] {18, 23, 24, 25, 26, 27, 28, 29, 30, 31};
         if(fieldAttributes.size() > 10) {
             availableFieldIndices = addHighIndices(availableFieldIndices);
         }
-        addAttributeDefinitions(fieldAttributes, availableFieldIndices, 0);
+        addAttributeDefinitions(fieldAttributes, availableFieldIndices, CONTEXT_FIELD);
         int[] availableCodeIndices = new int[] {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
         if(codeAttributes.size() > 15) {
             availableCodeIndices = addHighIndices(availableCodeIndices);
         }
-        addAttributeDefinitions(codeAttributes, availableCodeIndices, 0);
+        addAttributeDefinitions(codeAttributes, availableCodeIndices, CONTEXT_CODE);
 
         int[] attributeDefinitionHeader = new int[attributeDefinitions.size()];
         int[] attributeDefinitionName = new int[attributeDefinitions.size()];
         int[] attributeDefinitionLayout = new int[attributeDefinitions.size()];
         for (int i = 0; i < attributeDefinitionLayout.length; i++) {
             AttributeDefinition def = (AttributeDefinition) attributeDefinitions.get(i);
-            attributeDefinitionHeader[i] = def.contextType | (def.index << 2);
-            attributeDefinitionName[i] = cpBands.getCPUtf8(def.name).getIndex();
-            attributeDefinitionLayout[i] = cpBands.getCPUtf8(def.layout).getIndex();
+            attributeDefinitionHeader[i] = def.contextType | (def.index + 1 << 2);
+            attributeDefinitionName[i] = def.name.getIndex();
+            attributeDefinitionLayout[i] = def.layout.getIndex();
         }
 
         out.write(encodeBandInt("attributeDefinitionHeader", attributeDefinitionHeader, Codec.BYTE1));
@@ -105,6 +114,25 @@
         out.write(encodeBandInt("attributeDefinitionLayout", attributeDefinitionLayout, Codec.UNSIGNED5));
     }
 
+    private void addSyntheticDefinitions() {
+        boolean anySytheticClasses = segment.getClassBands().isAnySyntheticClasses();
+        boolean anySyntheticMethods = segment.getClassBands().isAnySyntheticMethods();
+        boolean anySyntheticFields = segment.getClassBands().isAnySyntheticFields();
+        if(anySytheticClasses || anySyntheticMethods || anySyntheticFields) {
+            CPUTF8 syntheticUTF = cpBands.getCPUtf8("Synthetic");
+            CPUTF8 emptyUTF = cpBands.getCPUtf8("");
+            if(anySytheticClasses) {
+                attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_CLASS, syntheticUTF, emptyUTF));
+            }
+            if(anySyntheticMethods) {
+                attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_METHOD, syntheticUTF, emptyUTF));
+            }
+            if(anySyntheticFields) {
+                attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_FIELD, syntheticUTF, emptyUTF));
+            }
+        }
+    }
+
     private int[] addHighIndices(int[] availableIndices) {
         int[] temp = new int[availableIndices.length + 32];
         for (int i = 0; i < availableIndices.length; i++) {
@@ -125,7 +153,7 @@
             String name = (String) iterator.next();
             String layout = (String) layouts.get(name);
             int index = availableIndices[i];
-            attributeDefinitions.add(new AttributeDefinition(index, contextType, name, layout));
+            attributeDefinitions.add(new AttributeDefinition(index, contextType, cpBands.getCPUtf8(name), cpBands.getCPUtf8(layout)));
         }
     }
 
@@ -137,11 +165,11 @@
 
         public int index;
         public int contextType;
-        public String name;
-        public String layout;
+        public CPUTF8 name;
+        public CPUTF8 layout;
 
-        public AttributeDefinition(int index, int contextType, String name,
-                String layout) {
+        public AttributeDefinition(int index, int contextType, CPUTF8 name,
+                CPUTF8 layout) {
             this.index = index;
             this.contextType = contextType;
             this.name = name;

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=719007&r1=719006&r2=719007&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 Wed Nov 19 08:36:11 2008
@@ -283,6 +283,9 @@
 //        }
         long z = value;
         if (isSigned()) {
+            if(z < Integer.MIN_VALUE) {
+                z += 4294967296L;
+            }
             if (z < 0) {
                 z = (-z << s) - 1;
             } else {

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java Wed Nov 19 08:36:11 2008
@@ -154,27 +154,29 @@
                 bciRenumbering.add(i, new Integer(++renumberedOffset));
             }
         }
-        if (renumberedOffset + 1 != bciRenumbering.size()) {
-            throw new RuntimeException("Mistake made with renumbering");
-        }
-        for (int i = bcLabel.size() - 1; i >= 0; i--) {
-            Object label = bcLabel.get(i);
-            if (label instanceof Integer) {
-                break;
-            } else if (label instanceof Label) {
-                bcLabel.remove(i);
-                Integer offset = (Integer) labelsToOffsets.get(label);
-                Integer relativeOffset = (Integer) bcLabelRelativeOffsets.get(i);
-                bcLabel.add(i, new Integer(((Integer)bciRenumbering.get(offset.intValue())).intValue() - ((Integer)bciRenumbering.get(relativeOffset.intValue())).intValue()));
+        if (renumberedOffset != 0) {
+            if(renumberedOffset + 1 != bciRenumbering.size()) {
+                throw new RuntimeException("Mistake made with renumbering");
             }
+            for (int i = bcLabel.size() - 1; i >= 0; i--) {
+                Object label = bcLabel.get(i);
+                if (label instanceof Integer) {
+                    break;
+                } else if (label instanceof Label) {
+                    bcLabel.remove(i);
+                    Integer offset = (Integer) labelsToOffsets.get(label);
+                    Integer relativeOffset = (Integer) bcLabelRelativeOffsets.get(i);
+                    bcLabel.add(i, new Integer(((Integer)bciRenumbering.get(offset.intValue())).intValue() - ((Integer)bciRenumbering.get(relativeOffset.intValue())).intValue()));
+                }
+            }
+            bcCodes.add(endMarker);
+            segment.getClassBands().doBciRenumbering(bciRenumbering,
+                    labelsToOffsets);
+            bciRenumbering.clear();
+            labelsToOffsets.clear();
+            byteCodeOffset = 0;
+            renumberedOffset = 0;
         }
-        bcCodes.add(endMarker);
-        segment.getClassBands().doBciRenumbering(bciRenumbering,
-                labelsToOffsets);
-        bciRenumbering.clear();
-        labelsToOffsets.clear();
-        byteCodeOffset = 0;
-        renumberedOffset = 0;
     }
 
     public void visitLabel(Label label) {
@@ -299,6 +301,8 @@
             } else if (constant instanceof CPClass) {
                 bcCodes.add(new Integer(236)); // cldc
                 bcClassRef.add(constant);
+            } else {
+                throw new RuntimeException("Constant should not be null");
             }
         } else {
             byteCodeOffset += 2;
@@ -329,7 +333,7 @@
             bcLabel.add(labels[i]);
             bcLabelRelativeOffsets.add(new Integer(byteCodeOffset));
         }
-        int padding = (byteCodeOffset + 1) % 4 == 0 ? 0 : 4 - byteCodeOffset + 1;
+        int padding = (byteCodeOffset + 1) % 4 == 0 ? 0 : 4 - ((byteCodeOffset + 1) % 4);
         byteCodeOffset += padding + 8 + 8 * keys.length;
         updateRenumbering();
     }
@@ -407,7 +411,7 @@
             bcLabel.add(labels[i]);
             bcLabelRelativeOffsets.add(new Integer(byteCodeOffset));
         }
-        int padding = (byteCodeOffset + 1) % 4 == 0 ? 0 : 4 - byteCodeOffset + 1;
+        int padding = (byteCodeOffset + 1) % 4 == 0 ? 0 : 4 - ((byteCodeOffset + 1) % 4);
         byteCodeOffset+= (padding + 12 + 4 * labels.length);
         updateRenumbering();
     }

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPClass.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPClass.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPClass.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPClass.java Wed Nov 19 08:36:11 2008
@@ -21,10 +21,19 @@
 
     private final String className;
     private final CPUTF8 utf8;
+    private final boolean isInnerClass;
 
     public CPClass(CPUTF8 utf8) {
         this.utf8 = utf8;
         this.className = utf8.getUnderlyingString();
+        char[] chars = className.toCharArray();
+        for (int i = 0; i < chars.length; i++) {
+            if(chars[i] <= 0x2D) {
+                isInnerClass = true;
+                return;
+            }
+        }
+        isInnerClass = false;
     }
 
     public int compareTo(Object arg0) {
@@ -39,4 +48,8 @@
         return utf8.getIndex();
     }
 
+    public boolean isInnerClass() {
+        return isInnerClass;
+    }
+
 }

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPSignature.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPSignature.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPSignature.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CPSignature.java Wed Nov 19 08:36:11 2008
@@ -48,15 +48,14 @@
             return classes.size() - ((CPSignature) arg0).classes.size();
         }
         if (classes.size() > 0) {
-            int classComp = 0;
             for (int i = classes.size() - 1; i >=0; i--) {
                 CPClass cpClass = (CPClass) classes.get(i);
                 CPClass compareClass = (CPClass) ((CPSignature) arg0).classes
                         .get(i);
-                classComp = classComp * 10 + cpClass.compareTo(compareClass);
-            }
-            if(classComp != 0) {
-                return classComp;
+                int classComp = cpClass.compareTo(compareClass);
+                if(classComp != 0) {
+                    return classComp;
+                }
             }
         }
         return signature.compareTo(((CPSignature) arg0).signature);

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java Wed Nov 19 08:36:11 2008
@@ -19,9 +19,14 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import org.apache.harmony.pack200.IcBands.IcTuple;
 import org.objectweb.asm.Attribute;
 import org.objectweb.asm.Label;
 
@@ -91,11 +96,18 @@
     private final List tempMethodFlags = new ArrayList();
     private final List tempMethodDesc = new ArrayList();
 
-    public ClassBands(SegmentHeader header, CpBands cpBands,
-            AttributeDefinitionBands attrBands, int numClasses) {
-        this.header = header;
-        this.cpBands = cpBands;
-        this.attrBands = attrBands;
+    private boolean anySyntheticClasses = false;
+    private boolean anySyntheticFields = false;
+    private boolean anySyntheticMethods = false;
+    private final Segment segment;
+
+    private final Map classReferencesInnerClass = new HashMap();
+
+    public ClassBands(Segment segment, int numClasses) {
+        this.segment = segment;
+        this.header = segment.getSegmentHeader();
+        this.cpBands = segment.getCpBands();
+        this.attrBands = segment.getAttrBands();
         class_this = new CPClass[numClasses];
         class_super = new CPClass[numClasses];
         class_interface_count = new int[numClasses];
@@ -114,6 +126,11 @@
     private int index = 0;
 
     private int numMethodArgs = 0;
+    private int[] class_InnerClasses_N;
+    private CPClass[] class_InnerClasses_RC;
+    private int[] class_InnerClasses_F;
+    private List classInnerClassesOuterRCN;
+    private List classInnerClassesNameRUN;
 
     public void addClass(int major, int flags, String className,
             String superName, String[] interfaces) {
@@ -126,6 +143,24 @@
         }
         major_versions[index] = major;
         class_flags[index] = flags;
+        if(!anySyntheticClasses && ((flags & (1 << 12)) != 0)) {
+            cpBands.addCPUtf8("Synthetic");
+            anySyntheticClasses = true;
+        }
+    }
+
+    public void currentClassReferencesInnerClass(CPClass inner) {
+        if(!(index >= class_this.length)) {
+            CPClass currentClass = class_this[index];
+            if(currentClass != null && !currentClass.equals(inner)) {
+                Set referencedInnerClasses = (Set)classReferencesInnerClass.get(currentClass);
+                if(referencedInnerClasses == null) {
+                    referencedInnerClasses = new HashSet();
+                    classReferencesInnerClass.put(currentClass, referencedInnerClasses);
+                }
+                referencedInnerClasses.add(inner);
+            }
+        }
     }
 
     public void addField(int flags, String name, String desc, String signature,
@@ -141,6 +176,10 @@
             fieldConstantValueKQ.add(cpBands.getConstant(value));
             flags |= (1 << 17);
         }
+        if(!anySyntheticFields && ((flags & (1 << 12)) != 0)) {
+            cpBands.addCPUtf8("Synthetic");
+            anySyntheticFields = true;
+        }
         tempFieldFlags.add(new Long(flags));
     }
 
@@ -188,20 +227,64 @@
                 removed++;
             }
         }
-    }
 
-    public void pack(OutputStream out) throws IOException, Pack200Exception {
-        int[] classThis = new int[class_this.length];
-        for (int i = 0; i < classThis.length; i++) {
-            classThis[i] = class_this[i].getIndex();
+        // Compute any required IcLocals
+        List innerClassesN = new ArrayList();
+        List icLocal = new ArrayList();
+        Set keySet = classReferencesInnerClass.keySet();
+        for (int i = 0; i < class_this.length; i++) {
+            CPClass cpClass = class_this[i];
+            Set referencedInnerClasses = (Set) classReferencesInnerClass.get(cpClass);
+            if(referencedInnerClasses != null) {
+                int innerN = 0;
+                List innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
+                if(innerClasses != null) {
+                    for (Iterator iterator2 = innerClasses.iterator(); iterator2
+                            .hasNext();) {
+                        referencedInnerClasses.remove(((IcTuple)iterator2.next()).C);
+                    }
+                }
+                for (Iterator iterator2 = referencedInnerClasses.iterator(); iterator2
+                        .hasNext();) {
+                    CPClass inner = (CPClass) iterator2.next();
+                    IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
+                    if(icTuple != null) {
+                        // should transmit an icLocal entry
+                        icLocal.add(icTuple);
+                        innerN++;
+                    }
+                }
+                if(innerN != 0) {
+                    innerClassesN.add(new Integer(innerN));
+                    class_flags[i] |= (1 << 23);
+                }
+            }
         }
-        out.write(encodeBandInt("class_this", classThis, Codec.DELTA5));
-
-        int[] classSuper = new int[class_super.length];
-        for (int i = 0; i < classSuper.length; i++) {
-            classSuper[i] = class_super[i].getIndex();
+        class_InnerClasses_N = listToArray(innerClassesN);
+        class_InnerClasses_RC = new CPClass[icLocal.size()];
+        class_InnerClasses_F = new int[icLocal.size()];
+        classInnerClassesOuterRCN = new ArrayList();
+        classInnerClassesNameRUN = new ArrayList();
+        for (int i = 0; i < class_InnerClasses_RC.length; i++) {
+            IcTuple icTuple = (IcTuple) icLocal.get(i);
+            class_InnerClasses_RC[i] = (icTuple.C);
+            if(icTuple.C2 == null && icTuple.N == null) {
+                class_InnerClasses_F[i] = 0;
+            } else {
+                if (icTuple.F == 0) {
+                    class_InnerClasses_F[i] = 0x00010000;
+                } else {
+                    class_InnerClasses_F[i] = icTuple.F;
+                }
+                classInnerClassesOuterRCN.add(icTuple.C2);
+                classInnerClassesNameRUN.add(icTuple.N);
+            }
         }
-        out.write(encodeBandInt("class_super", classSuper, Codec.DELTA5));
+    }
+
+    public void pack(OutputStream out) throws IOException, Pack200Exception {
+        out.write(encodeBandInt("class_this", getInts(class_this), Codec.DELTA5));
+        out.write(encodeBandInt("class_super", getInts(class_super), Codec.DELTA5));
         out.write(encodeBandInt("class_interface_count", class_interface_count,
                 Codec.DELTA5));
 
@@ -217,9 +300,8 @@
                 }
             }
         }
-        out
-                .write(encodeBandInt("class_interface", classInterface,
-                        Codec.DELTA5));
+        out.write(encodeBandInt("class_interface", classInterface,
+                Codec.DELTA5));
         out.write(encodeBandInt("class_field_count", class_field_count,
                 Codec.DELTA5));
         out.write(encodeBandInt("class_method_count", class_method_count,
@@ -297,14 +379,27 @@
         out.write(encodeBandInt("class_EnclosingMethod_RDN",
                 cpEntryOrNullListToArray(classEnclosingMethodDesc),
                 Codec.UNSIGNED5));
-        out.write(encodeBandInt("classSignature",
+        out.write(encodeBandInt("class_Signature_RS",
                 cpEntryListToArray(classSignature), Codec.UNSIGNED5));
+        out.write(encodeBandInt("class_InnerClasses_N", class_InnerClasses_N, Codec.UNSIGNED5));
+        out.write(encodeBandInt("class_InnerClasses_RC", getInts(class_InnerClasses_RC), Codec.UNSIGNED5));
+        out.write(encodeBandInt("class_InnerClasses_F", class_InnerClasses_F, Codec.UNSIGNED5));
+        out.write(encodeBandInt("class_InnerClasses_outer_RCN", cpEntryOrNullListToArray(classInnerClassesOuterRCN), Codec.UNSIGNED5));
+        out.write(encodeBandInt("class_InnerClasses_name_RUN", cpEntryOrNullListToArray(classInnerClassesNameRUN), Codec.UNSIGNED5));
         out.write(encodeBandInt("classFileVersionMinor",
                 listToArray(classFileVersionMinor), Codec.UNSIGNED5));
         out.write(encodeBandInt("classFileVersionMajor",
                 listToArray(classFileVersionMajor), Codec.UNSIGNED5));
     }
 
+    private int[] getInts(CPClass[] cpClasses) {
+        int[] ints = new int[cpClasses.length];
+        for (int i = 0; i < ints.length; i++) {
+            ints[i] = cpClasses[i].getIndex();
+        }
+        return ints;
+    }
+
     private void writeCodeBands(OutputStream out) throws IOException,
             Pack200Exception {
         out.write(encodeBandInt("codeHeaders", codeHeaders, Codec.BYTE1));
@@ -388,8 +483,11 @@
             flags |= (1 << 18);
         }
         tempMethodFlags.add(new Long(flags));
-        codeHandlerCount.add(ZERO);
         numMethodArgs = countArgs(desc);
+        if(!anySyntheticMethods && ((flags & (1 << 12)) != 0)) {
+            cpBands.addCPUtf8("Synthetic");
+            anySyntheticMethods = true;
+        }
     }
 
     protected static int countArgs(String descriptor) {
@@ -457,6 +555,9 @@
 
     public void addSourceFile(String source) {
         String implicitSourceFileName = class_this[index].toString();
+        if(implicitSourceFileName.indexOf('$') != -1) {
+            implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
+        }
         implicitSourceFileName = implicitSourceFileName
                 .substring(implicitSourceFileName.lastIndexOf('/') + 1)
                 + ".java";
@@ -499,6 +600,7 @@
     }
 
     public void addCode() {
+        codeHandlerCount.add(ZERO);
         codeFlags.add(new Long(0));
     }
 
@@ -631,4 +733,16 @@
             }
         }
     }
+
+    public boolean isAnySyntheticClasses() {
+        return anySyntheticClasses;
+    }
+
+    public boolean isAnySyntheticFields() {
+        return anySyntheticFields;
+    }
+
+    public boolean isAnySyntheticMethods() {
+        return anySyntheticMethods;
+    }
 }

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=719007&r1=719006&r2=719007&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 Wed Nov 19 08:36:11 2008
@@ -27,6 +27,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import org.objectweb.asm.Type;
+
 /**
  * Pack200 Constant Pool Bands
  */
@@ -54,12 +56,17 @@
     private final Map stringsToCpNameAndType = new HashMap();
     private final Map stringsToCpClass = new HashMap();
     private final Map stringsToCpSignature = new HashMap();
-    private final Map stringsToCpMethodOrField = new HashMap();
+    private final Map stringsToCpMethod = new HashMap();
+    private final Map stringsToCpField = new HashMap();
+    private final Map stringsToCpIMethod = new HashMap();
 
     private final Map objectsToCPConstant = new HashMap();
 
-    public CpBands(SegmentHeader segmentHeader) {
-        this.segmentHeader = segmentHeader;
+    private final Segment segment;
+
+    public CpBands(Segment segment) {
+        this.segmentHeader = segment.getSegmentHeader();
+        this.segment = segment;
         defaultAttributeNames.add("AnnotationDefault");
         defaultAttributeNames.add("RuntimeVisibleAnnotations");
         defaultAttributeNames.add("RuntimeInvisibleAnnotations");
@@ -194,8 +201,8 @@
             loBits[i] = (int) l;
             i++;
         }
-        out.write(encodeBandInt("cp_Long_high", highBits, Codec.UDELTA5));
-        out.write(encodeBandInt("cp_Long_low", loBits, Codec.DELTA5));
+        out.write(encodeBandInt("cp_Long_hi", highBits, Codec.UDELTA5));
+        out.write(encodeBandInt("cp_Long_lo", loBits, Codec.DELTA5));
     }
 
     private void writeCpDouble(OutputStream out) throws IOException,
@@ -210,8 +217,8 @@
             loBits[i] = (int) l;
             i++;
         }
-        out.write(encodeBandInt("cp_Double_high", highBits, Codec.UDELTA5));
-        out.write(encodeBandInt("cp_Double_low", loBits, Codec.DELTA5));
+        out.write(encodeBandInt("cp_Double_hi", highBits, Codec.UDELTA5));
+        out.write(encodeBandInt("cp_Double_lo", loBits, Codec.DELTA5));
     }
 
     private void writeCpString(OutputStream out) throws IOException,
@@ -373,7 +380,7 @@
         }
     }
 
-    private void addCPUtf8(String utf8) {
+    void addCPUtf8(String utf8) {
         getCPUtf8(utf8);
     }
 
@@ -453,6 +460,9 @@
             cp_Class.add(cpClass);
             stringsToCpClass.put(className, cpClass);
         }
+        if(cpClass.isInnerClass()) {
+            segment.getClassBands().currentClassReferencesInnerClass(cpClass);
+        }
         return cpClass;
     }
 
@@ -475,13 +485,13 @@
 
     public CPMethodOrField getCPField(CPClass cpClass, String name, String desc) {
         String key = cpClass.toString() + ":" + name + ":" + desc;
-        CPMethodOrField cpF = (CPMethodOrField) stringsToCpMethodOrField
+        CPMethodOrField cpF = (CPMethodOrField) stringsToCpField
                 .get(key);
         if (cpF == null) {
             CPNameAndType nAndT = getCPNameAndType(name, desc);
             cpF = new CPMethodOrField(cpClass, nAndT);
             cp_Field.add(cpF);
-            stringsToCpMethodOrField.put(key, cpF);
+            stringsToCpField.put(key, cpF);
         }
         return cpF;
     }
@@ -504,6 +514,9 @@
             } else if (value instanceof String) {
                 constant = new CPString(getCPUtf8((String) value));
                 cp_String.add(constant);
+            } else if (value instanceof Type) {
+                constant = new CPClass(getCPUtf8(((Type) value).getClassName()));
+                cp_Class.add(constant);
             }
             objectsToCPConstant.put(value, constant);
         }
@@ -512,13 +525,13 @@
 
     public CPMethodOrField getCPMethod(CPClass cpClass, String name, String desc) {
         String key = cpClass.toString() + ":" + name + ":" + desc;
-        CPMethodOrField cpM = (CPMethodOrField) stringsToCpMethodOrField
+        CPMethodOrField cpM = (CPMethodOrField) stringsToCpMethod
                 .get(key);
         if (cpM == null) {
             CPNameAndType nAndT = getCPNameAndType(name, desc);
             cpM = new CPMethodOrField(cpClass, nAndT);
             cp_Method.add(cpM);
-            stringsToCpMethodOrField.put(key, cpM);
+            stringsToCpMethod.put(key, cpM);
         }
         return cpM;
     }
@@ -526,13 +539,13 @@
     public CPMethodOrField getCPIMethod(CPClass cpClass, String name,
             String desc) {
         String key = cpClass.toString() + ":" + name + ":" + desc;
-        CPMethodOrField cpIM = (CPMethodOrField) stringsToCpMethodOrField
+        CPMethodOrField cpIM = (CPMethodOrField) stringsToCpIMethod
                 .get(key);
         if (cpIM == null) {
             CPNameAndType nAndT = getCPNameAndType(name, desc);
             cpIM = new CPMethodOrField(cpClass, nAndT);
             cp_Imethod.add(cpIM);
-            stringsToCpMethodOrField.put(key, cpIM);
+            stringsToCpIMethod.put(key, cpIM);
         }
         return cpIM;
     }
@@ -551,12 +564,12 @@
 
     public CPMethodOrField addCPMethod(CPClass cpClass, String name, String desc) {
         String key = cpClass.toString() + ":" + name + ":" + desc;
-        CPMethodOrField cpM = (CPMethodOrField) stringsToCpMethodOrField
+        CPMethodOrField cpM = (CPMethodOrField) stringsToCpMethod
                 .get(key);
         if (cpM == null) {
             CPNameAndType nAndT = getCPNameAndType(name, desc);
             cpM = new CPMethodOrField(cpClass, nAndT);
-            stringsToCpMethodOrField.put(key, cpM);
+            stringsToCpMethod.put(key, cpM);
             cp_Method.add(cpM);
         }
         return cpM;
@@ -564,12 +577,12 @@
 
     public CPMethodOrField addCPField(CPClass cpClass, String name, String desc) {
         String key = cpClass.toString() + ":" + name + ":" + desc;
-        CPMethodOrField cpF = (CPMethodOrField) stringsToCpMethodOrField
+        CPMethodOrField cpF = (CPMethodOrField) stringsToCpField
                 .get(key);
         if (cpF == null) {
             CPNameAndType nAndT = getCPNameAndType(name, desc);
             cpF = new CPMethodOrField(cpClass, nAndT);
-            stringsToCpMethodOrField.put(key, cpF);
+            stringsToCpField.put(key, cpF);
             cp_Field.add(cpF);
         }
         return cpF;

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java?rev=719007&r1=719006&r2=719007&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java Wed Nov 19 08:36:11 2008
@@ -19,17 +19,22 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 public class IcBands extends BandSet {
 
-    private final Set innerClasses = new HashSet();
+    private final Set innerClasses = new TreeSet();
     private final SegmentHeader segmentHeader;
     private final CpBands cpBands;
     private int bit16Count = 0;
 
+    private final Map outerToInner = new HashMap();
+
     public IcBands(SegmentHeader segmentHeader, CpBands cpBands) {
         this.segmentHeader = segmentHeader;
         this.cpBands = cpBands;
@@ -66,17 +71,58 @@
     public void addInnerClass(String name, String outerName, String innerName,
             int flags) {
         if(outerName != null || innerName != null) {
-            flags |= (1<<16);
-            boolean added = innerClasses.add(new IcTuple(cpBands.getCPClass(name), flags, cpBands.getCPClass(outerName), cpBands.getCPUtf8(innerName)));
-            if(added) {
-                bit16Count++;
+            if(namesArePredictable(name, outerName, innerName)) {
+                IcTuple innerClass = new IcTuple(cpBands.getCPClass(name), flags, null, null);
+                addToMap(outerName, innerClass);
+                innerClasses.add(innerClass);
+            } else {
+                flags |= (1<<16);
+                IcTuple icTuple = new IcTuple(cpBands.getCPClass(name), flags, cpBands.getCPClass(outerName), cpBands.getCPUtf8(innerName));
+                boolean added = innerClasses.add(icTuple);
+                if(added) {
+                    bit16Count++;
+                    addToMap(outerName, icTuple);
+                }
             }
         } else {
-            innerClasses.add(new IcTuple(cpBands.getCPClass(name), flags, cpBands.getCPClass(outerName), cpBands.getCPUtf8(innerName)));
+            IcTuple innerClass = new IcTuple(cpBands.getCPClass(name), flags, null, null);
+            addToMap(getOuter(name), innerClass);
+            innerClasses.add(innerClass);
         }
     }
 
-    private class IcTuple {
+    public List getInnerClassesForOuter(String outerClassName) {
+        return (List) outerToInner.get(outerClassName);
+    }
+
+    private String getOuter(String name) {
+        return name.substring(0, name.lastIndexOf('$'));
+    }
+
+    private void addToMap(String outerName, IcTuple icTuple) {
+        List tuples = (List) outerToInner.get(outerName);
+        if(tuples == null) {
+            tuples = new ArrayList();
+            outerToInner.put(outerName, tuples);
+            tuples.add(icTuple);
+        } else {
+            for (Iterator iterator = tuples.iterator(); iterator.hasNext();) {
+                IcTuple icT = (IcTuple) iterator.next();
+                if(icTuple.equals(icT)) {
+                    return;
+                }
+            }
+            tuples.add(icTuple);
+        }
+    }
+
+    private boolean namesArePredictable(String name, String outerName,
+            String innerName) {
+        // TODO: Could be multiple characters, not just $
+        return name.equals(outerName + '$' + innerName) && innerName.indexOf('$') == -1;
+    }
+
+    class IcTuple implements Comparable {
 
         protected CPClass C; // this class
         protected int F; // flags
@@ -93,7 +139,7 @@
         public boolean equals(Object o) {
             if(o instanceof IcTuple) {
                 IcTuple icT = (IcTuple)o;
-                return C.equals(icT.C) && F == icT.F && C2 != null ? C2.equals(icT.C2) : icT.C2 == null && N != null ? N.equals(icT.N) : icT.N == null;
+                return C.equals(icT.C) && F == icT.F && (C2 != null ? C2.equals(icT.C2) : icT.C2 == null) && (N != null ? N.equals(icT.N) : icT.N == null);
             }
             return false;
         }
@@ -101,6 +147,25 @@
         public int hashCode() {
             return (C.hashCode() * 37) + F;
         }
+
+        public String toString() {
+            return C.toString();
+        }
+
+        public int compareTo(Object arg0) {
+            return C.compareTo(((IcTuple)arg0).C);
+        }
+
+    }
+
+    public IcTuple getIcTuple(CPClass inner) {
+        for (Iterator iterator = innerClasses.iterator(); iterator.hasNext();) {
+            IcTuple icTuple = (IcTuple) iterator.next();
+            if(icTuple.C.equals(inner)) {
+                return icTuple;
+            }
+        }
+        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=719007&r1=719006&r2=719007&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 Wed Nov 19 08:36:11 2008
@@ -38,10 +38,6 @@
     private BcBands bcBands;
     private FileBands fileBands;
 
-    // The current class - only to be used when processing the classes
-    private String currentClass;
-    private String superClass;
-
     private final SegmentFieldVisitor fieldVisitor = new SegmentFieldVisitor();
     private final SegmentMethodVisitor methodVisitor = new SegmentMethodVisitor();
     private final SegmentAnnotationVisitor annotationVisitor = new SegmentAnnotationVisitor();
@@ -51,12 +47,10 @@
             throws IOException, Pack200Exception {
         segmentHeader = new SegmentHeader();
         segmentHeader.setFile_count(files.size());
-        cpBands = new CpBands(segmentHeader);
-        attributeDefinitionBands = new AttributeDefinitionBands(segmentHeader,
-                cpBands);
+        cpBands = new CpBands(this);
+        attributeDefinitionBands = new AttributeDefinitionBands(this);
         icBands = new IcBands(segmentHeader, cpBands);
-        classBands = new ClassBands(segmentHeader, cpBands,
-                attributeDefinitionBands, classes.size());
+        classBands = new ClassBands(this, classes.size());
         bcBands = new BcBands(cpBands, this);
         fileBands = new FileBands(cpBands, segmentHeader, files);
 
@@ -90,8 +84,6 @@
 
     public void visit(int version, int access, String name, String signature,
             String superName, String[] interfaces) {
-        currentClass = name;
-        superClass = superName;
         bcBands.setCurrentClass(name);
         bcBands.setSuperClass(superName);
         segmentHeader.addMajorVersion(version);
@@ -299,4 +291,20 @@
     public boolean lastConstantHadWideIndex() {
         return currentClassReader.lastConstantHadWideIndex();
     }
+
+    public CpBands getCpBands() {
+        return cpBands;
+    }
+
+    public SegmentHeader getSegmentHeader() {
+        return segmentHeader;
+    }
+
+    public AttributeDefinitionBands getAttrBands() {
+        return attributeDefinitionBands;
+    }
+
+    public IcBands getIcBands() {
+        return icBands;
+    }
 }