diff options
author | Stephan Herhut <herhut@google.com> | 2017-10-24 12:12:31 +0200 |
---|---|---|
committer | Stephan Herhut <herhut@google.com> | 2017-10-24 12:12:31 +0200 |
commit | 2e74ac1dde05d47e14fd6edfcbe016730bfafef8 (patch) | |
tree | d0b3a0846fcd232b9ed0aee89556292e1f52cc06 | |
parent | 478befe3cc9a846d3897b23db0e8b893a8e2858e (diff) | |
download | r8-2e74ac1dde05d47e14fd6edfcbe016730bfafef8.tar.gz |
Also synchronize generation of staticValues.
Bug:
Change-Id: Idead3524d1e54cb000b29eb5421765d98dde2d27
3 files changed, 63 insertions, 40 deletions
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java index da3722f20..b1db651dc 100644 --- a/src/main/java/com/android/tools/r8/dex/FileWriter.java +++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java @@ -58,7 +58,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import java.security.MessageDigest; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -69,7 +68,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.ToIntFunction; import java.util.zip.Adler32; @@ -101,29 +99,13 @@ public class FileWriter { } dest.putUleb128(mapping.getOffsetFor(annotation.type)); dest.putUleb128(annotation.elements.length); - assert isSorted(annotation.elements, (element) -> element.name); + assert PresortedComparable.isSorted(annotation.elements, (element) -> element.name); for (DexAnnotationElement element : annotation.elements) { dest.putUleb128(mapping.getOffsetFor(element.name)); element.value.writeTo(dest, mapping); } } - private static <T extends PresortedComparable<T>> boolean isSorted(KeyedDexItem<T>[] items) { - return isSorted(items, KeyedDexItem::getKey); - } - - private static <S, T extends Comparable<T>> boolean isSorted(S[] items, Function<S, T> getter) { - T current = null; - for (S item : items) { - T next = getter.apply(item); - if (current != null && current.compareTo(next) >= 0) { - return false; - } - current = next; - } - return true; - } - public FileWriter collect() { // Use the class array from the mapping, as it has a deterministic iteration order. new ProgramClassDependencyCollector(application, mapping.getClasses()) @@ -518,7 +500,7 @@ public class FileWriter { private void writeAnnotationSet(DexAnnotationSet set) { assert !set.isEmpty(); - assert isSorted(set.annotations, (item) -> item.annotation.type); + assert PresortedComparable.isSorted(set.annotations, (item) -> item.annotation.type); mixedSectionOffsets.setOffsetFor(set, dest.align(4)); if (Log.ENABLED) { Log.verbose(getClass(), "Writing AnnotationSet @ 0x%08x.", dest.position()); @@ -564,7 +546,7 @@ public class FileWriter { } private void writeEncodedFields(DexEncodedField[] fields) { - assert isSorted(fields); + assert PresortedComparable.isSorted(fields); int currentOffset = 0; for (DexEncodedField field : fields) { int nextOffset = mapping.getOffsetFor(field.field); @@ -576,7 +558,7 @@ public class FileWriter { } private void writeEncodedMethods(DexEncodedMethod[] methods, boolean clearBodies) { - assert isSorted(methods); + assert PresortedComparable.isSorted(methods); int currentOffset = 0; for (DexEncodedMethod method : methods) { int nextOffset = mapping.getOffsetFor(method.method); @@ -614,21 +596,12 @@ public class FileWriter { } private void addStaticFieldValues(DexProgramClass clazz) { - DexEncodedField[] fields = clazz.staticFields(); - int length = 0; - List<DexValue> values = new ArrayList<>(fields.length); - for (int i = 0; i < fields.length; i++) { - DexEncodedField field = fields[i]; - assert field.staticValue != null; - values.add(field.staticValue); - if (!field.staticValue.isDefault(field.field.type, application.dexItemFactory)) { - length = i + 1; - } - } - if (length > 0) { - DexEncodedArray staticValues = new DexEncodedArray( - values.subList(0, length).toArray(new DexValue[length])); - clazz.setStaticValues(staticValues); + clazz.computeStaticValues(application.dexItemFactory); + // We have collected the individual components of this array due to the data stored in + // DexEncodedField#staticValues. However, we have to collect the DexEncodedArray itself + // here. + DexEncodedArray staticValues = clazz.getStaticValues(); + if (staticValues != null) { mixedSectionOffsets.add(staticValues); } } diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java index fcb4684ad..b64053ae0 100644 --- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java @@ -8,17 +8,22 @@ import com.android.tools.r8.dex.IndexedItemCollection; import com.android.tools.r8.dex.MixedSectionCollection; import com.android.tools.r8.utils.ProgramResource; import com.android.tools.r8.utils.ProgramResource.Kind; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.function.Supplier; public class DexProgramClass extends DexClass implements Supplier<DexProgramClass> { + + private static DexEncodedArray SENTINEL_NOT_YET_COMPUTED = new DexEncodedArray(new DexValue[0]); + private final ProgramResource.Kind originKind; - private DexEncodedArray staticValues; + private DexEncodedArray staticValues = SENTINEL_NOT_YET_COMPUTED; private final Collection<DexProgramClass> synthesizedFrom; public DexProgramClass( @@ -214,11 +219,38 @@ public class DexProgramClass extends DexClass implements Supplier<DexProgramClas return accumulated; } - public void setStaticValues(DexEncodedArray staticValues) { - this.staticValues = staticValues; + public void computeStaticValues(DexItemFactory factory) { + // It does not actually hurt to compute this multiple times. So racing on staticValues is OK. + if (staticValues == SENTINEL_NOT_YET_COMPUTED) { + synchronized (staticFields) { + assert PresortedComparable.isSorted(staticFields); + DexEncodedField[] fields = staticFields; + int length = 0; + List<DexValue> values = new ArrayList<>(fields.length); + for (int i = 0; i < fields.length; i++) { + DexEncodedField field = fields[i]; + assert field.staticValue != null; + values.add(field.staticValue); + if (!field.staticValue.isDefault(field.field.type, factory)) { + length = i + 1; + } + } + if (length > 0) { + staticValues = new DexEncodedArray( + values.subList(0, length).toArray(new DexValue[length])); + } else { + staticValues = null; + } + } + } } public DexEncodedArray getStaticValues() { + // The sentinel value is left over for classes that actually have no fields. + if (staticValues == SENTINEL_NOT_YET_COMPUTED) { + assert !hasMethodsOrFields(); + return null; + } return staticValues; } diff --git a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java index eb130d6e1..a4ee2ee88 100644 --- a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java +++ b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java @@ -4,8 +4,26 @@ package com.android.tools.r8.graph; import com.android.tools.r8.naming.NamingLens; +import java.util.function.Function; public interface PresortedComparable<T> extends Presorted, Comparable<T> { + + static <T extends PresortedComparable<T>> boolean isSorted(KeyedDexItem<T>[] items) { + return isSorted(items, KeyedDexItem::getKey); + } + + static <S, T extends Comparable<T>> boolean isSorted(S[] items, Function<S, T> getter) { + T current = null; + for (S item : items) { + T next = getter.apply(item); + if (current != null && current.compareTo(next) >= 0) { + return false; + } + current = next; + } + return true; + } + // Slow comparison methods that make no use of indices for comparisons. These are used // for sorting operations when reading dex files. int slowCompareTo(T other); |