Merge "Add a test about optimizing unused Kotlin singleton."
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 5737aa0..4b1d11f 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexReference;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.shaking.DiscardedChecker;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
@@ -45,8 +44,7 @@
DexApplication application =
new ApplicationReader(app, options, timing).read(executor).toDirect();
AppView<? extends AppInfoWithSubtyping> appView =
- new AppView<>(
- new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+ AppView.createForR8(new AppInfoWithSubtyping(application), options);
RootSet mainDexRootSet =
new RootSetBuilder(appView, application, options.mainDexKeepRules, options).run(executor);
diff --git a/src/main/java/com/android/tools/r8/PrintSeeds.java b/src/main/java/com/android/tools/r8/PrintSeeds.java
index 475ca70..865b60d 100644
--- a/src/main/java/com/android/tools/r8/PrintSeeds.java
+++ b/src/main/java/com/android/tools/r8/PrintSeeds.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder;
@@ -84,8 +83,7 @@
DexApplication application =
new ApplicationReader(command.getInputApp(), options, timing).read(executor).toDirect();
AppView<? extends AppInfoWithSubtyping> appView =
- new AppView<>(
- new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+ AppView.createForR8(new AppInfoWithSubtyping(application), options);
RootSet rootSet =
new RootSetBuilder(
appView, application, options.getProguardConfiguration().getRules(), options)
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 6bade2f..a47351c 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -268,8 +268,7 @@
inputApp.closeInternalArchiveProviders();
AppView<AppInfoWithSubtyping> appView =
- new AppView<>(
- new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+ AppView.createForR8(new AppInfoWithSubtyping(application), options);
appView.setAppServices(AppServices.builder(appView).build());
List<ProguardConfigurationRule> synthesizedProguardRules = new ArrayList<>();
@@ -420,7 +419,7 @@
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
- appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness, options).run());
+ appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
if (options.enableHorizontalClassMerging) {
StaticClassMerger staticClassMerger =
new StaticClassMerger(appViewWithLiveness, options, mainDexClasses);
@@ -477,9 +476,8 @@
}
// Collect switch maps and ordinals maps.
- appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness, options).run());
- appViewWithLiveness.setAppInfo(
- new EnumOrdinalMapCollector(appViewWithLiveness, options).run());
+ appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness).run());
+ appViewWithLiveness.setAppInfo(new EnumOrdinalMapCollector(appViewWithLiveness).run());
}
appView.setAppServices(appView.appServices().rewrittenWithLens(appView.graphLense()));
@@ -488,9 +486,7 @@
Set<DexCallSite> desugaredCallSites;
CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
try {
- IRConverter converter =
- new IRConverter(
- appView.withLiveness(), options, timing, printer, mainDexClasses, rootSet);
+ IRConverter converter = new IRConverter(appView, timing, printer, mainDexClasses, rootSet);
application = converter.optimize(application, executorService);
desugaredCallSites = converter.getDesugaredCallSites();
} finally {
@@ -632,7 +628,8 @@
NamingLens namingLens;
if (options.getProguardConfiguration().hasApplyMappingFile()) {
SeedMapper seedMapper =
- SeedMapper.seedMapperFromFile(options.getProguardConfiguration().getApplyMappingFile());
+ SeedMapper.seedMapperFromFile(
+ options.reporter, options.getProguardConfiguration().getApplyMappingFile());
timing.begin("apply-mapping");
namingLens =
new ProguardMapMinifier(appView.withLiveness(), rootSet, seedMapper, desugaredCallSites)
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 93db17b..a01f840 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -17,7 +17,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
-public class AppInfo {
+public class AppInfo implements DexDefinitionSupplier {
public final DexApplication app;
public final DexItemFactory dexItemFactory;
@@ -48,6 +48,11 @@
this(application);
}
+ @Override
+ public DexItemFactory dexItemFactory() {
+ return dexItemFactory;
+ }
+
public void addSynthesizedClass(DexProgramClass clazz) {
assert clazz.type.isD8R8SynthesizedClassType();
DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
@@ -76,6 +81,7 @@
return app.classesWithDeterministicOrder();
}
+ @Override
public DexDefinition definitionFor(DexReference reference) {
if (reference.isDexType()) {
return definitionFor(reference.asDexType());
@@ -87,6 +93,7 @@
return definitionFor(reference.asDexField());
}
+ @Override
public DexClass definitionFor(DexType type) {
DexProgramClass cached = synthesizedClasses.get(type);
if (cached != null) {
@@ -101,6 +108,7 @@
return definition == null ? Origin.unknown() : definition.origin;
}
+ @Override
public DexEncodedMethod definitionFor(DexMethod method) {
DexType holderType = method.getHolder();
DexEncodedMethod cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
@@ -111,6 +119,7 @@
return cached;
}
+ @Override
public DexEncodedField definitionFor(DexField field) {
return (DexEncodedField) getDefinitions(field.getHolder()).get(field);
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 084ad80..8690894 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -8,22 +8,40 @@
import com.android.tools.r8.shaking.VerticalClassMerger.VerticallyMergedClasses;
import com.android.tools.r8.utils.InternalOptions;
-public class AppView<T extends AppInfo> {
+public class AppView<T extends AppInfo> implements DexDefinitionSupplier {
private T appInfo;
private AppServices appServices;
private final DexItemFactory dexItemFactory;
+ private final boolean enableWholeProgramOptimizations;
private GraphLense graphLense;
private final InternalOptions options;
private VerticallyMergedClasses verticallyMergedClasses;
- public AppView(T appInfo, GraphLense graphLense, InternalOptions options) {
+ private AppView(
+ T appInfo,
+ boolean enableWholeProgramOptimizations,
+ GraphLense graphLense,
+ InternalOptions options) {
this.appInfo = appInfo;
this.dexItemFactory = appInfo != null ? appInfo.dexItemFactory : null;
+ this.enableWholeProgramOptimizations = enableWholeProgramOptimizations;
this.graphLense = graphLense;
this.options = options;
}
+ public static <T extends AppInfo> AppView<T> createForD8(T appInfo, InternalOptions options) {
+ boolean enableWholeProgramOptimizations = false;
+ return new AppView<>(
+ appInfo, enableWholeProgramOptimizations, GraphLense.getIdentityLense(), options);
+ }
+
+ public static <T extends AppInfo> AppView<T> createForR8(T appInfo, InternalOptions options) {
+ boolean enableWholeProgramOptimizations = true;
+ return new AppView<>(
+ appInfo, enableWholeProgramOptimizations, GraphLense.getIdentityLense(), options);
+ }
+
public T appInfo() {
return appInfo;
}
@@ -40,14 +58,33 @@
this.appServices = appServices;
}
+ @Override
+ public final DexDefinition definitionFor(DexReference reference) {
+ return appInfo().definitionFor(reference);
+ }
+
+ @Override
+ public final DexEncodedField definitionFor(DexField field) {
+ return appInfo().definitionFor(field);
+ }
+
+ @Override
+ public final DexEncodedMethod definitionFor(DexMethod method) {
+ return appInfo().definitionFor(method);
+ }
+
+ @Override
+ public final DexClass definitionFor(DexType type) {
+ return appInfo().definitionFor(type);
+ }
+
+ @Override
public DexItemFactory dexItemFactory() {
return dexItemFactory;
}
- // TODO(b/114469298): If we at some point replace all occurences of AppInfo with AppView,
- // then this method should return false when we are running with D8.
public boolean enableWholeProgramOptimizations() {
- return true;
+ return enableWholeProgramOptimizations;
}
public GraphLense graphLense() {
@@ -79,7 +116,7 @@
private class AppViewWithLiveness extends AppView<AppInfoWithLiveness> {
private AppViewWithLiveness() {
- super(null, null, null);
+ super(null, false, null, null);
}
@Override
@@ -110,6 +147,11 @@
}
@Override
+ public boolean enableWholeProgramOptimizations() {
+ return AppView.this.enableWholeProgramOptimizations();
+ }
+
+ @Override
public GraphLense graphLense() {
return AppView.this.graphLense();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
new file mode 100644
index 0000000..7d9888e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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;
+
+public interface DexDefinitionSupplier {
+
+ DexDefinition definitionFor(DexReference reference);
+
+ DexEncodedField definitionFor(DexField field);
+
+ DexEncodedMethod definitionFor(DexMethod method);
+
+ DexClass definitionFor(DexType type);
+
+ DexItemFactory dexItemFactory();
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 249a2b5..4f90719 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -160,68 +160,70 @@
type.directSubtypes = NO_DIRECT_SUBTYPE;
}
- public boolean isSubtypeOf(DexType other, AppInfo appInfo) {
- return this == other || isStrictSubtypeOf(other, appInfo);
+ public boolean isSubtypeOf(DexType other, DexDefinitionSupplier definitions) {
+ return this == other || isStrictSubtypeOf(other, definitions);
}
public boolean hasSubtypes() {
return !directSubtypes.isEmpty();
}
- public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo) {
+ public boolean isStrictSubtypeOf(DexType other, DexDefinitionSupplier definitions) {
// For all erroneous cases, saying `no`---not a strict subtype---is conservative.
- return isStrictSubtypeOf(other, appInfo, false);
+ return isStrictSubtypeOf(other, definitions, false);
}
// Depending on optimizations, conservative answer of subtype relation may vary.
// Pass different `orElse` in that case.
- public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo, boolean orElse) {
+ public boolean isStrictSubtypeOf(
+ DexType other, DexDefinitionSupplier definitions, boolean orElse) {
if (this == other) {
return false;
}
// Treat the object class special as it is always the supertype, even in the case of broken
// subtype chains.
- if (this == appInfo.dexItemFactory.objectType) {
+ if (this == definitions.dexItemFactory().objectType) {
return false;
}
- if (other == appInfo.dexItemFactory.objectType) {
+ if (other == definitions.dexItemFactory().objectType) {
return true;
}
if (this.hierarchyLevel == INTERFACE_LEVEL) {
- return isInterfaceSubtypeOf(this, other, appInfo);
+ return isInterfaceSubtypeOf(this, other, definitions);
}
if (other.hierarchyLevel == INTERFACE_LEVEL) {
- return other.directSubtypes.stream().anyMatch(subtype -> this.isSubtypeOf(subtype,
- appInfo));
+ return other.directSubtypes.stream().anyMatch(subtype -> isSubtypeOf(subtype, definitions));
}
- return isSubtypeOfClass(other, appInfo, orElse);
+ return isSubtypeOfClass(other, definitions, orElse);
}
- private boolean isInterfaceSubtypeOf(DexType candidate, DexType other, AppInfo appInfo) {
- if (candidate == other || other == appInfo.dexItemFactory.objectType) {
+ private boolean isInterfaceSubtypeOf(
+ DexType candidate, DexType other, DexDefinitionSupplier definitions) {
+ if (candidate == other || other == definitions.dexItemFactory().objectType) {
return true;
}
- DexClass candidateHolder = appInfo.definitionFor(candidate);
+ DexClass candidateHolder = definitions.definitionFor(candidate);
if (candidateHolder == null) {
return false;
}
for (DexType iface : candidateHolder.interfaces.values) {
assert iface.hierarchyLevel == INTERFACE_LEVEL;
- if (isInterfaceSubtypeOf(iface, other, appInfo)) {
+ if (isInterfaceSubtypeOf(iface, other, definitions)) {
return true;
}
}
return false;
}
- private boolean isSubtypeOfClass(DexType other, AppInfo appInfo, boolean orElse) {
+ private boolean isSubtypeOfClass(
+ DexType other, DexDefinitionSupplier definitions, boolean orElse) {
DexType self = this;
if (other.hierarchyLevel == UNKNOWN_LEVEL) {
// We have no definition for this class, hence it is not part of the hierarchy.
return orElse;
}
while (other.hierarchyLevel < self.hierarchyLevel) {
- DexClass holder = appInfo.definitionFor(self);
+ DexClass holder = definitions.definitionFor(self);
assert holder != null && !holder.isInterface();
self = holder.superType;
}
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index a09ba4f..42a427c 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -669,11 +669,6 @@
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- visitMethodInsn(opcode, owner, name, desc, false);
- }
-
- @Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
DexMethod method = application.getMethod(owner, name, desc);
instructions.add(new CfInvoke(opcode, method, itf));
diff --git a/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java b/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
index e8d6a4f..7562e84 100644
--- a/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
+++ b/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
@@ -53,7 +53,7 @@
// Add super classes to worklist.
if (clazz.superType != null) {
- DexClass definition = appView.appInfo().definitionFor(clazz.superType);
+ DexClass definition = appView.definitionFor(clazz.superType);
if (definition != null && definition.isProgramClass()) {
addAncestorsToWorklist(definition.asProgramClass(), worklist, visited, appView);
}
@@ -61,7 +61,7 @@
// Add super interfaces to worklist.
for (DexType interfaceType : clazz.interfaces.values) {
- DexClass definition = appView.appInfo().definitionFor(interfaceType);
+ DexClass definition = appView.definitionFor(interfaceType);
if (definition != null && definition.isProgramClass()) {
addAncestorsToWorklist(definition.asProgramClass(), worklist, visited, appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index 9532404..4e08835 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.analysis;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfo.ResolutionResult;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexItemFactory;
@@ -196,7 +196,7 @@
|| exceptionalExit.isInvokeMethodWithReceiver()) {
// If an instance-get, instance-put, or instance-invoke instruction does not fail with a
// NullPointerException, then the receiver class must have been initialized.
- if (!dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
+ if (!dexItemFactory.npeType.isSubtypeOf(guard, appView)) {
continue;
}
}
@@ -205,7 +205,7 @@
|| exceptionalExit.isInvokeStatic()) {
// If a static-get, static-put, or invoke-static does not fail with an ExceptionIn-
// InitializerError, then the holder class must have been initialized.
- if (!dexItemFactory.exceptionInInitializerErrorType.isSubtypeOf(guard, appView.appInfo())) {
+ if (!dexItemFactory.exceptionInInitializerErrorType.isSubtypeOf(guard, appView)) {
continue;
}
}
@@ -246,7 +246,7 @@
public static boolean forInstanceGet(
InstanceGet instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -255,7 +255,7 @@
public static boolean forInstancePut(
InstancePut instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -264,7 +264,7 @@
private static boolean forInstanceGetOrPut(
FieldInstruction instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
assert instruction.isInstanceGet() || instruction.isInstancePut();
@@ -284,7 +284,7 @@
public static boolean forInvokeDirect(
InvokeDirect instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -299,7 +299,7 @@
public static boolean forInvokeStatic(
InvokeStatic instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -312,7 +312,7 @@
public static boolean forInvokeSuper(
InvokeSuper instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -328,7 +328,7 @@
return false;
}
DexMethod method = instruction.getInvokedMethod();
- DexClass enclosingClass = appView.appInfo().definitionFor(method.holder);
+ DexClass enclosingClass = appView.definitionFor(method.holder);
if (enclosingClass == null) {
return false;
}
@@ -341,13 +341,13 @@
return false;
}
DexType holder = resolutionResult.asSingleTarget().method.holder;
- return holder.isSubtypeOf(type, appView.appInfo());
+ return holder.isSubtypeOf(type, appView);
}
public static boolean forInvokeVirtual(
InvokeVirtual instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -368,13 +368,13 @@
return false;
}
DexType holder = resolutionResult.asSingleTarget().method.holder;
- return holder.isSubtypeOf(type, appView.appInfo());
+ return holder.isSubtypeOf(type, appView);
}
public static boolean forNewInstance(
NewInstance instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return isTypeInitializedBy(type, instruction.clazz, appView, mode);
@@ -383,7 +383,7 @@
public static boolean forStaticGet(
StaticGet instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -392,7 +392,7 @@
public static boolean forStaticPut(
StaticPut instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -401,7 +401,7 @@
private static boolean forStaticGetOrPut(
FieldInstruction instruction,
DexType type,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
assert instruction.isStaticGet() || instruction.isStaticPut();
@@ -415,12 +415,12 @@
private static boolean isTypeInitializedBy(
DexType typeToBeInitialized,
DexType typeKnownToBeInitialized,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode) {
if (mode == Query.DIRECTLY) {
return typeKnownToBeInitialized == typeToBeInitialized;
} else {
- return typeKnownToBeInitialized.isSubtypeOf(typeToBeInitialized, appView.appInfo());
+ return typeKnownToBeInitialized.isSubtypeOf(typeToBeInitialized, appView);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
index 1d42746..d419cbb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class AlwaysMaterializingDefinition extends ConstInstruction {
@@ -21,8 +20,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// This instruction may never be considered dead as it must remain.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
index 37bbd07..7f8c6eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class AlwaysMaterializingNop extends Instruction {
@@ -22,8 +21,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
index ecb7a81..c36ee42 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class AlwaysMaterializingUser extends Instruction {
@@ -21,8 +20,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// This instruction may never be considered dead as it must remain.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index 4ae0c3e..997f1c5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
/**
* Argument pseudo instruction used to introduce values for all arguments for SSA conversion.
@@ -28,8 +27,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appview, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appview, IRCode code) {
// Never remove argument instructions. That would change the signature of the method.
// TODO(b/65810338): If we can tell that a method never uses an argument we might be able to
// rewrite the signature and call-sites.
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 34a0041..f0be051 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -24,7 +24,6 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.Arrays;
public class ArrayPut extends Instruction implements ImpreciseMemberTypeInstruction {
@@ -130,8 +129,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// ArrayPut has side-effects on input values.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index ea1d912..b3ab484 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class ConstClass extends ConstInstruction {
@@ -85,16 +84,14 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
- assert appView == null || appView.appInfo() == appInfo;
-
- DexType baseType = getValue().toBaseType(appInfo.dexItemFactory);
+ AppView<? extends AppInfo> appView, DexType context) {
+ DexType baseType = getValue().toBaseType(appView.dexItemFactory());
if (baseType.isPrimitiveType()) {
return false;
}
- if (appView != null && appView.enableWholeProgramOptimizations()) {
- DexClass clazz = appView.appInfo().definitionFor(baseType);
+ if (appView.enableWholeProgramOptimizations()) {
+ DexClass clazz = appView.definitionFor(baseType);
if (clazz != null && clazz.isProgramClass()) {
return false;
}
@@ -108,9 +105,8 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
- return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+ return !instructionMayHaveSideEffects(appView, code.method.method.holder);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index 356b73d..f6f1ccf 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -16,7 +16,6 @@
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.io.UTFDataFormatException;
public class ConstString extends ConstInstruction {
@@ -116,8 +115,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// No side-effect, such as throwing an exception, in CF.
return code.options.isGeneratingClassFiles() || !instructionInstanceCanThrow();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
index 1c372ed..8697b79 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class DebugLocalRead extends Instruction {
private static final String ERROR_MESSAGE = "Unexpected attempt to emit debug-local read.";
@@ -63,8 +62,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// Reads are never dead code.
// They should also have a non-empty set of debug values (see RegAlloc::computeDebugInfo)
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
index a2aa761..4f097ff 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.StringUtils;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
@@ -75,8 +74,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index 6990e18..02957b6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class DebugPosition extends Instruction {
@@ -59,8 +58,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index e4e0e10..7d0d44f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class DexItemBasedConstString extends ConstInstruction {
@@ -111,8 +110,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// No side-effect, such as throwing an exception, in CF.
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index fba69c0..44cc6a1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
@@ -34,7 +33,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import org.objectweb.asm.Opcodes;
public class InstanceGet extends FieldInstruction {
@@ -102,17 +100,18 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// Not applicable for D8.
- if (appView == null || !appView.enableWholeProgramOptimizations()) {
+ if (!appView.enableWholeProgramOptimizations()) {
return false;
}
+
// instance-get can be dead code as long as it cannot have any of the following:
// * NoSuchFieldError (resolution failure)
// * IllegalAccessError (not visible from the access context)
// * NullPointerException (null receiver).
// TODO(b/123857022): Should be possible to use definitionFor().
+ AppInfo appInfo = appView.appInfo();
DexEncodedField resolvedField = appInfo.resolveFieldOn(getField().getHolder(), getField());
if (resolvedField == null) {
return false;
@@ -197,7 +196,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInstanceGet(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index 57fe121..327138b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.code.IputWide;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -150,7 +150,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInstancePut(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 38e5d32..b05cd55 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexItemFactory;
@@ -25,7 +24,6 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -505,13 +503,12 @@
}
public boolean instructionMayHaveSideEffects(
- AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
+ AppView<? extends AppInfo> appView, DexType context) {
return instructionInstanceCanThrow();
}
/** Returns true is this instruction can be treated as dead code if its outputs are not used. */
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return !instructionInstanceCanThrow();
}
@@ -1260,7 +1257,7 @@
*/
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index 301f710..462da0d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.code.InvokeDirectRange;
import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -128,7 +129,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeDirect(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index 77c21fe..dbff861 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -127,7 +127,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeStatic(
@@ -136,8 +136,8 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
- if (appView == null || !appView.enableWholeProgramOptimizations()) {
+ AppView<? extends AppInfo> appView, DexType context) {
+ if (!appView.enableWholeProgramOptimizations()) {
return true;
}
@@ -178,8 +178,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
- return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+ return !instructionMayHaveSideEffects(appView, code.method.method.holder);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index bc3d982..0fe6c63 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.code.InvokeSuperRange;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -115,7 +116,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeSuper(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 26efb4f..d404a6c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -107,7 +107,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeVirtual(
@@ -116,8 +116,8 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
- if (appView == null || !appView.enableWholeProgramOptimizations()) {
+ AppView<? extends AppInfo> appView, DexType context) {
+ if (!appView.enableWholeProgramOptimizations()) {
return true;
}
@@ -140,8 +140,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
- return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+ return !instructionMayHaveSideEffects(appView, code.method.method.holder);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index 8e7c646..44bdd23 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.List;
public abstract class JumpInstruction extends Instruction {
@@ -34,8 +33,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index a82bfa1..96d5186 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
public class MoveException extends Instruction {
@@ -71,8 +70,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return !(code.options.debug || code.method.getOptimizationInfo().isReachabilitySensitive())
&& code.options.isGeneratingDex();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index fb4d23b..a8bcea2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class NewArrayEmpty extends Instruction {
@@ -73,14 +72,13 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
if (instructionInstanceCanThrow()) {
return false;
}
// This would belong better in instructionInstanceCanThrow, but that is not passed an appInfo.
- DexType baseType = type.toBaseType(appInfo.dexItemFactory);
- return baseType.isPrimitiveType() || appInfo.definitionFor(baseType) != null;
+ DexType baseType = type.toBaseType(appView.dexItemFactory());
+ return baseType.isPrimitiveType() || appView.definitionFor(baseType) != null;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index f107c90..3151a94 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.Arrays;
public class NewArrayFilledData extends Instruction {
@@ -76,8 +75,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
if (!src().getTypeLattice().isNullable() && src().numberOfAllUsers() == 1) {
// The NewArrayFilledData instruction is only inserted by an R8 optimization following
// a NewArrayEmpty when there are more than one entry.
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 3d7c81b..b5401b0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
@@ -113,7 +112,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forNewInstance(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Pop.java b/src/main/java/com/android/tools/r8/ir/code/Pop.java
index 41d17b0..32bd532 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Pop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Pop.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class Pop extends Instruction {
@@ -83,8 +82,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// Pop cannot be dead code as it modifies the stack height.
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index d446f4c..f4b0beb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
@@ -32,7 +31,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import org.objectweb.asm.Opcodes;
public class StaticGet extends FieldInstruction {
@@ -95,18 +93,19 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
// Not applicable for D8.
- if (appView == null || !appView.enableWholeProgramOptimizations()) {
+ if (!appView.enableWholeProgramOptimizations()) {
return false;
}
+
// static-get can be dead as long as it cannot have any of the following:
// * NoSuchFieldError (resolution failure)
// * IllegalAccessError (not visible from the access context)
// * side-effects in <clinit>
// TODO(b/123857022): Should be possible to use definitionFor().
- DexEncodedField resolvedField = appInfo.resolveFieldOn(getField().getHolder(), getField());
+ AppInfo appInfo = appView.appInfo();
+ DexEncodedField resolvedField = appInfo.resolveField(getField());
if (resolvedField == null) {
return false;
}
@@ -188,7 +187,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forStaticGet(
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index 29ce40c..4609bb1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.code.SputWide;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
@@ -137,7 +137,7 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forStaticPut(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Store.java b/src/main/java/com/android/tools/r8/ir/code/Store.java
index 07cb184..f09107f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Store.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Store.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
public class Store extends Instruction {
@@ -91,8 +90,7 @@
}
@Override
- public boolean canBeDeadCode(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
return !(outValue instanceof FixedLocalValue);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 88fd645..3b783d9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.ir.regalloc.LiveIntervals;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.LongInterval;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
@@ -848,17 +847,12 @@
}
}
- public boolean isDead(
- AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+ public boolean isDead(AppView<? extends AppInfo> appView, IRCode code) {
// Totally unused values are trivially dead.
- return !isUsed() || isDead(appView, appInfo, code, new HashSet<>());
+ return !isUsed() || isDead(appView, code, new HashSet<>());
}
- protected boolean isDead(
- AppView<? extends AppInfoWithLiveness> appView,
- AppInfo appInfo,
- IRCode code,
- Set<Value> active) {
+ protected boolean isDead(AppView<? extends AppInfo> appView, IRCode code, Set<Value> active) {
// Give up when the dependent set of values reach a given threshold (otherwise this fails with
// a StackOverflowError on Art003_omnibus_opcodesTest).
if (active.size() > 100) {
@@ -874,18 +868,18 @@
// currently active values.
active.add(this);
for (Instruction instruction : uniqueUsers()) {
- if (!instruction.canBeDeadCode(appView, appInfo, code)) {
+ if (!instruction.canBeDeadCode(appView, code)) {
return false;
}
Value outValue = instruction.outValue();
if (outValue != null
&& !active.contains(outValue)
- && !outValue.isDead(appView, appInfo, code, active)) {
+ && !outValue.isDead(appView, code, active)) {
return false;
}
}
for (Phi phi : uniquePhiUsers()) {
- if (!active.contains(phi) && !phi.isDead(appView, appInfo, code, active)) {
+ if (!active.contains(phi) && !phi.isDead(appView, code, active)) {
return false;
}
}
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 f8702db..e9c825d 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
@@ -150,7 +150,7 @@
public static CallGraph build(
DexApplication application,
- AppView<AppInfoWithLiveness> appView,
+ AppView<? extends AppInfoWithLiveness> appView,
InternalOptions options,
Timing timing) {
CallGraph graph = new CallGraph(options);
@@ -488,7 +488,7 @@
private final Node caller;
private final CallGraph graph;
- InvokeExtractor(AppView<AppInfoWithLiveness> appView, Node caller, CallGraph graph) {
+ InvokeExtractor(AppView<? extends AppInfoWithLiveness> appView, Node caller, CallGraph graph) {
super(appView.dexItemFactory());
this.appInfo = appView.appInfo();
this.graphLense = appView.graphLense();
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 e025553..f23b8ab 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
@@ -9,7 +9,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.Code;
@@ -109,8 +108,7 @@
private static final int PEEPHOLE_OPTIMIZATION_PASSES = 2;
- private final AppInfo appInfoD8; // Used only from D8, null in R8.
- public final AppView<? extends AppInfoWithSubtyping> appView;
+ public final AppView<? extends AppInfo> appView;
public final Set<DexType> mainDexClasses;
public final RootSet rootSet;
@@ -142,8 +140,6 @@
final DeadCodeRemover deadCodeRemover;
- public final boolean enableWholeProgramOptimizations;
-
private final OptimizationFeedbackDelayed delayedOptimizationFeedback =
new OptimizationFeedbackDelayed();
private final OptimizationFeedback ignoreOptimizationFeedback = new OptimizationFeedbackIgnore();
@@ -154,66 +150,58 @@
// The argument `appView` is only available when full program optimizations are allowed
// (i.e., when running R8).
- private IRConverter(
- AppView<? extends AppInfoWithLiveness> appView,
- InternalOptions options,
+ public IRConverter(
+ AppView<? extends AppInfo> appView,
Timing timing,
CfgPrinter printer,
MainDexClasses mainDexClasses,
- RootSet rootSet,
- AppInfo appInfoD8) {
- assert (appInfoD8 == null) != (appView == null);
- assert options != null;
- assert options.programConsumer != null;
- assert appView == null
- || appView.appInfo().hasLiveness()
- || appView.graphLense().isIdentityLense();
+ RootSet rootSet) {
+ assert appView.appInfo().hasLiveness() || appView.graphLense().isIdentityLense();
+ assert appView.options() != null;
+ assert appView.options().programConsumer != null;
this.timing = timing != null ? timing : new Timing("internal");
- this.appInfoD8 = appInfoD8;
this.appView = appView;
+ this.options = appView.options();
this.rootSet = rootSet;
- this.options = options;
this.printer = printer;
this.mainDexClasses = mainDexClasses.getClasses();
- this.codeRewriter = new CodeRewriter(this, libraryMethodsReturningReceiver(), options);
+ this.codeRewriter = new CodeRewriter(appView, this, libraryMethodsReturningReceiver());
this.classInitializerDefaultsOptimization =
- options.debug
- ? null
- : new ClassInitializerDefaultsOptimization(appInfo(), appView, this, options);
- this.stringConcatRewriter = new StringConcatRewriter(appInfo());
- this.lambdaRewriter = options.enableDesugaring ? new LambdaRewriter(this) : null;
+ options.debug ? null : new ClassInitializerDefaultsOptimization(appView, this);
+ this.stringConcatRewriter = new StringConcatRewriter(appView);
+ this.lambdaRewriter = options.enableDesugaring ? new LambdaRewriter(appView, this) : null;
this.interfaceMethodRewriter =
options.isInterfaceMethodDesugaringEnabled()
- ? new InterfaceMethodRewriter(appView, this, options)
+ ? new InterfaceMethodRewriter(appView, this)
: null;
this.twrCloseResourceRewriter =
(options.enableDesugaring && enableTwrCloseResourceDesugaring())
- ? new TwrCloseResourceRewriter(this) : null;
+ ? new TwrCloseResourceRewriter(appView, this)
+ : null;
this.java8MethodRewriter =
(options.enableDesugaring && !options.canUseJava8Methods())
- ? new Java8MethodRewriter(this) : null;
- this.lambdaMerger =
- options.enableLambdaMerging ? new LambdaMerger(appInfo(), options.reporter) : null;
+ ? new Java8MethodRewriter(appView, this)
+ : null;
+ this.lambdaMerger = options.enableLambdaMerging ? new LambdaMerger(appView) : null;
this.covariantReturnTypeAnnotationTransformer =
options.processCovariantReturnTypeAnnotations
- ? new CovariantReturnTypeAnnotationTransformer(this, appInfo().dexItemFactory)
+ ? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
: null;
- this.stringOptimizer = new StringOptimizer(appInfo(), options.getInternalOutputMode());
- this.enableWholeProgramOptimizations =
- appView != null && appView.enableWholeProgramOptimizations();
- if (enableWholeProgramOptimizations) {
- assert appInfo().hasLiveness();
- AppInfoWithLiveness appInfoWithLiveness = appInfo().withLiveness();
+ this.stringOptimizer = new StringOptimizer(appView);
+ if (appView.enableWholeProgramOptimizations()) {
+ assert appView.appInfo().hasLiveness();
AppView<? extends AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+ AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
assert rootSet != null;
+ this.classStaticizer = new ClassStaticizer(appViewWithLiveness, this);
this.nonNullTracker =
new NonNullTracker(
- appInfoWithLiveness, libraryMethodsReturningNonNull(appInfo().dexItemFactory));
+ appInfoWithLiveness, libraryMethodsReturningNonNull(appView.dexItemFactory()));
this.inliner = new Inliner(appViewWithLiveness, this, options, mainDexClasses);
this.outliner = new Outliner(appInfoWithLiveness, options, this);
this.memberValuePropagation =
- options.enableValuePropagation ? new MemberValuePropagation(appView) : null;
- this.lensCodeRewriter = new LensCodeRewriter(appView, options);
+ options.enableValuePropagation ? new MemberValuePropagation(appViewWithLiveness) : null;
+ this.lensCodeRewriter = new LensCodeRewriter(appViewWithLiveness);
if (!appInfoWithLiveness.identifierNameStrings.isEmpty() && options.enableMinification) {
this.identifierNameStringMarker =
new IdentifierNameStringMarker(appInfoWithLiveness, options);
@@ -228,6 +216,7 @@
: null;
this.typeChecker = new TypeChecker(appView);
} else {
+ this.classStaticizer = null;
this.nonNullTracker = null;
this.inliner = null;
this.outliner = null;
@@ -241,15 +230,11 @@
this.classInliner =
(options.enableClassInlining && options.enableInlining && inliner != null)
? new ClassInliner(
- appInfo().dexItemFactory, lambdaRewriter, options.classInliningInstructionLimit)
+ appView.dexItemFactory(), lambdaRewriter, options.classInliningInstructionLimit)
: null;
- this.classStaticizer =
- options.enableClassStaticizer && appInfo().hasLiveness()
- ? new ClassStaticizer(appInfo().withLiveness(), this)
- : null;
- this.deadCodeRemover = new DeadCodeRemover(appView, appInfo(), codeRewriter, options);
+ this.deadCodeRemover = new DeadCodeRemover(appView, codeRewriter);
this.idempotentFunctionCallCanonicalizer =
- new IdempotentFunctionCallCanonicalizer(appInfo().dexItemFactory);
+ new IdempotentFunctionCallCanonicalizer(appView.dexItemFactory());
}
public GraphLense graphLense() {
@@ -264,35 +249,16 @@
}
}
- /**
- * Create an IR converter for processing methods with full program optimization disabled.
- */
- public IRConverter(AppInfo appInfo, InternalOptions options) {
- this(null, options, null, null, MainDexClasses.NONE, null, appInfo);
+ /** Create an IR converter for processing methods with full program optimization disabled. */
+ public IRConverter(AppView<? extends AppInfo> appView) {
+ this(appView, null, null, MainDexClasses.NONE, null);
}
/**
* Create an IR converter for processing methods with full program optimization disabled.
*/
public IRConverter(AppInfo appInfo, InternalOptions options, Timing timing, CfgPrinter printer) {
- this(null, options, timing, printer, MainDexClasses.NONE, null, appInfo);
- }
-
- /**
- * Create an IR converter for processing methods with full program optimization enabled.
- */
- public IRConverter(
- AppView<? extends AppInfoWithLiveness> appView,
- InternalOptions options,
- Timing timing,
- CfgPrinter printer,
- MainDexClasses mainDexClasses,
- RootSet rootSet) {
- this(appView, options, timing, printer, mainDexClasses, rootSet, null);
- }
-
- public AppInfo appInfo() {
- return appView == null ? appInfoD8 : appView.appInfo();
+ this(AppView.createForD8(appInfo, options), timing, printer, MainDexClasses.NONE, null);
}
private boolean enableTwrCloseResourceDesugaring() {
@@ -311,7 +277,7 @@
private Set<DexMethod> libraryMethodsReturningReceiver() {
Set<DexMethod> methods = new HashSet<>();
- DexItemFactory dexItemFactory = appInfo().dexItemFactory;
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
dexItemFactory.stringBufferMethods.forEachAppendMethod(methods::add);
dexItemFactory.stringBuilderMethods.forEachAppendMethod(methods::add);
return methods;
@@ -329,7 +295,7 @@
private boolean removeLambdaDeserializationMethods() {
if (lambdaRewriter != null) {
- return lambdaRewriter.removeLambdaDeserializationMethods(appInfo().classes());
+ return lambdaRewriter.removeLambdaDeserializationMethods(appView.appInfo().classes());
}
return false;
}
@@ -615,7 +581,7 @@
outliner.identifyOutlineSites(code, method);
});
DexProgramClass outlineClass = outliner.buildOutlinerClass(computeOutlineClassType());
- appInfo().addSynthesizedClass(outlineClass);
+ appView.appInfo().addSynthesizedClass(outlineClass);
optimizeSynthesizedClass(outlineClass, executorService);
forEachSelectedOutliningMethod(
executorService,
@@ -642,12 +608,13 @@
// Check if what we've added to the application builder as synthesized classes are same as
// what we've added and used through AppInfo.
- assert appInfo()
+ assert appView
+ .appInfo()
.getSynthesizedClassesForSanityCheck()
.containsAll(builder.getSynthesizedClasses())
&& builder
.getSynthesizedClasses()
- .containsAll(appInfo().getSynthesizedClassesForSanityCheck());
+ .containsAll(appView.appInfo().getSynthesizedClassesForSanityCheck());
return builder.build();
}
@@ -662,7 +629,7 @@
}
public void addWaveDoneAction(Action action) {
- if (appView == null || !appView.enableWholeProgramOptimizations()) {
+ if (!appView.enableWholeProgramOptimizations()) {
throw new Unreachable("addWaveDoneAction() should never be used in D8.");
}
if (!isInWave()) {
@@ -696,10 +663,10 @@
() -> {
IRCode code =
method.buildIR(
- appInfo(),
+ appView.appInfo(),
appView.graphLense(),
options,
- appInfo().originFor(method.method.holder));
+ appView.appInfo().originFor(method.method.holder));
assert code != null;
assert !method.getCode().isOutlineCode();
// Instead of repeating all the optimizations of rewriteCode(), only run the
@@ -717,7 +684,7 @@
private void collectLambdaMergingCandidates(DexApplication application) {
if (lambdaMerger != null) {
- lambdaMerger.collectGroupCandidates(application, appInfo().withLiveness(), options);
+ lambdaMerger.collectGroupCandidates(application, appView.appInfo().withLiveness(), options);
}
}
@@ -734,7 +701,7 @@
}
private void clearDexMethodCompilationState() {
- appInfo().classes().forEach(this::clearDexMethodCompilationState);
+ appView.appInfo().classes().forEach(this::clearDexMethodCompilationState);
}
private void clearDexMethodCompilationState(DexProgramClass clazz) {
@@ -769,7 +736,7 @@
private DexType computeOutlineClassType() {
DexType result;
int count = 0;
- AppInfo appInfo = appInfo();
+ AppInfo appInfo = appView.appInfo();
do {
String name = OutlineOptions.CLASS_NAME + (count == 0 ? "" : Integer.toString(count));
count++;
@@ -878,7 +845,7 @@
feedback.markProcessed(method, ConstraintWithTarget.NEVER);
return;
}
- AppInfo appInfo = appInfo();
+ AppInfo appInfo = appView.appInfo();
IRCode code =
method.buildIR(appInfo, graphLense(), options, appInfo.originFor(method.method.holder));
if (code == null) {
@@ -915,7 +882,7 @@
}
if (typeChecker != null && !typeChecker.check(code)) {
- assert enableWholeProgramOptimizations;
+ assert appView.enableWholeProgramOptimizations();
assert options.testing.allowTypeErrors;
StringDiagnostic warning =
new StringDiagnostic(
@@ -998,7 +965,7 @@
assert code.verifyTypes(appInfo, appView, graphLense());
codeRewriter.removeTrivialCheckCastAndInstanceOfInstructions(
- code, enableWholeProgramOptimizations);
+ code, appView.enableWholeProgramOptimizations());
codeRewriter.rewriteLongCompareAndRequireNonNull(code, options);
codeRewriter.commonSubexpressionElimination(code);
@@ -1011,7 +978,8 @@
codeRewriter.simplifyIf(code);
// TODO(b/123284765) This produces a runtime-crash in Q. Activate again when fixed.
// codeRewriter.redundantConstNumberRemoval(code);
- new RedundantFieldLoadElimination(appInfo, code, enableWholeProgramOptimizations).run();
+ new RedundantFieldLoadElimination(appInfo, code, appView.enableWholeProgramOptimizations())
+ .run();
if (options.testing.invertConditionals) {
invertConditionalsForTesting(code);
@@ -1127,7 +1095,7 @@
}
// Track usage of parameters and compute their nullability and possibility of NPE.
- if (enableWholeProgramOptimizations) {
+ if (appView.enableWholeProgramOptimizations()) {
if (method.getOptimizationInfo().getNonNullParamOrThrow() == null) {
computeNonNullParamHints(feedback, method, code);
}
@@ -1173,7 +1141,6 @@
printMethod(code, "Optimized IR (SSA)", previous);
finalizeIR(method, code, feedback);
- assert appInfo == appInfo();
}
private void computeNonNullParamHints(
@@ -1203,7 +1170,7 @@
// merging). Then, we find the type that now corresponds to the the original holder.
DexMethod originalSignature = graphLense().getOriginalMethodSignature(method.method);
DexClass originalHolder =
- appInfo().definitionFor(graphLense().lookupType(originalSignature.holder));
+ appView.definitionFor(graphLense().lookupType(originalSignature.holder));
if (originalHolder.hasKotlinInfo()) {
KotlinInfo kotlinInfo = originalHolder.getKotlinInfo();
if (kotlinInfo.hasNonNullParameterHints()) {
@@ -1235,8 +1202,7 @@
|| Streams.stream(code.instructions())
.anyMatch(
instruction ->
- instruction.instructionMayHaveSideEffects(
- appInfo(), appView, method.method.holder));
+ instruction.instructionMayHaveSideEffects(appView, method.method.holder));
if (!mayHaveSideEffects) {
feedback.methodMayNotHaveSideEffects(method);
}
@@ -1266,14 +1232,14 @@
private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
assert !method.getCode().isDexCode();
CfBuilder builder = new CfBuilder(method, code, options.itemFactory);
- CfCode result = builder.build(codeRewriter, graphLense(), options, appInfo());
+ CfCode result = builder.build(codeRewriter, graphLense(), options, appView.appInfo());
method.setCode(result);
markProcessed(method, code, feedback);
}
private void finalizeToDex(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
// Workaround massive dex2oat memory use for self-recursive methods.
- CodeRewriter.disableDex2OatInliningForSelfRecursiveMethods(code, options, appInfo());
+ CodeRewriter.disableDex2OatInliningForSelfRecursiveMethods(code, options, appView.appInfo());
// Perform register allocation.
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
method.setCode(code, registerAllocator, options);
@@ -1316,7 +1282,7 @@
materializeInstructionBeforeLongOperationsWorkaround(code);
workaroundForwardingInitializerBug(code);
LinearScanRegisterAllocator registerAllocator =
- new LinearScanRegisterAllocator(appInfo(), code, options);
+ new LinearScanRegisterAllocator(appView.appInfo(), code, options);
registerAllocator.allocateRegisters();
if (options.canHaveExceptionTargetingLoopHeaderBug()) {
codeRewriter.workaroundExceptionTargetingLoopHeaderBug(code);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 01c1556..b88a262 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -9,6 +9,7 @@
import static com.android.tools.r8.ir.code.Invoke.Type.VIRTUAL;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
@@ -69,19 +70,14 @@
public class LensCodeRewriter {
- private final AppInfoWithSubtyping appInfo;
- private final GraphLense graphLense;
- private final VerticallyMergedClasses verticallyMergedClasses;
+ private final AppView<? extends AppInfo> appView;
private final InternalOptions options;
private final Map<DexProto, DexProto> protoFixupCache = new ConcurrentHashMap<>();
- public LensCodeRewriter(
- AppView<? extends AppInfoWithSubtyping> appView, InternalOptions options) {
- this.appInfo = appView.appInfo();
- this.graphLense = appView.graphLense();
- this.verticallyMergedClasses = appView.verticallyMergedClasses();
- this.options = options;
+ public LensCodeRewriter(AppView<? extends AppInfoWithSubtyping> appView) {
+ this.appView = appView;
+ this.options = appView.options();
}
private Value makeOutValue(Instruction insn, IRCode code, Set<Value> collector) {
@@ -98,6 +94,9 @@
* Replace type appearances, invoke targets and field accesses with actual definitions.
*/
public void rewrite(IRCode code, DexEncodedMethod method) {
+ AppInfo appInfo = appView.appInfo();
+ GraphLense graphLense = appView.graphLense();
+
Set<Value> newSSAValues = Sets.newIdentityHashSet();
ListIterator<BasicBlock> blocks = code.blocks.listIterator();
boolean mayHaveUnreachableBlocks = false;
@@ -381,12 +380,13 @@
// A and B although this will lead to invalid code, because this code pattern does generally
// not occur in practice (it leads to a verification error on the JVM, but not on Art).
private void checkInvokeDirect(DexMethod method, InvokeDirect invoke) {
+ VerticallyMergedClasses verticallyMergedClasses = appView.verticallyMergedClasses();
if (verticallyMergedClasses == null) {
// No need to check the invocation.
return;
}
DexMethod invokedMethod = invoke.getInvokedMethod();
- if (invokedMethod.name != appInfo.dexItemFactory.constructorMethodName) {
+ if (invokedMethod.name != appView.dexItemFactory().constructorMethodName) {
// Not a constructor call.
return;
}
@@ -431,7 +431,7 @@
List<BasicBlock> deadCatchHandlers = new ArrayList<>();
for (int i = 0; i < guards.size(); i++) {
// The type may have changed due to class merging.
- DexType guard = graphLense.lookupType(guards.get(i));
+ DexType guard = appView.graphLense().lookupType(guards.get(i));
boolean guardSeenBefore = !previouslySeenGuards.add(guard);
if (guardSeenBefore) {
deadCatchHandlers.add(targets.get(i));
@@ -458,7 +458,7 @@
newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
} else if (argument instanceof DexValueType) {
DexType oldType = ((DexValueType) argument).value;
- DexType newType = graphLense.lookupType(oldType);
+ DexType newType = appView.graphLense().lookupType(oldType);
if (newType != oldType) {
newArgument = new DexValueType(newType);
}
@@ -489,7 +489,7 @@
DexMethod invokedMethod = methodHandle.asMethod();
MethodHandleType oldType = methodHandle.type;
GraphLenseLookupResult lenseLookup =
- graphLense.lookupMethod(invokedMethod, context.method, oldType.toInvokeType());
+ appView.graphLense().lookupMethod(invokedMethod, context.method, oldType.toInvokeType());
DexMethod rewrittenTarget = lenseLookup.getMethod();
DexMethod actualTarget;
MethodHandleType newType;
@@ -505,8 +505,9 @@
// we cannot member rebind. We therefore keep the receiver and also pin the receiver
// with a keep rule (see Enqueuer.registerMethodHandle).
actualTarget =
- appInfo.dexItemFactory.createMethod(
- invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
+ appView
+ .dexItemFactory()
+ .createMethod(invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
newType = oldType;
if (oldType.isInvokeDirect()) {
// For an invoke direct, the rewritten target must have the same holder as the original.
@@ -526,7 +527,7 @@
}
} else {
DexField field = methodHandle.asField();
- DexField actualField = graphLense.lookupField(field);
+ DexField actualField = appView.graphLense().lookupField(field);
if (actualField != field) {
return new DexMethodHandle(methodHandle.type, actualField);
}
@@ -537,8 +538,9 @@
private DexValueMethodType rewriteDexMethodType(DexValueMethodType type) {
DexProto oldProto = type.value;
DexProto newProto =
- appInfo.dexItemFactory.applyClassMappingToProto(
- oldProto, graphLense::lookupType, protoFixupCache);
+ appView
+ .dexItemFactory()
+ .applyClassMappingToProto(oldProto, appView.graphLense()::lookupType, protoFixupCache);
return newProto != oldProto ? new DexValueMethodType(newProto) : type;
}
@@ -557,7 +559,7 @@
if (!receiver.getTypeLattice().isClassType()) {
return target;
}
- DexEncodedMethod encodedTarget = appInfo.definitionFor(target);
+ DexEncodedMethod encodedTarget = appView.definitionFor(target);
if (encodedTarget == null
|| !canInvokeTargetWithInvokeVirtual(encodedTarget)
|| !hasAccessToInvokeTargetFromContext(encodedTarget, context)) {
@@ -565,12 +567,14 @@
return target;
}
DexType receiverType =
- graphLense.lookupType(receiver.getTypeLattice().asClassTypeLatticeElement().getClassType());
+ appView
+ .graphLense()
+ .lookupType(receiver.getTypeLattice().asClassTypeLatticeElement().getClassType());
if (receiverType == target.holder) {
// Virtual invoke is already as specific as it can get.
return target;
}
- DexEncodedMethod newTarget = appInfo.lookupVirtualTarget(receiverType, target);
+ DexEncodedMethod newTarget = appView.appInfo().lookupVirtualTarget(receiverType, target);
if (newTarget == null || newTarget.method == target) {
// Most likely due to a missing class, or invoke is already as specific as it gets.
return target;
@@ -594,7 +598,7 @@
// It is always safe to invoke a method from the same enclosing class.
return true;
}
- DexClass clazz = appInfo.definitionFor(holder);
+ DexClass clazz = appView.definitionFor(holder);
if (clazz == null) {
// Conservatively report an illegal access.
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index c49b0e9..b6bcb9c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -5,8 +5,11 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
+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.MethodAccessFlags;
@@ -26,13 +29,17 @@
// Adds default interface methods into the class when needed.
final class ClassProcessor {
+ private final AppView<? extends AppInfo> appView;
+ private final DexItemFactory dexItemFactory;
private final InterfaceMethodRewriter rewriter;
// Set of already processed classes.
private final Set<DexClass> processedClasses = Sets.newIdentityHashSet();
// Maps already created methods into default methods they were generated based on.
private final Map<DexEncodedMethod, DexEncodedMethod> createdMethods = new IdentityHashMap<>();
- ClassProcessor(InterfaceMethodRewriter rewriter) {
+ ClassProcessor(AppView<? extends AppInfo> appView, InterfaceMethodRewriter rewriter) {
+ this.appView = appView;
+ this.dexItemFactory = appView.dexItemFactory();
this.rewriter = rewriter;
}
@@ -60,8 +67,8 @@
DexType superType = clazz.superType;
// If superClass definition is missing, just skip this part and let real processing of its
// subclasses report the error if it is required.
- DexClass superClass = superType == null ? null : rewriter.appInfo().definitionFor(superType);
- if (superClass != null && superType != rewriter.factory.objectType) {
+ DexClass superClass = superType == null ? null : appView.definitionFor(superType);
+ if (superClass != null && superType != dexItemFactory.objectType) {
if (superClass.isInterface()) {
throw new CompilationError("Interface `" + superClass.toSourceString()
+ "` used as super class of `" + clazz.toSourceString() + "`.");
@@ -96,13 +103,13 @@
private DexEncodedMethod addForwardingMethod(DexEncodedMethod defaultMethod, DexClass clazz) {
DexMethod method = defaultMethod.method;
- DexClass target = rewriter.appInfo().definitionFor(method.holder);
+ DexClass target = appView.definitionFor(method.holder);
// NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
// even if this results in invalid code, these classes are never desugared.
assert target != null && !target.isLibraryClass();
// New method will have the same name, proto, and also all the flags of the
// default method, including bridge flag.
- DexMethod newMethod = rewriter.factory.createMethod(clazz.type, method.proto, method.name);
+ DexMethod newMethod = dexItemFactory.createMethod(clazz.type, method.proto, method.name);
MethodAccessFlags newFlags = defaultMethod.accessFlags.copy();
// Some debuggers (like IntelliJ) automatically skip synthetic methods on single step.
newFlags.setSynthetic();
@@ -140,7 +147,7 @@
// methods is supposed to fail with a compilation error.
// Note that this last assumption will be broken if Object API is augmented with a new method in
// the future.
- while (current.type != rewriter.factory.objectType) {
+ while (current.type != dexItemFactory.objectType) {
for (DexType type : current.interfaces.values) {
helper.merge(rewriter.getOrCreateInterfaceInfo(clazz, current, type));
}
@@ -168,7 +175,7 @@
if (current.superType == null) {
break;
} else {
- DexClass superClass = rewriter.appInfo().definitionFor(current.superType);
+ DexClass superClass = appView.definitionFor(current.superType);
if (superClass != null) {
current = superClass;
} else {
@@ -206,11 +213,11 @@
DexType superType = current.superType;
DexClass superClass = null;
if (superType != null) {
- superClass = rewriter.appInfo().definitionFor(superType);
+ superClass = appView.definitionFor(superType);
// It's available or we would have failed while analyzing the hierarchy for interfaces.
assert superClass != null;
}
- if (superClass == null || superType == rewriter.factory.objectType) {
+ if (superClass == null || superType == dexItemFactory.objectType) {
// Note that default interface methods must never have same
// name/signature as any method in java.lang.Object (JLS §9.4.1.2).
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 85ff1ba..3551a7c 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
@@ -7,7 +7,6 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexCallSite;
@@ -33,7 +32,6 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.DefaultMethodsHelper.Collection;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Sets;
@@ -80,7 +78,7 @@
public static final String DEFAULT_METHOD_PREFIX = "$default$";
public static final String PRIVATE_METHOD_PREFIX = "$private$";
- private final AppView<? extends AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfo> appView;
private final IRConverter converter;
private final InternalOptions options;
final DexItemFactory factory;
@@ -115,19 +113,12 @@
ExcludeDexResources
}
- public InterfaceMethodRewriter(
- AppView<? extends AppInfoWithLiveness> appView,
- IRConverter converter,
- InternalOptions options) {
+ public InterfaceMethodRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
assert converter != null;
this.appView = appView;
this.converter = converter;
- this.options = options;
- this.factory = options.itemFactory;
- }
-
- public AppInfo appInfo() {
- return converter.appInfo();
+ this.options = appView.options();
+ this.factory = appView.dexItemFactory();
}
// Rewrites the references to static and default interface methods.
@@ -138,7 +129,7 @@
}
ListIterator<BasicBlock> blocks = code.listIterator();
- AppInfo appInfo = appInfo();
+ AppInfo appInfo = appView.appInfo();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
InstructionListIterator instructions = block.listIterator();
@@ -281,12 +272,11 @@
}
}
}
- assert appInfo == appInfo();
}
private void reportStaticInterfaceMethodHandle(DexMethod referencedFrom, DexMethodHandle handle) {
if (handle.type.isInvokeStatic()) {
- DexClass holderClass = appInfo().definitionFor(handle.asMethod().holder);
+ DexClass holderClass = appView.definitionFor(handle.asMethod().holder);
// NOTE: If the class definition is missing we can't check. Let it be handled as any other
// missing call target.
if (holderClass == null) {
@@ -332,7 +322,7 @@
}
private boolean isInMainDexList(DexType iface) {
- return appInfo().isInMainDexList(iface);
+ return appView.appInfo().isInMainDexList(iface);
}
// Represent a static interface method as a method of companion class.
@@ -401,7 +391,7 @@
// methods to companion class, copy default interface methods to companion classes,
// make original default methods abstract, remove bridge methods, create dispatch
// classes if needed.
- AppInfo appInfo = appInfo();
+ AppInfo appInfo = appView.appInfo();
for (Entry<DexType, DexProgramClass> entry : processInterfaces(builder, flavour).entrySet()) {
// Don't need to optimize synthesized class since all of its methods
// are just moved from interfaces and don't need to be re-processed.
@@ -439,15 +429,14 @@
for (Entry<DexLibraryClass, Set<DexProgramClass>> entry : requiredDispatchClasses.entrySet()) {
synthesizedMethods.addAll(processor.process(entry.getKey(), entry.getValue()));
}
- if (converter.enableWholeProgramOptimizations) {
- AppView<? extends AppInfoWithSubtyping> appView = converter.appView;
+ if (appView.enableWholeProgramOptimizations()) {
appView.setGraphLense(graphLensBuilder.build(appView.dexItemFactory(), appView.graphLense()));
}
return processor.syntheticClasses;
}
private Set<DexEncodedMethod> processClasses(Builder<?> builder, Flavor flavour) {
- ClassProcessor processor = new ClassProcessor(this);
+ ClassProcessor processor = new ClassProcessor(appView, this);
for (DexProgramClass clazz : builder.getProgramClasses()) {
if (shouldProcess(clazz, flavour, false)) {
processor.process(clazz);
@@ -523,7 +512,7 @@
if (isCompanionClassType(holder)) {
holder = getInterfaceClassType(holder);
}
- DexClass clazz = appInfo().definitionFor(holder);
+ DexClass clazz = appView.definitionFor(holder);
return clazz == null ? Origin.unknown() : clazz.getOrigin();
}
@@ -545,7 +534,7 @@
DexClass implementing,
DexType iface) {
DefaultMethodsHelper helper = new DefaultMethodsHelper();
- DexClass definedInterface = appInfo().definitionFor(iface);
+ DexClass definedInterface = appView.definitionFor(iface);
if (definedInterface == null) {
warnMissingInterface(classToDesugar, implementing, iface);
return helper.wrapInCollection();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 9bd7b9d..c89019c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -51,14 +51,13 @@
// Also moves static interface methods into a companion class.
final class InterfaceProcessor {
- private final AppView<? extends AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfo> appView;
private final InterfaceMethodRewriter rewriter;
// All created companion and dispatch classes indexed by interface type.
final Map<DexType, DexProgramClass> syntheticClasses = new IdentityHashMap<>();
- InterfaceProcessor(
- AppView<? extends AppInfoWithLiveness> appView, InterfaceMethodRewriter rewriter) {
+ InterfaceProcessor(AppView<? extends AppInfo> appView, InterfaceMethodRewriter rewriter) {
this.appView = appView;
this.rewriter = rewriter;
}
@@ -308,11 +307,12 @@
// methods. Bridge methods that does not override an implementation in a super-interface must
// also be kept (such a situation can happen if the vertical class merger merges two interfaces).
private boolean interfaceMethodRemovalChangesApi(DexEncodedMethod method, DexClass iface) {
- if (appView != null && appView.appInfo().isPinned(method.method)) {
- return true;
+ if (appView.enableWholeProgramOptimizations()) {
+ AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
+ if (appInfoWithLiveness.isPinned(method.method)) {
+ return true;
+ }
}
- AppInfo appInfo = rewriter.appInfo();
- assert appView == null || appInfo == appView.appInfo();
if (method.accessFlags.isBridge()) {
Deque<DexType> worklist = new ArrayDeque<>();
Set<DexType> seenBefore = new HashSet<>();
@@ -325,7 +325,7 @@
if (!seenBefore.add(superType)) {
continue;
}
- DexClass clazz = appInfo.definitionFor(superType);
+ DexClass clazz = appView.definitionFor(superType);
if (clazz != null) {
if (clazz.lookupVirtualMethod(method.method) != null) {
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
index 50a2450..9b096a2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication.Builder;
@@ -46,15 +47,18 @@
public static final String UTILITY_CLASS_NAME_PREFIX = "$r8$java8methods$utility";
private static final String UTILITY_CLASS_DESCRIPTOR_PREFIX = "L$r8$java8methods$utility";
private final Set<DexType> holders = Sets.newConcurrentHashSet();
+
+ private final AppView<? extends AppInfo> appView;
private final IRConverter converter;
private final DexItemFactory factory;
private final RewritableMethods rewritableMethods;
private Map<DexMethod, MethodGenerator> methodGenerators = new ConcurrentHashMap<>();
- public Java8MethodRewriter(IRConverter converter) {
+ public Java8MethodRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
+ this.appView = appView;
this.converter = converter;
- this.factory = converter.appInfo().dexItemFactory;
+ this.factory = appView.dexItemFactory();
this.rewritableMethods = new RewritableMethods(factory);
}
@@ -99,7 +103,7 @@
return;
}
Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
- AppInfo appInfo = converter.appInfo();
+ AppInfo appInfo = appView.appInfo();
for (DexType holder : holders) {
DexClass definitionFor = appInfo.definitionFor(holder);
if (definitionFor == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 091ec9f..1bb56ea 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -95,7 +95,7 @@
: factory.createField(lambdaClassType, lambdaClassType, rewriter.instanceFieldName);
// We have to register this new class as a subtype of object.
- rewriter.converter.appInfo().registerNewType(type, factory.objectType);
+ rewriter.converter.appView.appInfo().registerNewType(type, factory.objectType);
}
// Generate unique lambda class type for lambda descriptor and instantiation point context.
@@ -153,7 +153,7 @@
synthesizeVirtualMethods(mainMethod),
rewriter.factory.getSkipNameValidationForTesting());
// Optimize main method.
- rewriter.converter.appInfo().addSynthesizedClass(clazz);
+ rewriter.converter.appView.appInfo().addSynthesizedClass(clazz);
rewriter.converter.optimizeSynthesizedMethod(clazz.lookupVirtualMethod(mainMethod));
// The method addSynthesizedFrom() may be called concurrently. To avoid a Concurrent-
@@ -348,7 +348,7 @@
// If the lambda$ method is an instance-private method on an interface we convert it into a
// public static method as it will be placed on the companion class.
if (implHandle.type.isInvokeDirect()
- && rewriter.converter.appInfo().definitionFor(implMethod.holder).isInterface()) {
+ && rewriter.converter.appView.definitionFor(implMethod.holder).isInterface()) {
DexProto implProto = implMethod.proto;
DexType[] implParams = implProto.parameters.values;
DexType[] newParams = new DexType[implParams.length + 1];
@@ -470,11 +470,11 @@
abstract boolean ensureAccessibility();
DexClass definitionFor(DexType type) {
- return rewriter.converter.appInfo().app.definitionFor(type);
+ return rewriter.converter.appView.appInfo().app.definitionFor(type);
}
DexProgramClass programDefinitionFor(DexType type) {
- return rewriter.converter.appInfo().app.programDefinitionFor(type);
+ return rewriter.converter.appView.appInfo().app.programDefinitionFor(type);
}
}
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 acd199a..92d7a9d 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
@@ -6,6 +6,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -53,6 +54,7 @@
static final String EXPECTED_LAMBDA_METHOD_PREFIX = "lambda$";
static final String LAMBDA_INSTANCE_FIELD_NAME = "INSTANCE";
+ private final AppView<? extends AppInfo> appView;
final IRConverter converter;
final DexItemFactory factory;
@@ -80,10 +82,11 @@
return clazz.getName().startsWith(LAMBDA_CLASS_NAME_PREFIX);
}
- public LambdaRewriter(IRConverter converter) {
+ public LambdaRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
assert converter != null;
+ this.appView = appView;
this.converter = converter;
- this.factory = converter.appInfo().dexItemFactory;
+ this.factory = appView.dexItemFactory();
this.constructorName = factory.createString(Constants.INSTANCE_INITIALIZER_NAME);
DexProto initProto = factory.createProto(factory.voidType);
@@ -135,7 +138,7 @@
for (int i = 0; i < methodCount; i++) {
DexEncodedMethod encoded = directMethods.get(i);
DexMethod method = encoded.method;
- if (method.isLambdaDeserializeMethod(converter.appInfo().dexItemFactory)) {
+ if (method.isLambdaDeserializeMethod(appView.dexItemFactory())) {
assert encoded.accessFlags.isStatic();
assert encoded.accessFlags.isSynthetic();
clazz.removeDirectMethod(i);
@@ -161,9 +164,9 @@
// This call may cause methodMapping to be updated.
lambdaClass.target.ensureAccessibility();
}
- if (converter.enableWholeProgramOptimizations && !methodMapping.isEmpty()) {
- converter.appView.setGraphLense(
- new LambdaRewriterGraphLense(methodMapping, converter.appView.graphLense(), factory));
+ if (appView.enableWholeProgramOptimizations() && !methodMapping.isEmpty()) {
+ appView.setGraphLense(
+ new LambdaRewriterGraphLense(methodMapping, appView.graphLense(), factory));
}
}
@@ -179,7 +182,7 @@
/** Generates lambda classes and adds them to the builder. */
public void synthesizeLambdaClasses(Builder<?> builder, ExecutorService executorService)
throws ExecutionException {
- AppInfo appInfo = converter.appInfo();
+ AppInfo appInfo = appView.appInfo();
for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
DexProgramClass synthesizedClass = lambdaClass.getLambdaClass();
appInfo.addSynthesizedClass(synthesizedClass);
@@ -210,11 +213,11 @@
return descriptor != null
? descriptor
: putIfAbsent(
- knownCallSites, callSite, LambdaDescriptor.infer(callSite, this.converter.appInfo()));
+ knownCallSites, callSite, LambdaDescriptor.infer(callSite, appView.appInfo()));
}
private boolean isInMainDexList(DexType type) {
- return converter.appInfo().isInMainDexList(type);
+ return appView.appInfo().isInMainDexList(type);
}
// Returns a lambda class corresponding to the lambda descriptor and context,
@@ -227,8 +230,7 @@
lambdaClass = putIfAbsent(knownLambdaClasses, lambdaClassType,
new LambdaClass(this, accessedFrom, lambdaClassType, descriptor));
}
- lambdaClass.addSynthesizedFrom(
- converter.appInfo().definitionFor(accessedFrom).asProgramClass());
+ lambdaClass.addSynthesizedFrom(appView.definitionFor(accessedFrom).asProgramClass());
if (isInMainDexList(accessedFrom)) {
lambdaClass.addToMainDexList.set(true);
}
@@ -272,7 +274,7 @@
lambdaInstanceValue =
code.createValue(
TypeLatticeElement.fromDexType(
- lambdaClass.type, Nullability.maybeNull(), converter.appInfo()));
+ lambdaClass.type, Nullability.maybeNull(), appView.appInfo()));
}
// For stateless lambdas we replace InvokeCustom instruction with StaticGet
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index 8bad12a..4e7636c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -47,7 +48,7 @@
private static final String TO_STRING = "toString";
private static final String APPEND = "append";
- private final AppInfo appInfo;
+ private final AppView<? extends AppInfo> appView;
private final DexItemFactory factory;
private final DexMethod makeConcat;
@@ -59,10 +60,9 @@
private final Map<DexType, DexMethod> paramTypeToAppendMethod = new IdentityHashMap<>();
private final DexMethod defaultAppendMethod;
- public StringConcatRewriter(AppInfo appInfo) {
- this.appInfo = appInfo;
- assert appInfo.dexItemFactory != null;
- this.factory = appInfo.dexItemFactory;
+ public StringConcatRewriter(AppView<? extends AppInfo> appView) {
+ this.appView = appView;
+ this.factory = appView.dexItemFactory();
DexType factoryType = factory.createType(CONCAT_FACTORY_TYPE_DESCR);
DexType callSiteType = factory.createType(CALLSITE_TYPE_DESCR);
@@ -165,7 +165,7 @@
}
// Collect chunks.
- ConcatBuilder builder = new ConcatBuilder(appInfo, code, blocks, instructions);
+ ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
for (int i = 0; i < paramCount; i++) {
builder.addChunk(arguments.get(i),
paramTypeToAppendMethod.getOrDefault(parameters[i], defaultAppendMethod));
@@ -220,7 +220,7 @@
String recipe = ((DexValue.DexValueString) recipeValue).getValue().toString();
// Collect chunks and patch the instruction.
- ConcatBuilder builder = new ConcatBuilder(appInfo, code, blocks, instructions);
+ ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
StringBuilder acc = new StringBuilder();
int argIndex = 0;
int constArgIndex = 0;
@@ -282,7 +282,7 @@
}
private final class ConcatBuilder {
- private final AppInfo appInfo;
+ private final AppView<? extends AppInfo> appView;
private final IRCode code;
private final ListIterator<BasicBlock> blocks;
private final InstructionListIterator instructions;
@@ -291,11 +291,11 @@
private final List<Chunk> chunks = new ArrayList<>();
private ConcatBuilder(
- AppInfo appInfo,
+ AppView<? extends AppInfo> appView,
IRCode code,
ListIterator<BasicBlock> blocks,
InstructionListIterator instructions) {
- this.appInfo = appInfo;
+ this.appView = appView;
this.code = code;
this.blocks = blocks;
this.instructions = instructions;
@@ -341,7 +341,7 @@
// new-instance v0, StringBuilder
TypeLatticeElement stringBuilderTypeLattice =
TypeLatticeElement.fromDexType(
- factory.stringBuilderType, definitelyNotNull(), appInfo);
+ factory.stringBuilderType, definitelyNotNull(), appView.appInfo());
Value sbInstance = code.createValue(stringBuilderTypeLattice);
appendInstruction(new NewInstance(factory.stringBuilderType, sbInstance));
@@ -364,7 +364,8 @@
if (concatValue == null) {
// The out value might be empty in case it was optimized out.
concatValue =
- code.createValue(TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()));
+ code.createValue(
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()));
}
// Replace the instruction.
@@ -443,10 +444,13 @@
@Override
Value getOrCreateValue() {
Value value =
- code.createValue(TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()));
- ThrowingInfo throwingInfo =
- code.options.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
- appendInstruction(new ConstString(value, factory.createString(str), throwingInfo));
+ code.createValue(
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()));
+ appendInstruction(
+ new ConstString(
+ value,
+ factory.createString(str),
+ ThrowingInfo.defaultForConstString(appView.options())));
return value;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
index 7fd815e..f8ebb06 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication.Builder;
@@ -51,6 +52,7 @@
public static final String UTILITY_CLASS_NAME = "$r8$twr$utility";
public static final String UTILITY_CLASS_DESCRIPTOR = "L$r8$twr$utility;";
+ private final AppView<? extends AppInfo> appView;
private final IRConverter converter;
private final DexItemFactory factory;
@@ -58,9 +60,10 @@
private final Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
- public TwrCloseResourceRewriter(IRConverter converter) {
+ public TwrCloseResourceRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
+ this.appView = appView;
this.converter = converter;
- this.factory = converter.appInfo().dexItemFactory;
+ this.factory = appView.dexItemFactory();
DexType twrUtilityClass = factory.createType(UTILITY_CLASS_DESCRIPTOR);
DexProto twrCloseResourceProto = factory.createProto(
@@ -72,14 +75,14 @@
// Rewrites calls to $closeResource() method. Can be invoked concurrently.
public void rewriteMethodCode(IRCode code) {
InstructionIterator iterator = code.instructionIterator();
- AppInfo appInfo = converter.appInfo();
+ AppInfo appInfo = appView.appInfo();
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
if (!instruction.isInvokeStatic()) {
continue;
}
InvokeStatic invoke = instruction.asInvokeStatic();
- if (!isSynthesizedCloseResourceMethod(invoke.getInvokedMethod(), converter)) {
+ if (!isSynthesizedCloseResourceMethod(invoke.getInvokedMethod(), appView)) {
continue;
}
@@ -95,8 +98,9 @@
}
}
- public static boolean isSynthesizedCloseResourceMethod(DexMethod method, IRConverter converter) {
- DexMethod original = converter.graphLense().getOriginalMethodSignature(method);
+ public static boolean isSynthesizedCloseResourceMethod(
+ DexMethod method, AppView<? extends AppInfo> appView) {
+ DexMethod original = appView.graphLense().getOriginalMethodSignature(method);
assert original != null;
// We consider all methods of *any* class with expected name and signature
// to be synthesized by java 9 compiler for try-with-resources, reasoning:
@@ -107,7 +111,7 @@
// right attributes, but it still does not guarantee much since we also
// need to look into code and doing this seems an overkill
//
- DexItemFactory dexItemFactory = converter.appInfo().dexItemFactory;
+ DexItemFactory dexItemFactory = appView.appInfo().dexItemFactory;
return original.name == dexItemFactory.twrCloseResourceMethodName
&& original.proto == dexItemFactory.twrCloseResourceMethodProto;
}
@@ -149,7 +153,7 @@
code.setUpContext(utilityClass);
// Process created class and method.
- AppInfo appInfo = converter.appInfo();
+ AppInfo appInfo = appView.appInfo();
boolean addToMainDexList =
referencingClasses.stream().anyMatch(clazz -> appInfo.isInMainDexList(clazz.type));
appInfo.addSynthesizedClass(utilityClass);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index bebf225..29b6aa7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -49,7 +49,6 @@
import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.Action;
-import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IteratorUtils;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -92,28 +91,17 @@
}
}
- private final AppInfo appInfo;
private final AppView<? extends AppInfo> appView;
private final IRConverter converter;
private final DexItemFactory dexItemFactory;
- private final InternalOptions options;
private WaveDoneAction waveDoneAction = null;
public ClassInitializerDefaultsOptimization(
- AppInfo appInfo,
- AppView<? extends AppInfo> appView,
- IRConverter converter,
- InternalOptions options) {
- this.appInfo = appInfo;
+ AppView<? extends AppInfo> appView, IRConverter converter) {
this.appView = appView;
this.converter = converter;
- this.dexItemFactory = appInfo.dexItemFactory;
- this.options = options;
- }
-
- public AppInfo appInfo() {
- return appView != null ? appView.appInfo() : appInfo;
+ this.dexItemFactory = appView.dexItemFactory();
}
public void optimize(DexEncodedMethod method, IRCode code) {
@@ -121,7 +109,7 @@
return;
}
- DexClass clazz = appInfo().definitionFor(method.method.holder);
+ DexClass clazz = appView.definitionFor(method.method.holder);
if (clazz == null) {
return;
}
@@ -142,7 +130,7 @@
// Set initial values for static fields from the definitive static put instructions collected.
for (StaticPut put : finalFieldPuts) {
- DexEncodedField field = appInfo().resolveField(put.getField());
+ DexEncodedField field = appView.appInfo().resolveField(put.getField());
DexType fieldType = field.field.type;
Value inValue = put.inValue();
if (fieldType == dexItemFactory.stringType) {
@@ -216,14 +204,14 @@
// that the field is no longer written.
if (appView != null && appView.enableWholeProgramOptimizations() && converter.isInWave()) {
if (appView.appInfo().hasLiveness()) {
- AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+ AppView<? extends AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
// First collect all the candidate fields that are *potentially* no longer being written to.
Set<DexField> candidates =
finalFieldPuts.stream()
.map(FieldInstruction::getField)
- .map(field -> appInfo().resolveField(field).field)
+ .map(field -> appInfoWithLiveness.resolveField(field).field)
.filter(appInfoWithLiveness::isStaticFieldWrittenOnlyInEnclosingStaticInitializer)
.collect(Collectors.toSet());
@@ -286,13 +274,13 @@
}
private DexValue getDexStringValueForInvoke(DexMethod invokedMethod, DexType holder) {
- DexClass clazz = appInfo().definitionFor(holder);
+ DexClass clazz = appView.definitionFor(holder);
if (clazz == null) {
assert false;
return null;
}
- if (options.enableMinification && !converter.rootSet.noObfuscation.contains(holder)) {
+ if (appView.options().enableMinification && !converter.rootSet.noObfuscation.contains(holder)) {
if (invokedMethod == dexItemFactory.classMethods.getName) {
return new DexItemBasedValueString(holder, new ClassNameComputationInfo(NAME));
}
@@ -341,10 +329,10 @@
Instruction instruction = it.next();
if (instruction.isStaticGet()) {
StaticGet get = instruction.asStaticGet();
- DexEncodedField field = appInfo().resolveField(get.getField());
+ DexEncodedField field = appView.appInfo().resolveField(get.getField());
if (field != null && field.field.clazz == clazz.type) {
isReadBefore.add(field.field);
- } else if (instruction.instructionMayHaveSideEffects(appInfo(), appView, clazz.type)) {
+ } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
// Reading another field is only OK if the read does not have side-effects.
return finalFieldPut.values();
}
@@ -384,7 +372,7 @@
// Writing another field is not OK.
return finalFieldPut.values();
}
- } else if (instruction.instructionMayHaveSideEffects(appInfo(), appView, clazz.type)) {
+ } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
// Some other instruction that has side-effects. Stop here.
return finalFieldPut.values();
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 86bae46..304c86d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexClass;
@@ -153,21 +152,20 @@
private static final int SELF_RECURSION_LIMIT = 4;
public final IRConverter converter;
- private final AppInfo appInfo;
+
private final AppView<? extends AppInfo> appView;
private final DexItemFactory dexItemFactory;
private final Set<DexMethod> libraryMethodsReturningReceiver;
private final InternalOptions options;
public CodeRewriter(
+ AppView<? extends AppInfo> appView,
IRConverter converter,
- Set<DexMethod> libraryMethodsReturningReceiver,
- InternalOptions options) {
+ Set<DexMethod> libraryMethodsReturningReceiver) {
+ this.appView = appView;
this.converter = converter;
- this.appInfo = converter.appInfo();
- this.appView = converter.appView;
- this.options = options;
- this.dexItemFactory = appInfo.dexItemFactory;
+ this.options = appView.options();
+ this.dexItemFactory = appView.dexItemFactory();
this.libraryMethodsReturningReceiver = libraryMethodsReturningReceiver;
}
@@ -884,8 +882,8 @@
// Pattern match a switch on a switch map as input.
if (insn.isSwitch()) {
Switch switchInsn = insn.asSwitch();
- EnumSwitchInfo info = SwitchUtils
- .analyzeSwitchOverEnum(switchInsn, appInfo.withLiveness());
+ EnumSwitchInfo info =
+ SwitchUtils.analyzeSwitchOverEnum(switchInsn, appView.withLiveness());
if (info != null) {
Int2IntMap targetMap = new Int2IntArrayMap();
IntList keys = new IntArrayList(switchInsn.numberOfKeys());
@@ -1018,7 +1016,7 @@
public void identifyInvokeSemanticsForInlining(
DexEncodedMethod method,
IRCode code,
- AppView<? extends AppInfoWithSubtyping> appView,
+ AppView<? extends AppInfo> appView,
OptimizationFeedback feedback) {
if (method.isStatic()) {
// Identifies if the method preserves class initialization after inlining.
@@ -1058,7 +1056,7 @@
return;
}
- DexClass clazz = appInfo.definitionFor(method.method.holder);
+ DexClass clazz = appView.definitionFor(method.method.holder);
if (clazz == null) {
return;
}
@@ -1129,6 +1127,7 @@
return;
}
+ AppInfo appInfo = appView.appInfo();
DexClass clazz = appInfo.definitionFor(method.method.holder);
if (clazz == null) {
return;
@@ -1364,7 +1363,7 @@
* <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
*/
public static boolean checksNullBeforeSideEffect(
- IRCode code, Value value, AppView<? extends AppInfoWithSubtyping> appView) {
+ IRCode code, Value value, AppView<? extends AppInfo> appView) {
return alwaysTriggerExpectedEffectBeforeAnythingElse(
code,
(instr, it) -> {
@@ -1412,8 +1411,7 @@
// We found a NPE check on the value.
return InstructionEffect.DESIRED_EFFECT;
}
- } else if (instr.instructionMayHaveSideEffects(
- appView.appInfo(), appView, code.method.method.holder)) {
+ } else if (instr.instructionMayHaveSideEffects(appView, code.method.method.holder)) {
// If the current instruction is const-string, this could load the parameter name.
// Just make sure it is indeed not throwing.
if (instr.isConstString() && !instr.instructionInstanceCanThrow()) {
@@ -1430,7 +1428,7 @@
// declare a method called checkParameterIsNotNull(parameter, message) or
// throwParameterIsNullException(parameterName) in a package that starts with "kotlin".
private static boolean isKotlinNullCheck(
- Instruction instr, Value value, AppView<? extends AppInfoWithSubtyping> appView) {
+ Instruction instr, Value value, AppView<? extends AppInfo> appView) {
if (!instr.isInvokeStatic()) {
return false;
}
@@ -1485,7 +1483,7 @@
* <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
*/
private static boolean triggersClassInitializationBeforeSideEffect(
- DexType clazz, IRCode code, AppView<? extends AppInfoWithSubtyping> appView) {
+ DexType clazz, IRCode code, AppView<? extends AppInfo> appView) {
return alwaysTriggerExpectedEffectBeforeAnythingElse(
code,
(instruction, it) -> {
@@ -1500,7 +1498,7 @@
// We found an instruction that preserves initialization of the class.
return InstructionEffect.DESIRED_EFFECT;
}
- } else if (instruction.instructionMayHaveSideEffects(appView.appInfo(), appView, clazz)) {
+ } else if (instruction.instructionMayHaveSideEffects(appView, clazz)) {
// We found a side effect before class initialization.
return InstructionEffect.OTHER_EFFECT;
}
@@ -1581,17 +1579,16 @@
private boolean checkArgumentType(InvokeMethod invoke, int argumentIndex) {
// TODO(sgjesse): Insert cast if required.
+ AppInfo appInfo = appView.appInfo();
TypeLatticeElement returnType =
TypeLatticeElement.fromDexType(
invoke.getInvokedMethod().proto.returnType, maybeNull(), appInfo);
TypeLatticeElement argumentType =
TypeLatticeElement.fromDexType(
getArgumentType(invoke, argumentIndex), maybeNull(), appInfo);
- if (appView != null && appView.enableWholeProgramOptimizations()) {
- return argumentType.lessThanOrEqual(returnType, appInfo);
- } else {
- return argumentType.equals(returnType);
- }
+ return appView.enableWholeProgramOptimizations()
+ ? argumentType.lessThanOrEqual(returnType, appInfo)
+ : argumentType.equals(returnType);
}
private DexType getArgumentType(InvokeMethod invoke, int argumentIndex) {
@@ -1609,6 +1606,7 @@
if (options.isGeneratingClassFiles()) {
return;
}
+ AppInfo appInfo = appView.appInfo();
AppInfoWithLiveness appInfoWithLiveness = appInfo.withLiveness();
Set<Value> needToWidenValues = Sets.newIdentityHashSet();
Set<Value> needToNarrowValues = Sets.newIdentityHashSet();
@@ -1877,6 +1875,7 @@
// Returns true if the given check-cast instruction was removed.
private boolean removeCheckCastInstructionIfTrivial(
CheckCast checkCast, InstructionIterator it, IRCode code) {
+ AppInfo appInfo = appView.appInfo();
Value inValue = checkCast.object();
Value outValue = checkCast.outValue();
DexType castType = checkCast.getType();
@@ -1901,7 +1900,7 @@
// We might see chains of casts on subtypes. It suffices to cast to the lowest subtype,
// as that will fail if a cast on a supertype would have failed.
Predicate<Instruction> isCheckcastToSubtype =
- user -> user.isCheckCast() && user.asCheckCast().getType().isSubtypeOf(castType, appInfo);
+ user -> user.isCheckCast() && user.asCheckCast().getType().isSubtypeOf(castType, appView);
if (!checkCast.getBlock().hasCatchHandlers()
&& outValue.isUsed()
&& outValue.numberOfPhiUsers() == 0
@@ -1941,6 +1940,7 @@
}
private boolean isTypeInaccessibleInCurrentContext(DexType type, DexEncodedMethod context) {
+ AppInfo appInfo = appView.appInfo();
DexType baseType = type.toBaseType(appInfo.dexItemFactory);
if (baseType.isPrimitiveType()) {
return false;
@@ -1965,6 +1965,7 @@
return false;
}
+ AppInfo appInfo = appView.appInfo();
Value inValue = instanceOf.value();
TypeLatticeElement inType = inValue.getTypeLattice();
TypeLatticeElement instanceOfType =
@@ -2013,6 +2014,7 @@
}
private boolean isNeverInstantiatedDirectlyOrIndirectly(DexType type) {
+ AppInfo appInfo = appView.appInfo();
assert appInfo.hasLiveness();
assert type.isClassType();
DexClass clazz = appInfo.definitionFor(type);
@@ -2929,7 +2931,7 @@
}
Set<Value> affectedValues = code.removeUnreachableBlocks();
if (!affectedValues.isEmpty()) {
- new TypeAnalysis(appInfo, code.method).narrowing(affectedValues);
+ new TypeAnalysis(appView.appInfo(), code.method).narrowing(affectedValues);
}
assert code.isConsistentSSA();
}
@@ -3130,7 +3132,7 @@
}
if (dominatorTree.get().dominatedBy(block, dominator)) {
- if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appInfo)) {
+ if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appView.appInfo())) {
value.replaceUsers(newValue);
block.listIterator(constNumber).removeOrReplaceByDebugLocalRead();
constantWithValueIterator.remove();
@@ -3154,7 +3156,7 @@
// null value (which should result in NPE). Note that this throw is not
// expected to be ever reached, but is intended to satisfy verifier.
public void processMethodsNeverReturningNormally(IRCode code) {
- AppInfoWithLiveness appInfoWithLiveness = appInfo.withLiveness();
+ AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
if (appInfoWithLiveness == null) {
return;
}
@@ -3623,7 +3625,7 @@
if (type == dexItemFactory.throwableType) {
return true;
}
- DexClass dexClass = appInfo.definitionFor(type);
+ DexClass dexClass = appView.definitionFor(type);
if (dexClass == null) {
throw new CompilationError("Class or interface " + type.toSourceString() +
" required for desugaring of try-with-resources is not found.");
@@ -3635,7 +3637,7 @@
private Value addConstString(IRCode code, InstructionListIterator iterator, String s) {
TypeLatticeElement typeLattice =
- TypeLatticeElement.stringClassType(appInfo, definitelyNotNull());
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull());
Value value = code.createValue(typeLattice);
ThrowingInfo throwingInfo =
options.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
@@ -3667,8 +3669,10 @@
assert !block.hasCatchHandlers();
DexType javaLangSystemType = dexItemFactory.createType("Ljava/lang/System;");
DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
- Value out = code.createValue(
- TypeLatticeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appInfo));
+ Value out =
+ code.createValue(
+ TypeLatticeElement.fromDexType(
+ javaIoPrintStreamType, definitelyNotNull(), appView.appInfo()));
DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
DexMethod print = dexItemFactory.createMethod(javaIoPrintStreamType, proto, "print");
@@ -3733,7 +3737,9 @@
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, nul)));
iterator = isNotNullBlock.listIterator();
iterator.setInsertionPosition(position);
- value = code.createValue(TypeLatticeElement.classClassType(appInfo, definitelyNotNull()));
+ value =
+ code.createValue(
+ TypeLatticeElement.classClassType(appView.appInfo(), definitelyNotNull()));
iterator.add(new InvokeVirtual(dexItemFactory.objectMethods.getClass, value,
ImmutableList.of(arguments.get(i))));
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 9c8168e..04227ac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -16,7 +16,6 @@
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
-import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.Iterator;
@@ -25,27 +24,12 @@
public class DeadCodeRemover {
- private final AppView<? extends AppInfoWithLiveness> appView;
- private final AppInfo appInfo;
+ private final AppView<? extends AppInfo> appView;
private final CodeRewriter codeRewriter;
- private final InternalOptions options;
- private final boolean enableWholeProgramOptimizations;
- public DeadCodeRemover(
- AppView<? extends AppInfoWithLiveness> appView,
- AppInfo appInfo,
- CodeRewriter codeRewriter,
- InternalOptions options) {
+ public DeadCodeRemover(AppView<? extends AppInfo> appView, CodeRewriter codeRewriter) {
this.appView = appView;
- this.appInfo = appInfo;
this.codeRewriter = codeRewriter;
- this.options = options;
- this.enableWholeProgramOptimizations =
- appView != null && appView.enableWholeProgramOptimizations();
- }
-
- public AppInfo appInfo() {
- return appView != null ? appView.appInfo() : appInfo;
}
public void run(IRCode code) {
@@ -92,7 +76,7 @@
Iterator<Phi> phiIt = block.getPhis().iterator();
while (phiIt.hasNext()) {
Phi phi = phiIt.next();
- if (phi.isDead(appView, appInfo(), code)) {
+ if (phi.isDead(appView, code)) {
phiIt.remove();
for (Value operand : phi.getOperands()) {
operand.removePhiUser(phi);
@@ -112,11 +96,11 @@
&& !current.outValue().isUsed()) {
current.setOutValue(null);
}
- if (!current.canBeDeadCode(appView, appInfo(), code)) {
+ if (!current.canBeDeadCode(appView, code)) {
continue;
}
Value outValue = current.outValue();
- if (outValue != null && !outValue.isDead(appView, appInfo(), code)) {
+ if (outValue != null && !outValue.isDead(appView, code)) {
continue;
}
updateWorklist(worklist, current);
@@ -134,7 +118,7 @@
for (BasicBlock block : code.blocks) {
if (block.hasCatchHandlers()) {
if (block.canThrow()) {
- if (enableWholeProgramOptimizations) {
+ if (appView.enableWholeProgramOptimizations()) {
Collection<CatchHandler<BasicBlock>> deadCatchHandlers = getDeadCatchHandlers(block);
if (!deadCatchHandlers.isEmpty()) {
for (CatchHandler<BasicBlock> catchHandler : deadCatchHandlers) {
@@ -163,7 +147,7 @@
* Returns the catch handlers of the given block that are dead, if any.
*/
private Collection<CatchHandler<BasicBlock>> getDeadCatchHandlers(BasicBlock block) {
- AppInfoWithLiveness appInfoWithLiveness = appInfo().withLiveness();
+ AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
ImmutableList.Builder<CatchHandler<BasicBlock>> builder = ImmutableList.builder();
CatchHandlers<BasicBlock> catchHandlers = block.getCatchHandlers();
for (int i = 0; i < catchHandlers.size(); ++i) {
@@ -175,7 +159,7 @@
boolean isSubsumedByPreviousGuard = false;
for (int j = 0; j < i; ++j) {
DexType previousGuard = catchHandlers.getGuards().get(j);
- if (guard.isSubtypeOf(previousGuard, appInfo())) {
+ if (guard.isSubtypeOf(previousGuard, appView)) {
isSubsumedByPreviousGuard = true;
break;
}
@@ -187,8 +171,8 @@
// We can exploit that a catch handler must be dead if its guard is never instantiated
// directly or indirectly.
- if (appInfoWithLiveness != null && options.enableUninstantiatedTypeOptimization) {
- DexClass clazz = appInfo().definitionFor(guard);
+ if (appInfoWithLiveness != null && appView.options().enableUninstantiatedTypeOptimization) {
+ DexClass clazz = appView.definitionFor(guard);
if (clazz != null
&& clazz.isProgramClass()
&& !appInfoWithLiveness.isInstantiatedDirectlyOrIndirectly(guard)) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 93c8add..019c3ac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -78,7 +78,7 @@
invoke.lookupSingleTarget(inliner.appView.appInfo(), invocationContext);
if ((candidate == null)
|| (candidate.getCode() == null)
- || inliner.appView.appInfo().definitionFor(candidate.method.getHolder()).isLibraryClass()) {
+ || inliner.appView.definitionFor(candidate.method.getHolder()).isLibraryClass()) {
if (info != null) {
info.exclude(invoke, "No inlinee");
}
@@ -132,7 +132,7 @@
if (method.method.holder.isSubtypeOf(targetHolder, appView.appInfo())) {
return true;
}
- DexClass clazz = inliner.appView.appInfo().definitionFor(targetHolder);
+ DexClass clazz = inliner.appView.definitionFor(targetHolder);
assert clazz != null;
if (target.getOptimizationInfo().triggersClassInitBeforeAnySideEffect()) {
return true;
@@ -198,7 +198,7 @@
return false;
}
- DexClass holder = inliner.appView.appInfo().definitionFor(candidate.method.getHolder());
+ DexClass holder = inliner.appView.definitionFor(candidate.method.getHolder());
if (holder.isInterface()) {
// Art978_virtual_interfaceTest correctly expects an IncompatibleClassChangeError exception at
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index b045d44..930ac78 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -113,7 +113,7 @@
continue;
}
DexType holderType = target.method.getHolder();
- DexClass holderClass = appView.appInfo().definitionFor(holderType);
+ DexClass holderClass = appView.definitionFor(holderType);
// Make sure we are not landing on another interface, e.g., interface's default method.
if (holderClass == null || holderClass.isInterface()) {
continue;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
index 8c8f428..fd387a3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
@@ -37,10 +37,10 @@
private final Map<DexType, Reference2IntMap<DexField>> ordinalsMaps = new IdentityHashMap<>();
- public EnumOrdinalMapCollector(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+ public EnumOrdinalMapCollector(AppView<? extends AppInfoWithLiveness> appView) {
this.appInfo = appView.appInfo();
this.graphLense = appView.graphLense();
- this.options = options;
+ this.options = appView.options();
}
public AppInfoWithLiveness run() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index aa42b7b..299181e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -81,7 +81,7 @@
public boolean isBlackListed(DexMethod method) {
return blackList.contains(appView.graphLense().getOriginalMethodSignature(method))
|| appView.appInfo().neverInline.contains(method)
- || TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, converter);
+ || TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, appView);
}
private ConstraintWithTarget instructionAllowedForInlining(
@@ -117,7 +117,7 @@
return false;
}
// The class needs also to be visible for us to have access.
- DexClass targetClass = appView.appInfo().definitionFor(target.method.holder);
+ DexClass targetClass = appView.definitionFor(target.method.holder);
return isVisibleWithFlags(target.method.holder, method.method.holder, targetClass.accessFlags);
}
@@ -438,7 +438,7 @@
callerPosition,
origin);
if (!target.isProcessed()) {
- new LensCodeRewriter(appView, options).rewrite(code, target);
+ new LensCodeRewriter(appView).rewrite(code, target);
}
return new InlineeWithReason(code, reason);
}
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 5f2e41c..002461f 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
@@ -295,7 +295,7 @@
// be updated outside the class constructor, e.g. via reflections), it is safe
// to assume that the static-get instruction reads the value it initialized value
// in class initializer and is never null.
- DexClass holderDefinition = appView.appInfo().definitionFor(field.getHolder());
+ DexClass holderDefinition = appView.definitionFor(field.getHolder());
if (holderDefinition != null
&& holderDefinition.accessFlags.isFinal()
&& !field.getHolder().initializationOfParentTypesMayHaveSideEffects(appView.appInfo())) {
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 a620ea9..47284cc 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
@@ -70,10 +70,10 @@
private final Map<DexField, Int2ReferenceMap<DexField>> switchMaps = new IdentityHashMap<>();
- public SwitchMapCollector(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+ public SwitchMapCollector(AppView<? extends AppInfoWithLiveness> appView) {
this.appInfo = appView.appInfo();
this.graphLense = appView.graphLense();
- this.options = options;
+ this.options = appView.options();
switchMapPrefix = appInfo.dexItemFactory.createString("$SwitchMap$");
intArrayType = appInfo.dexItemFactory.createType("[I");
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
index 035f3d1..7331b00 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -43,18 +44,22 @@
/**
* Looks for a switch statement over the enum companion class of the form
*
- * <blockquote><pre>
+ * <blockquote>
+ *
+ * <pre>
* switch(CompanionClass.$switchmap$field[enumValue.ordinal()]) {
* ...
* }
- * </pre></blockquote>
+ * </pre>
*
- * and extracts the components and the index and ordinal maps. See
- * {@link EnumOrdinalMapCollector} and
- * {@link SwitchMapCollector} for details.
+ * </blockquote>
+ *
+ * and extracts the components and the index and ordinal maps. See {@link EnumOrdinalMapCollector}
+ * and {@link SwitchMapCollector} for details.
*/
- public static EnumSwitchInfo analyzeSwitchOverEnum(Instruction switchInsn,
- AppInfoWithLiveness appInfo) {
+ public static EnumSwitchInfo analyzeSwitchOverEnum(
+ Instruction switchInsn, AppView<? extends AppInfoWithLiveness> appView) {
+ AppInfoWithLiveness appInfo = appView.appInfo();
Instruction input = switchInsn.inValues().get(0).definition;
if (input == null || !input.isArrayGet()) {
return null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index ff330e1..4daeb9e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -452,7 +452,7 @@
if (isAlwaysNull(fieldType)) {
// Before trying to remove this instruction, we need to be sure that the field actually
// exists. Otherwise this instruction would throw a NoSuchFieldError exception.
- DexEncodedField field = appView.appInfo().definitionFor(instruction.getField());
+ DexEncodedField field = appView.definitionFor(instruction.getField());
if (field == null) {
return;
}
@@ -460,7 +460,7 @@
// We also need to be sure that this field instruction cannot trigger static class
// initialization.
if (field.field.clazz != code.method.method.holder) {
- DexClass enclosingClass = appView.appInfo().definitionFor(code.method.method.holder);
+ DexClass enclosingClass = appView.definitionFor(code.method.method.holder);
if (enclosingClass == null
|| enclosingClass.classInitializationMayHaveSideEffects(appView.appInfo())) {
return;
@@ -608,7 +608,7 @@
private boolean isAlwaysNull(DexType type) {
if (type.isClassType()) {
- DexClass clazz = appView.appInfo().definitionFor(type);
+ DexClass clazz = appView.definitionFor(type);
return clazz != null
&& clazz.isProgramClass()
&& !appView.appInfo().isInstantiatedDirectlyOrIndirectly(type);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
index ad5f3be..96bce47 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
@@ -40,7 +40,7 @@
public class UnusedArgumentsCollector {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfoWithLiveness> appView;
private final BiMap<DexMethod, DexMethod> methodMapping = HashBiMap.create();
private final Map<DexMethod, RemovedArgumentsInfo> removedArguments = new IdentityHashMap<>();
@@ -81,7 +81,7 @@
}
}
- public UnusedArgumentsCollector(AppView<AppInfoWithLiveness> appView) {
+ public UnusedArgumentsCollector(AppView<? extends AppInfoWithLiveness> appView) {
this.appView = appView;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
index 030cd4f..854ac19 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -140,7 +141,7 @@
}
};
- public final AppInfo appInfo;
+ public final AppView<? extends AppInfo> appView;
public final DexItemFactory factory;
public final Kotlin kotlin;
@@ -159,14 +160,14 @@
private InstructionListIterator instructions;
CodeProcessor(
- AppInfo appInfo,
+ AppView<? extends AppInfo> appView,
Function<DexType, Strategy> strategyProvider,
LambdaTypeVisitor lambdaChecker,
- DexEncodedMethod method, IRCode code) {
-
- this.appInfo = appInfo;
+ DexEncodedMethod method,
+ IRCode code) {
+ this.appView = appView;
this.strategyProvider = strategyProvider;
- this.factory = appInfo.dexItemFactory;
+ this.factory = appView.dexItemFactory();
this.kotlin = factory.kotlin;
this.lambdaChecker = lambdaChecker;
this.method = method;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
index f3fecde..b0af387 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -89,11 +90,11 @@
return false;
}
- final boolean shouldAddToMainDex(AppInfo appInfo) {
+ final boolean shouldAddToMainDex(AppView<? extends AppInfo> appView) {
// We add the group class to main index if any of the
// lambda classes it replaces is added to main index.
for (DexType type : lambdas.keySet()) {
- if (appInfo.isInMainDexList(type)) {
+ if (appView.appInfo().isInMainDexList(type)) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 586297d..3538e8c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexClass;
@@ -100,7 +101,7 @@
// should not be happening very frequently and we ignore possible overhead.
private final Set<DexEncodedMethod> methodsToReprocess = Sets.newIdentityHashSet();
- private final AppInfo appInfo;
+ private final AppView<? extends AppInfo> appView;
private final DexItemFactory factory;
private final Kotlin kotlin;
private final DiagnosticsHandler reporter;
@@ -112,11 +113,11 @@
// Lambda visitor throwing Unreachable on each lambdas it sees.
private final LambdaTypeVisitor lambdaChecker;
- public LambdaMerger(AppInfo appInfo, DiagnosticsHandler reporter) {
- this.appInfo = appInfo;
- this.factory = appInfo.dexItemFactory;
+ public LambdaMerger(AppView<? extends AppInfo> appView) {
+ this.appView = appView;
+ this.factory = appView.dexItemFactory();
this.kotlin = factory.kotlin;
- this.reporter = reporter;
+ this.reporter = appView.options().reporter;
this.lambdaInvalidator = new LambdaTypeVisitor(factory, this::isMergeableLambda,
this::invalidateLambda);
@@ -206,13 +207,14 @@
analyzeReferencesInProgramClasses(app, executorService);
// Analyse more complex aspects of lambda classes including method code.
- assert converter.appInfo().hasSubtyping();
- AppInfoWithSubtyping appInfo = converter.appInfo().withSubtyping();
- analyzeLambdaClassesStructure(appInfo, executorService);
+ assert appView.appInfo().hasSubtyping();
+ AppInfoWithSubtyping appInfoWithSubtyping = appView.appInfo().withSubtyping();
+ analyzeLambdaClassesStructure(appInfoWithSubtyping, executorService);
// Remove invalidated lambdas, compact groups to ensure
// sequential lambda ids, create group lambda classes.
- Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses = finalizeLambdaGroups(appInfo);
+ Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses =
+ finalizeLambdaGroups(appInfoWithSubtyping);
// Switch to APPLY strategy.
this.strategyFactory = ApplyStrategy::new;
@@ -221,9 +223,8 @@
for (Entry<LambdaGroup, DexProgramClass> entry : lambdaGroupsClasses.entrySet()) {
DexProgramClass synthesizedClass = entry.getValue();
- converter.appInfo().addSynthesizedClass(synthesizedClass);
- builder.addSynthesizedClass(
- synthesizedClass, entry.getKey().shouldAddToMainDex(converter.appInfo()));
+ appView.appInfo().addSynthesizedClass(synthesizedClass);
+ builder.addSynthesizedClass(synthesizedClass, entry.getKey().shouldAddToMainDex(appView));
// Eventually, we need to process synthesized methods in the lambda group.
// Otherwise, abstract SynthesizedCode will be flown to Enqueuer.
// But that process should not see the holder. Otherwise, lambda calls in the main dispatch
@@ -323,7 +324,7 @@
}
Set<DexEncodedMethod> methods =
methodsToReprocess.stream()
- .map(method -> converter.graphLense().mapDexEncodedMethod(method, converter.appInfo()))
+ .map(method -> converter.graphLense().mapDexEncodedMethod(method, appView.appInfo()))
.collect(Collectors.toSet());
List<Future<?>> futures = new ArrayList<>();
for (DexEncodedMethod method : methods) {
@@ -379,8 +380,12 @@
private final class AnalysisStrategy extends CodeProcessor {
private AnalysisStrategy(DexEncodedMethod method, IRCode code) {
- super(LambdaMerger.this.appInfo,
- LambdaMerger.this::strategyProvider, lambdaInvalidator, method, code);
+ super(
+ LambdaMerger.this.appView,
+ LambdaMerger.this::strategyProvider,
+ lambdaInvalidator,
+ method,
+ code);
}
@Override
@@ -416,8 +421,12 @@
private final class ApplyStrategy extends CodeProcessor {
private ApplyStrategy(DexEncodedMethod method, IRCode code) {
- super(LambdaMerger.this.appInfo,
- LambdaMerger.this::strategyProvider, lambdaChecker, method, code);
+ super(
+ LambdaMerger.this.appView,
+ LambdaMerger.this::strategyProvider,
+ lambdaChecker,
+ method,
+ code);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
index 71fbf44..144487b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
@@ -115,11 +115,12 @@
@Override
public void patch(CodeProcessor context, NewInstance newInstance) {
- NewInstance patchedNewInstance = new NewInstance(
- group.getGroupClassType(),
- context.code.createValue(
- TypeLatticeElement.fromDexType(
- newInstance.clazz, definitelyNotNull(), context.appInfo)));
+ NewInstance patchedNewInstance =
+ new NewInstance(
+ group.getGroupClassType(),
+ context.code.createValue(
+ TypeLatticeElement.fromDexType(
+ newInstance.clazz, definitelyNotNull(), context.appView.appInfo())));
context.instructions().replaceCurrentInstruction(patchedNewInstance);
}
@@ -166,7 +167,7 @@
// Since all captured values of non-primitive types are stored in fields of type
// java.lang.Object, we need to cast them to appropriate type to satisfy the verifier.
TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(fieldType, definitelyNotNull(), context.appInfo);
+ TypeLatticeElement.fromDexType(fieldType, definitelyNotNull(), context.appView.appInfo());
Value newValue = context.code.createValue(castTypeLattice, newInstanceGet.getLocalInfo());
newInstanceGet.outValue().replaceUsers(newValue);
CheckCast cast = new CheckCast(newValue, newInstanceGet.outValue(), fieldType);
@@ -189,11 +190,14 @@
@Override
public void patch(CodeProcessor context, StaticGet staticGet) {
- context.instructions().replaceCurrentInstruction(
- new StaticGet(
- context.code.createValue(
- TypeLatticeElement.fromDexType(staticGet.getField().type, maybeNull(), context.appInfo)),
- mapSingletonInstanceField(context.factory, staticGet.getField())));
+ context
+ .instructions()
+ .replaceCurrentInstruction(
+ new StaticGet(
+ context.code.createValue(
+ TypeLatticeElement.fromDexType(
+ staticGet.getField().type, maybeNull(), context.appView.appInfo())),
+ mapSingletonInstanceField(context.factory, staticGet.getField())));
}
private void patchInitializer(CodeProcessor context, InvokeDirect invoke) {
@@ -225,9 +229,10 @@
}
private Value createValueForType(CodeProcessor context, DexType returnType) {
- return returnType == context.factory.voidType ? null :
- context.code.createValue(
- TypeLatticeElement.fromDexType(returnType, maybeNull(), context.appInfo));
+ return returnType == context.factory.voidType
+ ? null
+ : context.code.createValue(
+ TypeLatticeElement.fromDexType(returnType, maybeNull(), context.appView.appInfo()));
}
private List<Value> mapInitializerArgs(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 443a2f4..d69190f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.ir.optimize.staticizer;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
@@ -43,7 +45,8 @@
import java.util.function.BiConsumer;
public final class ClassStaticizer {
- final AppInfoWithLiveness appInfo;
+
+ final AppView<? extends AppInfoWithLiveness> appView;
final DexItemFactory factory;
final IRConverter converter;
@@ -86,7 +89,7 @@
}
DexClass hostClass() {
- DexClass hostClass = appInfo.definitionFor(hostType());
+ DexClass hostClass = appView.definitionFor(hostType());
assert hostClass != null;
return hostClass;
}
@@ -100,9 +103,9 @@
// The map storing all the potential candidates for staticizing.
final ConcurrentHashMap<DexType, CandidateInfo> candidates = new ConcurrentHashMap<>();
- public ClassStaticizer(AppInfoWithLiveness appInfo, IRConverter converter) {
- this.appInfo = appInfo;
- this.factory = appInfo.dexItemFactory;
+ public ClassStaticizer(AppView<? extends AppInfoWithLiveness> appView, IRConverter converter) {
+ this.appView = appView;
+ this.factory = appView.dexItemFactory();
this.converter = converter;
}
@@ -178,6 +181,7 @@
}
private boolean isPinned(DexClass clazz, DexEncodedField singletonField) {
+ AppInfoWithLiveness appInfo = appView.appInfo();
if (appInfo.isPinned(clazz.type) || appInfo.isPinned(singletonField.field)) {
return true;
}
@@ -423,7 +427,8 @@
// Check constructor.
InvokeDirect invoke = instruction.asInvokeDirect();
- DexEncodedMethod methodInvoked = appInfo.lookupDirectTarget(invoke.getInvokedMethod());
+ DexEncodedMethod methodInvoked =
+ appView.appInfo().lookupDirectTarget(invoke.getInvokedMethod());
List<Value> values = invoke.inValues();
if (values.lastIndexOf(candidateValue) != 0 ||
@@ -450,7 +455,7 @@
// Allow single assignment to a singleton field.
StaticPut staticPut = instruction.asStaticPut();
DexEncodedField fieldAccessed =
- appInfo.lookupStaticTarget(staticPut.getField().clazz, staticPut.getField());
+ appView.appInfo().lookupStaticTarget(staticPut.getField().clazz, staticPut.getField());
return fieldAccessed == info.singletonField;
}
@@ -465,7 +470,7 @@
return null;
}
- assert candidateInfo.singletonField == appInfo.lookupStaticTarget(field.clazz, field)
+ assert candidateInfo.singletonField == appView.appInfo().lookupStaticTarget(field.clazz, field)
: "Added reference after collectCandidates(...)?";
Value singletonValue = staticGet.dest();
@@ -499,6 +504,7 @@
}
return candidateInfo.invalidate();
}
+ AppInfo appInfo = appView.appInfo();
DexEncodedMethod methodInvoked = user.isInvokeDirect()
? appInfo.lookupDirectTarget(methodReferenced)
: appInfo.lookupVirtualTarget(methodReferenced.holder, methodReferenced);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 0fd8cc4..7106005 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -413,11 +413,9 @@
new StaticGet(
code.createValue(
TypeLatticeElement.fromDexType(
- field.type, maybeNull(), classStaticizer.appInfo),
+ field.type, maybeNull(), classStaticizer.appView.appInfo()),
outValue.getLocalInfo()),
- field
- )
- );
+ field));
}
continue;
}
@@ -438,11 +436,13 @@
if (hostType != null) {
DexMethod newMethod = factory().createMethod(hostType, method.proto, method.name);
Value outValue = invoke.outValue();
- Value newOutValue = method.proto.returnType.isVoidType() ? null
- : code.createValue(
- TypeLatticeElement.fromDexType(
- method.proto.returnType, maybeNull(), classStaticizer.appInfo),
- outValue == null ? null : outValue.getLocalInfo());
+ Value newOutValue =
+ method.proto.returnType.isVoidType()
+ ? null
+ : code.createValue(
+ TypeLatticeElement.fromDexType(
+ method.proto.returnType, maybeNull(), classStaticizer.appView.appInfo()),
+ outValue == null ? null : outValue.getLocalInfo());
it.replaceCurrentInstruction(
new InvokeStatic(newMethod, newOutValue, invoke.inValues()));
}
@@ -490,7 +490,7 @@
// Consider moving static members from candidate into host.
DexType hostType = candidate.hostType();
if (candidateClass.type != hostType) {
- DexClass hostClass = classStaticizer.appInfo.definitionFor(hostType);
+ DexClass hostClass = classStaticizer.appView.definitionFor(hostType);
assert hostClass != null;
if (!classMembersConflict(candidateClass, hostClass)) {
// Move all members of the candidate class into host class.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index f18d26d..942265e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -12,6 +12,7 @@
import static com.android.tools.r8.utils.DescriptorUtils.INNER_CLASS_SEPARATOR;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
@@ -33,7 +34,6 @@
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.utils.InternalOutputMode;
import com.google.common.annotations.VisibleForTesting;
import java.util.Set;
import java.util.function.BiFunction;
@@ -41,15 +41,14 @@
public class StringOptimizer {
- private final AppInfo appInfo;
+ private final AppView<? extends AppInfo> appView;
private final DexItemFactory factory;
private final ThrowingInfo throwingInfo;
- public StringOptimizer(AppInfo appInfo, InternalOutputMode outputMode) {
- this.appInfo = appInfo;
- this.factory = appInfo.dexItemFactory;
- this.throwingInfo =
- outputMode.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
+ public StringOptimizer(AppView<? extends AppInfo> appView) {
+ this.appView = appView;
+ this.factory = appView.dexItemFactory();
+ this.throwingInfo = ThrowingInfo.defaultForConstString(appView.options());
}
// int String#length()
@@ -83,7 +82,7 @@
continue;
}
DexMethod invokedMethod = invoke.getInvokedMethod();
- if (invokedMethod.name == appInfo.dexItemFactory.substringName) {
+ if (invokedMethod.name == factory.substringName) {
assert invoke.inValues().size() == 2 || invoke.inValues().size() == 3;
Value rcv = invoke.getReceiver().getAliasedValue();
if (rcv.definition == null
@@ -121,7 +120,7 @@
String sub = rcvString.substring(beginIndexValue, endIndexValue);
Value stringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
invoke.getLocalInfo());
it.replaceCurrentInstruction(
new ConstString(stringValue, factory.createString(sub), throwingInfo));
@@ -234,7 +233,8 @@
// case, the result of this optimization can lead to a regression if the corresponding class
// is in a deep package hierarchy.
if (!code.options.testing.forceNameReflectionOptimization
- && !hasPotentialReadOutside(appInfo, code.method, EscapeAnalysis.escape(code, out))) {
+ && !hasPotentialReadOutside(
+ appView.appInfo(), code.method, EscapeAnalysis.escape(code, out))) {
continue;
}
@@ -265,7 +265,7 @@
if (!baseType.isClassType()) {
continue;
}
- DexClass holder = appInfo.definitionFor(baseType);
+ DexClass holder = appView.definitionFor(baseType);
if (holder == null) {
continue;
}
@@ -335,7 +335,7 @@
if (name != null) {
Value stringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
invoke.getLocalInfo());
ConstString constString = new ConstString(stringValue, name, throwingInfo);
it.replaceCurrentInstruction(constString);
@@ -401,7 +401,7 @@
if (inType.isNullType()) {
Value nullStringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+ TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
invoke.getLocalInfo());
ConstString nullString =
new ConstString(nullStringValue, factory.createString("null"), throwingInfo);
diff --git a/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java b/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java
new file mode 100644
index 0000000..597dfbc
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, 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.naming;
+
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+
+public class ApplyMappingError extends CompilationError {
+
+ private static final String EXISTING_MESSAGE_START =
+ "'%s' cannot be mapped to '%s' because it is in conflict with an existing ";
+ private static final String EXISTING_MESSAGE_END =
+ ". This usually happens when compiling a test application against a source application and "
+ + "having short generic names in the test application. Try giving '%s' a more specific "
+ + "name or add a keep rule to keep '%s'.";
+
+ protected static final String EXISTING_CLASS_MESSAGE =
+ EXISTING_MESSAGE_START + "class with the same name" + EXISTING_MESSAGE_END;
+ protected static final String EXISTING_MEMBER_MESSAGE =
+ EXISTING_MESSAGE_START + "member with the same signature" + EXISTING_MESSAGE_END;
+
+ private ApplyMappingError(String message, Position position) {
+ super(message, null, Origin.unknown(), position);
+ }
+
+ static ApplyMappingError mapToExistingClass(
+ String originalName, String renamedName, Position position) {
+ return new ApplyMappingError(
+ String.format(EXISTING_CLASS_MESSAGE, originalName, renamedName, renamedName, originalName),
+ position);
+ }
+
+ static ApplyMappingError mapToExistingMember(
+ String originalName, String renamedName, Position position) {
+ return new ApplyMappingError(
+ String.format(
+ EXISTING_MEMBER_MESSAGE, originalName, renamedName, renamedName, originalName),
+ position);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index bcc0af3..1e7094d 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.BiMapContainer;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
@@ -32,7 +33,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Consumer;
public class ClassNameMapper implements ProguardMap {
@@ -50,7 +50,7 @@
@Override
public ClassNamingForNameMapper.Builder classNamingBuilder(
- String renamedName, String originalName) {
+ String renamedName, String originalName, Position position) {
ClassNamingForNameMapper.Builder classNamingBuilder =
ClassNamingForNameMapper.builder(renamedName, originalName);
mapBuilder.put(renamedName, classNamingBuilder);
@@ -181,10 +181,6 @@
}
}
- public void forAllClassNamings(Consumer<ClassNaming> consumer) {
- classNameMappings.values().forEach(consumer);
- }
-
@Override
public String toString() {
try {
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 92c07d1..c073bb5 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -39,7 +39,7 @@
class ClassNameMinifier {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final ClassNamingStrategy classNamingStrategy;
private final PackageNamingStrategy packageNamingStrategy;
@@ -62,7 +62,7 @@
private final Namespace topLevelState;
ClassNameMinifier(
- AppView<AppInfoWithLiveness> appView,
+ AppView<? extends AppInfoWithLiveness> appView,
RootSet rootSet,
ClassNamingStrategy classNamingStrategy,
PackageNamingStrategy packageNamingStrategy,
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
index ba7963b..4c24731 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.google.common.collect.ImmutableMap;
import java.util.Arrays;
@@ -32,12 +34,16 @@
public static class Builder extends ClassNaming.Builder {
private final String originalName;
private final String renamedName;
+ private final Position position;
+ private final Reporter reporter;
private final Map<MethodSignature, MemberNaming> methodMembers = new HashMap<>();
private final Map<FieldSignature, MemberNaming> fieldMembers = new HashMap<>();
- private Builder(String renamedName, String originalName) {
+ private Builder(String renamedName, String originalName, Position position, Reporter reporter) {
this.originalName = originalName;
this.renamedName = renamedName;
+ this.position = position;
+ this.reporter = reporter;
}
@Override
@@ -45,16 +51,27 @@
// Unlike {@link ClassNamingForNameMapper.Builder#addMemberEntry},
// the key is original signature.
if (entry.isMethodNaming()) {
- methodMembers.put((MethodSignature) entry.getOriginalSignature(), entry);
+ MethodSignature signature = (MethodSignature) entry.getOriginalSignature();
+ if (methodMembers.put(signature, entry) != null) {
+ reporter.error(
+ ProguardMapError.duplicateSourceMember(
+ signature.toString(), this.originalName, entry.position));
+ }
} else {
- fieldMembers.put((FieldSignature) entry.getOriginalSignature(), entry);
+ FieldSignature signature = (FieldSignature) entry.getOriginalSignature();
+ if (fieldMembers.put(signature, entry) != null) {
+ reporter.error(
+ ProguardMapError.duplicateSourceMember(
+ signature.toString(), this.originalName, entry.position));
+ }
}
return this;
}
@Override
public ClassNamingForMapApplier build() {
- return new ClassNamingForMapApplier(renamedName, originalName, methodMembers, fieldMembers);
+ return new ClassNamingForMapApplier(
+ renamedName, originalName, position, methodMembers, fieldMembers);
}
@Override
@@ -66,28 +83,37 @@
String obfuscatedName) {}
}
- static Builder builder(String renamedName, String originalName) {
- return new Builder(renamedName, originalName);
+ static Builder builder(
+ String renamedName, String originalName, Position position, Reporter reporter) {
+ return new Builder(renamedName, originalName, position, reporter);
}
private final String originalName;
final String renamedName;
+ final Position position;
private final ImmutableMap<MethodSignature, MemberNaming> methodMembers;
private final ImmutableMap<FieldSignature, MemberNaming> fieldMembers;
// Constructor to help chaining {@link ClassNamingForMapApplier} according to class hierarchy.
ClassNamingForMapApplier(ClassNamingForMapApplier proxy) {
- this(proxy.renamedName, proxy.originalName, proxy.methodMembers, proxy.fieldMembers);
+ this(
+ proxy.renamedName,
+ proxy.originalName,
+ proxy.position,
+ proxy.methodMembers,
+ proxy.fieldMembers);
}
private ClassNamingForMapApplier(
String renamedName,
String originalName,
+ Position position,
Map<MethodSignature, MemberNaming> methodMembers,
Map<FieldSignature, MemberNaming> fieldMembers) {
this.renamedName = renamedName;
this.originalName = originalName;
+ this.position = position;
this.methodMembers = ImmutableMap.copyOf(methodMembers);
this.fieldMembers = ImmutableMap.copyOf(fieldMembers);
}
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index 1247b90..577da26 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -20,7 +20,9 @@
class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
FieldNameMinifier(
- AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+ AppView<? extends AppInfoWithLiveness> appView,
+ RootSet rootSet,
+ MemberNamingStrategy strategy) {
super(appView, rootSet, strategy);
}
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 6f6b64b..42e3f76 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -22,7 +22,7 @@
abstract class MemberNameMinifier<MemberType, StateType extends CachedHashValueDexItem> {
- protected final AppView<AppInfoWithLiveness> appView;
+ protected final AppView<? extends AppInfoWithLiveness> appView;
protected final AppInfoWithLiveness appInfo;
protected final RootSet rootSet;
protected final InternalOptions options;
@@ -41,7 +41,9 @@
private final BiMap<DexType, NamingState<StateType, ?>> states = HashBiMap.create();
MemberNameMinifier(
- AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+ AppView<? extends AppInfoWithLiveness> appView,
+ RootSet rootSet,
+ MemberNamingStrategy strategy) {
this.appView = appView;
this.appInfo = appView.appInfo();
this.rootSet = rootSet;
@@ -104,5 +106,7 @@
DexString next(DexReference source, InternalState internalState);
boolean bypassDictionary();
+
+ boolean breakOnNotAvailable(DexReference source, DexString name);
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index db57862..e8ea970 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.DescriptorUtils;
import java.io.IOException;
import java.io.StringWriter;
@@ -47,18 +48,21 @@
return result;
}
- /**
- * Original signature of the member
- */
+ /** Original signature of the member. */
final Signature signature;
- /**
- * Renamed signature where the name (but not the types) have been renamed.
- */
+ /** Renamed signature where the name (but not the types) have been renamed. */
final Signature renamedSignature;
+ /** Position of the member in the file. */
+ final Position position;
public MemberNaming(Signature signature, String renamedName) {
+ this(signature, renamedName, Position.UNKNOWN);
+ }
+
+ public MemberNaming(Signature signature, String renamedName, Position position) {
this.signature = signature;
this.renamedSignature = signature.asRenamed(renamedName);
+ this.position = position;
}
public Signature getOriginalSignature() {
@@ -81,6 +85,10 @@
return signature.kind() == SignatureKind.METHOD;
}
+ public Position getPosition() {
+ return position;
+ }
+
@Override
public String toString() {
return signature.toString() + " -> " + renamedSignature.name;
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index e9932e1..50b22b0 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -94,7 +94,9 @@
private final MemberNamingStrategy strategy;
MethodNameMinifier(
- AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+ AppView<? extends AppInfoWithLiveness> appView,
+ RootSet rootSet,
+ MemberNamingStrategy strategy) {
super(appView, rootSet, strategy);
this.strategy = strategy;
equivalence =
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 9aa8502..96b174e 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -28,14 +28,14 @@
public class Minifier {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final RootSet rootSet;
private final Set<DexCallSite> desugaredCallSites;
private final InternalOptions options;
public Minifier(
- AppView<AppInfoWithLiveness> appView,
+ AppView<? extends AppInfoWithLiveness> appView,
RootSet rootSet,
Set<DexCallSite> desugaredCallSites) {
this.appView = appView;
@@ -156,5 +156,10 @@
public boolean bypassDictionary() {
return false;
}
+
+ @Override
+ public boolean breakOnNotAvailable(DexReference source, DexString name) {
+ return false;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index a3352ad..c44c70d 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -234,7 +234,7 @@
}
do {
name = nextSuggestedName(source);
- } while (!isAvailable(name));
+ } while (!isAvailable(name) && !strategy.breakOnNotAvailable(source, name));
if (markAsUsed) {
addRenaming(original, proto, name);
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMap.java b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
index 5b5c76e..221f064 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMap.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
@@ -4,11 +4,14 @@
package com.android.tools.r8.naming;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.position.Position;
public interface ProguardMap {
abstract class Builder {
- abstract ClassNaming.Builder classNamingBuilder(String renamedName, String originalName);
+ abstract ClassNaming.Builder classNamingBuilder(
+ String renamedName, String originalName, Position position);
+
abstract ProguardMap build();
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
index a447e37..f8b690b 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
@@ -37,7 +37,7 @@
private final GraphLense previousLense;
private final SeedMapper seedMapper;
- public ProguardMapApplier(AppView<AppInfoWithLiveness> appView, SeedMapper seedMapper) {
+ public ProguardMapApplier(AppView<? extends AppInfoWithLiveness> appView, SeedMapper seedMapper) {
assert appView.graphLense().isContextFreeForMethods();
this.appInfo = appView.appInfo();
this.previousLense = appView.graphLense();
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapError.java b/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
index 684c79b..cb06a96 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
@@ -7,16 +7,47 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
public class ProguardMapError extends CompilationError {
+
+ protected static final String DUPLICATE_TARGET_MESSAGE = "'%s' and '%s' map to same name: '%s'";
+ protected static final String DUPLICATE_SOURCE_MESSAGE = "'%s' already has a mapping";
+
private ProguardMapError(String message) {
super(message);
}
- private ProguardMapError(String message, Throwable cause) {
- super(message, cause);
+ private ProguardMapError(String message, Position position) {
+ super(message, null, Origin.unknown(), position);
}
+ static ProguardMapError duplicateSourceClass(String typeName, Position position) {
+ return new ProguardMapError(String.format(DUPLICATE_SOURCE_MESSAGE, typeName), position);
+ }
+
+ static ProguardMapError duplicateSourceMember(
+ String signature, String typeName, Position position) {
+ return new ProguardMapError(
+ String.format(DUPLICATE_SOURCE_MESSAGE, signature, typeName), position);
+ }
+
+ static ProguardMapError duplicateTargetClass(
+ String source, String other, String mappedName, Position position) {
+ return new ProguardMapError(
+ String.format(DUPLICATE_TARGET_MESSAGE, source, other, mappedName), position);
+ }
+
+ static ProguardMapError duplicateTargetSignature(
+ Signature source, Signature other, String mappedName, Position position) {
+ return new ProguardMapError(
+ String.format(DUPLICATE_TARGET_MESSAGE, source.toString(), other.toString(), mappedName),
+ position);
+ }
+
+ // TODO(mkroghj) Remove these and when the ProguardMapApplier is removed.
static ProguardMapError keptTypeWasRenamed(DexType type, String keptName, String rename) {
return new ProguardMapError(
type + createMessageForConflict(keptName, rename));
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 42a574d..227a0b4 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -24,8 +24,10 @@
import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
import com.android.tools.r8.naming.Minifier.MinificationPackageNamingStrategy;
import com.android.tools.r8.naming.NamingState.InternalState;
+import com.android.tools.r8.position.Position;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.Timing;
import java.util.ArrayList;
import java.util.IdentityHashMap;
@@ -35,7 +37,7 @@
public class ProguardMapMinifier {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final RootSet rootSet;
private final SeedMapper seedMapper;
@@ -43,7 +45,7 @@
private final DexItemFactory factory;
public ProguardMapMinifier(
- AppView<AppInfoWithLiveness> appView,
+ AppView<? extends AppInfoWithLiveness> appView,
RootSet rootSet,
SeedMapper seedMapper,
Set<DexCallSite> desugaredCallSites) {
@@ -64,8 +66,9 @@
Map<DexType, DexString> mappedNames = new IdentityHashMap<>();
List<DexClass> mappedClasses = new ArrayList<>();
- Map<DexReference, DexString> memberNames = new IdentityHashMap<>();
+ Map<DexReference, MemberNaming> memberNames = new IdentityHashMap<>();
for (String key : seedMapper.getKeyset()) {
+ ClassNamingForMapApplier classNaming = seedMapper.getMapping(key);
DexType type = factory.lookupType(factory.createString(key));
if (type == null) {
// The map contains additional mapping of classes compared to what we have seen. This should
@@ -76,33 +79,47 @@
if (dexClass == null) {
continue;
}
- ClassNamingForMapApplier classNaming = seedMapper.getClassNaming(type);
- mappedNames.put(type, factory.createString(classNaming.renamedName));
+ DexString mappedName = factory.createString(classNaming.renamedName);
+ DexType mappedType = factory.lookupType(mappedName);
+ // The mappedType has to be available:
+ // - If it is null we have not seen it.
+ // - If the mapped type is itself the name is already reserved (by itself).
+ // - If the there is no definition for the mapped type we will not get a naming clash.
+ // Otherwise, there will be a naming conflict.
+ if (mappedType != null && type != mappedType && appInfo.definitionFor(mappedType) != null) {
+ appView
+ .options()
+ .reporter
+ .error(
+ ApplyMappingError.mapToExistingClass(
+ type.toString(), mappedType.toString(), classNaming.position));
+ }
+ mappedNames.put(type, mappedName);
mappedClasses.add(dexClass);
classNaming.forAllMethodNaming(
memberNaming -> {
- Signature signature = memberNaming.getOriginalSignature();
+ Signature signature = memberNaming.getOriginalSignature();
if (signature.isQualified()) {
return;
}
DexMethod originalMethod = ((MethodSignature) signature).toDexMethod(factory, type);
assert !memberNames.containsKey(originalMethod);
- memberNames.put(
- originalMethod, factory.createString(memberNaming.getRenamedName()));
+ memberNames.put(originalMethod, memberNaming);
});
classNaming.forAllFieldNaming(
memberNaming -> {
- Signature signature = memberNaming.getOriginalSignature();
+ Signature signature = memberNaming.getOriginalSignature();
if (signature.isQualified()) {
return;
}
DexField originalField = ((FieldSignature) signature).toDexField(factory, type);
assert !memberNames.containsKey(originalField);
- memberNames.put(
- originalField, factory.createString(memberNaming.getRenamedName()));
+ memberNames.put(originalField, memberNaming);
});
}
+ appView.options().reporter.failIfPendingErrors();
+
ClassNameMinifier classNameMinifier =
new ClassNameMinifier(
appView,
@@ -118,7 +135,8 @@
timing.end();
ApplyMappingMemberNamingStrategy nameStrategy =
- new ApplyMappingMemberNamingStrategy(memberNames);
+ new ApplyMappingMemberNamingStrategy(
+ memberNames, appInfo.dexItemFactory, appView.options().reporter);
timing.begin("MinifyMethods");
MethodRenaming methodRenaming =
new MethodNameMinifier(appView, rootSet, nameStrategy)
@@ -130,6 +148,8 @@
new FieldNameMinifier(appView, rootSet, nameStrategy).computeRenaming(timing);
timing.end();
+ appView.options().reporter.failIfPendingErrors();
+
NamingLens lens =
new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appView.appInfo());
return lens;
@@ -156,16 +176,21 @@
static class ApplyMappingMemberNamingStrategy implements MemberNamingStrategy {
- private final Map<DexReference, DexString> mappedNames;
+ private final Map<DexReference, MemberNaming> mappedNames;
+ private final DexItemFactory factory;
+ private final Reporter reporter;
- public ApplyMappingMemberNamingStrategy(Map<DexReference, DexString> mappedNames) {
+ public ApplyMappingMemberNamingStrategy(
+ Map<DexReference, MemberNaming> mappedNames, DexItemFactory factory, Reporter reporter) {
this.mappedNames = mappedNames;
+ this.factory = factory;
+ this.reporter = reporter;
}
@Override
public DexString next(DexReference reference, InternalState internalState) {
if (mappedNames.containsKey(reference)) {
- return mappedNames.get(reference);
+ return factory.createString(mappedNames.get(reference).getRenamedName());
} else if (reference.isDexMethod()) {
return reference.asDexMethod().name;
} else {
@@ -178,5 +203,19 @@
public boolean bypassDictionary() {
return true;
}
+
+ @Override
+ public boolean breakOnNotAvailable(DexReference source, DexString name) {
+ // This is an error where we have renamed a member to an name that exists in a subtype or
+ // renamed a field to something that exists in a subclass.
+ MemberNaming memberNaming = mappedNames.get(source);
+ assert source.isDexMethod() || source.isDexField();
+ reporter.error(
+ ApplyMappingError.mapToExistingMember(
+ source.toSourceString(),
+ name.toString(),
+ memberNaming == null ? Position.UNKNOWN : memberNaming.position));
+ return true;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index 8a1bb87..a21adfa 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.utils.IdentifierUtils;
import java.io.BufferedReader;
import java.io.IOException;
@@ -185,7 +186,8 @@
skipWhitespace();
String after = parseType(false);
expect(':');
- ClassNaming.Builder currentClassBuilder = mapBuilder.classNamingBuilder(after, before);
+ ClassNaming.Builder currentClassBuilder =
+ mapBuilder.classNamingBuilder(after, before, getPosition());
if (nextLine()) {
parseMemberMappings(currentClassBuilder);
}
@@ -260,7 +262,8 @@
}
}
if (activeMemberNaming == null) {
- activeMemberNaming = new MemberNaming(previousSignature, previousRenamedName);
+ activeMemberNaming =
+ new MemberNaming(previousSignature, previousRenamedName, getPosition());
}
}
@@ -280,7 +283,7 @@
if (activeMemberNaming != null) {
classNamingBuilder.addMemberEntry(activeMemberNaming);
}
- activeMemberNaming = new MemberNaming(signature, renamedName);
+ activeMemberNaming = new MemberNaming(signature, renamedName, getPosition());
} else {
// Note that at this point originalRange may be null which either means, it's the same as
@@ -304,6 +307,10 @@
}
}
+ private TextPosition getPosition() {
+ return new TextPosition(0, lineNo, 1);
+ }
+
// Parsing of components
private void skipIdentifier(boolean allowInit) {
diff --git a/src/main/java/com/android/tools/r8/naming/SeedMapper.java b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
index 895605f..8d0ece57 100644
--- a/src/main/java/com/android/tools/r8/naming/SeedMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
@@ -3,10 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import static com.android.tools.r8.utils.DescriptorUtils.descriptorToInternalName;
+import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;
import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableMap;
import java.io.BufferedReader;
import java.io.IOException;
@@ -15,6 +19,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -31,52 +36,93 @@
public class SeedMapper implements ProguardMap {
static class Builder extends ProguardMap.Builder {
- final ImmutableMap.Builder<String, ClassNamingForMapApplier.Builder> mapBuilder;
+ final Map<String, ClassNamingForMapApplier.Builder> map = new HashMap<>();
+ private final Reporter reporter;
- private Builder() {
- mapBuilder = ImmutableMap.builder();
+ private Builder(Reporter reporter) {
+ this.reporter = reporter;
}
@Override
- ClassNamingForMapApplier.Builder classNamingBuilder(String renamedName, String originalName) {
+ ClassNamingForMapApplier.Builder classNamingBuilder(
+ String renamedName, String originalName, Position position) {
String originalDescriptor = javaTypeToDescriptor(originalName);
ClassNamingForMapApplier.Builder classNamingBuilder =
- ClassNamingForMapApplier.builder(javaTypeToDescriptor(renamedName), originalDescriptor);
- mapBuilder.put(originalDescriptor, classNamingBuilder);
+ ClassNamingForMapApplier.builder(
+ javaTypeToDescriptor(renamedName), originalDescriptor, position, reporter);
+ if (map.put(originalDescriptor, classNamingBuilder) != null) {
+ reporter.error(ProguardMapError.duplicateSourceClass(originalName, position));
+ }
return classNamingBuilder;
}
@Override
SeedMapper build() {
- return new SeedMapper(mapBuilder.build());
+ reporter.failIfPendingErrors();
+ return new SeedMapper(ImmutableMap.copyOf(map), reporter);
}
}
- static Builder builder() {
- return new Builder();
+ static Builder builder(Reporter reporter) {
+ return new Builder(reporter);
}
- private static SeedMapper seedMapperFromInputStream(InputStream in) throws IOException {
+ private static SeedMapper seedMapperFromInputStream(Reporter reporter, InputStream in)
+ throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
try (ProguardMapReader proguardReader = new ProguardMapReader(reader)) {
- SeedMapper.Builder builder = SeedMapper.builder();
+ SeedMapper.Builder builder = SeedMapper.builder(reporter);
proguardReader.parse(builder);
return builder.build();
}
}
- public static SeedMapper seedMapperFromFile(Path path) throws IOException {
- return seedMapperFromInputStream(Files.newInputStream(path));
+ public static SeedMapper seedMapperFromFile(Reporter reporter, Path path) throws IOException {
+ return seedMapperFromInputStream(reporter, Files.newInputStream(path));
}
private final ImmutableMap<String, ClassNamingForMapApplier> mappings;
+ private final Reporter reporter;
- private SeedMapper(Map<String, ClassNamingForMapApplier.Builder> mappings) {
+ private SeedMapper(Map<String, ClassNamingForMapApplier.Builder> mappings, Reporter reporter) {
+ this.reporter = reporter;
ImmutableMap.Builder<String, ClassNamingForMapApplier> builder = ImmutableMap.builder();
for(Map.Entry<String, ClassNamingForMapApplier.Builder> entry : mappings.entrySet()) {
builder.put(entry.getKey(), entry.getValue().build());
}
this.mappings = builder.build();
+ verifyMappingsAreConflictFree();
+ }
+
+ private void verifyMappingsAreConflictFree() {
+ Map<String, String> seenMappings = new HashMap<>();
+ for (String key : mappings.keySet()) {
+ ClassNamingForMapApplier classNaming = mappings.get(key);
+ String existing = seenMappings.put(classNaming.renamedName, key);
+ if (existing != null) {
+ reporter.error(
+ ProguardMapError.duplicateTargetClass(
+ descriptorToJavaType(key),
+ descriptorToJavaType(existing),
+ descriptorToInternalName(classNaming.renamedName),
+ classNaming.position));
+ }
+ Map<Signature, MemberNaming> seenMembers = new HashMap<>();
+ classNaming.forAllMemberNaming(
+ memberNaming -> {
+ MemberNaming existingMember =
+ seenMembers.put(memberNaming.renamedSignature, memberNaming);
+ if (existingMember != null) {
+ reporter.error(
+ ProguardMapError.duplicateTargetSignature(
+ existingMember.signature,
+ memberNaming.signature,
+ memberNaming.getRenamedName(),
+ memberNaming.position));
+ }
+ });
+ }
+ reporter.failIfPendingErrors();
}
@Override
@@ -92,4 +138,8 @@
public Set<String> getKeyset() {
return mappings.keySet();
}
+
+ public ClassNamingForMapApplier getMapping(String key) {
+ return mappings.get(key);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index 20f4bc2..1f9570c 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -28,17 +28,17 @@
public class GenericSignatureRewriter {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<? extends AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
private final Map<DexType, DexString> renaming;
private final Reporter reporter;
- public GenericSignatureRewriter(AppView<AppInfoWithLiveness> appView) {
+ public GenericSignatureRewriter(AppView<? extends AppInfoWithLiveness> appView) {
this(appView, Maps.newIdentityHashMap());
}
public GenericSignatureRewriter(
- AppView<AppInfoWithLiveness> appView, Map<DexType, DexString> renaming) {
+ AppView<? extends AppInfoWithLiveness> appView, Map<DexType, DexString> renaming) {
this.appView = appView;
this.appInfo = appView.appInfo();
this.renaming = renaming;
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 871525d..e751336 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -36,11 +36,11 @@
private final MemberRebindingLense.Builder builder;
- public MemberRebindingAnalysis(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+ public MemberRebindingAnalysis(AppView<? extends AppInfoWithLiveness> appView) {
assert appView.graphLense().isContextFreeForMethods();
this.appInfo = appView.appInfo();
this.lense = appView.graphLense();
- this.options = options;
+ this.options = appView.options();
this.builder = MemberRebindingLense.builder(appInfo);
this.searchInLibrary = options.getProguardConfiguration().hasApplyMappingFile();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
index 29ecf33..ab8999a 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
@@ -55,7 +55,7 @@
GraphLenseLookupResult lookup =
appView.graphLense().lookupMethod(method, context, Type.VIRTUAL);
DexMethod signatureInCurrentWorld = lookup.getMethod();
- DexClass clazz = appView.appInfo().definitionFor(signatureInCurrentWorld.holder);
+ DexClass clazz = appView.definitionFor(signatureInCurrentWorld.holder);
assert clazz != null;
DexEncodedMethod actualEncodedTarget = clazz.lookupVirtualMethod(signatureInCurrentWorld);
assert actualEncodedTarget != null;
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 2b1a6cd..208fb9c 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -328,7 +328,7 @@
// -keep rule may vary (due to back references). So, we need to try all pairs of -if
// rule and live types.
for (DexType type : liveTypes) {
- DexClass clazz = appView.appInfo().definitionFor(type);
+ DexClass clazz = appView.definitionFor(type);
if (clazz == null) {
continue;
}
@@ -343,7 +343,7 @@
// `sourceType` is still available until the second round of tree shaking. This
// way
// we can still retrieve the access flags of `sourceType`.
- DexClass sourceClass = appView.appInfo().definitionFor(sourceType);
+ DexClass sourceClass = appView.definitionFor(sourceType);
assert sourceClass != null;
evaluateIfRule(ifRule, sourceClass, clazz);
}
@@ -740,8 +740,7 @@
&& appView.verticallyMergedClasses().getSourcesFor(clazz.type).stream()
.filter(
sourceType ->
- appView.appInfo().definitionFor(sourceType).accessFlags.isInterface()
- == isInterface)
+ appView.definitionFor(sourceType).accessFlags.isInterface() == isInterface)
.anyMatch(rule.getInheritanceClassName()::matches);
}
@@ -871,7 +870,7 @@
if (type.isPrimitiveType()) {
return;
}
- DexClass definition = appView.appInfo().definitionFor(type);
+ DexClass definition = appView.definitionFor(type);
if (definition == null || definition.isLibraryClass()) {
return;
}
@@ -916,7 +915,7 @@
if (options.isInterfaceMethodDesugaringEnabled()
&& encodedMethod.hasCode()
&& (encodedMethod.isPrivateMethod() || encodedMethod.isStaticMember())) {
- DexClass holder = appView.appInfo().definitionFor(encodedMethod.method.getHolder());
+ DexClass holder = appView.definitionFor(encodedMethod.method.getHolder());
if (holder != null && holder.isInterface()) {
if (rule.isSpecific()) {
options.reporter.warning(
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 2152d3c..613ec66 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -229,7 +229,7 @@
public VerticalClassMerger(
DexApplication application,
- AppView<AppInfoWithLiveness> appView,
+ AppView<? extends AppInfoWithLiveness> appView,
ExecutorService executorService,
InternalOptions options,
Timing timing,
@@ -1761,7 +1761,7 @@
checkTypeReference(field.clazz);
checkTypeReference(field.type);
- DexEncodedField definition = appView.appInfo().definitionFor(field);
+ DexEncodedField definition = appView.definitionFor(field);
if (definition == null || !definition.accessFlags.isPublic()) {
foundIllegalAccess = true;
}
@@ -1780,7 +1780,7 @@
for (DexType type : method.proto.parameters.values) {
checkTypeReference(type);
}
- DexEncodedMethod definition = appView.appInfo().definitionFor(method);
+ DexEncodedMethod definition = appView.definitionFor(method);
if (definition == null || !definition.accessFlags.isPublic()) {
foundIllegalAccess = true;
}
@@ -1794,7 +1794,7 @@
DexType baseType =
appView.graphLense().lookupType(type.toBaseType(appView.dexItemFactory()));
if (baseType.isClassType() && baseType.isSamePackage(source.type)) {
- DexClass clazz = appView.appInfo().definitionFor(baseType);
+ DexClass clazz = appView.definitionFor(baseType);
if (clazz == null || !clazz.accessFlags.isPublic()) {
foundIllegalAccess = true;
}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 427341f..c60ba34 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -180,7 +180,8 @@
() ->
classNameMapperBuilder.classNamingBuilder(
DescriptorUtils.descriptorToJavaType(renamedClassName.toString()),
- originalType.toSourceString()));
+ originalType.toSourceString(),
+ com.android.tools.r8.position.Position.UNKNOWN));
// If the class is renamed add it to the classNamingBuilder.
addClassToClassNaming(originalType, renamedClassName, onDemandClassNamingBuilder);
diff --git a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
index bfd929e..ff3d385 100644
--- a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
+++ b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DirectMappedDexApplication;
@@ -42,7 +43,8 @@
options.programConsumer = DexIndexedConsumer.emptyConsumer();
DirectMappedDexApplication application =
new ApplicationReader(input, options, timing).read(executorService).toDirect();
- IRConverter converter = new IRConverter(new AppInfoWithSubtyping(application), options);
+ IRConverter converter =
+ new IRConverter(AppView.createForR8(new AppInfoWithSubtyping(application), options));
converter.optimize(application);
DexProgramClass clazz = application.classes().iterator().next();
assertEquals(4, clazz.directMethods().size());
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java b/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java
new file mode 100644
index 0000000..9453575
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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.desugar;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import org.junit.Test;
+
+// Test if the static method of the lambda implementation (SINGLE_CALLER) is inlined into the
+// interface method of the lambda class.
+public class DesugaredLambdaImplementationInliningTest extends TestBase {
+ @Test
+ public void test() throws Exception {
+ class Counter {
+ private int i = 0;
+ }
+ Counter counter = new Counter();
+ R8TestRunResult result =
+ testForR8Compat(Backend.DEX)
+ .addInnerClasses(DesugaredLambdaImplementationInliningTest.class)
+ .addKeepMainRule(DesugaredLambdaImplementationInliningTest.TestClass.class)
+ .noMinification()
+ .run(TestClass.class)
+ .assertSuccess()
+ .inspect(
+ inspector -> {
+ inspector
+ .clazz(DesugaredLambdaImplementationInliningTest.TestClass.class)
+ .forAllMethods(
+ fms -> {
+ if (fms.isStatic() && !fms.getOriginalName().equals("main")) {
+ ++counter.i;
+ }
+ });
+ });
+
+ // TODO(b/126323172) Change expected value to zero after fixed.
+ assertEquals(2, counter.i);
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ Runnable runnable = () -> System.out.println("Running desugared stateless lambda.");
+ runnable.run();
+
+ String s = "lambda-state";
+ runnable = () -> System.out.println("Running desugared stateful lambda: " + s + ".");
+ runnable.run();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index 298ffe1..df2d769 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -48,6 +48,7 @@
import java.util.concurrent.ExecutorService;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
public class SharedClassWritingTest {
@@ -110,6 +111,7 @@
synthesizedFrom);
}
+ @Ignore("b/128281550")
@Test
public void manyFilesWithSharedSynthesizedClass() throws ExecutionException, IOException {
diff --git a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
index 066c51a..0251cf3 100644
--- a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -131,11 +132,10 @@
public String run() throws IOException {
AppInfo appInfo = new AppInfo(application);
- IRConverter converter = new IRConverter(appInfo, options);
+ IRConverter converter = new IRConverter(AppView.createForD8(appInfo, options));
converter.replaceCodeForTesting(method, code);
AndroidApp app = writeDex(application, options);
return runOnArtRaw(app, DEFAULT_MAIN_CLASS_NAME).stdout;
}
}
-
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
index ede89dc..61421a8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardClassFilter;
@@ -31,9 +30,8 @@
AndroidApp app = buildAndroidApp(ToolHelper.getClassAsBytes(mainClass));
DexApplication dexApplication =
new ApplicationReader(app, TEST_OPTIONS, timing).read().toDirect();
- AppView<AppInfoWithSubtyping> appView =
- new AppView<>(
- new AppInfoWithSubtyping(dexApplication), GraphLense.getIdentityLense(), TEST_OPTIONS);
+ AppView<? extends AppInfoWithSubtyping> appView =
+ AppView.createForR8(new AppInfoWithSubtyping(dexApplication), TEST_OPTIONS);
ExecutorService executorService = ThreadUtils.getExecutorService(TEST_OPTIONS);
RootSet rootSet =
new RootSetBuilder(
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index b722683..a60be5d 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -121,6 +121,13 @@
return classSubject;
}
+ protected void checkClassIsRemoved(CodeInspector inspector, String className) {
+ checkClassExistsInInput(className);
+ ClassSubject classSubject = inspector.clazz(className);
+ assertNotNull(classSubject);
+ assertThat(classSubject, not(isPresent()));
+ }
+
protected FieldSubject checkFieldIsKept(
ClassSubject classSubject, String fieldType, String fieldName) {
// Field must exist in the input.
@@ -138,8 +145,6 @@
}
protected void checkFieldIsAbsent(ClassSubject classSubject, String fieldType, String fieldName) {
- // Field must NOT exist in the input.
- checkFieldPresenceInInput(classSubject.getOriginalName(), fieldType, fieldName, false);
FieldSubject fieldSubject = classSubject.field(fieldType, fieldName);
assertNotNull(fieldSubject);
assertFalse(fieldSubject.isPresent());
@@ -162,6 +167,12 @@
return checkMethodIsKeptOrRemoved(classSubject, methodSignature, true);
}
+ protected MethodSubject checkMethodIsMoved(
+ String inputClassName, ClassSubject outputClassSubject, MethodSignature methodSignature) {
+ checkMethodPresenceInInput(inputClassName, methodSignature, true);
+ return checkMethodPresenceInOutput(outputClassSubject, methodSignature, true);
+ }
+
protected MethodSubject checkMethodIsKept(ClassSubject classSubject, String methodName) {
MethodSubject methodSubject = classSubject.uniqueMethodWithName(methodName);
assertThat(methodSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
index 3f02c70..15015cd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
@@ -4,15 +4,16 @@
package com.android.tools.r8.kotlin;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.concurrent.atomic.AtomicInteger;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import org.junit.Test;
public class KotlinClassStaticizerTest extends AbstractR8KotlinTestBase {
@@ -28,32 +29,34 @@
final String mainClassName = "class_staticizer.MainKt";
// Without class staticizer.
- runTest("class_staticizer", mainClassName, false, (app) -> {
- CodeInspector inspector = new CodeInspector(app);
- assertTrue(inspector.clazz("class_staticizer.Regular$Companion").isPresent());
- assertTrue(inspector.clazz("class_staticizer.Derived$Companion").isPresent());
+ runTest(
+ "class_staticizer",
+ mainClassName,
+ false,
+ (app) -> {
+ CodeInspector inspector = new CodeInspector(app);
+ assertThat(inspector.clazz("class_staticizer.Regular$Companion"), not(isPresent()));
+ assertThat(inspector.clazz("class_staticizer.Derived$Companion"), not(isPresent()));
- ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
- assertTrue(utilClass.isPresent());
- AtomicInteger nonStaticMethodCount = new AtomicInteger();
- utilClass.forAllMethods(method -> {
- if (!method.isStatic()) {
- nonStaticMethodCount.incrementAndGet();
- }
- });
- assertEquals(4, nonStaticMethodCount.get());
- });
+ ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
+ assertThat(utilClass, isPresent());
+ assertTrue(utilClass.allMethods().stream().allMatch(FoundMethodSubject::isStatic));
+ });
// With class staticizer.
- runTest("class_staticizer", mainClassName, true, (app) -> {
- CodeInspector inspector = new CodeInspector(app);
- assertFalse(inspector.clazz("class_staticizer.Regular$Companion").isPresent());
- assertFalse(inspector.clazz("class_staticizer.Derived$Companion").isPresent());
+ runTest(
+ "class_staticizer",
+ mainClassName,
+ true,
+ (app) -> {
+ CodeInspector inspector = new CodeInspector(app);
+ assertThat(inspector.clazz("class_staticizer.Regular$Companion"), not(isPresent()));
+ assertThat(inspector.clazz("class_staticizer.Derived$Companion"), not(isPresent()));
- ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
- assertTrue(utilClass.isPresent());
- utilClass.forAllMethods(method -> assertTrue(method.isStatic()));
- });
+ ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
+ assertThat(utilClass, isPresent());
+ assertTrue(utilClass.allMethods().stream().allMatch(FoundMethodSubject::isStatic));
+ });
}
protected void runTest(String folder, String mainClass,
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
index 0048b1b..5630c1f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
@@ -75,28 +75,31 @@
final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
"companionProperties_usePrimitiveProp");
- runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- String propertyName = "primitiveProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PROPERTIES_PACKAGE_NAME,
+ mainClass,
+ disableClassStaticizer,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+ String propertyName = "primitiveProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getterAccessor = testedClass
- .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- MemberNaming.MethodSignature setterAccessor = testedClass
- .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature getterAccessor =
+ testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature setterAccessor =
+ testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ checkMethodIsRemoved(outerClass, getterAccessor);
+ checkMethodIsRemoved(outerClass, setterAccessor);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(outerClass, getterAccessor);
- checkMethodIsRemoved(outerClass, setterAccessor);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(outerClass, getterAccessor);
- checkMethodIsKept(outerClass, setterAccessor);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -104,29 +107,31 @@
final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
"companionProperties_usePrivateProp");
- runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- String propertyName = "privateProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PROPERTIES_PACKAGE_NAME,
+ mainClass,
+ disableClassStaticizer,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+ String propertyName = "privateProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getterAccessor = testedClass
- .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- MemberNaming.MethodSignature setterAccessor = testedClass
- .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ MemberNaming.MethodSignature getterAccessor =
+ testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature setterAccessor =
+ testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ checkMethodIsRemoved(outerClass, getterAccessor);
+ checkMethodIsRemoved(outerClass, setterAccessor);
- checkMethodIsRemoved(outerClass, getterAccessor);
- checkMethodIsRemoved(outerClass, setterAccessor);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-
- checkMethodIsKept(outerClass, getterAccessor);
- checkMethodIsKept(outerClass, setterAccessor);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -134,28 +139,31 @@
final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
"companionProperties_useInternalProp");
- runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- String propertyName = "internalProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PROPERTIES_PACKAGE_NAME,
+ mainClass,
+ disableClassStaticizer,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+ String propertyName = "internalProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getterAccessor = testedClass
- .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- MemberNaming.MethodSignature setterAccessor = testedClass
- .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature getterAccessor =
+ testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature setterAccessor =
+ testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ checkMethodIsRemoved(outerClass, getterAccessor);
+ checkMethodIsRemoved(outerClass, setterAccessor);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(outerClass, getterAccessor);
- checkMethodIsRemoved(outerClass, setterAccessor);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(outerClass, getterAccessor);
- checkMethodIsKept(outerClass, setterAccessor);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -163,28 +171,31 @@
final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
"companionProperties_usePublicProp");
- runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- String propertyName = "publicProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PROPERTIES_PACKAGE_NAME,
+ mainClass,
+ disableClassStaticizer,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+ String propertyName = "publicProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getterAccessor = testedClass
- .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- MemberNaming.MethodSignature setterAccessor = testedClass
- .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature getterAccessor =
+ testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature setterAccessor =
+ testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ checkMethodIsRemoved(outerClass, getterAccessor);
+ checkMethodIsRemoved(outerClass, setterAccessor);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(outerClass, getterAccessor);
- checkMethodIsRemoved(outerClass, setterAccessor);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(outerClass, getterAccessor);
- checkMethodIsKept(outerClass, setterAccessor);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -192,27 +203,32 @@
final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
"companionLateInitProperties_usePrivateLateInitProp");
- runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- String propertyName = "privateLateInitProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PROPERTIES_PACKAGE_NAME,
+ mainClass,
+ disableClassStaticizer,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+ String propertyName = "privateLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getterAccessor = testedClass
- .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- MemberNaming.MethodSignature setterAccessor = testedClass
- .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(outerClass, getterAccessor);
- checkMethodIsRemoved(outerClass, setterAccessor);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(outerClass, getterAccessor);
- checkMethodIsKept(outerClass, setterAccessor);
- }
- });
+ MemberNaming.MethodSignature getterAccessor =
+ testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ MemberNaming.MethodSignature setterAccessor =
+ testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+ checkMethodIsRemoved(outerClass, setterAccessor);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ checkMethodIsRemoved(outerClass, getterAccessor);
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ checkMethodIsKept(outerClass, getterAccessor);
+ }
+ });
}
@Test
@@ -276,23 +292,18 @@
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject outerClass =
checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = testedClass.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
+
String propertyName = "property";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ checkFieldIsAbsent(outerClass, JAVA_LANG_STRING, propertyName);
// The getter is always inlined since it just calls into the accessor.
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- checkMethodIsAbsent(companionClass, getter);
-
MemberNaming.MethodSignature getterAccessor =
testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- checkMethodIsKept(outerClass, getterAccessor);
+ checkMethodIsRemoved(outerClass, getterAccessor);
});
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
index d310c6e..c76798e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
@@ -389,127 +389,148 @@
public void testCompanionProperty_primitivePropertyCannotBeInlined() throws Exception {
String mainClass = addMainToClasspath(
"properties.CompanionPropertiesKt", "companionProperties_usePrimitiveProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector,
- "properties.CompanionProperties");
- ClassSubject companionClass = checkClassIsKept(codeInspector,
- COMPANION_PROPERTY_CLASS.getClassName());
- String propertyName = "primitiveProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, "properties.CompanionProperties");
- MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
- .getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
- .getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Getter and setter cannot be inlined because we don't know if null check semantic is
- // preserved.
- checkMethodIsKept(companionClass, getter);
- checkMethodIsKept(companionClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- });
+ String propertyName = "primitiveProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
public void testCompanionProperty_privatePropertyIsAlwaysInlined() throws Exception {
String mainClass = addMainToClasspath(
"properties.CompanionPropertiesKt", "companionProperties_usePrivateProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector,
- "properties.CompanionProperties");
- ClassSubject companionClass = checkClassIsKept(codeInspector,
- COMPANION_PROPERTY_CLASS.getClassName());
- String propertyName = "privateProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, "properties.CompanionProperties");
- MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
- .getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
- .getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Because the getter/setter are private, they can only be called from another method in the
- // class. If this is an instance method, they will be called on 'this' which is known to be
- // non-null, thus the getter/setter can be inlined if their code is small enough.
- // Because the backing field is private, they will call into an accessor (static) method. If
- // access relaxation is enabled, this accessor can be removed.
- checkMethodIsAbsent(companionClass, getter);
- checkMethodIsAbsent(companionClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- });
+ String propertyName = "privateProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter =
+ COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter =
+ COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+ // Because the getter/setter are private, they can only be called from another method in
+ // the class. If this is an instance method, they will be called on 'this' which is known
+ // to be non-null, thus the getter/setter can be inlined if their code is small enough.
+ // Because the backing field is private, they will call into an accessor (static) method.
+ // If access relaxation is enabled, this accessor can be removed.
+ checkMethodIsAbsent(outerClass, getter);
+ checkMethodIsAbsent(outerClass, setter);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
public void testCompanionProperty_internalPropertyCannotBeInlined() throws Exception {
String mainClass = addMainToClasspath(
"properties.CompanionPropertiesKt", "companionProperties_useInternalProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector,
- "properties.CompanionProperties");
- ClassSubject companionClass = checkClassIsKept(codeInspector,
- COMPANION_PROPERTY_CLASS.getClassName());
- String propertyName = "internalProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, "properties.CompanionProperties");
- MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
- .getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
- .getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Getter and setter cannot be inlined because we don't know if null check semantic is
- // preserved.
- checkMethodIsKept(companionClass, getter);
- checkMethodIsKept(companionClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- });
+ String propertyName = "internalProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter =
+ COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter =
+ COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined because we don't know if null check semantic is
+ // preserved.
+ checkMethodIsMoved(companionClassName, outerClass, getter);
+ checkMethodIsMoved(companionClassName, outerClass, setter);
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
public void testCompanionProperty_publicPropertyCannotBeInlined() throws Exception {
String mainClass = addMainToClasspath(
"properties.CompanionPropertiesKt", "companionProperties_usePublicProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector,
- "properties.CompanionProperties");
- ClassSubject companionClass = checkClassIsKept(codeInspector,
- COMPANION_PROPERTY_CLASS.getClassName());
- String propertyName = "publicProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, "properties.CompanionProperties");
- MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
- .getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
- .getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Getter and setter cannot be inlined because we don't know if null check semantic is
- // preserved.
- checkMethodIsKept(companionClass, getter);
- checkMethodIsKept(companionClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- });
+ String propertyName = "publicProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter =
+ COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter =
+ COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined because we don't know if null check semantic is
+ // preserved.
+ checkMethodIsMoved(companionClassName, outerClass, getter);
+ checkMethodIsMoved(companionClassName, outerClass, setter);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -517,30 +538,28 @@
final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
"companionLateInitProperties_usePrivateLateInitProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "privateLateInitProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = testedClass.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Because the getter/setter are private, they can only be called from another method in the
- // class. If this is an instance method, they will be called on 'this' which is known to be
- // non-null, thus the getter/setter can be inlined if their code is small enough.
- // Because the backing field is private, they will call into an accessor (static) method. If
- // access relaxation is enabled, this accessor can be removed.
- checkMethodIsAbsent(companionClass, getter);
- checkMethodIsAbsent(companionClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- }
- });
+ String propertyName = "privateLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -548,23 +567,32 @@
final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
"companionLateInitProperties_useInternalLateInitProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "internalLateInitProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = testedClass.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Getter and setter cannot be inlined because we don't know if null check semantic is
- // preserved.
- checkMethodIsKept(companionClass, getter);
- checkMethodIsKept(companionClass, setter);
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- });
+ String propertyName = "internalLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined because we don't know if null check semantic is
+ // preserved.
+ checkMethodIsMoved(companionClassName, outerClass, getter);
+ checkMethodIsMoved(companionClassName, outerClass, setter);
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ });
}
@Test
@@ -572,23 +600,32 @@
final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
"companionLateInitProperties_usePublicLateInitProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "publicLateInitProp";
- FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject outerClass =
+ checkClassIsKept(codeInspector, testedClass.getOuterClassName());
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+ // Companion class has been removed because of class staticizing.
+ String companionClassName = testedClass.getClassName();
+ checkClassIsRemoved(codeInspector, companionClassName);
- // Getter and setter cannot be inlined because we don't know if null check semantic is
- // preserved.
- checkMethodIsKept(companionClass, getter);
- checkMethodIsKept(companionClass, setter);
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- });
+ String propertyName = "publicLateInitProp";
+ FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+ // Getter and setter cannot be inlined because we don't know if null check semantic is
+ // preserved.
+ checkMethodIsMoved(companionClassName, outerClass, getter);
+ checkMethodIsMoved(companionClassName, outerClass, setter);
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ });
}
@Test
@@ -773,26 +810,28 @@
final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
String mainClass = addMainToClasspath(
"properties.FilePropertiesKt", "fileProperties_usePrimitiveProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "primitiveProp";
- FieldSubject fieldSubject = checkFieldIsKept(objectClass, "int", propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+ String propertyName = "primitiveProp";
+ FieldSubject fieldSubject = checkFieldIsKept(objectClass, "int", propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+ checkMethodIsRemoved(objectClass, getter);
+ checkMethodIsRemoved(objectClass, setter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(objectClass, getter);
- checkMethodIsRemoved(objectClass, setter);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(objectClass, getter);
- checkMethodIsKept(objectClass, setter);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -826,25 +865,29 @@
final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
String mainClass = addMainToClasspath(
"properties.FilePropertiesKt", "fileProperties_useInternalProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "internalProp";
- FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+ String propertyName = "internalProp";
+ FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- // We expect getter to be inlined when access (of the backing field) is relaxed to public.
- // Note: the setter is considered as a regular method (because of KotlinC adding extra null
- // checks), thus we cannot say if the setter would be inlined or not by R8.
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(objectClass, getter);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(objectClass, getter);
- }
- });
+ // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+ // Note: the setter is considered as a regular method (because of KotlinC adding extra
+ // null checks), thus we cannot say if the setter would be inlined or not by R8.
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ checkMethodIsRemoved(objectClass, getter);
+
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
@@ -852,26 +895,29 @@
final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
String mainClass = addMainToClasspath(
"properties.FilePropertiesKt", "fileProperties_usePublicProp");
- runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
- CodeInspector codeInspector = new CodeInspector(app);
- ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
- String propertyName = "publicProp";
- FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
- assertTrue(fieldSubject.getField().accessFlags.isStatic());
+ runTest(
+ PACKAGE_NAME,
+ mainClass,
+ disableAggressiveClassOptimizations,
+ (app) -> {
+ CodeInspector codeInspector = new CodeInspector(app);
+ ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+ String propertyName = "publicProp";
+ FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
+ assertTrue(fieldSubject.getField().accessFlags.isStatic());
- // We expect getter to be inlined when access (of the backing field) is relaxed to public.
- // On the other hand, the setter is considered as a regular method (because of null checks),
- // thus we cannot say if it can be inlined or not.
- MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+ // On the other hand, the setter is considered as a regular method (because of null
+ // checks), thus we cannot say if it can be inlined or not.
+ MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+ checkMethodIsRemoved(objectClass, getter);
- if (allowAccessModification) {
- assertTrue(fieldSubject.getField().accessFlags.isPublic());
- checkMethodIsRemoved(objectClass, getter);
- } else {
- assertTrue(fieldSubject.getField().accessFlags.isPrivate());
- checkMethodIsKept(objectClass, getter);
- }
- });
+ if (allowAccessModification) {
+ assertTrue(fieldSubject.getField().accessFlags.isPublic());
+ } else {
+ assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+ }
+ });
}
@Test
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 1e5d3f6..5cba429 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfiguration;
@@ -69,18 +68,15 @@
ExecutorService executor = ThreadUtils.getExecutorService(1);
- AppView<AppInfoWithSubtyping> appView =
- new AppView<>(new AppInfoWithSubtyping(program), GraphLense.getIdentityLense(), options);
+ AppView<? extends AppInfoWithSubtyping> appView =
+ AppView.createForR8(new AppInfoWithSubtyping(program), options);
RootSet rootSet =
new RootSetBuilder(appView, program, configuration.getRules(), options).run(executor);
Enqueuer enqueuer = new Enqueuer(appView, options, null);
AppInfoWithLiveness appInfo =
enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing);
- return new Minifier(
- new AppView<>(appInfo, GraphLense.getIdentityLense(), options),
- rootSet,
- Collections.emptySet())
+ return new Minifier(AppView.createForR8(appInfo, options), rootSet, Collections.emptySet())
.run(timing);
}
diff --git a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
index 7cb49d3..841b6cd 100644
--- a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.naming;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.position.Position;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Paths;
@@ -51,7 +52,7 @@
public void parseIdentifierArrowAmbiguity1() throws IOException {
ClassNameMapper mapper = ClassNameMapper.mapperFromString("a->b:");
ClassNameMapper.Builder builder = ClassNameMapper.builder();
- builder.classNamingBuilder("b", "a");
+ builder.classNamingBuilder("b", "a", Position.UNKNOWN);
Assert.assertEquals(builder.build(), mapper);
}
@@ -59,7 +60,7 @@
public void parseIdentifierArrowAmbiguity2() throws IOException {
ClassNameMapper mapper = ClassNameMapper.mapperFromString("-->b:");
ClassNameMapper.Builder builder = ClassNameMapper.builder();
- builder.classNamingBuilder("b", "-");
+ builder.classNamingBuilder("b", "-", Position.UNKNOWN);
Assert.assertEquals(builder.build(), mapper);
}
diff --git a/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java b/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java
new file mode 100644
index 0000000..91da18d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2019, 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.naming;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.utils.AbortException;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.Reporter;
+import java.io.IOException;
+import java.nio.file.Path;
+import org.junit.Test;
+
+public class SeedMapperTests extends TestBase {
+
+ private Path getApplyMappingFile(String... pgMap) throws IOException {
+ Path mapPath = temp.newFile().toPath();
+ FileUtils.writeTextFile(mapPath, pgMap);
+ return mapPath;
+ }
+
+ @Test
+ public void testNoDuplicates() throws IOException {
+ Path applyMappingFile =
+ getApplyMappingFile(
+ "A.B.C -> a:",
+ " int aaaa(B) -> a",
+ " int bbbb(B) -> b",
+ " void cccc() -> a",
+ " B foo -> a",
+ "A.B.D -> b:",
+ " int aaaa(B) -> a");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ testDiagnosticMessages.assertNoMessages();
+ }
+
+ @Test
+ public void testDuplicateSourceClasses() throws IOException {
+ Path applyMappingFile = getApplyMappingFile("A.B.C -> a:", "A.B.C -> b:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ try {
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ fail("Should have thrown an error");
+ } catch (AbortException e) {
+ assertEquals(1, testDiagnosticMessages.getErrors().size());
+ Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+ assertEquals(
+ String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "A.B.C"),
+ diagnostic.getDiagnosticMessage());
+ assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+ }
+ }
+
+ @Test
+ public void testDuplicateSourceMethods() throws IOException {
+ Path applyMappingFile =
+ getApplyMappingFile(
+ "A.B.C -> a:",
+ " int aaaa(B) -> a",
+ " int aaaa(B) -> a",
+ "A.B.D -> b:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ try {
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ fail("Should have thrown an error");
+ } catch (AbortException e) {
+ assertEquals(1, testDiagnosticMessages.getErrors().size());
+ Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+ assertEquals(
+ String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "int aaaa(B)"),
+ diagnostic.getDiagnosticMessage());
+ assertEquals(3, ((TextPosition) diagnostic.getPosition()).getLine());
+ }
+ }
+
+ @Test
+ public void testDuplicateSourceFields() throws IOException {
+ Path applyMappingFile =
+ getApplyMappingFile(
+ "A.B.C -> a:",
+ " int aaaa -> a",
+ " int aaaa -> a",
+ "A.B.D -> b:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ try {
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ fail("Should have thrown an error");
+ } catch (AbortException e) {
+ assertEquals(1, testDiagnosticMessages.getErrors().size());
+ Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+ assertEquals(
+ String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "int aaaa"),
+ diagnostic.getDiagnosticMessage());
+ assertEquals(3, ((TextPosition) diagnostic.getPosition()).getLine());
+ }
+ }
+
+ @Test
+ public void testDuplicateClassTargets() throws IOException {
+ Path applyMappingFile = getApplyMappingFile("A.B.C -> a:", "A.B.D -> a:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ try {
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ fail("Should have thrown an error");
+ } catch (AbortException e) {
+ assertEquals(1, testDiagnosticMessages.getErrors().size());
+ Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+ assertEquals(
+ String.format(ProguardMapError.DUPLICATE_TARGET_MESSAGE, "A.B.D", "A.B.C", "a"),
+ diagnostic.getDiagnosticMessage());
+ assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+ }
+ }
+
+ @Test
+ public void testSameNameMethodTargets() throws IOException {
+ Path applyMappingFile =
+ getApplyMappingFile(
+ "A.B.C -> A:",
+ " int foo(A) -> a",
+ " int bar(B) -> a",
+ " int baz(A,B) -> a",
+ "A.B.D -> b:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ testDiagnosticMessages.assertNoMessages();
+ }
+
+ @Test
+ public void testDuplicateMethodTargets() throws IOException {
+ Path applyMappingFile =
+ getApplyMappingFile(
+ "A.B.C -> a:",
+ " int foo(A) -> a",
+ " int bar(A) -> a",
+ "A.B.D -> b:");
+ TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+ Reporter reporter = new Reporter(testDiagnosticMessages);
+ try {
+ SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+ fail("Should have thrown an error");
+ } catch (AbortException e) {
+ assertEquals(1, testDiagnosticMessages.getErrors().size());
+ Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+ assertEquals(
+ String.format(ProguardMapError.DUPLICATE_TARGET_MESSAGE, "int bar(A)", "int foo(A)", "a"),
+ diagnostic.getDiagnosticMessage());
+ assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
index 048f281..0fdbe2d 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
@@ -76,7 +76,7 @@
// 2) otherwise, those classes/members will be renamed if minification is enabled, resulting in
// no name clash, which is definitely not intended.
- private String mappingToExistingClassName() {
+ private String mappingToAlreadyMappedName() {
return StringUtils.lines(
LibraryClass.class.getTypeName()
+ " -> " + AnotherLibraryClass.class.getTypeName() + ":",
@@ -102,6 +102,13 @@
);
}
+ private String mappingToExistingClassName() {
+ return StringUtils.lines(
+ LibraryClass.class.getTypeName() + " -> " + ProgramClass.class.getTypeName() + ":",
+ " void foo() -> bar",
+ AnotherLibraryClass.class.getTypeName() + " -> B:");
+ }
+
private String mappingToTheSameMethodName() {
return StringUtils.lines(
LibraryClass.class.getTypeName() + " -> A:",
@@ -188,7 +195,7 @@
@Test
public void testProguard_prgClassRenamedToExistingPrgClass() throws Exception {
- FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+ FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
try {
testProguard_inputJar(mappingFile);
fail("Expect compilation failure.");
@@ -198,22 +205,22 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_prgClassRenamedToExistingPrgClass() throws Exception {
- FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+ FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
try {
testR8_inputJar(mappingFile);
fail("Expect compilation failure.");
} catch (CompilationFailedException e) {
- assertThat(e.getCause().getMessage(), containsString("Program type already present"));
- assertThat(e.getCause().getMessage(), containsString("AnotherLibraryClass"));
+ assertThat(e.getCause().getMessage(), containsString("map to same name"));
+ assertThat(e.getCause().getMessage(), containsString("$AnotherLibraryClass"));
+ assertThat(e.getCause().getMessage(), containsString("$LibraryClass"));
}
}
@Test
public void testProguard_originalLibClassRenamedToExistingLibClass() throws Exception {
- FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+ FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
try {
testProguard_originalLibraryJar(mappingFile);
fail("Expect compilation failure.");
@@ -223,11 +230,17 @@
}
}
- @Ignore("b/123092153")
@Test
- public void testR8_originalLibClassRenamedToExistingLibClass() throws Exception {
- FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
- testR8_originalLibraryJar(mappingFile);
+ public void testR8_originalLibClassRenamedToSameLibClass() throws Exception {
+ FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
+ try {
+ testR8_originalLibraryJar(mappingFile);
+ fail("Expect compilation failure.");
+ } catch (CompilationFailedException e) {
+ assertThat(e.getCause().getMessage(), containsString("map to same name"));
+ assertThat(e.getCause().getMessage(), containsString("$AnotherLibraryClass"));
+ assertThat(e.getCause().getMessage(), containsString("$LibraryClass"));
+ }
}
@Test
@@ -241,7 +254,6 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_prgClassesRenamedToSameName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToTheSameClassName());
@@ -249,7 +261,7 @@
testR8_inputJar(mappingFile);
fail("Expect compilation failure.");
} catch (CompilationFailedException e) {
- assertThat(e.getCause().getMessage(), containsString("Program type already present"));
+ assertThat(e.getCause().getMessage(), containsString("map to same name"));
assertThat(e.getCause().getMessage(), containsString("Clash"));
}
}
@@ -266,11 +278,16 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_originalLibClassesRenamedToSameName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToTheSameClassName());
- testR8_originalLibraryJar(mappingFile);
+ try {
+ testR8_originalLibraryJar(mappingFile);
+ fail("Expect compilation failure.");
+ } catch (CompilationFailedException e) {
+ assertThat(e.getCause().getMessage(), containsString("map to same name"));
+ assertThat(e.getCause().getMessage(), containsString("Clash"));
+ }
}
@Test
@@ -286,7 +303,6 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_prgMethodRenamedToExistingName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToExistingMethodName());
@@ -294,9 +310,13 @@
testR8_inputJar(mappingFile);
fail("Expect compilation failure.");
} catch (CompilationFailedException e) {
- assertThat(e.getMessage(), containsString("method 'void bar()' can't be mapped to 'bar'"));
- assertThat(e.getMessage(), containsString("it would conflict with method 'foo'"));
- assertThat(e.getMessage(), containsString("which is already being mapped to 'bar'"));
+ assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'bar'"));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString(
+ "because it is in conflict with an existing member with the same signature."));
+ assertThat(
+ e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
}
}
@@ -312,11 +332,21 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_originalLibMethodRenamedToExistingName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToExistingMethodName());
- testR8_originalLibraryJar(mappingFile);
+ try {
+ testR8_originalLibraryJar(mappingFile);
+ fail("Expect compilation failure.");
+ } catch (CompilationFailedException e) {
+ assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'bar'"));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString(
+ "because it is in conflict with an existing member with the same signature."));
+ assertThat(
+ e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
+ }
}
@Test
@@ -332,7 +362,6 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_prgMethodRenamedToSameName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToTheSameMethodName());
@@ -340,9 +369,13 @@
testR8_inputJar(mappingFile);
fail("Expect compilation failure.");
} catch (CompilationFailedException e) {
- assertThat(e.getMessage(), containsString("method 'void bar()' can't be mapped to 'bar'"));
- assertThat(e.getMessage(), containsString("it would conflict with method 'foo'"));
- assertThat(e.getMessage(), containsString("which is already being mapped to 'bar'"));
+ assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'clash'"));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString(
+ "because it is in conflict with an existing member with the same signature."));
+ assertThat(
+ e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
}
}
@@ -358,11 +391,36 @@
}
}
- @Ignore("b/123092153")
@Test
public void testR8_originalLibMethodRenamedToSameName() throws Exception {
FileUtils.writeTextFile(mappingFile, mappingToTheSameMethodName());
- testR8_originalLibraryJar(mappingFile);
+ try {
+ testR8_originalLibraryJar(mappingFile);
+ fail("Expect compilation failure.");
+ } catch (CompilationFailedException e) {
+ assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'clash'"));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString(
+ "because it is in conflict with an existing member with the same signature."));
+ assertThat(
+ e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
+ }
+ }
+
+ @Test
+ public void testR8_originalLibClassRenamedToExistingName() throws Exception {
+ FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+ try {
+ testR8_originalLibraryJar(mappingFile);
+ fail("Expect compilation failure.");
+ } catch (CompilationFailedException e) {
+ assertThat(e.getCause().getMessage(), containsString("cannot be mapped to"));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString("because it is in conflict with an existing class with the same name."));
+ assertThat(e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName()));
+ }
}
@Test
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 7ec1613..a9ce818 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -12,7 +12,6 @@
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.GraphLense;
import com.android.tools.r8.resolution.singletarget.Main;
import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
import com.android.tools.r8.resolution.singletarget.one.AbstractTopClass;
@@ -105,8 +104,7 @@
AndroidApp app = readClassesAndAsmDump(CLASSES, ASM_CLASSES);
DexApplication application = new ApplicationReader(app, options, timing).read().toDirect();
AppView<? extends AppInfoWithSubtyping> appView =
- new AppView<>(
- new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+ AppView.createForR8(new AppInfoWithSubtyping(application), options);
ExecutorService executor = Executors.newSingleThreadExecutor();
RootSet rootSet =
diff --git a/third_party/opensource_apps.tar.gz.sha1 b/third_party/opensource_apps.tar.gz.sha1
index 1c81fa1..cf48de7 100644
--- a/third_party/opensource_apps.tar.gz.sha1
+++ b/third_party/opensource_apps.tar.gz.sha1
@@ -1 +1 @@
-402a7c84fe03ecba7e6c0ee7947fd215d981fd2e
\ No newline at end of file
+0d99c09e8fd3ab48bae4642147bcbff26a474ca8
\ No newline at end of file
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index b9e17ab..e0e2df1 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -138,7 +138,7 @@
Repo({
'name': 'chanu',
'url': 'https://github.com/mkj-gram/chanu.git',
- 'revision': '04ade1e9c33d707f0850d5eb9d6fa5e8af814a26',
+ 'revision': 'f5dae10b965974f7bf7cf75b8fa80ba9c844f102',
'apps': [
App({
'id': 'com.chanapps.four.activity'
@@ -208,7 +208,7 @@
Repo({
'name': 'rover-android',
'url': 'https://github.com/mkj-gram/rover-android.git',
- 'revision': '859af82ba56fe9035ae9949156c7a88e6012d930',
+ 'revision': 'a5e155a1ed7d19b1cecd9a7b075e2852623a06bf',
'apps': [
App({
'id': 'io.rover.app.debug',
@@ -219,7 +219,7 @@
Repo({
'name': 'Signal-Android',
'url': 'https://github.com/mkj-gram/Signal-Android.git',
- 'revision': 'a45d0c1fed20fa39e8b9445fe7790326f46b3166',
+ 'revision': 'cd542cab9bf860e71504ecb1caaf0a8476ba3989',
'apps': [
App({
'id': 'org.thoughtcrime.securesms',
@@ -284,7 +284,7 @@
Repo({
'name': 'Tusky',
'url': 'https://github.com/mkj-gram/Tusky.git',
- 'revision': 'b794f3ab90388add98461ffe70edb65c39351c33',
+ 'revision': 'e7fbd190fb53bf9fde72253b816920cb6fe34518',
'apps': [
App({
'id': 'com.keylesspalace.tusky',
@@ -295,7 +295,7 @@
Repo({
'name': 'Vungle-Android-SDK',
'url': 'https://github.com/mkj-gram/Vungle-Android-SDK.git',
- 'revision': '3e231396ea7ce97b2655e03607497c75730e45f6',
+ 'revision': '138d3f18c027b61b195c98911f1c5ab7d87ad18b',
'apps': [
App({
'id': 'com.publisher.vungle.sample'