aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Herhut <herhut@google.com>2017-10-24 12:12:31 +0200
committerStephan Herhut <herhut@google.com>2017-10-24 12:12:31 +0200
commit2e74ac1dde05d47e14fd6edfcbe016730bfafef8 (patch)
treed0b3a0846fcd232b9ed0aee89556292e1f52cc06
parent478befe3cc9a846d3897b23db0e8b893a8e2858e (diff)
downloadr8-2e74ac1dde05d47e14fd6edfcbe016730bfafef8.tar.gz
Also synchronize generation of staticValues.
Bug: Change-Id: Idead3524d1e54cb000b29eb5421765d98dde2d27
-rw-r--r--src/main/java/com/android/tools/r8/dex/FileWriter.java47
-rw-r--r--src/main/java/com/android/tools/r8/graph/DexProgramClass.java38
-rw-r--r--src/main/java/com/android/tools/r8/graph/PresortedComparable.java18
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);