summaryrefslogtreecommitdiffstats
path: root/dex
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-09-06 18:32:05 -0700
committerIan Rogers <irogers@google.com>2013-09-21 21:30:34 -0700
commitd4ec55c4e1acc3c3df937facbd367aff6618536c (patch)
tree5285b96b42f7c061a743eb78ad35bd88071fe134 /dex
parent12f0b0057dc5fc8a157b45c79cf75e54eafa8f40 (diff)
downloadlibcore-d4ec55c4e1acc3c3df937facbd367aff6618536c.zip
libcore-d4ec55c4e1acc3c3df937facbd367aff6618536c.tar.gz
libcore-d4ec55c4e1acc3c3df937facbd367aff6618536c.tar.bz2
Lazier annotation signature parsing.
Bug: 10244719. Also, make wider use of empty arrays. Also, use named inner classes to aid profiling. Remove caching as the empty result will be fast. Porting the ART changes to DVM, to avoid the caching, results in bringing in a bunch of other ART clean-up. TODO, avoid modified-UTF8 to String conversions by Dex. Change-Id: I051b6e34b5a4e7a7f1383461a799755947a5ba36 Conflicts: libdvm/src/main/java/java/lang/Class.java
Diffstat (limited to 'dex')
-rw-r--r--dex/src/main/java/com/android/dex/Dex.java367
1 files changed, 201 insertions, 166 deletions
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
index bf24998..89edf6e 100644
--- a/dex/src/main/java/com/android/dex/Dex.java
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -56,77 +56,16 @@ public final class Dex {
// Provided as a convenience to avoid a memory allocation to benefit Dalvik.
// Note: libcore.util.EmptyArray cannot be accessed when this code isn't run on Dalvik.
static final short[] EMPTY_SHORT_ARRAY = new short[0];
+
private ByteBuffer data;
private final TableOfContents tableOfContents = new TableOfContents();
private int nextSectionStart = 0;
-
- private static abstract class AbstractRandomAccessList<T>
- extends AbstractList<T> implements RandomAccess {
- }
-
- private List<String> strings = new AbstractRandomAccessList<String>() {
- @Override public String get(int index) {
- checkBounds(index, tableOfContents.stringIds.size);
- return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM))
- .readString();
- }
- @Override public int size() {
- return tableOfContents.stringIds.size;
- }
- };
-
- private final List<Integer> typeIds = new AbstractRandomAccessList<Integer>() {
- @Override public Integer get(int index) {
- checkBounds(index, tableOfContents.typeIds.size);
- return open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt();
- }
- @Override public int size() {
- return tableOfContents.typeIds.size;
- }
- };
-
- private final List<String> typeNames = new AbstractRandomAccessList<String>() {
- @Override public String get(int index) {
- checkBounds(index, tableOfContents.typeIds.size);
- return strings.get(typeIds.get(index));
- }
- @Override public int size() {
- return tableOfContents.typeIds.size;
- }
- };
-
- private final List<ProtoId> protoIds = new AbstractRandomAccessList<ProtoId>() {
- @Override public ProtoId get(int index) {
- checkBounds(index, tableOfContents.protoIds.size);
- return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index))
- .readProtoId();
- }
- @Override public int size() {
- return tableOfContents.protoIds.size;
- }
- };
-
- private final List<FieldId> fieldIds = new AbstractRandomAccessList<FieldId>() {
- @Override public FieldId get(int index) {
- checkBounds(index, tableOfContents.fieldIds.size);
- return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index))
- .readFieldId();
- }
- @Override public int size() {
- return tableOfContents.fieldIds.size;
- }
- };
-
- private final List<MethodId> methodIds = new AbstractRandomAccessList<MethodId>() {
- @Override public MethodId get(int index) {
- checkBounds(index, tableOfContents.methodIds.size);
- return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index))
- .readMethodId();
- }
- @Override public int size() {
- return tableOfContents.methodIds.size;
- }
- };
+ private final StringTable strings = new StringTable();
+ private final TypeIndexToDescriptorIndexTable typeIds = new TypeIndexToDescriptorIndexTable();
+ private final TypeIndexToDescriptorTable typeNames = new TypeIndexToDescriptorTable();
+ private final ProtoIdTable protoIds = new ProtoIdTable();
+ private final FieldIdTable fieldIds = new FieldIdTable();
+ private final MethodIdTable methodIds = new MethodIdTable();
/**
* Creates a new dex that reads from {@code data}. It is an error to modify
@@ -314,31 +253,7 @@ public final class Dex {
}
public Iterable<ClassDef> classDefs() {
- return new Iterable<ClassDef>() {
- public Iterator<ClassDef> iterator() {
- if (!tableOfContents.classDefs.exists()) {
- return Collections.<ClassDef>emptySet().iterator();
- }
- return new Iterator<ClassDef>() {
- private Dex.Section in = open(tableOfContents.classDefs.off);
- private int count = 0;
-
- public boolean hasNext() {
- return count < tableOfContents.classDefs.size;
- }
- public ClassDef next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- count++;
- return in.readClassDef();
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- };
+ return new ClassDefIterable();
}
public TypeList readTypeList(int offset) {
@@ -414,6 +329,113 @@ public final class Dex {
open(CHECKSUM_OFFSET).writeInt(computeChecksum());
}
+ /**
+ * Look up a field id name index from a field index. Cheaper than:
+ * {@code fieldIds().get(fieldDexIndex).getNameIndex();}
+ */
+ public int nameIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // typeIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ public int findStringIndex(String s) {
+ return Collections.binarySearch(strings, s);
+ }
+
+ public int findTypeIndex(String descriptor) {
+ return Collections.binarySearch(typeNames, descriptor);
+ }
+
+ public int findFieldIndex(FieldId fieldId) {
+ return Collections.binarySearch(fieldIds, fieldId);
+ }
+
+ public int findMethodIndex(MethodId methodId) {
+ return Collections.binarySearch(methodIds, methodId);
+ }
+
+ /**
+ * Look up a field id type index from a field index. Cheaper than:
+ * {@code fieldIds().get(fieldDexIndex).getTypeIndex();}
+ */
+ public int typeIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ return data.getShort(position) & 0xFFFF; // typeIndex
+ }
+
+ /**
+ * Look up a method id name index from a method index. Cheaper than:
+ * {@code methodIds().get(methodIndex).getNameIndex();}
+ */
+ public int nameIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // protoIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ /**
+ * Look up a parameter type ids from a method index. Cheaper than:
+ * {@code readTypeList(protoIds.get(methodIds().get(methodDexIndex).getProtoIndex()).getParametersOffset()).getTypes();}
+ */
+ public short[] parameterTypeIndicesFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ position += SizeOf.UINT; // returnTypeIndex
+ int parametersOffset = data.getInt(position);
+ if (parametersOffset == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ position = parametersOffset;
+ int size = data.getInt(position);
+ if (size <= 0) {
+ throw new AssertionError("Unexpected parameter type list size: " + size);
+ }
+ position += SizeOf.UINT;
+ short[] types = new short[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = data.getShort(position);
+ position += SizeOf.USHORT;
+ }
+ return types;
+ }
+
+ /**
+ * Look up a method id return type index from a method index. Cheaper than:
+ * {@code protoIds().get(methodIds().get(methodDexIndex).getProtoIndex()).getReturnTypeIndex();}
+ */
+ public int returnTypeIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ return data.getInt(position); // returnTypeIndex
+ }
+
+ /**
+ * Look up a descriptor index from a type index. Cheaper than:
+ * {@code open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt();}
+ */
+ private int descriptorIndexFromTypeIndex(int typeIndex) {
+ checkBounds(typeIndex, tableOfContents.typeIds.size);
+ int position = tableOfContents.typeIds.off + (SizeOf.TYPE_ID_ITEM * typeIndex);
+ return data.getInt(position);
+ }
+
public final class Section implements ByteInput, ByteOutput {
private final String name;
private final ByteBuffer data;
@@ -791,84 +813,97 @@ public final class Dex {
}
}
- /**
- * Look up a field id name index from a field index. Equivalent to:
- * {@code fieldIds().get(fieldDexIndex).getNameIndex();}
- */
- public int nameIndexFromFieldIndex(int fieldIndex) {
- checkBounds(fieldIndex, tableOfContents.fieldIds.size);
- int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
- position += SizeOf.USHORT; // declaringClassIndex
- position += SizeOf.USHORT; // typeIndex
- return data.getInt(position); // nameIndex
- }
+ private final class StringTable extends AbstractList<String> implements RandomAccess {
+ @Override public String get(int index) {
+ checkBounds(index, tableOfContents.stringIds.size);
+ return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM))
+ .readString();
+ }
+ @Override public int size() {
+ return tableOfContents.stringIds.size;
+ }
+ };
- /**
- * Look up a field id type index from a field index. Equivalent to:
- * {@code fieldIds().get(fieldDexIndex).getTypeIndex();}
- */
- public int typeIndexFromFieldIndex(int fieldIndex) {
- checkBounds(fieldIndex, tableOfContents.fieldIds.size);
- int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
- position += SizeOf.USHORT; // declaringClassIndex
- return data.getShort(position) & 0xFFFF; // typeIndex
- }
+ private final class TypeIndexToDescriptorIndexTable extends AbstractList<Integer>
+ implements RandomAccess {
+ @Override public Integer get(int index) {
+ return descriptorIndexFromTypeIndex(index);
+ }
+ @Override public int size() {
+ return tableOfContents.typeIds.size;
+ }
+ };
- /**
- * Look up a method id name index from a method index. Equivalent to:
- * {@code methodIds().get(methodIndex).getNameIndex();}
- */
- public int nameIndexFromMethodIndex(int methodIndex) {
- checkBounds(methodIndex, tableOfContents.methodIds.size);
- int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
- position += SizeOf.USHORT; // declaringClassIndex
- position += SizeOf.USHORT; // protoIndex
- return data.getInt(position); // nameIndex
- }
+ private final class TypeIndexToDescriptorTable extends AbstractList<String>
+ implements RandomAccess {
+ @Override public String get(int index) {
+ return strings.get(descriptorIndexFromTypeIndex(index));
+ }
+ @Override public int size() {
+ return tableOfContents.typeIds.size;
+ }
+ };
- /**
- * Lookup a parameter type ids from a method index. Equivalent to:
- * {@code readTypeList(protoIds.get(methodIds().get(methodDexIndex).getProtoIndex()).getParametersOffset()).getTypes();}
- */
- public short[] parameterTypeIndicesFromMethodIndex(int methodIndex) {
- checkBounds(methodIndex, tableOfContents.methodIds.size);
- int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
- position += SizeOf.USHORT; // declaringClassIndex
- int protoIndex = data.getShort(position) & 0xFFFF;
- checkBounds(protoIndex, tableOfContents.protoIds.size);
- position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
- position += SizeOf.UINT; // shortyIndex
- position += SizeOf.UINT; // returnTypeIndex
- int parametersOffset = data.getInt(position);
- if (parametersOffset == 0) {
- return EMPTY_SHORT_ARRAY;
+ private final class ProtoIdTable extends AbstractList<ProtoId> implements RandomAccess {
+ @Override public ProtoId get(int index) {
+ checkBounds(index, tableOfContents.protoIds.size);
+ return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index))
+ .readProtoId();
}
- position = parametersOffset;
- int size = data.getInt(position);
- if (size <= 0) {
- throw new AssertionError("Unexpected parameter type list size: " + size);
+ @Override public int size() {
+ return tableOfContents.protoIds.size;
}
- position += SizeOf.UINT;
- short[] types = new short[size];
- for (int i = 0; i < size; i++) {
- types[i] = data.getShort(position);
- position += SizeOf.USHORT;
+ };
+
+ private final class FieldIdTable extends AbstractList<FieldId> implements RandomAccess {
+ @Override public FieldId get(int index) {
+ checkBounds(index, tableOfContents.fieldIds.size);
+ return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+ .readFieldId();
}
- return types;
- }
+ @Override public int size() {
+ return tableOfContents.fieldIds.size;
+ }
+ };
- /**
- * Look up a method id return type index from a method index. Equivalent to:
- * {@code protoIds().get(methodIds().get(methodDexIndex).getProtoIndex()).getReturnTypeIndex();}
- */
- public int returnTypeIndexFromMethodIndex(int methodIndex) {
- checkBounds(methodIndex, tableOfContents.methodIds.size);
- int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
- position += SizeOf.USHORT; // declaringClassIndex
- int protoIndex = data.getShort(position) & 0xFFFF;
- checkBounds(protoIndex, tableOfContents.protoIds.size);
- position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
- position += SizeOf.UINT; // shortyIndex
- return data.getInt(position); // returnTypeIndex
- }
+ private final class MethodIdTable extends AbstractList<MethodId> implements RandomAccess {
+ @Override public MethodId get(int index) {
+ checkBounds(index, tableOfContents.methodIds.size);
+ return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+ .readMethodId();
+ }
+ @Override public int size() {
+ return tableOfContents.methodIds.size;
+ }
+ };
+
+ private final class ClassDefIterator implements Iterator<ClassDef> {
+ private final Dex.Section in = open(tableOfContents.classDefs.off);
+ private int count = 0;
+
+ @Override
+ public boolean hasNext() {
+ return count < tableOfContents.classDefs.size;
+ }
+ @Override
+ public ClassDef next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ count++;
+ return in.readClassDef();
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ private final class ClassDefIterable implements Iterable<ClassDef> {
+ public Iterator<ClassDef> iterator() {
+ return !tableOfContents.classDefs.exists()
+ ? Collections.<ClassDef>emptySet().iterator()
+ : new ClassDefIterator();
+ }
+ };
}