From 7eca83ddb6b9958c04cb19f71b0124338f9fc631 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Mon, 24 Aug 2009 05:46:45 +0000 Subject: [PATCH] Various changes mostly relating to changing the getInterned* item methods to accept lists instead of arrays git-svn-id: https://smali.googlecode.com/svn/trunk@412 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../jf/dexlib/AnnotationDirectoryItem.java | 48 +++++----- .../java/org/jf/dexlib/AnnotationSetItem.java | 8 +- .../org/jf/dexlib/AnnotationSetRefList.java | 8 +- .../java/org/jf/dexlib/ClassDataItem.java | 51 ++++++++--- .../main/java/org/jf/dexlib/ClassDefItem.java | 88 ++++++++----------- .../src/main/java/org/jf/dexlib/CodeItem.java | 36 ++++++-- .../main/java/org/jf/dexlib/TypeListItem.java | 6 +- 7 files changed, 144 insertions(+), 101 deletions(-) diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java index 8af92b77..4d157216 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java @@ -201,14 +201,10 @@ public class AnnotationDirectoryItem extends Item { /** {@inheritDoc} */ protected int placeItem(int offset) { - if (!dexFile.getInplace()) { - ArrayUtils.sortTwoArrays(fieldAnnotationFields, fieldAnnotations); - ArrayUtils.sortTwoArrays(methodAnnotationMethods, methodAnnotations); - ArrayUtils.sortTwoArrays(parameterAnnotationMethods, parameterAnnotations); - } - - return offset + 16 + fieldAnnotations.length * 8 + methodAnnotations.length * 8 + - parameterAnnotations.length * 8; + return offset + 16 + ( + (fieldAnnotations==null?0:fieldAnnotations.length) + + (methodAnnotations==null?0:methodAnnotations.length) + + (parameterAnnotations==null?0:parameterAnnotations.length)) * 8; } /** {@inheritDoc} */ @@ -261,23 +257,29 @@ public class AnnotationDirectoryItem extends Item { } out.writeInt(classAnnotations==null?0:classAnnotations.getOffset()); - out.writeInt(fieldAnnotations.length); - out.writeInt(methodAnnotations.length); - out.writeInt(parameterAnnotations.length); + out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length); + out.writeInt(methodAnnotations==null?0:methodAnnotations.length); + out.writeInt(parameterAnnotations==null?0:parameterAnnotations.length); - for (int i=0; i { */ private boolean isInternable() { return classAnnotations != null && - fieldAnnotations.length == 0 && - methodAnnotations.length == 0 && - parameterAnnotations.length == 0; + (fieldAnnotations == null || fieldAnnotations.length == 0) && + (methodAnnotations == null || methodAnnotations.length == 0) && + (parameterAnnotations == null || parameterAnnotations.length == 0); } /** diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java index 6bb94538..9aabf8be 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetItem.java @@ -31,6 +31,8 @@ package org.jf.dexlib; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.AnnotatedOutput; +import java.util.List; + public class AnnotationSetItem extends Item { private int hashCode = 0; @@ -61,8 +63,10 @@ public class AnnotationSetItem extends Item { * @param annotations The annotations for this AnnotationSetItem * @return an AnnotationSetItem for the given annotations */ - public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) { - AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotations); + public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List annotations) { + AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()]; + annotations.toArray(annotationsArray); + AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray); return dexFile.AnnotationSetsSection.intern(annotationSetItem); } diff --git a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java index e44b3c04..27a0b1f7 100644 --- a/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java +++ b/dexlib/src/main/java/org/jf/dexlib/AnnotationSetRefList.java @@ -31,6 +31,8 @@ package org.jf.dexlib; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.AnnotatedOutput; +import java.util.List; + public class AnnotationSetRefList extends Item { private int hashCode = 0; @@ -62,8 +64,10 @@ public class AnnotationSetRefList extends Item { * @return an AnnotationSetItem for the given annotations */ public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile, - AnnotationSetItem[] annotationSets) { - AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSets); + List annotationSets) { + AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()]; + annotationSets.toArray(annotationSetsArray); + AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray); return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList); } diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java index 03745d98..11beb268 100644 --- a/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java @@ -30,8 +30,8 @@ package org.jf.dexlib; import org.jf.dexlib.Util.*; -import java.util.Arrays; -import java.util.Comparator; +import java.util.List; +import java.util.Collections; public class ClassDataItem extends Item { private EncodedField[] staticFields; @@ -75,18 +75,41 @@ public class ClassDataItem extends Item { * @param virtualMethods The virtual methods for this class * @return a new ClassDataItem with the given values */ - public static ClassDataItem getInternedClassDataItem(DexFile dexFile, EncodedField[] staticFields, - EncodedField[] instanceFields, EncodedMethod[] directMethods, - EncodedMethod[] virtualMethods) { - if (!dexFile.getInplace()) { - Arrays.sort(staticFields); - Arrays.sort(instanceFields); - Arrays.sort(directMethods); - Arrays.sort(virtualMethods); + public static ClassDataItem getInternedClassDataItem(DexFile dexFile, List staticFields, + List instanceFields, + List directMethods, + List virtualMethods) { + EncodedField[] staticFieldsArray = null; + EncodedField[] instanceFieldsArray = null; + EncodedMethod[] directMethodsArray = null; + EncodedMethod[] virtualMethodsArray = null; + + if (staticFields != null && staticFields.size() > 0) { + Collections.sort(staticFields); + staticFieldsArray = new EncodedField[staticFields.size()]; + staticFields.toArray(staticFieldsArray); } - ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFields, instanceFields, directMethods, - virtualMethods); + if (instanceFields != null && instanceFields.size() > 0) { + Collections.sort(instanceFields); + instanceFieldsArray = new EncodedField[instanceFields.size()]; + instanceFields.toArray(instanceFieldsArray); + } + + if (directMethods != null && directMethods.size() > 0) { + Collections.sort(directMethods); + directMethodsArray = new EncodedMethod[directMethods.size()]; + directMethods.toArray(directMethodsArray); + } + + if (virtualMethods != null && virtualMethods.size() > 0) { + Collections.sort(virtualMethods); + virtualMethodsArray = new EncodedMethod[virtualMethods.size()]; + virtualMethods.toArray(virtualMethodsArray); + } + + ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray, + directMethodsArray, virtualMethodsArray); return dexFile.ClassDataSection.intern(classDataItem); } @@ -301,7 +324,7 @@ public class ClassDataItem extends Item { return virtualMethods; } - public static class EncodedField { + public static class EncodedField implements Comparable { /** * The FieldIdItem that this EncodedField is associated with */ @@ -390,7 +413,7 @@ public class ClassDataItem extends Item { } } - public static class EncodedMethod { + public static class EncodedMethod implements Comparable { /** * The MethodIdItem that this EncodedMethod is associated with */ diff --git a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java index 45b4f0d8..a838d71f 100644 --- a/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/ClassDefItem.java @@ -104,24 +104,22 @@ public class ClassDefItem extends Item { * @param sourceFile The main source file that this class is defined in, or null if not available * @param annotations The annotations for this class and its fields, methods and method parameters, or null if none * @param classData The ClassDataItem containing the method and field definitions for this class - * @param staticFieldInitializers The initial values for this class's static fields, or null if none. The initial - * values should be in the same order as the fields in the staticFieldsstaticFieldInitializers. The static fields are needed in order to sort the initial values correctly + * @param staticFieldInitializers The initial values for this class's static fields, or null if none. If it is not + * null, it must contain the same number of items as the number of static fields in this class. The value in the + * StaticFieldInitializer for any field that doesn't have an explicit initial value can either be null + * or be the type-appropriate null/0 value. * @return a ClassDefItem for the given values, and that has been interned into the given * DexFile */ public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile, AnnotationDirectoryItem annotations, ClassDataItem classData, - EncodedValue[] staticFieldInitializers, ClassDataItem.EncodedField[] staticFields) { + List staticFieldInitializers) { EncodedArrayItem encodedArrayItem = null; - if(!dexFile.getInplace() && staticFieldInitializers != null) { - encodedArrayItem = makeStaticFieldInitializersItem(dexFile, staticFieldInitializers, - staticFields); + if(!dexFile.getInplace() && staticFieldInitializers != null && staticFieldInitializers.size() > 0) { + assert classData != null; + assert staticFieldInitializers.size() == classData.getStaticFields().length; + encodedArrayItem = makeStaticFieldInitializersItem(dexFile, staticFieldInitializers); } ClassDefItem classDefItem = new ClassDefItem(dexFile, classType, accessFlags, superType, implementedInterfaces, @@ -301,63 +299,51 @@ public class ClassDefItem extends Item { } } - currentOffset = classDefItem.placeAt(currentIndex++, currentOffset); + currentOffset = classDefItem.placeAt(currentOffset, currentIndex++); unplacedClassDefsByType.remove(classDefItem.classType); } } } + public static class StaticFieldInitializer implements Comparable { + public final EncodedValue value; + public final ClassDataItem.EncodedField field; + public StaticFieldInitializer(EncodedValue value, ClassDataItem.EncodedField field) { + this.value = value; + this.field = field; + } + + public int compareTo(StaticFieldInitializer other) { + return field.compareTo(other.field); + } + } + + /** * A helper method to sort the static field initializers and populate the default values as needed * @param dexFile the DexFile * @param staticFieldInitializers the initial values - * @param fields the fields that correspond to each initial value in staticFieldInitializers * @return an interned EncodedArrayItem containing the static field initializers */ private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile, - EncodedValue[] staticFieldInitializers, - ClassDataItem.EncodedField[] fields) { - class FieldAndValue { - public final EncodedValue value; - public final ClassDataItem.EncodedField field; - public FieldAndValue(ClassDataItem.EncodedField field, EncodedValue value) { - this.field = field; - this.value = value; - } - } - - if (staticFieldInitializers == null || staticFieldInitializers.length == 0) { + List staticFieldInitializers) { + if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) { return null; } - int len = fields.length; + int len = staticFieldInitializers.size(); - FieldAndValue[] fieldAndValues = new FieldAndValue[len]; - - for (int i=0; i() { - public int compare(FieldAndValue a, FieldAndValue b) { - return a.field.compareTo(b.field); - } - }); + Collections.sort(staticFieldInitializers); int lastIndex = -1; - for (int i=0; i=0; i--) { + StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i); - if (fav.value != null && - (fav.value.compareTo(TypeUtils.makeDefaultValueForType(dexFile, - fav.field.field.getFieldType().getTypeDescriptor())) != 0)) { + if (staticFieldInitializer.value != null && + (staticFieldInitializer.value.compareTo(TypeUtils.makeDefaultValueForType(dexFile, + staticFieldInitializer.field.field.getFieldType().getTypeDescriptor())) != 0)) { lastIndex = i; + break; } } @@ -369,11 +355,11 @@ public class ClassDefItem extends Item { EncodedValue[] values = new EncodedValue[lastIndex+1]; for (int i=0; i<=lastIndex; i++) { - FieldAndValue fav = fieldAndValues[i]; - EncodedValue encodedValue = fav.value; + StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i); + EncodedValue encodedValue = staticFieldInitializer.value; if (encodedValue == null) { encodedValue = TypeUtils.makeDefaultValueForType(dexFile, - fav.field.field.getFieldType().getTypeDescriptor()); + staticFieldInitializer.field.field.getFieldType().getTypeDescriptor()); } values[i] = encodedValue; diff --git a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java index 7a4583ab..7372ef3f 100644 --- a/dexlib/src/main/java/org/jf/dexlib/CodeItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/CodeItem.java @@ -37,6 +37,8 @@ import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.SparseArray; import org.jf.dexlib.Util.Leb128Utils; +import java.util.List; + public class CodeItem extends Item { private int registerCount; private int inWords; @@ -101,9 +103,10 @@ public class CodeItem extends Item { * @param outWords the maximum number of 2-byte words for the arguments of any method call in this code * @param debugInfo the debug information for this code/method * @param encodedInstructions the instructions, encoded as a byte array - * @param referencedItems an array of the items referenced by instructions, in order of occurance in the code - * @param tries an array of the tries defined for this code/method - * @param encodedCatchHandlers an array of the exception handlers defined for this code/method + * @param referencedItems a list of the items referenced by instructions, in order of occurance in the code, + * or null if none + * @param tries a list of the tries defined for this code/method or null if none + * @param encodedCatchHandlers a list of the exception handlers defined for this code/method or null if none * @return a new CodeItem with the given values. */ public static CodeItem getInternedCodeItem(DexFile dexFile, @@ -112,11 +115,30 @@ public class CodeItem extends Item { int outWords, DebugInfoItem debugInfo, byte[] encodedInstructions, - Item[] referencedItems, - TryItem[] tries, - EncodedCatchHandler[] encodedCatchHandlers) { + List referencedItems, + List tries, + List encodedCatchHandlers) { + Item[] referencedItemsArray = null; + TryItem[] triesArray = null; + EncodedCatchHandler[] encodedCatchHandlersArray = null; + + if (referencedItems != null && referencedItems.size() > 0) { + referencedItemsArray = new Item[referencedItems.size()]; + referencedItems.toArray(referencedItemsArray); + } + + if (tries != null && tries.size() > 0) { + triesArray = new TryItem[tries.size()]; + tries.toArray(triesArray); + } + + if (encodedCatchHandlers != null && encodedCatchHandlers.size() > 0) { + encodedCatchHandlersArray = new EncodedCatchHandler[encodedCatchHandlers.size()]; + encodedCatchHandlers.toArray(encodedCatchHandlersArray); + } + CodeItem codeItem = new CodeItem(dexFile, registerCount, inWords, outWords, debugInfo, encodedInstructions, - referencedItems, tries, encodedCatchHandlers); + referencedItemsArray, triesArray, encodedCatchHandlersArray); return dexFile.CodeItemsSection.intern(codeItem); } diff --git a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java index 79b6357e..ac7aed88 100644 --- a/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/TypeListItem.java @@ -66,8 +66,10 @@ public class TypeListItem extends Item { * @return a TypeListItem for the given values, and that has been interned into * the given DexFile */ - public static TypeListItem getInternedTypeListItem(DexFile dexFile, TypeIdItem[] typeList) { - TypeListItem typeListItem = new TypeListItem(dexFile, typeList); + public static TypeListItem getInternedTypeListItem(DexFile dexFile, List typeList) { + TypeIdItem[] typeArray = new TypeIdItem[typeList.size()]; + typeList.toArray(typeArray); + TypeListItem typeListItem = new TypeListItem(dexFile, typeArray); return dexFile.TypeListsSection.intern(typeListItem); }