From: Jesse Wilson Date: Mon, 26 Mar 2012 18:53:18 +0000 (-0400) Subject: Transform static values eagerly rather than on use. X-Git-Tag: android-x86-4.4-r1~362 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=fa3b293a068fd521a6ba6019a051ad502dfaca55;p=android-x86%2Fdalvik.git Transform static values eagerly rather than on use. Apparently there is some situations where a single static value may be referenced by multiple sites. Not transforming them eagerly lead to oversized dex files (and could crash the merge). Change-Id: I4ac5b9cd621b0fff1e5ba247c9590aa0d562cd65 --- diff --git a/dx/src/com/android/dx/io/DexBuffer.java b/dx/src/com/android/dx/io/DexBuffer.java index d10b08c55..217de725b 100644 --- a/dx/src/com/android/dx/io/DexBuffer.java +++ b/dx/src/com/android/dx/io/DexBuffer.java @@ -217,7 +217,7 @@ public final class DexBuffer { return length; } - private static int fourByteAlign(int position) { + public static int fourByteAlign(int position) { return (position + 3) & ~3; } diff --git a/dx/src/com/android/dx/merge/DexMerger.java b/dx/src/com/android/dx/merge/DexMerger.java index b8071176a..1ba876aef 100644 --- a/dx/src/com/android/dx/merge/DexMerger.java +++ b/dx/src/com/android/dx/merge/DexMerger.java @@ -33,7 +33,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Combine two dex files into one. @@ -595,6 +597,8 @@ public final class DexMerger { transformAnnotationSets(dexB, bIndexMap); transformAnnotationDirectories(dexA, aIndexMap); transformAnnotationDirectories(dexB, bIndexMap); + transformStaticValues(dexA, aIndexMap); + transformStaticValues(dexB, bIndexMap); } private void transformAnnotationSets(DexBuffer in, IndexMap indexMap) { @@ -617,6 +621,16 @@ public final class DexMerger { } } + private void transformStaticValues(DexBuffer in, IndexMap indexMap) { + TableOfContents.Section section = in.getTableOfContents().encodedArrays; + if (section.exists()) { + DexBuffer.Section staticValuesIn = in.open(section.off); + for (int i = 0; i < section.size; i++) { + transformStaticValues(staticValuesIn, indexMap); + } + } + } + /** * Reads a class_def_item beginning at {@code in} and writes the index and * data. @@ -644,13 +658,7 @@ public final class DexMerger { } int staticValuesOff = classDef.getStaticValuesOffset(); - if (staticValuesOff == 0) { - idsDefsOut.writeInt(0); - } else { - DexBuffer.Section staticValuesIn = in.open(staticValuesOff); - idsDefsOut.writeInt(encodedArrayOut.getPosition()); - transformStaticValues(staticValuesIn, indexMap); - } + idsDefsOut.writeInt(indexMap.adjustStaticValues(staticValuesOff)); } /** @@ -839,6 +847,7 @@ public final class DexMerger { private void transformStaticValues(DexBuffer.Section in, IndexMap indexMap) { contentsOut.encodedArrays.size++; + indexMap.putStaticValuesOffset(in.getPosition(), encodedArrayOut.getPosition()); indexMap.adjustEncodedArray(in.readEncodedArray()).writeTo(encodedArrayOut); } @@ -914,6 +923,9 @@ public final class DexMerger { // at most 1/3 of the bytes in an encoding arrays section are uleb/sleb annotation += (int) Math.ceil(contents.annotations.byteCount * 1.34); } + + typeList = DexBuffer.fourByteAlign(typeList); + code = DexBuffer.fourByteAlign(code); } public void minusWaste(DexMerger dexMerger) { diff --git a/dx/src/com/android/dx/merge/IndexMap.java b/dx/src/com/android/dx/merge/IndexMap.java index a7b20bede..a5c9584dc 100644 --- a/dx/src/com/android/dx/merge/IndexMap.java +++ b/dx/src/com/android/dx/merge/IndexMap.java @@ -48,6 +48,7 @@ public final class IndexMap { private final HashMap annotationOffsets; private final HashMap annotationSetOffsets; private final HashMap annotationDirectoryOffsets; + private final HashMap staticValuesOffsets; public IndexMap(DexBuffer target, TableOfContents tableOfContents) { this.target = target; @@ -60,14 +61,16 @@ public final class IndexMap { this.annotationOffsets = new HashMap(); this.annotationSetOffsets = new HashMap(); this.annotationDirectoryOffsets = new HashMap(); + this.staticValuesOffsets = new HashMap(); /* - * A type list, annotation set, or annotation directory at offset 0 is - * always empty. Always map offset 0 to 0. + * A type list, annotation set, annotation directory, or static value at + * offset 0 is always empty. Always map offset 0 to 0. */ this.typeListOffsets.put(0, 0); this.annotationSetOffsets.put(0, 0); this.annotationDirectoryOffsets.put(0, 0); + this.staticValuesOffsets.put(0, 0); } public void putTypeListOffset(int oldOffset, int newOffset) { @@ -98,6 +101,13 @@ public final class IndexMap { annotationDirectoryOffsets.put(oldOffset, newOffset); } + public void putStaticValuesOffset(int oldOffset, int newOffset) { + if (oldOffset <= 0 || newOffset <= 0) { + throw new IllegalArgumentException(); + } + staticValuesOffsets.put(oldOffset, newOffset); + } + public int adjustString(int stringIndex) { return stringIndex == ClassDef.NO_INDEX ? ClassDef.NO_INDEX : stringIds[stringIndex]; } @@ -145,6 +155,10 @@ public final class IndexMap { return annotationDirectoryOffsets.get(annotationDirectoryOffset); } + public int adjustStaticValues(int staticValuesOffset) { + return staticValuesOffsets.get(staticValuesOffset); + } + public MethodId adjust(MethodId methodId) { return new MethodId(target, adjustType(methodId.getDeclaringClassIndex()),