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
This commit is contained in:
JesusFreke@JesusFreke.com 2009-08-24 05:46:45 +00:00
parent eb21bb1783
commit 7eca83ddb6
7 changed files with 144 additions and 101 deletions

View File

@ -201,14 +201,10 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
/** {@inheritDoc} */ /** {@inheritDoc} */
protected int placeItem(int offset) { protected int placeItem(int offset) {
if (!dexFile.getInplace()) { return offset + 16 + (
ArrayUtils.sortTwoArrays(fieldAnnotationFields, fieldAnnotations); (fieldAnnotations==null?0:fieldAnnotations.length) +
ArrayUtils.sortTwoArrays(methodAnnotationMethods, methodAnnotations); (methodAnnotations==null?0:methodAnnotations.length) +
ArrayUtils.sortTwoArrays(parameterAnnotationMethods, parameterAnnotations); (parameterAnnotations==null?0:parameterAnnotations.length)) * 8;
}
return offset + 16 + fieldAnnotations.length * 8 + methodAnnotations.length * 8 +
parameterAnnotations.length * 8;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@ -261,23 +257,29 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
} }
out.writeInt(classAnnotations==null?0:classAnnotations.getOffset()); out.writeInt(classAnnotations==null?0:classAnnotations.getOffset());
out.writeInt(fieldAnnotations.length); out.writeInt(fieldAnnotations==null?0:fieldAnnotations.length);
out.writeInt(methodAnnotations.length); out.writeInt(methodAnnotations==null?0:methodAnnotations.length);
out.writeInt(parameterAnnotations.length); out.writeInt(parameterAnnotations==null?0:parameterAnnotations.length);
for (int i=0; i<fieldAnnotations.length; i++) { if (fieldAnnotations != null) {
out.writeInt(fieldAnnotationFields[i].getIndex()); for (int i=0; i<fieldAnnotations.length; i++) {
out.writeInt(fieldAnnotations[i].getOffset()); out.writeInt(fieldAnnotationFields[i].getIndex());
out.writeInt(fieldAnnotations[i].getOffset());
}
} }
for (int i=0; i<methodAnnotations.length; i++) { if (methodAnnotations != null) {
out.writeInt(methodAnnotationMethods[i].getIndex()); for (int i=0; i<methodAnnotations.length; i++) {
out.writeInt(methodAnnotations[i].getOffset()); out.writeInt(methodAnnotationMethods[i].getIndex());
out.writeInt(methodAnnotations[i].getOffset());
}
} }
for (int i=0; i<parameterAnnotations.length; i++) { if (parameterAnnotations != null) {
out.writeInt(parameterAnnotationMethods[i].getIndex()); for (int i=0; i<parameterAnnotations.length; i++) {
out.writeInt(parameterAnnotations[i].getOffset()); out.writeInt(parameterAnnotationMethods[i].getIndex());
out.writeInt(parameterAnnotations[i].getOffset());
}
} }
} }
@ -361,9 +363,9 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
*/ */
private boolean isInternable() { private boolean isInternable() {
return classAnnotations != null && return classAnnotations != null &&
fieldAnnotations.length == 0 && (fieldAnnotations == null || fieldAnnotations.length == 0) &&
methodAnnotations.length == 0 && (methodAnnotations == null || methodAnnotations.length == 0) &&
parameterAnnotations.length == 0; (parameterAnnotations == null || parameterAnnotations.length == 0);
} }
/** /**

View File

@ -31,6 +31,8 @@ package org.jf.dexlib;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
import java.util.List;
public class AnnotationSetItem extends Item<AnnotationSetItem> { public class AnnotationSetItem extends Item<AnnotationSetItem> {
private int hashCode = 0; private int hashCode = 0;
@ -61,8 +63,10 @@ public class AnnotationSetItem extends Item<AnnotationSetItem> {
* @param annotations The annotations for this <code>AnnotationSetItem</code> * @param annotations The annotations for this <code>AnnotationSetItem</code>
* @return an <code>AnnotationSetItem</code> for the given annotations * @return an <code>AnnotationSetItem</code> for the given annotations
*/ */
public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, AnnotationItem[] annotations) { public static AnnotationSetItem getInternedAnnotationSetItem(DexFile dexFile, List<AnnotationItem> annotations) {
AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotations); AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()];
annotations.toArray(annotationsArray);
AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray);
return dexFile.AnnotationSetsSection.intern(annotationSetItem); return dexFile.AnnotationSetsSection.intern(annotationSetItem);
} }

View File

@ -31,6 +31,8 @@ package org.jf.dexlib;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
import java.util.List;
public class AnnotationSetRefList extends Item<AnnotationSetRefList> { public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
private int hashCode = 0; private int hashCode = 0;
@ -62,8 +64,10 @@ public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
* @return an <code>AnnotationSetItem</code> for the given annotations * @return an <code>AnnotationSetItem</code> for the given annotations
*/ */
public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile, public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
AnnotationSetItem[] annotationSets) { List<AnnotationSetItem> annotationSets) {
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSets); AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
annotationSets.toArray(annotationSetsArray);
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList); return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
} }

View File

@ -30,8 +30,8 @@ package org.jf.dexlib;
import org.jf.dexlib.Util.*; import org.jf.dexlib.Util.*;
import java.util.Arrays; import java.util.List;
import java.util.Comparator; import java.util.Collections;
public class ClassDataItem extends Item<ClassDataItem> { public class ClassDataItem extends Item<ClassDataItem> {
private EncodedField[] staticFields; private EncodedField[] staticFields;
@ -75,18 +75,41 @@ public class ClassDataItem extends Item<ClassDataItem> {
* @param virtualMethods The virtual methods for this class * @param virtualMethods The virtual methods for this class
* @return a new <code>ClassDataItem</code> with the given values * @return a new <code>ClassDataItem</code> with the given values
*/ */
public static ClassDataItem getInternedClassDataItem(DexFile dexFile, EncodedField[] staticFields, public static ClassDataItem getInternedClassDataItem(DexFile dexFile, List<EncodedField> staticFields,
EncodedField[] instanceFields, EncodedMethod[] directMethods, List<EncodedField> instanceFields,
EncodedMethod[] virtualMethods) { List<EncodedMethod> directMethods,
if (!dexFile.getInplace()) { List<EncodedMethod> virtualMethods) {
Arrays.sort(staticFields); EncodedField[] staticFieldsArray = null;
Arrays.sort(instanceFields); EncodedField[] instanceFieldsArray = null;
Arrays.sort(directMethods); EncodedMethod[] directMethodsArray = null;
Arrays.sort(virtualMethods); 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, if (instanceFields != null && instanceFields.size() > 0) {
virtualMethods); 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); return dexFile.ClassDataSection.intern(classDataItem);
} }
@ -301,7 +324,7 @@ public class ClassDataItem extends Item<ClassDataItem> {
return virtualMethods; return virtualMethods;
} }
public static class EncodedField { public static class EncodedField implements Comparable<EncodedField> {
/** /**
* The <code>FieldIdItem</code> that this <code>EncodedField</code> is associated with * The <code>FieldIdItem</code> that this <code>EncodedField</code> is associated with
*/ */
@ -390,7 +413,7 @@ public class ClassDataItem extends Item<ClassDataItem> {
} }
} }
public static class EncodedMethod { public static class EncodedMethod implements Comparable<EncodedMethod> {
/** /**
* The <code>MethodIdItem</code> that this <code>EncodedMethod</code> is associated with * The <code>MethodIdItem</code> that this <code>EncodedMethod</code> is associated with
*/ */

View File

@ -104,24 +104,22 @@ public class ClassDefItem extends Item<ClassDefItem> {
* @param sourceFile The main source file that this class is defined in, or null if not available * @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 annotations The annotations for this class and its fields, methods and method parameters, or null if none
* @param classData The <code>ClassDataItem</code> containing the method and field definitions for this class * @param classData The <code>ClassDataItem</code> 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 * @param staticFieldInitializers The initial values for this class's static fields, or null if none. If it is not
* values should be in the same order as the fields in the <code>staticFields</code. parameter It can contain * null, it must contain the same number of items as the number of static fields in this class. The value in the
* fewer items than static fields, in which case the remaining static fields will be initialized with a default * <code>StaticFieldInitializer</code> for any field that doesn't have an explicit initial value can either be null
* value of null/0. The initial value for any fields that don't specifically have a value can be either the * or be the type-appropriate null/0 value.
* type-appropriate null/0 encoded value, or null.
* @param staticFields The static fields that correspond to the initial values in
* <code>staticFieldInitializers</code>. The static fields are needed in order to sort the initial values correctly
* @return a <code>ClassDefItem</code> for the given values, and that has been interned into the given * @return a <code>ClassDefItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code> * <code>DexFile</code>
*/ */
public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags, public static ClassDefItem getInternedClassDefItem(DexFile dexFile, TypeIdItem classType, int accessFlags,
TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile, TypeIdItem superType, TypeListItem implementedInterfaces, StringIdItem sourceFile,
AnnotationDirectoryItem annotations, ClassDataItem classData, AnnotationDirectoryItem annotations, ClassDataItem classData,
EncodedValue[] staticFieldInitializers, ClassDataItem.EncodedField[] staticFields) { List<StaticFieldInitializer> staticFieldInitializers) {
EncodedArrayItem encodedArrayItem = null; EncodedArrayItem encodedArrayItem = null;
if(!dexFile.getInplace() && staticFieldInitializers != null) { if(!dexFile.getInplace() && staticFieldInitializers != null && staticFieldInitializers.size() > 0) {
encodedArrayItem = makeStaticFieldInitializersItem(dexFile, staticFieldInitializers, assert classData != null;
staticFields); assert staticFieldInitializers.size() == classData.getStaticFields().length;
encodedArrayItem = makeStaticFieldInitializersItem(dexFile, staticFieldInitializers);
} }
ClassDefItem classDefItem = new ClassDefItem(dexFile, classType, accessFlags, superType, implementedInterfaces, ClassDefItem classDefItem = new ClassDefItem(dexFile, classType, accessFlags, superType, implementedInterfaces,
@ -301,63 +299,51 @@ public class ClassDefItem extends Item<ClassDefItem> {
} }
} }
currentOffset = classDefItem.placeAt(currentIndex++, currentOffset); currentOffset = classDefItem.placeAt(currentOffset, currentIndex++);
unplacedClassDefsByType.remove(classDefItem.classType); unplacedClassDefsByType.remove(classDefItem.classType);
} }
} }
} }
public static class StaticFieldInitializer implements Comparable<StaticFieldInitializer> {
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 * A helper method to sort the static field initializers and populate the default values as needed
* @param dexFile the <code>DexFile</code> * @param dexFile the <code>DexFile</code>
* @param staticFieldInitializers the initial values * @param staticFieldInitializers the initial values
* @param fields the fields that correspond to each initial value in <code>staticFieldInitializers</code>
* @return an interned EncodedArrayItem containing the static field initializers * @return an interned EncodedArrayItem containing the static field initializers
*/ */
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile, private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
EncodedValue[] staticFieldInitializers, List<StaticFieldInitializer> staticFieldInitializers) {
ClassDataItem.EncodedField[] fields) { if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) {
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) {
return null; return null;
} }
int len = fields.length; int len = staticFieldInitializers.size();
FieldAndValue[] fieldAndValues = new FieldAndValue[len]; Collections.sort(staticFieldInitializers);
for (int i=0; i<len; i++) {
EncodedValue encodedValue = null;
if (i < staticFieldInitializers.length) {
encodedValue = staticFieldInitializers[i];
}
ClassDataItem.EncodedField encodedField = fields[i];
fieldAndValues[i] = new FieldAndValue(encodedField, encodedValue);
}
Arrays.sort(fieldAndValues, new Comparator<FieldAndValue>() {
public int compare(FieldAndValue a, FieldAndValue b) {
return a.field.compareTo(b.field);
}
});
int lastIndex = -1; int lastIndex = -1;
for (int i=0; i<len; i++) { for (int i=len-1; i>=0; i--) {
FieldAndValue fav = fieldAndValues[i]; StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i);
if (fav.value != null && if (staticFieldInitializer.value != null &&
(fav.value.compareTo(TypeUtils.makeDefaultValueForType(dexFile, (staticFieldInitializer.value.compareTo(TypeUtils.makeDefaultValueForType(dexFile,
fav.field.field.getFieldType().getTypeDescriptor())) != 0)) { staticFieldInitializer.field.field.getFieldType().getTypeDescriptor())) != 0)) {
lastIndex = i; lastIndex = i;
break;
} }
} }
@ -369,11 +355,11 @@ public class ClassDefItem extends Item<ClassDefItem> {
EncodedValue[] values = new EncodedValue[lastIndex+1]; EncodedValue[] values = new EncodedValue[lastIndex+1];
for (int i=0; i<=lastIndex; i++) { for (int i=0; i<=lastIndex; i++) {
FieldAndValue fav = fieldAndValues[i]; StaticFieldInitializer staticFieldInitializer = staticFieldInitializers.get(i);
EncodedValue encodedValue = fav.value; EncodedValue encodedValue = staticFieldInitializer.value;
if (encodedValue == null) { if (encodedValue == null) {
encodedValue = TypeUtils.makeDefaultValueForType(dexFile, encodedValue = TypeUtils.makeDefaultValueForType(dexFile,
fav.field.field.getFieldType().getTypeDescriptor()); staticFieldInitializer.field.field.getFieldType().getTypeDescriptor());
} }
values[i] = encodedValue; values[i] = encodedValue;

View File

@ -37,6 +37,8 @@ import org.jf.dexlib.Util.Input;
import org.jf.dexlib.Util.SparseArray; import org.jf.dexlib.Util.SparseArray;
import org.jf.dexlib.Util.Leb128Utils; import org.jf.dexlib.Util.Leb128Utils;
import java.util.List;
public class CodeItem extends Item<CodeItem> { public class CodeItem extends Item<CodeItem> {
private int registerCount; private int registerCount;
private int inWords; private int inWords;
@ -101,9 +103,10 @@ public class CodeItem extends Item<CodeItem> {
* @param outWords the maximum number of 2-byte words for the arguments of any method call in this code * @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 debugInfo the debug information for this code/method
* @param encodedInstructions the instructions, encoded as a byte array * @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 referencedItems a list 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 * or null if none
* @param encodedCatchHandlers an array of the exception handlers defined for this code/method * @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 <code>CodeItem</code> with the given values. * @return a new <code>CodeItem</code> with the given values.
*/ */
public static CodeItem getInternedCodeItem(DexFile dexFile, public static CodeItem getInternedCodeItem(DexFile dexFile,
@ -112,11 +115,30 @@ public class CodeItem extends Item<CodeItem> {
int outWords, int outWords,
DebugInfoItem debugInfo, DebugInfoItem debugInfo,
byte[] encodedInstructions, byte[] encodedInstructions,
Item[] referencedItems, List<Item> referencedItems,
TryItem[] tries, List<TryItem> tries,
EncodedCatchHandler[] encodedCatchHandlers) { List<EncodedCatchHandler> 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, CodeItem codeItem = new CodeItem(dexFile, registerCount, inWords, outWords, debugInfo, encodedInstructions,
referencedItems, tries, encodedCatchHandlers); referencedItemsArray, triesArray, encodedCatchHandlersArray);
return dexFile.CodeItemsSection.intern(codeItem); return dexFile.CodeItemsSection.intern(codeItem);
} }

View File

@ -66,8 +66,10 @@ public class TypeListItem extends Item<TypeListItem> {
* @return a <code>TypeListItem</code> for the given values, and that has been interned into * @return a <code>TypeListItem</code> for the given values, and that has been interned into
* the given <code>DexFile</code> * the given <code>DexFile</code>
*/ */
public static TypeListItem getInternedTypeListItem(DexFile dexFile, TypeIdItem[] typeList) { public static TypeListItem getInternedTypeListItem(DexFile dexFile, List<TypeIdItem> typeList) {
TypeListItem typeListItem = new TypeListItem(dexFile, typeList); TypeIdItem[] typeArray = new TypeIdItem[typeList.size()];
typeList.toArray(typeArray);
TypeListItem typeListItem = new TypeListItem(dexFile, typeArray);
return dexFile.TypeListsSection.intern(typeListItem); return dexFile.TypeListsSection.intern(typeListItem);
} }