Get rid of the annotation set ref list pool

This commit is contained in:
Ben Gruver
2013-04-28 13:55:29 -07:00
parent fbdc6cb9cb
commit 1726f028a8
7 changed files with 88 additions and 228 deletions

View File

@ -1,40 +0,0 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer;
import javax.annotation.Nonnull;
import java.util.Collection;
public interface AnnotationSetRefSection<AnnotationSetKey, AnnotationSetRefKey>
extends NullableOffsetSection<AnnotationSetRefKey> {
@Nonnull Collection<AnnotationSetKey> getAnnotationSets(@Nonnull AnnotationSetRefKey key);
}

View File

@ -41,8 +41,7 @@ import java.util.List;
import java.util.Map;
public interface ClassSection<StringKey extends CharSequence, TypeKey extends CharSequence, TypeListKey, ClassKey,
FieldKey, MethodKey, AnnotationSetKey,
AnnotationSetRefKey, EncodedValue, DebugItem, Insn,
FieldKey, MethodKey, AnnotationSetKey, EncodedValue, DebugItem, Insn,
ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> extends IndexSection<ClassKey> {
@Nonnull Collection<? extends ClassKey> getSortedClasses();
@ -68,7 +67,7 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
@Nullable AnnotationSetKey getClassAnnotations(@Nonnull ClassKey key);
@Nullable AnnotationSetKey getFieldAnnotations(@Nonnull FieldKey key);
@Nullable AnnotationSetKey getMethodAnnotations(@Nonnull MethodKey key);
@Nullable AnnotationSetRefKey getParameterAnnotations(@Nonnull MethodKey key);
@Nullable List<? extends AnnotationSetKey> getParameterAnnotations(@Nonnull MethodKey key);
@Nullable Iterable<? extends DebugItem> getDebugItems(@Nonnull MethodKey key);
@Nullable Iterable<? extends StringKey> getParameterNames(@Nonnull MethodKey key);
@ -84,6 +83,9 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
void setAnnotationDirectoryOffset(@Nonnull ClassKey key, int offset);
int getAnnotationDirectoryOffset(@Nonnull ClassKey key);
void setAnnotationSetRefListOffset(@Nonnull MethodKey key, int offset);
int getAnnotationSetRefListOffset(@Nonnull MethodKey key);
void setCodeItemOffset(@Nonnull MethodKey key, int offset);
int getCodeItemOffset(@Nonnull MethodKey key);

View File

@ -73,7 +73,7 @@ public abstract class DexWriter<
TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
ClassKey extends Comparable<? super ClassKey>,
AnnotationKey extends Annotation, AnnotationSetKey, AnnotationSetRefKey,
AnnotationKey extends Annotation, AnnotationSetKey,
TypeListKey,
FieldKey extends FieldRefKey, MethodKey extends MethodRefKey,
EncodedValue, AnnotationElement,
@ -102,6 +102,7 @@ public abstract class DexWriter<
protected int mapSectionOffset = NO_OFFSET;
protected int numEncodedArrayItems = 0;
protected int numAnnotationSetRefItems = 0;
protected int numAnnotationDirectoryItems = 0;
protected int numDebugInfoItems = 0;
protected int numCodeItemItems = 0;
@ -115,12 +116,11 @@ public abstract class DexWriter<
protected FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection;
protected MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection;
protected ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
AnnotationSetRefKey, EncodedValue, DebugItem, Insn, ExceptionHandler> classSection;
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection;
protected TypeListSection<TypeKey, TypeListKey> typeListSection;
protected AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection;
protected AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection;
protected AnnotationSetRefSection<AnnotationSetKey, AnnotationSetRefKey> annotationSetRefSection;
protected DexWriter(InstructionFactory<? extends Insn> instructionFactory,
StringSection<StringKey, StringRef> stringSection,
@ -129,12 +129,11 @@ public abstract class DexWriter<
FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection,
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
AnnotationSetRefKey, EncodedValue, DebugItem, Insn, ExceptionHandler> classSection,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection,
TypeListSection<TypeKey, TypeListKey> typeListSection,
AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement,
EncodedValue> annotationSection,
AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection,
AnnotationSetRefSection<AnnotationSetKey, AnnotationSetRefKey> annotationSetRefSection) {
AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection) {
this.instructionFactory = instructionFactory;
this.stringSection = stringSection;
this.typeSection = typeSection;
@ -145,7 +144,6 @@ public abstract class DexWriter<
this.typeListSection = typeListSection;
this.annotationSection = annotationSection;
this.annotationSetSection = annotationSetSection;
this.annotationSetRefSection = annotationSetRefSection;
}
protected abstract void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer,
@ -590,15 +588,29 @@ public abstract class DexWriter<
private void writeAnnotationSetRefs(@Nonnull DexDataWriter writer) throws IOException {
writer.align();
annotationSetRefSectionOffset = writer.getPosition();
for (Map.Entry<? extends AnnotationSetRefKey, Integer> entry: annotationSetRefSection.getItems()) {
writer.align();
entry.setValue(writer.getPosition());
HashMap<List<? extends AnnotationSetKey>, Integer> internedItems = Maps.newHashMap();
Collection<AnnotationSetKey> annotationSets = annotationSetRefSection.getAnnotationSets(entry.getKey());
for (ClassKey classKey: classSection.getSortedClasses()) {
for (MethodKey methodKey: classSection.getSortedMethods(classKey)) {
List<? extends AnnotationSetKey> parameterAnnotations = classSection.getParameterAnnotations(methodKey);
if (parameterAnnotations != null) {
Integer prev = internedItems.get(parameterAnnotations);
if (prev != null) {
classSection.setAnnotationSetRefListOffset(methodKey, prev);
} else {
writer.align();
int position = writer.getPosition();
classSection.setAnnotationSetRefListOffset(methodKey, position);
internedItems.put(parameterAnnotations, position);
writer.writeInt(annotationSets.size());
for (AnnotationSetKey annotationSetKey: annotationSets) {
writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey));
numAnnotationSetRefItems++;
writer.writeInt(parameterAnnotations.size());
for (AnnotationSetKey annotationSetKey: parameterAnnotations) {
writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey));
}
}
}
}
}
}
@ -653,11 +665,11 @@ public abstract class DexWriter<
}
for (MethodKey method: classSection.getSortedMethods(key)) {
AnnotationSetRefKey parameterAnnotationsKey = classSection.getParameterAnnotations(method);
if (parameterAnnotationsKey != null) {
int offset = classSection.getAnnotationSetRefListOffset(method);
if (offset != DexWriter.NO_OFFSET) {
methodAnnotations++;
tempBuffer.putInt(methodSection.getItemIndex(method));
tempBuffer.putInt(annotationSetRefSection.getItemOffset(parameterAnnotationsKey));
tempBuffer.putInt(offset);
}
}
@ -1016,7 +1028,7 @@ public abstract class DexWriter<
if (annotationSetSection.getItems().size() > 0) {
numItems++;
}
if (annotationSetRefSection.getItems().size() > 0) {
if (numAnnotationSetRefItems > 0) {
numItems++;
}
if (numAnnotationDirectoryItems > 0) {
@ -1063,8 +1075,7 @@ public abstract class DexWriter<
writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM, annotationSetSection.getItems().size(),
annotationSetSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, annotationSetRefSection.getItems().size(),
annotationSetRefSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset);
writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems,
annotationDirectorySectionOffset);
writeMapItem(writer, ItemType.DEBUG_INFO_ITEM, numDebugInfoItems, debugSectionOffset);

View File

@ -1,147 +0,0 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.pool;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.dexlib2.writer.pool.AnnotationSetRefPool.Key;
import org.jf.dexlib2.writer.AnnotationSetRefSection;
import org.jf.util.CollectionUtils;
import javax.annotation.Nonnull;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
public class AnnotationSetRefPool extends BaseNullableOffsetPool<Key>
implements AnnotationSetRefSection<Set<? extends Annotation>, Key> {
@Nonnull private final AnnotationSetPool annotationSetPool;
public AnnotationSetRefPool(@Nonnull AnnotationSetPool annotationSetPool) {
this.annotationSetPool = annotationSetPool;
}
public void intern(@Nonnull Method method) {
Key annotationSetRefKey = new Key(method);
Integer prev = internedItems.put(annotationSetRefKey, 0);
if (prev == null) {
for (Set<? extends Annotation> annotationSet: annotationSetRefKey.getAnnotationSets()) {
annotationSetPool.intern(annotationSet);
}
}
}
@Nonnull @Override public Collection<Set<? extends Annotation>> getAnnotationSets(@Nonnull Key key) {
return key.getAnnotationSets();
}
public static class Key implements Comparable<Key> {
@Nonnull private final Method method;
private final int size;
public Key(@Nonnull Method method) {
this.method = method;
this.size = CollectionUtils.lastIndexOf(method.getParameters(), HAS_ANNOTATIONS) + 1;
}
public Collection<Set<? extends Annotation>> getAnnotationSets() {
return new AbstractCollection<Set<? extends Annotation>>() {
@Nonnull @Override public Iterator<Set<? extends Annotation>> iterator() {
return FluentIterable.from(method.getParameters())
.limit(size)
.transform(PARAMETER_ANNOTATIONS).iterator();
}
@Override public int size() {
return size;
}
};
}
@Override
public int hashCode() {
int hashCode = 1;
for (Set<? extends Annotation> annotationSet: getAnnotationSets()) {
hashCode = hashCode*31 + annotationSet.hashCode();
}
return hashCode;
}
@Override
public boolean equals(Object o) {
if (o instanceof Key) {
Key other = (Key)o;
if (size != other.size) {
return false;
}
Iterator<Set<? extends Annotation>> otherAnnotationSets = getAnnotationSets().iterator();
for (Set<? extends Annotation> annotationSet: getAnnotationSets()) {
if (!annotationSet.equals(otherAnnotationSets.next())) {
return false;
}
}
return true;
}
return false;
}
private static final Predicate<MethodParameter> HAS_ANNOTATIONS = new Predicate<MethodParameter>() {
@Override
public boolean apply(MethodParameter input) {
return input.getAnnotations().size() > 0;
}
};
private static final Function<MethodParameter, Set<? extends Annotation>> PARAMETER_ANNOTATIONS =
new Function<MethodParameter, Set<? extends Annotation>>() {
@Override
public Set<? extends Annotation> apply(MethodParameter input) {
return input.getAnnotations();
}
};
@Override
public int compareTo(Key o) {
int res = Ints.compare(size, o.size);
if (res != 0) return res;
return CollectionUtils.compareAsIterable(CollectionUtils.setComparator(Ordering.natural()),
getAnnotationSets(), o.getAnnotationSets());
}
}
}

View File

@ -47,6 +47,7 @@ import org.jf.dexlib2.util.EncodedValueUtils;
import org.jf.dexlib2.util.ReferenceUtil;
import org.jf.dexlib2.writer.ClassSection;
import org.jf.dexlib2.writer.DebugWriter;
import org.jf.util.AbstractForwardSequentialList;
import org.jf.util.CollectionUtils;
import org.jf.util.ExceptionWithContext;
@ -58,7 +59,7 @@ import java.util.Map.Entry;
public class ClassPool implements ClassSection<CharSequence, CharSequence,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, PoolClassDef, Field, PoolMethod,
Set<? extends Annotation>, AnnotationSetRefPool.Key,
Set<? extends Annotation>,
EncodedValue, DebugItem, Instruction, ExceptionHandler> {
@Nonnull private HashMap<String, PoolClassDef> internedItems = Maps.newHashMap();
@ -67,7 +68,6 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
@Nonnull private final FieldPool fieldPool;
@Nonnull private final MethodPool methodPool;
@Nonnull private final AnnotationSetPool annotationSetPool;
@Nonnull private final AnnotationSetRefPool annotationSetRefPool;
@Nonnull private final TypeListPool typeListPool;
public ClassPool(@Nonnull StringPool stringPool,
@ -75,14 +75,12 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
@Nonnull FieldPool fieldPool,
@Nonnull MethodPool methodPool,
@Nonnull AnnotationSetPool annotationSetPool,
@Nonnull AnnotationSetRefPool annotationSetRefPool,
@Nonnull TypeListPool typeListPool) {
this.stringPool = stringPool;
this.typePool = typePool;
this.fieldPool = fieldPool;
this.methodPool = methodPool;
this.annotationSetPool = annotationSetPool;
this.annotationSetRefPool = annotationSetRefPool;
this.typeListPool = typeListPool;
}
@ -127,7 +125,10 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
internCode(method);
internDebug(method);
annotationSetPool.intern(method.getAnnotations());
annotationSetRefPool.intern(method);
for (MethodParameter parameter: method.getParameters()) {
annotationSetPool.intern(parameter.getAnnotations());
}
}
annotationSetPool.intern(poolClassDef.getAnnotations());
@ -353,13 +354,39 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
return annotations;
}
@Nullable @Override public AnnotationSetRefPool.Key getParameterAnnotations(@Nonnull PoolMethod method) {
AnnotationSetRefPool.Key key = new AnnotationSetRefPool.Key(method);
Collection<Set<? extends Annotation>> annotations = key.getAnnotationSets();
if (annotations.size() == 0) {
return null;
private static final Predicate<MethodParameter> HAS_PARAMETER_ANNOTATIONS = new Predicate<MethodParameter>() {
@Override
public boolean apply(MethodParameter input) {
return input.getAnnotations().size() > 0;
}
return key;
};
private static final Function<MethodParameter, Set<? extends Annotation>> PARAMETER_ANNOTATIONS =
new Function<MethodParameter, Set<? extends Annotation>>() {
@Override
public Set<? extends Annotation> apply(MethodParameter input) {
return input.getAnnotations();
}
};
@Nullable @Override public List<? extends Set<? extends Annotation>> getParameterAnnotations(
@Nonnull final PoolMethod method) {
final int lastIndex = CollectionUtils.lastIndexOf(method.getParameters(), HAS_PARAMETER_ANNOTATIONS);
if (lastIndex > -1) {
return new AbstractForwardSequentialList<Set<? extends Annotation>>() {
@Nonnull @Override public Iterator<Set<? extends Annotation>> iterator() {
return FluentIterable.from(method.getParameters())
.limit(lastIndex+1)
.transform(PARAMETER_ANNOTATIONS).iterator();
}
@Override public int size() {
return lastIndex+1;
}
};
}
return null;
}
@Nullable @Override public Iterable<? extends DebugItem> getDebugItems(@Nonnull PoolMethod method) {
@ -423,6 +450,14 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
return classDef.annotationDirectoryOffset;
}
@Override public void setAnnotationSetRefListOffset(@Nonnull PoolMethod method, int offset) {
method.annotationSetRefListOffset = offset;
}
@Override public int getAnnotationSetRefListOffset(@Nonnull PoolMethod method) {
return method.annotationSetRefListOffset;
}
@Override public void setCodeItemOffset(@Nonnull PoolMethod method, int offset) {
method.codeItemOffset = offset;
}

View File

@ -52,7 +52,7 @@ import java.util.Set;
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key,
FieldReference, MethodReference, PoolClassDef,
Annotation, Set<? extends Annotation>, AnnotationSetRefPool.Key,
Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> {
@ -65,21 +65,19 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
MethodPool methodPool = new MethodPool(stringPool, typePool, protoPool);
AnnotationPool annotationPool = new AnnotationPool(stringPool, typePool, fieldPool, methodPool);
AnnotationSetPool annotationSetPool = new AnnotationSetPool(annotationPool);
AnnotationSetRefPool annotationSetRefPool = new AnnotationSetRefPool(annotationSetPool);
ClassPool classPool = new ClassPool(stringPool, typePool, fieldPool, methodPool, annotationSetPool,
annotationSetRefPool, typeListPool);
typeListPool);
return new DexPool(stringPool, typePool, protoPool, fieldPool, methodPool, classPool, typeListPool,
annotationPool, annotationSetPool, annotationSetRefPool);
annotationPool, annotationSetPool);
}
private DexPool(StringPool stringPool, TypePool typePool, ProtoPool protoPool, FieldPool fieldPool,
MethodPool methodPool, ClassPool classPool, TypeListPool typeListPool,
AnnotationPool annotationPool, AnnotationSetPool annotationSetPool,
AnnotationSetRefPool annotationSetRefPool) {
AnnotationPool annotationPool, AnnotationSetPool annotationSetPool) {
super(ImmutableInstructionFactory.INSTANCE, stringPool, typePool, protoPool, fieldPool, methodPool, classPool,
typeListPool, annotationPool, annotationSetPool, annotationSetRefPool);
typeListPool, annotationPool, annotationSetPool);
}
public static void writeTo(@Nonnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input) throws IOException {

View File

@ -46,6 +46,7 @@ import java.util.Set;
class PoolMethod extends BaseMethodReference implements Method {
@Nonnull private final Method method;
protected int annotationSetRefListOffset = DexPool.NO_OFFSET;
protected int codeItemOffset = DexPool.NO_OFFSET;
protected int debugInfoOffset = DexPool.NO_OFFSET;