diff options
| author | Jesse Wilson <jessewilson@google.com> | 2011-03-15 14:19:33 -0700 |
|---|---|---|
| committer | Jesse Wilson <jessewilson@google.com> | 2011-03-15 14:19:33 -0700 |
| commit | 0ebdfc22385095c75fbced79edc1d1e75b504213 (patch) | |
| tree | f025c883d945e585f5b8cf181473073c13acb6a1 /dx | |
| parent | f1bd0dab7ec89b909b27c7e48e364e32ecd61ae6 (diff) | |
| download | android_dalvik-0ebdfc22385095c75fbced79edc1d1e75b504213.tar.gz android_dalvik-0ebdfc22385095c75fbced79edc1d1e75b504213.tar.bz2 android_dalvik-0ebdfc22385095c75fbced79edc1d1e75b504213.zip | |
Fix bugs in instruction parsing for incremental dx.
Change-Id: I9557e835e846d42689786833395eecdbbbe6174c
http://b/3447216
Diffstat (limited to 'dx')
| -rw-r--r-- | dx/src/com/android/dx/io/instructions/InstructionCodec.java | 6 | ||||
| -rw-r--r-- | dx/src/com/android/dx/merge/DexMerger.java | 96 |
2 files changed, 92 insertions, 10 deletions
diff --git a/dx/src/com/android/dx/io/instructions/InstructionCodec.java b/dx/src/com/android/dx/io/instructions/InstructionCodec.java index 079038554..b864b8365 100644 --- a/dx/src/com/android/dx/io/instructions/InstructionCodec.java +++ b/dx/src/com/android/dx/io/instructions/InstructionCodec.java @@ -227,7 +227,7 @@ public enum InstructionCodec { CodeInput in) throws EOFException { int opcode = byte0(opcodeUnit); int a = byte1(opcodeUnit); - int literal = (short) in.read(); // sign-extend + long literal = (short) in.read(); // sign-extend /* * Format 21h decodes differently depending on the opcode, @@ -741,7 +741,7 @@ public enum InstructionCodec { FORMAT_PACKED_SWITCH_PAYLOAD() { @Override public DecodedInstruction decode(int opcodeUnit, CodeInput in) throws EOFException { - int baseAddress = in.baseAddressForCursor(); + int baseAddress = in.baseAddressForCursor() - 1; // already read opcode int size = in.read(); int firstKey = in.readInt(); int[] targets = new int[size]; @@ -773,7 +773,7 @@ public enum InstructionCodec { FORMAT_SPARSE_SWITCH_PAYLOAD() { @Override public DecodedInstruction decode(int opcodeUnit, CodeInput in) throws EOFException { - int baseAddress = in.baseAddressForCursor(); + int baseAddress = in.baseAddressForCursor() - 1; // already read opcode int size = in.read(); int[] keys = new int[size]; int[] targets = new int[size]; diff --git a/dx/src/com/android/dx/merge/DexMerger.java b/dx/src/com/android/dx/merge/DexMerger.java index d67c0737b..475670946 100644 --- a/dx/src/com/android/dx/merge/DexMerger.java +++ b/dx/src/com/android/dx/merge/DexMerger.java @@ -28,7 +28,10 @@ import com.android.dx.io.MethodId; import com.android.dx.io.ProtoId; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * Combine two dex files into one. @@ -204,7 +207,11 @@ public final class DexMerger { this.out = out; } - public final void merge() { + /** + * Merges already-sorted sections, reading only two values into memory + * at a time. + */ + public final void mergeSorted() { TableOfContents.Section aSection = getSection(dexA.getTableOfContents()); TableOfContents.Section bSection = getSection(dexB.getTableOfContents()); getSection(contentsOut).off = out.getPosition(); @@ -264,10 +271,85 @@ public final class DexMerger { getSection(contentsOut).size = outCount; } + /** + * Merges unsorted sections by reading them completely into memory and + * sorting in memory. + */ + public final void mergeUnsorted() { + getSection(contentsOut).off = out.getPosition(); + + List<UnsortedValue> all = new ArrayList<UnsortedValue>(); + all.addAll(readUnsortedValues(dexA, aIndexMap)); + all.addAll(readUnsortedValues(dexB, bIndexMap)); + Collections.sort(all); + + int outCount = 0; + for (int i = 0; i < all.size(); ) { + UnsortedValue e1 = all.get(i++); + updateIndex(e1.offset, getIndexMap(e1.source), e1.index, outCount - 1); + + while (i < all.size() && e1.compareTo(all.get(i)) == 0) { + UnsortedValue e2 = all.get(i++); + updateIndex(e2.offset, getIndexMap(e2.source), e2.index, outCount - 1); + } + + write(e1.value); + outCount++; + } + + getSection(contentsOut).size = outCount; + } + + private List<UnsortedValue> readUnsortedValues(DexBuffer source, IndexMap indexMap) { + TableOfContents.Section section = getSection(source.getTableOfContents()); + if (!section.exists()) { + return Collections.emptyList(); + } + + List<UnsortedValue> result = new ArrayList<UnsortedValue>(); + DexBuffer.Section in = source.open(section.off); + for (int i = 0; i < section.size; i++) { + int offset = in.getPosition(); + T value = read(in, indexMap, 0); + result.add(new UnsortedValue(source, indexMap, value, i, offset)); + } + return result; + } + abstract TableOfContents.Section getSection(TableOfContents tableOfContents); abstract T read(DexBuffer.Section in, IndexMap indexMap, int index); abstract void updateIndex(int offset, IndexMap indexMap, int oldIndex, int newIndex); abstract void write(T value); + + class UnsortedValue implements Comparable<UnsortedValue> { + final DexBuffer source; + final IndexMap indexMap; + final T value; + final int index; + final int offset; + + UnsortedValue(DexBuffer source, IndexMap indexMap, T value, int index, int offset) { + this.source = source; + this.indexMap = indexMap; + this.value = value; + this.index = index; + this.offset = offset; + } + + public int compareTo(UnsortedValue unsortedValue) { + return value.compareTo(unsortedValue.value); + } + } + } + + private IndexMap getIndexMap(DexBuffer dexBuffer) { + if (dexBuffer == dexA) { + return aIndexMap; + } else if (dexBuffer == dexB) { + return bIndexMap; + } else { + throw new IllegalArgumentException(); + } } private void mergeStringIds() { @@ -289,7 +371,7 @@ public final class DexMerger { idsDefsOut.writeInt(stringDataOut.getPosition()); stringDataOut.writeStringData(value); } - }.merge(); + }.mergeSorted(); } private void mergeTypeIds() { @@ -310,7 +392,7 @@ public final class DexMerger { @Override void write(Integer value) { idsDefsOut.writeInt(value); } - }.merge(); + }.mergeSorted(); } private void mergeTypeLists() { @@ -330,7 +412,7 @@ public final class DexMerger { @Override void write(TypeList value) { typeListOut.writeTypeList(value); } - }.merge(); + }.mergeUnsorted(); } private void mergeProtoIds() { @@ -350,7 +432,7 @@ public final class DexMerger { @Override void write(ProtoId value) { value.writeTo(idsDefsOut); } - }.merge(); + }.mergeSorted(); } private void mergeFieldIds() { @@ -370,7 +452,7 @@ public final class DexMerger { @Override void write(FieldId value) { value.writeTo(idsDefsOut); } - }.merge(); + }.mergeSorted(); } private void mergeMethodIds() { @@ -390,7 +472,7 @@ public final class DexMerger { @Override void write(MethodId methodId) { methodId.writeTo(idsDefsOut); } - }.merge(); + }.mergeSorted(); } private void mergeClassDefs() { |
