Enable GraphLense to also rewrite the type of classes.
Bug:
Change-Id: I644b8abcb337c4396ed14bea0156e674a402155f
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 8a92ef0..e025665 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -205,8 +205,8 @@
throws IOException, ExecutionException, ApiLevelException {
final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
- IRConverter converter = new IRConverter(timing, application, appInfo, options, printer);
- application = converter.convertToDex(executor);
+ IRConverter converter = new IRConverter(timing, appInfo, options, printer);
+ application = converter.convertToDex(application, executor);
if (options.printCfg) {
if (options.printCfgFile == null || options.printCfgFile.isEmpty()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index f72dd9f..27e7d02 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -131,8 +131,8 @@
timing.begin("Create IR");
try {
IRConverter converter = new IRConverter(
- timing, application, appInfo, options, printer, graphLense);
- application = converter.optimize(executorService);
+ timing, appInfo, options, printer, graphLense);
+ application = converter.optimize(application, executorService);
} finally {
timing.end();
}
@@ -226,7 +226,7 @@
if (options.proguardConfiguration.isPrintSeeds()) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bytes);
- RootSetBuilder.writeSeeds(appInfo.withLiveness().pinnedItems, out);
+ RootSetBuilder.writeSeeds(appInfo.withLiveness().getPinnedItems(), out);
out.flush();
proguardSeedsData = bytes.toByteArray();
}
@@ -261,10 +261,12 @@
appInfo.withLiveness(), graphLense, timing);
graphLense = classMerger.run();
timing.end();
+
appInfo = appInfo.withLiveness()
.prunedCopyFrom(application, classMerger.getRemovedClasses());
}
- appInfo = appInfo.withLiveness().rewrittenWithLense(graphLense);
+ application = application.asDirect().rewrittenWithLense(graphLense);
+ appInfo = appInfo.withLiveness().rewrittenWithLense(application.asDirect(), graphLense);
// Collect switch maps and ordinals maps.
new SwitchMapCollector(appInfo.withLiveness(), options).run();
new EnumOrdinalMapCollector(appInfo.withLiveness(), options).run();
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 2d111f0..820e49d 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -32,10 +32,12 @@
this.definitions.putAll(previous.definitions);
}
- protected AppInfo(AppInfo previous, GraphLense lense) {
- // Do not rewrite basic structure, as the type information in the lense is about applied uses
- // and not definitions.
- this(previous);
+ protected AppInfo(DirectMappedDexApplication application, GraphLense lense) {
+ // Rebuild information from scratch, as the application object has changed. We do not
+ // use the lense here, as it is about applied occurrences and not definitions.
+ // In particular, we have to invalidate the definitions cache, as its keys are no longer
+ // valid.
+ this(application);
}
private Map<Descriptor, KeyedDexItem> computeDefinitions(DexType type) {
@@ -331,6 +333,10 @@
// We do not track subtyping relationships in the basic AppInfo. So do nothing.
}
+ public boolean isInMainDexList(DexType type) {
+ return app.mainDexList.contains(type);
+ }
+
public List<DexClass> getSuperTypeClasses(DexType type) {
List<DexClass> result = new ArrayList<>();
do {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 54b2a51..a98ec9e 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -6,7 +6,6 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
@@ -33,10 +32,10 @@
assert app instanceof DirectMappedDexApplication;
}
- protected AppInfoWithSubtyping(AppInfoWithSubtyping previous, GraphLense lense) {
- super(previous, lense);
+ protected AppInfoWithSubtyping(DirectMappedDexApplication application, GraphLense lense) {
+ super(application, lense);
// Recompute subtype map if we have modified the graph.
- populateSubtypeMap(previous.getDirectApplication(), dexItemFactory);
+ populateSubtypeMap(application, dexItemFactory);
}
private DirectMappedDexApplication getDirectApplication() {
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index e2583c3..b68b1d4 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -6,16 +6,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.ProgramClassCollection;
import com.android.tools.r8.utils.Timing;
-
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
public class DirectMappedDexApplication extends DexApplication {
@@ -65,22 +64,43 @@
return "DexApplication (direct)";
}
+ public DirectMappedDexApplication rewrittenWithLense(GraphLense graphLense) {
+ assert graphLense.isContextFree();
+ assert mappingIsValid(graphLense, programClasses.getAllTypes());
+ assert mappingIsValid(graphLense, libraryClasses.keySet());
+ // As a side effect, this will rebuild the program classes and library classes maps.
+ return this.builder().build().asDirect();
+ }
+
+ private boolean mappingIsValid(GraphLense graphLense, Iterable<DexType> types) {
+ // The lense might either map to a different type that is already present in the application
+ // (e.g. relinking a type) or it might encode a type that was renamed, in which case the
+ // original type will point to a definition that was renamed.
+ for (DexType type : types) {
+ DexType renamed = graphLense.lookupType(type, null);
+ if (renamed != type) {
+ if (definitionFor(type).type != renamed && definitionFor(renamed) == null) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
public static class Builder extends DexApplication.Builder<Builder> {
- private Map<DexType, DexLibraryClass> libraryClasses = new IdentityHashMap<>();
+ private List<DexLibraryClass> libraryClasses = new ArrayList<>();
Builder(LazyLoadedDexApplication application) {
super(application);
// As a side-effect, this will force-load all classes.
Map<DexType, DexClass> allClasses = application.getFullClassMap();
- Iterables.filter(allClasses.values(), DexLibraryClass.class)
- .forEach(k -> libraryClasses.put(k.type, k));
-
+ Iterables.filter(allClasses.values(), DexLibraryClass.class).forEach(libraryClasses::add);
}
private Builder(DirectMappedDexApplication application) {
super(application);
- this.libraryClasses.putAll(application.libraryClasses);
+ this.libraryClasses.addAll(application.libraryClasses.values());
}
@Override
@@ -90,9 +110,11 @@
@Override
public DexApplication build() {
+ // Rebuild the map. This will fail if keys are not unique.
return new DirectMappedDexApplication(proguardMap,
ProgramClassCollection.create(programClasses),
- ImmutableMap.copyOf(libraryClasses), ImmutableSet.copyOf(mainDexList), deadCode,
+ libraryClasses.stream().collect(ImmutableMap.toImmutableMap(c -> c.type, c -> c)),
+ ImmutableSet.copyOf(mainDexList), deadCode,
dexItemFactory, highestSortingString, timing);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
index b32f34d..5704e0f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -179,7 +179,7 @@
}
for (Node value : nodes.values()) {
// For non-pinned methods we know the exact number of call sites.
- if (!appInfo.withLiveness().pinnedItems.contains(value.method)) {
+ if (!appInfo.withLiveness().isPinned(value.method)) {
if (value.invokeCount == 1) {
singleCallSite.add(value.method);
} else if (value.invokeCount == 2) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index e83774d..c0f5b40 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -63,7 +63,6 @@
private static final int PEEPHOLE_OPTIMIZATION_PASSES = 2;
private final Timing timing;
- public final DexApplication application;
public final AppInfo appInfo;
private final Outliner outliner;
private final LambdaRewriter lambdaRewriter;
@@ -82,17 +81,14 @@
private IRConverter(
Timing timing,
- DexApplication application,
AppInfo appInfo,
GraphLense graphLense,
InternalOptions options,
CfgPrinter printer,
boolean enableWholeProgramOptimizations) {
- assert application != null;
assert appInfo != null;
assert options != null;
this.timing = timing != null ? timing : new Timing("internal");
- this.application = application;
this.appInfo = appInfo;
this.graphLense = graphLense != null ? graphLense : GraphLense.getIdentityLense();
this.options = options;
@@ -126,10 +122,9 @@
* Create an IR converter for processing methods with full program optimization disabled.
*/
public IRConverter(
- DexApplication application,
AppInfo appInfo,
InternalOptions options) {
- this(null, application, appInfo, null, options, null, false);
+ this(null, appInfo, null, options, null, false);
}
/**
@@ -137,11 +132,10 @@
*/
public IRConverter(
Timing timing,
- DexApplication application,
AppInfo appInfo,
InternalOptions options,
CfgPrinter printer) {
- this(timing, application, appInfo, null, options, printer, false);
+ this(timing, appInfo, null, options, printer, false);
}
/**
@@ -149,12 +143,11 @@
*/
public IRConverter(
Timing timing,
- DexApplication application,
AppInfoWithSubtyping appInfo,
InternalOptions options,
CfgPrinter printer,
GraphLense graphLense) {
- this(timing, application, appInfo, graphLense, options, printer, true);
+ this(timing, appInfo, graphLense, options, printer, true);
}
private boolean enableInterfaceMethodDesugaring() {
@@ -187,7 +180,7 @@
private void removeLambdaDeserializationMethods() {
if (lambdaRewriter != null) {
- lambdaRewriter.removeLambdaDeserializationMethods(application.classes());
+ lambdaRewriter.removeLambdaDeserializationMethods(appInfo.classes());
}
}
@@ -206,7 +199,7 @@
}
}
- public DexApplication convertToDex(ExecutorService executor)
+ public DexApplication convertToDex(DexApplication application, ExecutorService executor)
throws ExecutionException, ApiLevelException {
removeLambdaDeserializationMethods();
@@ -313,16 +306,18 @@
}
}
- public DexApplication optimize() throws ExecutionException, ApiLevelException {
+ public DexApplication optimize(DexApplication application)
+ throws ExecutionException, ApiLevelException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
- return optimize(executor);
+ return optimize(application, executor);
} finally {
executor.shutdown();
}
}
- public DexApplication optimize(ExecutorService executorService)
+ public DexApplication optimize(DexApplication application,
+ ExecutorService executorService)
throws ExecutionException, ApiLevelException {
removeLambdaDeserializationMethods();
@@ -390,7 +385,7 @@
}
private void clearDexMethodCompilationState() {
- application.classes().forEach(this::clearDexMethodCompilationState);
+ appInfo.classes().forEach(this::clearDexMethodCompilationState);
}
private void clearDexMethodCompilationState(DexProgramClass clazz) {
@@ -427,8 +422,8 @@
do {
String name = options.outline.className + (count == 0 ? "" : Integer.toString(count));
count++;
- result = application.dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(name));
- } while (application.definitionFor(result) != null);
+ result = appInfo.dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(name));
+ } while (appInfo.definitionFor(result) != null);
// Register the newly generated type in the subtyping hierarchy, if we have one.
appInfo.registerNewType(result, appInfo.dexItemFactory.objectType);
return result;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index c5545f5..a851831 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -27,7 +27,6 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Map;
@@ -199,8 +198,7 @@
}
private boolean isInMainDexList(DexType iface) {
- ImmutableSet<DexType> list = converter.application.mainDexList;
- return list.contains(iface);
+ return converter.appInfo.isInMainDexList(iface);
}
// Represent a static interface method as a method of companion class.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index acac84a..2004742 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -95,7 +95,7 @@
public LambdaRewriter(IRConverter converter) {
assert converter != null;
this.converter = converter;
- this.factory = converter.application.dexItemFactory;
+ this.factory = converter.appInfo.dexItemFactory;
this.appInfo = converter.appInfo;
DexType metafactoryType = factory.createType(METAFACTORY_TYPE_DESCR);
@@ -226,7 +226,7 @@
}
private boolean isInMainDexList(DexType type) {
- return converter.application.mainDexList.contains(type);
+ return converter.appInfo.isInMainDexList(type);
}
// Returns a lambda class corresponding to the lambda descriptor and context,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 12f1cf2..de0bab0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -239,7 +239,7 @@
// Without live set information we cannot tell and assume true.
if (liveSet == null
|| liveSet.fieldsRead.contains(field.field)
- || liveSet.pinnedItems.contains(field)) {
+ || liveSet.isPinned(field)) {
return true;
}
// For library classes we don't know whether a field is read.
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 358c1d3..da89ff1 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -23,6 +23,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.KeyedDexItem;
import com.android.tools.r8.graph.PresortedComparable;
@@ -1110,7 +1111,7 @@
/**
* Set of all items that have to be kept independent of whether they are used.
*/
- public final Set<DexItem> pinnedItems;
+ final Set<DexItem> pinnedItems;
/**
* All items with assumenosideeffects rule.
*/
@@ -1126,11 +1127,11 @@
/**
* Map from the class of an extension to the state it produced.
*/
- public final Map<Class, Object> extensions;
+ final Map<Class, Object> extensions;
/**
* A set of types that have been removed by the {@link TreePruner}.
*/
- public final Set<DexType> prunedTypes;
+ final Set<DexType> prunedTypes;
private AppInfoWithLiveness(AppInfoWithSubtyping appInfo, Enqueuer enqueuer) {
super(appInfo);
@@ -1138,9 +1139,9 @@
ImmutableSortedSet.copyOf(PresortedComparable::slowCompareTo, enqueuer.liveTypes);
this.instantiatedTypes = ImmutableSortedSet.copyOf(
PresortedComparable::slowCompareTo, enqueuer.instantiatedTypes.getItems());
- this.targetedMethods = toDescriptorSet(enqueuer.targetedMethods.getItems());
- this.liveMethods = toDescriptorSet(enqueuer.liveMethods.getItems());
- this.liveFields = toDescriptorSet(enqueuer.liveFields.getItems());
+ this.targetedMethods = toSortedDescriptorSet(enqueuer.targetedMethods.getItems());
+ this.liveMethods = toSortedDescriptorSet(enqueuer.liveMethods.getItems());
+ this.liveFields = toSortedDescriptorSet(enqueuer.liveFields.getItems());
this.instanceFieldReads = enqueuer.collectInstanceFieldsRead();
this.instanceFieldWrites = enqueuer.collectInstanceFieldsWritten();
this.staticFieldReads = enqueuer.collectStaticFieldsRead();
@@ -1176,6 +1177,7 @@
this.fieldsRead = previous.fieldsRead;
// TODO(herhut): We remove fields that are only written, so maybe update this.
this.fieldsWritten = previous.fieldsWritten;
+ assert assertNoItemRemoved(previous.pinnedItems, removedClasses);
this.pinnedItems = previous.pinnedItems;
this.noSideEffects = previous.noSideEffects;
this.assumedValues = previous.assumedValues;
@@ -1190,9 +1192,11 @@
assert Sets.intersection(instanceFieldWrites, staticFieldWrites).size() == 0;
}
- private AppInfoWithLiveness(AppInfoWithLiveness previous, GraphLense lense) {
- super(previous, lense);
- this.liveTypes = previous.liveTypes;
+ private AppInfoWithLiveness(AppInfoWithLiveness previous,
+ DirectMappedDexApplication application,
+ GraphLense lense) {
+ super(application, lense);
+ this.liveTypes = rewriteItems(previous.liveTypes, lense::lookupType);
this.instantiatedTypes = rewriteItems(previous.instantiatedTypes, lense::lookupType);
this.targetedMethods = rewriteItems(previous.targetedMethods, lense::lookupMethod);
this.liveMethods = rewriteItems(previous.liveMethods, lense::lookupMethod);
@@ -1203,19 +1207,61 @@
this.staticFieldWrites = rewriteItems(previous.staticFieldWrites, lense::lookupField);
this.fieldsRead = rewriteItems(previous.fieldsRead, lense::lookupField);
this.fieldsWritten = rewriteItems(previous.fieldsWritten, lense::lookupField);
- // TODO(herhut): Migrate these to Descriptors, as well.
+ assert assertNotModifiedByLense(previous.pinnedItems, lense);
this.pinnedItems = previous.pinnedItems;
- this.noSideEffects = previous.noSideEffects;
- this.assumedValues = previous.assumedValues;
this.virtualInvokes = rewriteItems(previous.virtualInvokes, lense::lookupMethod);
this.superInvokes = rewriteItems(previous.superInvokes, lense::lookupMethod);
this.directInvokes = rewriteItems(previous.directInvokes, lense::lookupMethod);
this.staticInvokes = rewriteItems(previous.staticInvokes, lense::lookupMethod);
+ this.prunedTypes = rewriteItems(previous.prunedTypes, lense::lookupType);
+ // TODO(herhut): Migrate these to Descriptors, as well.
+ assert assertNotModifiedByLense(previous.noSideEffects.keySet(), lense);
+ this.noSideEffects = previous.noSideEffects;
+ assert assertNotModifiedByLense(previous.assumedValues.keySet(), lense);
+ this.assumedValues = previous.assumedValues;
+ assert assertNotModifiedByLense(previous.alwaysInline, lense);
this.alwaysInline = previous.alwaysInline;
this.extensions = previous.extensions;
- this.prunedTypes = rewriteItems(previous.prunedTypes, lense::lookupType);
- assert Sets.intersection(instanceFieldReads, staticFieldReads).size() == 0;
- assert Sets.intersection(instanceFieldWrites, staticFieldWrites).size() == 0;
+ // Sanity check sets after rewriting.
+ assert Sets.intersection(instanceFieldReads, staticFieldReads).isEmpty();
+ assert Sets.intersection(instanceFieldWrites, staticFieldWrites).isEmpty();
+ }
+
+ private boolean assertNoItemRemoved(Collection<DexItem> items, Collection<DexType> types) {
+ Set<DexType> typeSet = ImmutableSet.copyOf(types);
+ for (DexItem item : items) {
+ if (item instanceof DexClass) {
+ assert !typeSet.contains(((DexClass) item).type);
+ } else if (item instanceof DexEncodedMethod) {
+ assert !typeSet.contains(((DexEncodedMethod) item).method.getHolder());
+ } else if (item instanceof DexEncodedField) {
+ assert !typeSet.contains(((DexEncodedField) item).field.getHolder());
+ } else {
+ assert false;
+ }
+ }
+ return true;
+ }
+
+ private boolean assertNotModifiedByLense(Iterable<DexItem> items, GraphLense lense) {
+ for (DexItem item : items) {
+ if (item instanceof DexClass) {
+ DexType type = ((DexClass) item).type;
+ assert lense.lookupType(type, null) == type;
+ } else if (item instanceof DexEncodedMethod) {
+ DexEncodedMethod method = (DexEncodedMethod) item;
+ // We only allow changes to bridge methods, as these get retargeted even if they
+ // are kept.
+ assert method.accessFlags.isBridge()
+ || lense.lookupMethod(method.method, null) == method.method;
+ } else if (item instanceof DexEncodedField) {
+ DexField field = ((DexEncodedField) item).field;
+ assert lense.lookupField(field, null) == field;
+ } else {
+ assert false;
+ }
+ }
+ return true;
}
private SortedSet<DexMethod> joinInvokedMethods(Map<DexType, Set<DexMethod>> invokes) {
@@ -1225,7 +1271,7 @@
return builder.build();
}
- private <T extends PresortedComparable<T>> SortedSet<T> toDescriptorSet(
+ private <T extends PresortedComparable<T>> SortedSet<T> toSortedDescriptorSet(
Set<? extends KeyedDexItem<T>> set) {
ImmutableSortedSet.Builder<T> builder =
new ImmutableSortedSet.Builder<>(PresortedComparable::slowCompareTo);
@@ -1276,6 +1322,14 @@
return this;
}
+ public boolean isPinned(DexItem item) {
+ return pinnedItems.contains(item);
+ }
+
+ public Iterable<DexItem> getPinnedItems() {
+ return pinnedItems;
+ }
+
/**
* Returns a copy of this AppInfoWithLiveness where the set of classes is pruned using the
* given DexApplication object.
@@ -1285,9 +1339,10 @@
return new AppInfoWithLiveness(this, application, removedClasses);
}
- public AppInfoWithLiveness rewrittenWithLense(GraphLense lense) {
+ public AppInfoWithLiveness rewrittenWithLense(DirectMappedDexApplication application,
+ GraphLense lense) {
assert lense.isContextFree();
- return new AppInfoWithLiveness(this, lense);
+ return new AppInfoWithLiveness(this, application, lense);
}
/**
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 3b5cdbc..bd72a80 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -18,6 +17,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
diff --git a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
index 193ebdf..bf2b761 100644
--- a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
@@ -76,7 +76,7 @@
// and we do not have to keep them.
return !clazz.isLibraryClass()
&& !appInfo.instantiatedTypes.contains(clazz.type)
- && !appInfo.pinnedItems.contains(clazz)
+ && !appInfo.isPinned(clazz.type)
&& clazz.type.getSingleSubtype() != null;
}
@@ -139,7 +139,7 @@
for (DexProgramClass clazz : application.classes()) {
if (isMergeCandidate(clazz)) {
DexClass targetClass = appInfo.definitionFor(clazz.type.getSingleSubtype());
- if (appInfo.pinnedItems.contains(targetClass)) {
+ if (appInfo.isPinned(targetClass)) {
// We have to keep the target class intact, so we cannot merge it.
continue;
}
diff --git a/src/main/java/com/android/tools/r8/utils/ClassMap.java b/src/main/java/com/android/tools/r8/utils/ClassMap.java
index 9677473..2e7ac84 100644
--- a/src/main/java/com/android/tools/r8/utils/ClassMap.java
+++ b/src/main/java/com/android/tools/r8/utils/ClassMap.java
@@ -101,6 +101,10 @@
return loadedClasses;
}
+ public Iterable<DexType> getAllTypes() {
+ return classes.keySet();
+ }
+
/**
* Forces loading of all the classes satisfying the criteria specified.
*
diff --git a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
index 082b5ee..7af3b05 100644
--- a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
+++ b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
@@ -38,8 +38,8 @@
.read(executorService)
.toDirect();
IRConverter converter =
- new IRConverter(application, new AppInfoWithSubtyping(application), new InternalOptions());
- converter.optimize();
+ new IRConverter(new AppInfoWithSubtyping(application), new InternalOptions());
+ converter.optimize(application);
DexProgramClass clazz = application.classes().iterator().next();
assertEquals(4, clazz.directMethods().length);
for (DexEncodedMethod method : clazz.directMethods()) {
diff --git a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
index afe0e2a..a1ea16a 100644
--- a/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
+++ b/src/test/java/com/android/tools/r8/smali/SmaliTestBase.java
@@ -439,7 +439,7 @@
public String run() throws DexOverflowException {
AppInfo appInfo = new AppInfo(application);
- IRConverter converter = new IRConverter(application, appInfo, options);
+ IRConverter converter = new IRConverter(appInfo, options);
converter.replaceCodeForTesting(method, code);
return runArt(application, options);
}