OSDN Git Service

Compact merged dexes on their byte aligned size
authorCharlie Groves <charlie.groves@gmail.com>
Sun, 11 Mar 2012 07:40:47 +0000 (23:40 -0800)
committerCharlie Groves <charlie.groves@gmail.com>
Sun, 11 Mar 2012 07:40:47 +0000 (23:40 -0800)
Previously, if a merged dex had too much free space, the compaction step
would subtract the unused space from the section sizes generated by
adding the merged dexes section sizes. The merged sizes weren't 4-byte
aligned, which meant if a section had been bumped in size for the
boundary, the compaction would fail when loading into a section eg
'Section limit 3665072 exceeded by string data'.

This gets the compacted section size from the actual used space instead
of from the non-aligned estimate, so everything fits.

Change-Id: I1aee1abd721ec21998bb3ea78f6f424e7421b614

dx/src/com/android/dx/io/DexBuffer.java
dx/src/com/android/dx/merge/DexMerger.java

index d10b08c..85fbcb6 100644 (file)
@@ -304,10 +304,11 @@ public final class DexBuffer {
         private final String name;
         private int position;
         private final int limit;
+        private final int initialPosition;
 
         private Section(String name, int position, int limit) {
             this.name = name;
-            this.position = position;
+            this.position = this.initialPosition = position;
             this.limit = limit;
         }
 
@@ -645,5 +646,12 @@ public final class DexBuffer {
         public int remaining() {
             return limit - position;
         }
+
+        /**
+         * Returns the number of bytes used by this section.
+         */
+        public int used () {
+            return position - initialPosition;
+        }
     }
 }
index b807117..e7276cb 100644 (file)
@@ -190,8 +190,7 @@ public final class DexMerger {
          * result in too many bytes wasted, compact the result. To compact,
          * simply merge the result with itself.
          */
-        WriterSizes compactedSizes = writerSizes.clone();
-        compactedSizes.minusWaste(this);
+        WriterSizes compactedSizes = new WriterSizes(this);
         int wastedByteCount = writerSizes.size() - compactedSizes.size();
         if (wastedByteCount >  + compactWasteThreshold) {
             DexMerger compacter = new DexMerger(
@@ -853,7 +852,7 @@ public final class DexMerger {
      * <li>By exactly measuring an existing dex.
      * </ul>
      */
-    private static class WriterSizes implements Cloneable {
+    private static class WriterSizes {
         private int header = SizeOf.HEADER_ITEM;
         private int idsDefs;
         private int mapList;
@@ -876,12 +875,20 @@ public final class DexMerger {
             plus(b.getTableOfContents(), false);
         }
 
-        @Override public WriterSizes clone() {
-            try {
-                return (WriterSizes) super.clone();
-            } catch (CloneNotSupportedException e) {
-                throw new AssertionError();
-            }
+        public WriterSizes(DexMerger dexMerger) {
+            header = dexMerger.headerOut.used();
+            idsDefs = dexMerger.idsDefsOut.used();
+            mapList = dexMerger.mapListOut.used();
+            typeList = dexMerger.typeListOut.used();
+            classData = dexMerger.classDataOut.used();
+            code = dexMerger.codeOut.used();
+            stringData = dexMerger.stringDataOut.used();
+            debugInfo = dexMerger.debugInfoOut.used();
+            encodedArray = dexMerger.encodedArrayOut.used();
+            annotationsDirectory = dexMerger.annotationsDirectoryOut.used();
+            annotationsSet = dexMerger.annotationSetOut.used();
+            annotationsSetRefList = dexMerger.annotationSetRefListOut.used();
+            annotation = dexMerger.annotationOut.used();
         }
 
         public void plus(TableOfContents contents, boolean exact) {
@@ -916,22 +923,6 @@ public final class DexMerger {
             }
         }
 
-        public void minusWaste(DexMerger dexMerger) {
-            header -= dexMerger.headerOut.remaining();
-            idsDefs -= dexMerger.idsDefsOut.remaining();
-            mapList -= dexMerger.mapListOut.remaining();
-            typeList -= dexMerger.typeListOut.remaining();
-            classData -= dexMerger.classDataOut.remaining();
-            code -= dexMerger.codeOut.remaining();
-            stringData -= dexMerger.stringDataOut.remaining();
-            debugInfo -= dexMerger.debugInfoOut.remaining();
-            encodedArray -= dexMerger.encodedArrayOut.remaining();
-            annotationsDirectory -= dexMerger.annotationsDirectoryOut.remaining();
-            annotationsSet -= dexMerger.annotationSetOut.remaining();
-            annotationsSetRefList -= dexMerger.annotationSetRefListOut.remaining();
-            annotation -= dexMerger.annotationOut.remaining();
-        }
-
         public int size() {
             return header + idsDefs + mapList + typeList + classData + code + stringData + debugInfo
                     + encodedArray + annotationsDirectory + annotationsSet + annotationsSetRefList