Introduce EnumValueInfoMap rewritten with lens.
Bug: 150193407
Change-Id: Id50ef36b7b4a38cd110bcfae1690718f5de52d00
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 65bf330..b0adc79 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -42,7 +42,7 @@
import com.android.tools.r8.ir.optimize.UninstantiatedTypeOptimization.UninstantiatedTypeOptimizationGraphLense;
import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector;
import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector.UnusedArgumentsGraphLense;
-import com.android.tools.r8.ir.optimize.enums.EnumInfoMapCollector;
+import com.android.tools.r8.ir.optimize.enums.EnumValueInfoMapCollector;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.kotlin.Kotlin;
@@ -516,7 +516,7 @@
appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness).run());
}
if (options.enableEnumValueOptimization || options.enableEnumUnboxing) {
- appViewWithLiveness.setAppInfo(new EnumInfoMapCollector(appViewWithLiveness).run());
+ appViewWithLiveness.setAppInfo(new EnumValueInfoMapCollector(appViewWithLiveness).run());
}
appView.setAppServices(appView.appServices().rewrittenWithLens(appView.graphLense()));
diff --git a/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java b/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java
new file mode 100644
index 0000000..470685f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java
@@ -0,0 +1,121 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import java.util.Set;
+
+public class EnumValueInfoMapCollection {
+
+ public static EnumValueInfoMapCollection empty() {
+ return new EnumValueInfoMapCollection(ImmutableMap.of());
+ }
+
+ private final Map<DexType, EnumValueInfoMap> maps;
+
+ private EnumValueInfoMapCollection(Map<DexType, EnumValueInfoMap> maps) {
+ this.maps = maps;
+ }
+
+ public EnumValueInfoMap getEnumValueInfoMap(DexType type) {
+ return maps.get(type);
+ }
+
+ public boolean isEmpty() {
+ return maps.isEmpty();
+ }
+
+ public boolean containsEnum(DexType type) {
+ return maps.containsKey(type);
+ }
+
+ public Set<DexType> enumSet() {
+ return maps.keySet();
+ }
+
+ public EnumValueInfoMapCollection rewrittenWithLens(GraphLense lens) {
+ Builder builder = builder();
+ maps.forEach(
+ (type, map) -> {
+ DexType dexType = lens.lookupType(type);
+ // Enum unboxing may have changed the type to int type.
+ // Do not keep the map for such enums.
+ if (!dexType.isPrimitiveType()) {
+ builder.put(dexType, map.rewrittenWithLens(lens));
+ }
+ });
+ return builder.build();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private ImmutableMap.Builder<DexType, EnumValueInfoMap> builder;
+
+ public Builder put(DexType type, EnumValueInfoMap map) {
+ if (builder == null) {
+ builder = ImmutableMap.builder();
+ }
+ builder.put(type, map);
+ return this;
+ }
+
+ public EnumValueInfoMapCollection build() {
+ if (builder == null) {
+ return empty();
+ }
+ return new EnumValueInfoMapCollection(builder.build());
+ }
+ }
+
+ public static final class EnumValueInfoMap {
+
+ private final Map<DexField, EnumValueInfo> map;
+
+ public EnumValueInfoMap(Map<DexField, EnumValueInfo> map) {
+ this.map = ImmutableMap.copyOf(map);
+ }
+
+ public int size() {
+ return map.size();
+ }
+
+ public EnumValueInfo getEnumValueInfo(DexField field) {
+ return map.get(field);
+ }
+
+ EnumValueInfoMap rewrittenWithLens(GraphLense lens) {
+ ImmutableMap.Builder<DexField, EnumValueInfo> builder = ImmutableMap.builder();
+ map.forEach(
+ (field, valueInfo) ->
+ builder.put(lens.lookupField(field), valueInfo.rewrittenWithLens(lens)));
+ return new EnumValueInfoMap(builder.build());
+ }
+ }
+
+ public static final class EnumValueInfo {
+
+ // The anonymous subtype of this specific value or the enum type.
+ public final DexType type;
+ public final int ordinal;
+
+ public EnumValueInfo(DexType type, int ordinal) {
+ this.type = type;
+ this.ordinal = ordinal;
+ }
+
+ EnumValueInfo rewrittenWithLens(GraphLense lens) {
+ DexType newType = lens.lookupType(type);
+ if (type == newType) {
+ return this;
+ }
+ return new EnumValueInfo(newType, ordinal);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLense.java b/src/main/java/com/android/tools/r8/graph/GraphLense.java
index 11bf08e..8588a9d 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLense.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLense.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.ir.code.Invoke.Type;
-import com.android.tools.r8.shaking.AppInfoWithLiveness.EnumValueInfo;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
@@ -328,20 +327,6 @@
return builder.build();
}
- // TODO(b/150193407): Move to enumInfoMap and rewrite fields.
- public static ImmutableMap<DexType, Map<DexField, EnumValueInfo>> rewriteEnumValueInfoMaps(
- Map<DexType, Map<DexField, EnumValueInfo>> original, GraphLense lens) {
- ImmutableMap.Builder<DexType, Map<DexField, EnumValueInfo>> builder = ImmutableMap.builder();
- original.forEach(
- (enumType, map) -> {
- DexType dexType = lens.lookupType(enumType);
- if (!dexType.isPrimitiveType()) {
- builder.put(dexType, map);
- }
- });
- return builder.build();
- }
-
public boolean verifyMappingToOriginalProgram(
Iterable<DexProgramClass> classes,
DexApplication originalApplication,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
index 2c8e6b9..d5d51e1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
@@ -81,7 +81,7 @@
processClasses(clazz);
}
if (!switchMaps.isEmpty()) {
- return appView.appInfo().addSwitchMaps(switchMaps);
+ return appView.appInfo().withSwitchMaps(switchMaps);
}
return appView.appInfo();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 6c95511..23fa539 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
@@ -38,7 +39,6 @@
import com.android.tools.r8.ir.conversion.PostMethodProcessor;
import com.android.tools.r8.ir.conversion.PostOptimization;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.AppInfoWithLiveness.EnumValueInfo;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
@@ -273,13 +273,13 @@
continue;
}
- Map<DexField, EnumValueInfo> enumValueInfoMapFor =
- appView.appInfo().withLiveness().getEnumValueInfoMapFor(enumClass.type);
- if (enumValueInfoMapFor == null) {
+ EnumValueInfoMap enumValueInfoMap =
+ appView.appInfo().withLiveness().getEnumValueInfoMap(enumClass.type);
+ if (enumValueInfoMap == null) {
markEnumAsUnboxable(Reason.MISSING_INFO_MAP, enumClass);
continue;
}
- if (enumValueInfoMapFor.size() != enumClass.staticFields().size() - 1) {
+ if (enumValueInfoMap.size() != enumClass.staticFields().size() - 1) {
markEnumAsUnboxable(Reason.UNEXPECTED_STATIC_FIELD, enumClass);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index 1626d7f..264d61f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -12,12 +12,14 @@
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.analysis.type.DestructivePhiTypeUpdater;
@@ -35,13 +37,10 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.origin.SynthesizedOrigin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.AppInfoWithLiveness.EnumValueInfo;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -53,8 +52,7 @@
private final AppView<AppInfoWithLiveness> appView;
private final DexItemFactory factory;
- // TODO(b/150193407): Use enumInfoMap instead of Map<DexField, EnumValueInfo>.
- private final Map<DexType, Map<DexField, EnumValueInfo>> enumsToUnbox;
+ private final EnumValueInfoMapCollection enumsToUnbox;
private final DexType utilityClassType;
private final DexMethod ordinalUtilityMethod;
@@ -64,9 +62,9 @@
EnumUnboxingRewriter(AppView<AppInfoWithLiveness> appView, Set<DexType> enumsToUnbox) {
this.appView = appView;
this.factory = appView.dexItemFactory();
- ImmutableMap.Builder<DexType, Map<DexField, EnumValueInfo>> builder = ImmutableMap.builder();
+ EnumValueInfoMapCollection.Builder builder = EnumValueInfoMapCollection.builder();
for (DexType toUnbox : enumsToUnbox) {
- builder.put(toUnbox, appView.appInfo().withLiveness().getEnumValueInfoMapFor(toUnbox));
+ builder.put(toUnbox, appView.appInfo().withLiveness().getEnumValueInfoMap(toUnbox));
}
this.enumsToUnbox = builder.build();
@@ -108,15 +106,15 @@
if (instruction.isStaticGet()) {
StaticGet staticGet = instruction.asStaticGet();
DexType holder = staticGet.getField().holder;
- if (enumsToUnbox.containsKey(holder)) {
+ if (enumsToUnbox.containsEnum(holder)) {
if (staticGet.outValue() == null) {
iterator.removeInstructionIgnoreOutValue();
continue;
}
- Map<DexField, EnumValueInfo> enumValueInfoMap = enumsToUnbox.get(holder);
+ EnumValueInfoMap enumValueInfoMap = enumsToUnbox.getEnumValueInfoMap(holder);
assert enumValueInfoMap != null;
// Replace by ordinal + 1 for null check (null is 0).
- EnumValueInfo enumValueInfo = enumValueInfoMap.get(staticGet.getField());
+ EnumValueInfo enumValueInfo = enumValueInfoMap.getEnumValueInfo(staticGet.getField());
assert enumValueInfo != null
: "Invalid read to " + staticGet.getField().name + ", error during enum analysis";
instruction = new ConstNumber(staticGet.outValue(), enumValueInfo.ordinal + 1);
@@ -142,12 +140,12 @@
}
TypeLatticeElement typeLattice = instruction.outValue().getTypeLattice();
assert !typeLattice.isClassType()
- || !enumsToUnbox.containsKey(typeLattice.asClassTypeLatticeElement().getClassType());
+ || !enumsToUnbox.containsEnum(typeLattice.asClassTypeLatticeElement().getClassType());
if (typeLattice.isArrayType()) {
TypeLatticeElement arrayBaseTypeLattice =
typeLattice.asArrayTypeLatticeElement().getArrayBaseTypeLattice();
assert !arrayBaseTypeLattice.isClassType()
- || !enumsToUnbox.containsKey(
+ || !enumsToUnbox.containsEnum(
arrayBaseTypeLattice.asClassTypeLatticeElement().getClassType());
}
return true;
@@ -195,7 +193,7 @@
// TODO(b/150178516): Add a test for this case.
private boolean utilityClassInMainDexList() {
- for (DexType toUnbox : enumsToUnbox.keySet()) {
+ for (DexType toUnbox : enumsToUnbox.enumSet()) {
if (appView.appInfo().isInMainDexList(toUnbox)) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumInfoMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueInfoMapCollector.java
similarity index 72%
rename from src/main/java/com/android/tools/r8/ir/optimize/enums/EnumInfoMapCollector.java
rename to src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueInfoMapCollector.java
index e0991e0..386a32d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumInfoMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueInfoMapCollector.java
@@ -8,31 +8,34 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.AppInfoWithLiveness.EnumValueInfo;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* Extracts the ordinal values and any anonymous subtypes for all Enum classes from their static
* initializer.
- * <p>
- * An Enum class has a field for each value. In the class initializer, each field is initialized
- * to a singleton object that represents the value. This code matches on the corresponding call
- * to the constructor (instance initializer) and extracts the value of the second argument, which
- * is the ordinal and the holder which is the concrete type.
+ *
+ * <p>An Enum class has a field for each value. In the class initializer, each field is initialized
+ * to a singleton object that represents the value. This code matches on the corresponding call to
+ * the constructor (instance initializer) and extracts the value of the second argument, which is
+ * the ordinal and the holder which is the concrete type.
*/
-public class EnumInfoMapCollector {
+public class EnumValueInfoMapCollector {
private final AppView<AppInfoWithLiveness> appView;
- private final Map<DexType, Map<DexField, EnumValueInfo>> valueInfoMaps = new IdentityHashMap<>();
+ private final EnumValueInfoMapCollection.Builder valueInfoMapsBuilder =
+ EnumValueInfoMapCollection.builder();
- public EnumInfoMapCollector(AppView<AppInfoWithLiveness> appView) {
+ public EnumValueInfoMapCollector(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
}
@@ -40,8 +43,9 @@
for (DexProgramClass clazz : appView.appInfo().classes()) {
processClasses(clazz);
}
+ EnumValueInfoMapCollection valueInfoMaps = valueInfoMapsBuilder.build();
if (!valueInfoMaps.isEmpty()) {
- return appView.appInfo().addEnumValueInfoMaps(valueInfoMaps);
+ return appView.appInfo().withEnumValueInfoMaps(valueInfoMaps);
}
return appView.appInfo();
}
@@ -53,7 +57,7 @@
}
DexEncodedMethod initializer = clazz.getClassInitializer();
IRCode code = initializer.getCode().buildIR(initializer, appView, clazz.origin);
- Map<DexField, EnumValueInfo> valueInfoMap = new IdentityHashMap<>();
+ Map<DexField, EnumValueInfo> enumValueInfoMap = new IdentityHashMap<>();
for (Instruction insn : code.instructions()) {
if (!insn.isStaticPut()) {
continue;
@@ -86,10 +90,10 @@
}
EnumValueInfo info = new EnumValueInfo(type, ordinal.asConstNumber().getIntValue());
- if (valueInfoMap.put(staticPut.getField(), info) != null) {
+ if (enumValueInfoMap.put(staticPut.getField(), info) != null) {
return;
}
}
- valueInfoMaps.put(clazz.type, valueInfoMap);
+ valueInfoMapsBuilder.put(clazz.type, new EnumValueInfoMap(enumValueInfoMap));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index ee749f0..ddf697d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.ir.code.ArrayGet;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -27,12 +29,10 @@
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.SwitchMapCollector;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.AppInfoWithLiveness.EnumValueInfo;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import java.util.Arrays;
-import java.util.Map;
public class EnumValueOptimizer {
@@ -76,8 +76,8 @@
}
DexField enumField = definition.asStaticGet().getField();
- Map<DexField, EnumValueInfo> valueInfoMap =
- appView.appInfo().withLiveness().getEnumValueInfoMapFor(enumField.type);
+ EnumValueInfoMap valueInfoMap =
+ appView.appInfo().withLiveness().getEnumValueInfoMap(enumField.type);
if (valueInfoMap == null) {
continue;
}
@@ -86,7 +86,7 @@
// that it is a static-get to a field whose type is the same as the enclosing class (which
// is known to be an enum type). An enum may still define a static field using the enum type
// so ensure the field is present in the ordinal map for final validation.
- EnumValueInfo valueInfo = valueInfoMap.get(enumField);
+ EnumValueInfo valueInfo = valueInfoMap.getEnumValueInfo(enumField);
if (valueInfo == null) {
continue;
}
@@ -153,9 +153,8 @@
Int2IntMap targetMap = new Int2IntArrayMap();
for (int i = 0; i < switchInsn.numberOfKeys(); i++) {
assert switchInsn.targetBlockIndices()[i] != switchInsn.getFallthroughBlockIndex();
- int key = switchInsn.getKey(i);
- DexField field = info.indexMap.get(key);
- EnumValueInfo valueInfo = info.valueInfoMap.get(field);
+ DexField field = info.indexMap.get(switchInsn.getKey(i));
+ EnumValueInfo valueInfo = info.valueInfoMap.getEnumValueInfo(field);
targetMap.put(valueInfo.ordinal, switchInsn.targetBlockIndices()[i]);
}
int[] keys = targetMap.keySet().toIntArray();
@@ -192,7 +191,7 @@
final Instruction arrayGet;
public final Instruction staticGet;
final Int2ReferenceMap<DexField> indexMap;
- final Map<DexField, EnumValueInfo> valueInfoMap;
+ final EnumValueInfoMap valueInfoMap;
private EnumSwitchInfo(
DexType enumClass,
@@ -200,7 +199,7 @@
Instruction arrayGet,
Instruction staticGet,
Int2ReferenceMap<DexField> indexMap,
- Map<DexField, EnumValueInfo> valueInfoMap) {
+ EnumValueInfoMap valueInfoMap) {
this.enumClass = enumClass;
this.ordinalInvoke = ordinalInvoke;
this.arrayGet = arrayGet;
@@ -223,8 +222,8 @@
*
* </blockquote>
*
- * and extracts the components and the index and ordinal maps. See {@link EnumInfoMapCollector}
- * and {@link SwitchMapCollector} for details.
+ * and extracts the components and the index and ordinal maps. See {@link
+ * EnumValueInfoMapCollector} and {@link SwitchMapCollector} for details.
*/
private EnumSwitchInfo analyzeSwitchOverEnum(IntSwitch switchInsn) {
Instruction input = switchInsn.inValues().get(0).definition;
@@ -253,7 +252,7 @@
return null;
}
StaticGet staticGet = array.asStaticGet();
- Int2ReferenceMap<DexField> indexMap = appView.appInfo().getSwitchMapFor(staticGet.getField());
+ Int2ReferenceMap<DexField> indexMap = appView.appInfo().getSwitchMap(staticGet.getField());
if (indexMap == null || indexMap.isEmpty()) {
return null;
}
@@ -264,7 +263,7 @@
}
// Due to member rebinding, only the fields are certain to provide the actual enums class.
DexType enumType = indexMap.values().iterator().next().holder;
- Map<DexField, EnumValueInfo> valueInfoMap = appView.appInfo().getEnumValueInfoMapFor(enumType);
+ EnumValueInfoMap valueInfoMap = appView.appInfo().getEnumValueInfoMap(enumType);
if (valueInfoMap == null) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 6e5899d..a1277ef 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.shaking;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-import static com.android.tools.r8.graph.GraphLense.rewriteEnumValueInfoMaps;
import static com.android.tools.r8.graph.GraphLense.rewriteReferenceKeys;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -21,6 +20,8 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
@@ -175,18 +176,7 @@
/** A map from switchmap class types to their corresponding switchmaps. */
final Map<DexField, Int2ReferenceMap<DexField>> switchMaps;
/** A map from enum types to their value types and ordinals. */
- final Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps;
-
- public static final class EnumValueInfo {
- /** The anonymous subtype of this specific value or the enum type. */
- public final DexType type;
- public final int ordinal;
-
- public EnumValueInfo(DexType type, int ordinal) {
- this.type = type;
- this.ordinal = ordinal;
- }
- }
+ final EnumValueInfoMapCollection enumValueInfoMaps;
final Set<DexType> instantiatedLambdas;
@@ -229,7 +219,7 @@
Object2BooleanMap<DexReference> identifierNameStrings,
Set<DexType> prunedTypes,
Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
- Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps,
+ EnumValueInfoMapCollection enumValueInfoMaps,
Set<DexType> instantiatedLambdas,
Set<DexType> constClassReferences) {
super(application);
@@ -312,7 +302,7 @@
Object2BooleanMap<DexReference> identifierNameStrings,
Set<DexType> prunedTypes,
Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
- Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps,
+ EnumValueInfoMapCollection enumValueInfoMaps,
Set<DexType> instantiatedLambdas,
Set<DexType> constClassReferences) {
super(appInfoWithSubtyping);
@@ -459,7 +449,7 @@
public AppInfoWithLiveness(
AppInfoWithLiveness previous,
Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
- Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps) {
+ EnumValueInfoMapCollection enumValueInfoMaps) {
super(previous);
this.missingTypes = previous.missingTypes;
this.liveTypes = previous.liveTypes;
@@ -705,12 +695,12 @@
return result;
}
- public Map<DexField, EnumValueInfo> getEnumValueInfoMapFor(DexType enumClass) {
+ public EnumValueInfoMap getEnumValueInfoMap(DexType enumType) {
assert checkIfObsolete();
- return enumValueInfoMaps.get(enumClass);
+ return enumValueInfoMaps.getEnumValueInfoMap(enumType);
}
- public Int2ReferenceMap<DexField> getSwitchMapFor(DexField field) {
+ public Int2ReferenceMap<DexField> getSwitchMap(DexField field) {
assert checkIfObsolete();
return switchMaps.get(field);
}
@@ -1066,7 +1056,7 @@
// Don't rewrite pruned types - the removed types are identified by their original name.
prunedTypes,
rewriteReferenceKeys(switchMaps, lens::lookupField),
- rewriteEnumValueInfoMaps(enumValueInfoMaps, lens),
+ enumValueInfoMaps.rewrittenWithLens(lens),
rewriteItems(instantiatedLambdas, lens::lookupType),
constClassReferences);
}
@@ -1448,14 +1438,13 @@
return result == null || !result.isVirtualMethod() ? null : result;
}
- public AppInfoWithLiveness addSwitchMaps(Map<DexField, Int2ReferenceMap<DexField>> switchMaps) {
+ public AppInfoWithLiveness withSwitchMaps(Map<DexField, Int2ReferenceMap<DexField>> switchMaps) {
assert checkIfObsolete();
assert this.switchMaps.isEmpty();
return new AppInfoWithLiveness(this, switchMaps, enumValueInfoMaps);
}
- public AppInfoWithLiveness addEnumValueInfoMaps(
- Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps) {
+ public AppInfoWithLiveness withEnumValueInfoMaps(EnumValueInfoMapCollection enumValueInfoMaps) {
assert checkIfObsolete();
assert this.enumValueInfoMaps.isEmpty();
return new AppInfoWithLiveness(this, switchMaps, enumValueInfoMaps);
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 309a6e4..36afff6 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -51,6 +51,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.DirectMappedDexApplication.Builder;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.InnerClassAttribute;
@@ -2556,7 +2557,7 @@
joinIdentifierNameStrings(rootSet.identifierNameStrings, identifierNameStrings),
Collections.emptySet(),
Collections.emptyMap(),
- Collections.emptyMap(),
+ EnumValueInfoMapCollection.empty(),
SetUtils.mapIdentityHashSet(
unknownInstantiatedInterfaceTypes.getItems(), DexProgramClass::getType),
constClassReferences);