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} */
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,25 +257,31 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
}
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);
if (fieldAnnotations != null) {
for (int i=0; i<fieldAnnotations.length; i++) {
out.writeInt(fieldAnnotationFields[i].getIndex());
out.writeInt(fieldAnnotations[i].getOffset());
}
}
if (methodAnnotations != null) {
for (int i=0; i<methodAnnotations.length; i++) {
out.writeInt(methodAnnotationMethods[i].getIndex());
out.writeInt(methodAnnotations[i].getOffset());
}
}
if (parameterAnnotations != null) {
for (int i=0; i<parameterAnnotations.length; i++) {
out.writeInt(parameterAnnotationMethods[i].getIndex());
out.writeInt(parameterAnnotations[i].getOffset());
}
}
}
/** {@inheritDoc} */public ItemType getItemType() {
return ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM;
@ -361,9 +363,9 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
*/
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);
}
/**

View File

@ -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<AnnotationSetItem> {
private int hashCode = 0;
@ -61,8 +63,10 @@ public class AnnotationSetItem extends Item<AnnotationSetItem> {
* @param annotations The annotations for this <code>AnnotationSetItem</code>
* @return an <code>AnnotationSetItem</code> 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<AnnotationItem> annotations) {
AnnotationItem[] annotationsArray = new AnnotationItem[annotations.size()];
annotations.toArray(annotationsArray);
AnnotationSetItem annotationSetItem = new AnnotationSetItem(dexFile, annotationsArray);
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.AnnotatedOutput;
import java.util.List;
public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
private int hashCode = 0;
@ -62,8 +64,10 @@ public class AnnotationSetRefList extends Item<AnnotationSetRefList> {
* @return an <code>AnnotationSetItem</code> for the given annotations
*/
public static AnnotationSetRefList getInternedAnnotationSetRefList(DexFile dexFile,
AnnotationSetItem[] annotationSets) {
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSets);
List<AnnotationSetItem> annotationSets) {
AnnotationSetItem[] annotationSetsArray = new AnnotationSetItem[annotationSets.size()];
annotationSets.toArray(annotationSetsArray);
AnnotationSetRefList annotationSetRefList = new AnnotationSetRefList(dexFile, annotationSetsArray);
return dexFile.AnnotationSetRefListsSection.intern(annotationSetRefList);
}

View File

@ -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<ClassDataItem> {
private EncodedField[] staticFields;
@ -75,18 +75,41 @@ public class ClassDataItem extends Item<ClassDataItem> {
* @param virtualMethods The virtual methods for this class
* @return a new <code>ClassDataItem</code> 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<EncodedField> staticFields,
List<EncodedField> instanceFields,
List<EncodedMethod> directMethods,
List<EncodedMethod> 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<ClassDataItem> {
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
*/
@ -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
*/

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 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 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 <code>staticFields</code. parameter It can contain
* fewer items than static fields, in which case the remaining static fields will be initialized with a default
* value of null/0. The initial value for any fields that don't specifically have a value can be either the
* 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
* @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
* <code>StaticFieldInitializer</code> 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 <code>ClassDefItem</code> for the given values, and that has been interned into the given
* <code>DexFile</code>
*/
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<StaticFieldInitializer> 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<ClassDefItem> {
}
}
currentOffset = classDefItem.placeAt(currentIndex++, currentOffset);
currentOffset = classDefItem.placeAt(currentOffset, currentIndex++);
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
* @param dexFile the <code>DexFile</code>
* @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
*/
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<StaticFieldInitializer> 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<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);
}
});
Collections.sort(staticFieldInitializers);
int lastIndex = -1;
for (int i=0; i<len; i++) {
FieldAndValue fav = fieldAndValues[i];
for (int i=len-1; 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<ClassDefItem> {
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;

View File

@ -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<CodeItem> {
private int registerCount;
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 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 <code>CodeItem</code> with the given values.
*/
public static CodeItem getInternedCodeItem(DexFile dexFile,
@ -112,11 +115,30 @@ public class CodeItem extends Item<CodeItem> {
int outWords,
DebugInfoItem debugInfo,
byte[] encodedInstructions,
Item[] referencedItems,
TryItem[] tries,
EncodedCatchHandler[] encodedCatchHandlers) {
List<Item> referencedItems,
List<TryItem> tries,
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,
referencedItems, tries, encodedCatchHandlers);
referencedItemsArray, triesArray, encodedCatchHandlersArray);
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
* the given <code>DexFile</code>
*/
public static TypeListItem getInternedTypeListItem(DexFile dexFile, TypeIdItem[] typeList) {
TypeListItem typeListItem = new TypeListItem(dexFile, typeList);
public static TypeListItem getInternedTypeListItem(DexFile dexFile, List<TypeIdItem> typeList) {
TypeIdItem[] typeArray = new TypeIdItem[typeList.size()];
typeList.toArray(typeArray);
TypeListItem typeListItem = new TypeListItem(dexFile, typeArray);
return dexFile.TypeListsSection.intern(typeListItem);
}