Merge commit 'f748d174fc9b0a9606f70fc9a6350e81ebff0857' into dev-release
Change-Id: I7f7cec9c24ccb267feb20c39a73fe12327025341
diff --git a/doc/keepanno-guide.md b/doc/keepanno-guide.md
index 9970ae4..75d6b24 100644
--- a/doc/keepanno-guide.md
+++ b/doc/keepanno-guide.md
@@ -16,8 +16,20 @@
[R8 component](https://issuetracker.google.com/issues?q=status:open%20componentid:326788).
+## Table of contents
-## Introduction
+- [Introduction](#introduction)
+- [Build configuration](#build-configuration)
+- [Annotating code using reflection](#using-reflection)
+- [Annotating code used by reflection (or via JNI)](#used-by-reflection)
+- [Annotating APIs](#apis)
+- [Migrating rules to annotations](#migrating-rules)
+- [My use case is not covered!](#other-uses)
+- [Troubleshooting](#troubleshooting)
+
+
+
+## Introduction<a id="introduction"></a>
When using a Java/Kotlin shrinker such as R8 or Proguard, developers must inform
the shrinker about parts of the program that are used either externally from the
@@ -35,7 +47,7 @@
hopefully more clear and direct meaning.
-## Build configuration
+## Build configuration<a id="build-configuration"></a>
To use the keep annotations your build must include the library of
annotations. It is currently built as part of each R8 build and if used with R8,
@@ -61,7 +73,7 @@
# ... the rest of your R8 compilation command here ...
```
-### Annotating code using reflection
+## Annotating code using reflection<a id="using-reflection"></a>
The keep annotation library defines a family of annotations depending on your
use case. You should generally prefer [@UsesReflection](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/UsesReflection.html) where applicable.
@@ -96,18 +108,68 @@
+## Annotating code used by reflection (or via JNI)<a id="used-by-reflection"></a>
-### Annotating code used by reflection (or via JNI)
+TODO
+
+
+## Annotating APIs<a id="apis"></a>
+
+TODO
+
+
+## Migrating rules to annotations<a id="migrating-rules"></a>
+
+There is no automatic migration of keep rules. Keep annotations often invert the
+direction and rules have no indication of where the reflection is taking
+place or why. Thus, migrating existing keep rules requires user involvement.
+Keep rules also have a tendency to be very general, matching a large
+number of classes and members. Often the rules are much too broad and are
+keeping more than needed which will have a negative impact on the shrinkers
+ability to reduce size.
+
+First step in converting a rule is to determine the purpose of the rule. Is it
+API surface or is it reflection? Note that a very general rule may be covering
+several use cases and even a mix of both reflection and API usage.
+
+When migrating it is preferable to use [@UsesReflection](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/UsesReflection.html) instead of
+[@UsedByReflection](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/UsedByReflection.html). For very general rules it might not be easy or worth it to
+migrate without completely reevaluating the rule. If one still wants to replace
+it by annotations, the general [@KeepEdge](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/KeepEdge.html) can be used to define a context
+independent keep annotation.
+
+For example, to keep all main methods in the program one could use:
+
+
+```
+@KeepEdge(
+ consequences = {
+ @KeepTarget(
+ kind = KeepItemKind.CLASS_AND_MEMBERS,
+ methodName = "main",
+ methodReturnType = "void",
+ methodParameters = {"java.lang.String[]"},
+ methodAccess = {MethodAccessFlags.PUBLIC, MethodAccessFlags.STATIC})
+ })
+public class SomeClass {
+ // ...
+}
+```
-### Annotating APIs
+## My use case is not covered!<a id="other-uses"></a>
+
+The annotation library is in active development and not all use cases are
+described here or supported. Reach out to the R8 team by
+[filing a new issue in our tracker](https://issuetracker.google.com/issues/new?component=326788).
+Describe your use case and we will look at how best to support it.
-### Migrating rules to annotations
+## Troubleshooting<a id="troubleshooting"></a>
-
-### My use case is not covered!
-
-
-### Troubleshooting
+If an annotation is not working as expected it may be helpful to inspect the
+rules that have been extracted for the annotation. This can be done by
+inspecting the configuration output of the shrinker. For R8 you can use the
+command line argument `--pg-conf-output <path>` to emit the full configuration
+used by R8.
diff --git a/doc/keepanno-guide.template.md b/doc/keepanno-guide.template.md
index 6e0a8df..cfa98e2 100644
--- a/doc/keepanno-guide.template.md
+++ b/doc/keepanno-guide.template.md
@@ -13,8 +13,10 @@
[R8 component](https://issuetracker.google.com/issues?q=status:open%20componentid:326788).
+[[[TOC]]]
-## Introduction
+
+## [Introduction](introduction)
When using a Java/Kotlin shrinker such as R8 or Proguard, developers must inform
the shrinker about parts of the program that are used either externally from the
@@ -32,7 +34,7 @@
hopefully more clear and direct meaning.
-## Build configuration
+## [Build configuration](build-configuration)
To use the keep annotations your build must include the library of
annotations. It is currently built as part of each R8 build and if used with R8,
@@ -58,7 +60,7 @@
# ... the rest of your R8 compilation command here ...
```
-### Annotating code using reflection
+## [Annotating code using reflection](using-reflection)
The keep annotation library defines a family of annotations depending on your
use case. You should generally prefer `@UsesReflection` where applicable.
@@ -68,18 +70,53 @@
[[[INCLUDE CODE:UsesReflectionOnVirtualMethod]]]
+## [Annotating code used by reflection (or via JNI)](used-by-reflection)
-### Annotating code used by reflection (or via JNI)
+TODO
+## [Annotating APIs](apis)
-### Annotating APIs
+TODO
-### Migrating rules to annotations
+## [Migrating rules to annotations](migrating-rules)
+
+There is no automatic migration of keep rules. Keep annotations often invert the
+direction and rules have no indication of where the reflection is taking
+place or why. Thus, migrating existing keep rules requires user involvement.
+Keep rules also have a tendency to be very general, matching a large
+number of classes and members. Often the rules are much too broad and are
+keeping more than needed which will have a negative impact on the shrinkers
+ability to reduce size.
+
+First step in converting a rule is to determine the purpose of the rule. Is it
+API surface or is it reflection? Note that a very general rule may be covering
+several use cases and even a mix of both reflection and API usage.
+
+When migrating it is preferable to use `@UsesReflection` instead of
+`@UsedByReflection`. For very general rules it might not be easy or worth it to
+migrate without completely reevaluating the rule. If one still wants to replace
+it by annotations, the general `@KeepEdge` can be used to define a context
+independent keep annotation.
+
+[[[INCLUDE DOC:KeepMainMethods]]]
+
+[[[INCLUDE CODE:KeepMainMethods]]]
-### My use case is not covered!
+## [My use case is not covered!](other-uses)
+
+The annotation library is in active development and not all use cases are
+described here or supported. Reach out to the R8 team by
+[filing a new issue in our tracker](https://issuetracker.google.com/issues/new?component=326788).
+Describe your use case and we will look at how best to support it.
-### Troubleshooting
+## [Troubleshooting](troubleshooting)
+
+If an annotation is not working as expected it may be helpful to inspect the
+rules that have been extracted for the annotation. This can be done by
+inspecting the configuration output of the shrinker. For R8 you can use the
+command line argument `--pg-conf-output <path>` to emit the full configuration
+used by R8.
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 09a8ceb..07b3ef5 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -131,7 +131,8 @@
private GraphConsumer keptGraphConsumer = null;
private GraphConsumer mainDexKeptGraphConsumer = null;
private InputDependencyGraphConsumer inputDependencyGraphConsumer = null;
- private final List<FeatureSplit> featureSplits = new ArrayList<>();
+ private final FeatureSplitConfiguration.Builder featureSplitConfigurationBuilder =
+ FeatureSplitConfiguration.builder();
private String synthesizedClassPrefix = "";
private boolean enableMissingLibraryApiModeling = false;
private boolean enableExperimentalKeepAnnotations =
@@ -354,6 +355,11 @@
return self();
}
+ /** Get the consumer for receiving the proguard configuration information if set. */
+ public StringConsumer getProguardConfigurationConsumer() {
+ return proguardConfigurationConsumer;
+ }
+
/**
* Set a consumer for receiving kept-graph events.
*/
@@ -441,7 +447,7 @@
public Builder addFeatureSplit(
Function<FeatureSplit.Builder, FeatureSplit> featureSplitGenerator) {
FeatureSplit featureSplit = featureSplitGenerator.apply(FeatureSplit.builder(getReporter()));
- featureSplits.add(featureSplit);
+ featureSplitConfigurationBuilder.addFeatureSplit(featureSplit);
for (ProgramResourceProvider programResourceProvider : featureSplit
.getProgramResourceProviders()) {
// Data resources are handled separately and passed directly to the feature split consumer.
@@ -462,6 +468,18 @@
}
/**
+ * Used to specify if the application is using isolated splits, i.e., if split APKs installed
+ * for this application are loaded into their own Context objects.
+ *
+ * <p>See also <a href="https://developer.android.com/reference/android/R.attr#isolatedSplits">
+ * R.attr#isolatedSplits</a>.
+ */
+ public Builder setEnableExperimentalIsolatedSplits(boolean enableIsolatedSplits) {
+ featureSplitConfigurationBuilder.setEnableIsolatedSplits(enableIsolatedSplits);
+ return this;
+ }
+
+ /**
* Enable experimental/pre-release support for modeling missing library APIs.
*
* <p>This allows enabling the feature while it is still default disabled by the compiler. Once
@@ -575,7 +593,7 @@
+ " and above");
}
}
- for (FeatureSplit featureSplit : featureSplits) {
+ for (FeatureSplit featureSplit : featureSplitConfigurationBuilder.getFeatureSplits()) {
verifyResourceSplitOrProgramSplit(featureSplit);
if (getProgramConsumer() != null && !(getProgramConsumer() instanceof DexIndexedConsumer)) {
reporter.error("R8 does not support class file output when using feature splits");
@@ -662,9 +680,6 @@
? DesugarState.OFF
: getDesugaringState();
- FeatureSplitConfiguration featureSplitConfiguration =
- !featureSplits.isEmpty() ? new FeatureSplitConfiguration(featureSplits) : null;
-
R8Command command =
new R8Command(
getAppBuilder().build(),
@@ -693,7 +708,7 @@
getDexClassChecksumFilter(),
desugaredLibraryKeepRuleConsumer,
desugaredLibrarySpecification,
- featureSplitConfiguration,
+ featureSplitConfigurationBuilder.build(),
getAssertionsConfiguration(),
getOutputInspections(),
synthesizedClassPrefix,
@@ -1289,6 +1304,7 @@
.setMinification(getEnableMinification())
.setForceProguardCompatibility(forceProguardCompatibility)
.setFeatureSplitConfiguration(featureSplitConfiguration)
+ .setAndroidResourceProvider(androidResourceProvider)
.setProguardConfiguration(proguardConfiguration)
.setMainDexKeepRules(mainDexKeepRules)
.setDesugaredLibraryConfiguration(desugaredLibrarySpecification)
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index 460a7d7..b407f34 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -165,6 +165,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 0c25941..068d034 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -34,6 +34,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index cd21707..a97e1ea 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -67,6 +67,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index aee2e6f..0cad424 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -75,6 +75,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index f450da4..091aa57 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -90,11 +90,12 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- DexType rewrittenType = graphLens.lookupType(type);
+ DexType rewrittenType = graphLens.lookupType(type, codeLens);
visitor.visitTypeInsn(Opcodes.CHECKCAST, namingLens.lookupInternalName(rewrittenType));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index 5b35a3e..6ca820e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -110,6 +110,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index bc226cb..151be2a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -103,11 +103,12 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- visitor.visitLdcInsn(Type.getObjectType(getInternalName(graphLens, namingLens)));
+ visitor.visitLdcInsn(Type.getObjectType(getInternalName(graphLens, codeLens, namingLens)));
}
@Override
@@ -126,8 +127,8 @@
return true;
}
- private String getInternalName(GraphLens graphLens, NamingLens namingLens) {
- DexType rewrittenType = graphLens.lookupType(type);
+ private String getInternalName(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
+ DexType rewrittenType = graphLens.lookupType(type, codeLens);
switch (rewrittenType.toShorty()) {
case '[':
case 'L':
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
index 9f3f073..d47a830 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
@@ -155,6 +155,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
@@ -172,15 +173,15 @@
ConstantDynamic constantDynamic =
new ConstantDynamic(
reference.getName().toString(),
- getConstantTypeDescriptor(graphLens, namingLens, dexItemFactory),
+ getConstantTypeDescriptor(graphLens, codeLens, namingLens, dexItemFactory),
rewrittenHandle.toAsmHandle(namingLens),
bsmArgs);
visitor.visitLdcInsn(constantDynamic);
}
private String getConstantTypeDescriptor(
- GraphLens graphLens, NamingLens namingLens, DexItemFactory factory) {
- DexType rewrittenType = graphLens.lookupType(reference.getType());
+ GraphLens graphLens, GraphLens codeLens, NamingLens namingLens, DexItemFactory factory) {
+ DexType rewrittenType = graphLens.lookupType(reference.getType(), codeLens);
DexType renamedType = namingLens.lookupType(rewrittenType, factory);
return renamedType.toDescriptorString();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index e02b1fe..9c59d83 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -63,6 +63,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index 7e8d519..b9f5d88 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -63,6 +63,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index 75eb939..5e6485a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -34,6 +34,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 21dbd68..991ed9d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -93,6 +93,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index 9756641..d60203a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -73,6 +73,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index 9bf20e3..b350e1f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -80,6 +80,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index 9045c59..9d91db7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -102,12 +102,13 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- DexField rewrittenField = graphLens.lookupField(field);
- DexField rewrittenDeclaringField = graphLens.lookupField(declaringField);
+ DexField rewrittenField = graphLens.lookupField(field, codeLens);
+ DexField rewrittenDeclaringField = graphLens.lookupField(declaringField, codeLens);
String owner = namingLens.lookupInternalName(rewrittenField.holder);
String name = namingLens.lookupName(rewrittenDeclaringField).toString();
String desc = namingLens.lookupDescriptor(rewrittenField.type).toString();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 6813ed1..c8308b4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -182,14 +182,15 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
int stackCount = computeStackCount();
- Object[] stackTypes = computeStackTypes(stackCount, graphLens, namingLens);
+ Object[] stackTypes = computeStackTypes(stackCount, graphLens, codeLens, namingLens);
int localsCount = computeLocalsCount();
- Object[] localsTypes = computeLocalsTypes(localsCount, graphLens, namingLens);
+ Object[] localsTypes = computeLocalsTypes(localsCount, graphLens, codeLens, namingLens);
visitor.visitFrame(F_NEW, localsCount, localsTypes, stackCount, stackTypes);
}
@@ -210,7 +211,8 @@
return size;
}
- private Object[] computeStackTypes(int stackCount, GraphLens graphLens, NamingLens namingLens) {
+ private Object[] computeStackTypes(
+ int stackCount, GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
assert stackCount == stack.size();
if (stackCount == 0) {
return null;
@@ -218,7 +220,7 @@
Object[] stackTypes = new Object[stackCount];
int index = 0;
for (PreciseFrameType frameType : stack) {
- stackTypes[index++] = frameType.getTypeOpcode(graphLens, namingLens);
+ stackTypes[index++] = frameType.getTypeOpcode(graphLens, codeLens, namingLens);
}
return stackTypes;
}
@@ -240,7 +242,8 @@
return localsCount;
}
- private Object[] computeLocalsTypes(int localsCount, GraphLens graphLens, NamingLens namingLens) {
+ private Object[] computeLocalsTypes(
+ int localsCount, GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
if (localsCount == 0) {
return null;
}
@@ -250,7 +253,7 @@
for (int i = 0; i <= maxRegister; i++) {
FrameType type = locals.get(i);
localsTypes[localIndex++] =
- type == null ? Opcodes.TOP : type.getTypeOpcode(graphLens, namingLens);
+ type == null ? Opcodes.TOP : type.getTypeOpcode(graphLens, codeLens, namingLens);
if (type != null && type.isWide()) {
i++;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index 48fe920..29dd22a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -85,6 +85,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index 25dfd77..0ac4689 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -92,6 +92,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index ee9ece8..24fc552 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -92,6 +92,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index 063f778..7a4ba0a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -65,6 +65,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
index 440f799f..21608ae 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -74,13 +74,14 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
// We intentionally apply the graph lens first, and then the init class lens, using the fact
// that the init class lens maps classes in the final program to fields in the final program.
- DexType rewrittenClass = graphLens.lookupType(clazz);
+ DexType rewrittenClass = graphLens.lookupType(clazz, codeLens);
DexField clinitField = initClassLens.getInitClassField(rewrittenClass);
String owner = namingLens.lookupInternalName(clinitField.holder);
String name = namingLens.lookupName(clinitField).toString();
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index 9a0308e..ec34784 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -89,11 +89,12 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- DexType rewrittenType = graphLens.lookupType(getType());
+ DexType rewrittenType = graphLens.lookupType(getType(), codeLens);
visitor.visitTypeInsn(Opcodes.INSTANCEOF, namingLens.lookupInternalName(rewrittenType));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index b13fbe8..ff95325 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -41,6 +41,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 8a87dd0..bcbe536 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -106,6 +106,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
@@ -124,7 +125,7 @@
itf);
} else {
MethodLookupResult lookup =
- graphLens.lookupMethod(method, context.getReference(), invokeType);
+ graphLens.lookupMethod(method, context.getReference(), invokeType, codeLens);
InvokeType rewrittenType = lookup.getType();
DexMethod rewrittenMethod = lookup.getReference();
String owner = namingLens.lookupInternalName(rewrittenMethod.holder);
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index c174214..79ba7f9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -79,6 +79,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index 6abd7ae..7ab3052 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -60,6 +60,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index 0cb0665..29701e6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -73,6 +73,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index 0479271..a0b7fdc 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -89,6 +89,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index a173410..14f30b1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -139,6 +139,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index edfb91a..d7ef8ee 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -61,6 +61,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index 344e65b..85f09af 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -91,11 +91,12 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- DexType rewrittenType = graphLens.lookupType(getType());
+ DexType rewrittenType = graphLens.lookupType(getType(), codeLens);
visitor.visitMultiANewArrayInsn(namingLens.lookupInternalName(rewrittenType), dimensions);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index d861c19..61216c1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -62,6 +62,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index e6a51f8..9e0af9c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -107,11 +107,12 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- DexType rewrittenType = graphLens.lookupType(getType());
+ DexType rewrittenType = graphLens.lookupType(getType(), codeLens);
visitor.visitTypeInsn(Opcodes.NEW, namingLens.lookupInternalName(rewrittenType));
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 5c2a657..943252d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -101,7 +101,10 @@
}
private String getElementInternalName(
- DexItemFactory dexItemFactory, GraphLens graphLens, NamingLens namingLens) {
+ DexItemFactory dexItemFactory,
+ GraphLens graphLens,
+ GraphLens codeLens,
+ NamingLens namingLens) {
assert !type.isPrimitiveArrayType();
StringBuilder renamedElementDescriptor = new StringBuilder();
// Intentionally starting from 1 to get the element descriptor.
@@ -110,7 +113,7 @@
renamedElementDescriptor.append("[");
}
DexType baseType = getType().toBaseType(dexItemFactory);
- DexType rewrittenBaseType = graphLens.lookupType(baseType);
+ DexType rewrittenBaseType = graphLens.lookupType(baseType, codeLens);
renamedElementDescriptor.append(
namingLens.lookupDescriptor(rewrittenBaseType).toSourceString());
return DescriptorUtils.descriptorToInternalName(renamedElementDescriptor.toString());
@@ -122,6 +125,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
@@ -130,7 +134,8 @@
visitor.visitIntInsn(Opcodes.NEWARRAY, getPrimitiveTypeCode());
} else {
visitor.visitTypeInsn(
- Opcodes.ANEWARRAY, getElementInternalName(dexItemFactory, graphLens, namingLens));
+ Opcodes.ANEWARRAY,
+ getElementInternalName(dexItemFactory, graphLens, codeLens, namingLens));
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
index 5864372..11efcd1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
@@ -83,6 +83,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index 139c2a7..fd5d76c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -49,6 +49,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index 856cc36..32a1d4f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -72,6 +72,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index 6a442c3..9e4bae3 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -63,6 +63,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
index 98c1e78..c34d876 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
@@ -48,6 +48,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index bddd05e..725acb1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -94,6 +94,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index 0a96d17..0197fc2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -59,6 +59,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index e3b70f6..7679a02 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -107,6 +107,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index 279014d..f59bfb6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -87,6 +87,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index f54eaa1..f190ae4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -125,6 +125,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index 4bdf343..f59f162 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -70,6 +70,7 @@
ProgramMethod context,
DexItemFactory dexItemFactory,
GraphLens graphLens,
+ GraphLens codeLens,
InitClassLens initClassLens,
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/BooleanFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/BooleanFrameType.java
index b0ec955..50e26e6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/BooleanFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/BooleanFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable("Unexpected value type: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/ByteFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/ByteFrameType.java
index e6aa4da..5fcbec8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/ByteFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/ByteFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable("Unexpected value type: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/CharFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/CharFrameType.java
index 8dc437d..81c1084 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/CharFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/CharFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable("Unexpected value type: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/DoubleFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/DoubleFrameType.java
index 7ad8dc2..2c14eb0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/DoubleFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/DoubleFrameType.java
@@ -62,7 +62,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.DOUBLE;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/DoubleHighFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/DoubleHighFrameType.java
index 655fa52..056eaf3 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/DoubleHighFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/DoubleHighFrameType.java
@@ -52,7 +52,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/FloatFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/FloatFrameType.java
index 9cc991a..8597b0e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/FloatFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/FloatFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.FLOAT;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
index 9db9a68..ba7cf84 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/FrameType.java
@@ -176,7 +176,7 @@
DexType getObjectType(DexItemFactory dexItemFactory, DexType context);
- Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens);
+ Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens);
CfLabel getUninitializedLabel();
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithInterfaces.java b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithInterfaces.java
index c92d003..16dceeb 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithInterfaces.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithInterfaces.java
@@ -55,7 +55,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable(
"Unexpected InitializedNonNullReferenceFrameTypeWithInterfaces in writer");
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithoutInterfaces.java b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithoutInterfaces.java
index a7475f8..7d09140 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithoutInterfaces.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/InitializedNonNullReferenceFrameTypeWithoutInterfaces.java
@@ -54,8 +54,8 @@
@Override
@SuppressWarnings("ReferenceEquality")
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
- DexType rewrittenType = graphLens.lookupType(type);
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
+ DexType rewrittenType = graphLens.lookupType(type, codeLens);
assert rewrittenType != DexItemFactory.nullValueType;
switch (rewrittenType.toShorty()) {
case 'L':
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/IntFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/IntFrameType.java
index 0f802b4..ad66a51 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/IntFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/IntFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.INTEGER;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/LongFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/LongFrameType.java
index a73ab16..cda7263 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/LongFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/LongFrameType.java
@@ -62,7 +62,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.LONG;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/LongHighFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/LongHighFrameType.java
index f2c5c9a..291cae7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/LongHighFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/LongHighFrameType.java
@@ -52,7 +52,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/NullFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/NullFrameType.java
index be3fa37..007bfd7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/NullFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/NullFrameType.java
@@ -78,7 +78,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.NULL;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java b/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
index 3153ef8..47e37f5 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/OneWord.java
@@ -33,7 +33,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.TOP;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/ShortFrameType.java b/src/main/java/com/android/tools/r8/cf/code/frame/ShortFrameType.java
index 82f0279..46d0316 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/ShortFrameType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/ShortFrameType.java
@@ -27,7 +27,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable("Unexpected value type: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/TwoWord.java b/src/main/java/com/android/tools/r8/cf/code/frame/TwoWord.java
index 95cab6f..2b5a049 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/TwoWord.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/TwoWord.java
@@ -41,7 +41,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
throw new Unreachable("Should only be used for verification");
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
index eadec8a..9159f99 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedNew.java
@@ -30,7 +30,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return label.getLabel();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
index a1654ab..ff15b98 100644
--- a/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
+++ b/src/main/java/com/android/tools/r8/cf/code/frame/UninitializedThis.java
@@ -24,7 +24,7 @@
}
@Override
- public Object getTypeOpcode(GraphLens graphLens, NamingLens namingLens) {
+ public Object getTypeOpcode(GraphLens graphLens, GraphLens codeLens, NamingLens namingLens) {
return Opcodes.UNINITIALIZED_THIS;
}
diff --git a/src/main/java/com/android/tools/r8/dex/DebugBytecodeWriter.java b/src/main/java/com/android/tools/r8/dex/DebugBytecodeWriter.java
index e314417..0b4b15c 100644
--- a/src/main/java/com/android/tools/r8/dex/DebugBytecodeWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/DebugBytecodeWriter.java
@@ -16,19 +16,24 @@
private final ObjectToOffsetMapping mapping;
private final GraphLens graphLens;
+ private final GraphLens codeLens;
private final DexDebugInfoForWriting info;
private ByteBuffer buffer;
public DebugBytecodeWriter(
- DexDebugInfoForWriting info, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DexDebugInfoForWriting info,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
this.info = info;
this.mapping = mapping;
this.graphLens = graphLens;
+ this.codeLens = codeLens;
this.buffer = ByteBuffer.allocate(info.estimatedWriteSize());
}
public byte[] generate() {
- info.write(this, mapping, graphLens);
+ info.write(this, mapping, graphLens, codeLens);
return Arrays.copyOf(buffer.array(), buffer.position());
}
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 0744b77..3aa1c44 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -235,10 +235,10 @@
layout.setDebugInfosOffset(dest.align(1));
Set<DexDebugInfoForWriting> seen = new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
for (ProgramMethod method : codes) {
- DexDebugInfoForWriting info =
- method.getDefinition().getCode().asDexWritableCode().getDebugInfoForWriting();
+ DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
+ DexDebugInfoForWriting info = code.getDebugInfoForWriting();
if (info != null && seen.add(info)) {
- writeDebugItem(info);
+ writeDebugItem(code, info);
}
}
}
@@ -485,6 +485,7 @@
}
private int sizeOfCodeItem(DexWritableCode code) {
+ GraphLens codeLens = code.getCodeLens(appView);
int result = 16;
int insnSize = code.codeSizeInBytes();
result += insnSize * 2;
@@ -497,7 +498,7 @@
result += LebUtils
.sizeAsSleb128(hasCatchAll ? -handler.pairs.length : handler.pairs.length);
for (TypeAddrPair pair : handler.pairs) {
- result += sizeAsUleb128(mapping.getOffsetFor(pair.getType(graphLens)));
+ result += sizeAsUleb128(mapping.getOffsetFor(pair.getType(graphLens, codeLens)));
result += sizeAsUleb128(pair.addr);
}
if (hasCatchAll) {
@@ -562,12 +563,14 @@
mixedSectionOffsets.getOffsetFor(mixedSectionOffsets.getStaticFieldValuesForClass(clazz)));
}
- private void writeDebugItem(DexDebugInfoForWriting debugInfo) {
+ private void writeDebugItem(DexWritableCode code, DexDebugInfoForWriting debugInfo) {
+ GraphLens codeLens = code.getCodeLens(appView);
mixedSectionOffsets.setOffsetFor(debugInfo, dest.position());
- dest.putBytes(new DebugBytecodeWriter(debugInfo, mapping, graphLens).generate());
+ dest.putBytes(new DebugBytecodeWriter(debugInfo, mapping, graphLens, codeLens).generate());
}
private int writeCodeItem(ProgramMethod method, DexWritableCode code) {
+ GraphLens codeLens = code.getCodeLens(appView);
int codeOffset = dest.align(4);
mixedSectionOffsets.setOffsetFor(method.getDefinition(), codeOffset);
// Fixed size header information.
@@ -600,9 +603,9 @@
boolean hasCatchAll = handler.catchAllAddr != TryHandler.NO_HANDLER;
dest.putSleb128(hasCatchAll ? -handler.pairs.length : handler.pairs.length);
for (TypeAddrPair pair : handler.pairs) {
- dest.putUleb128(mapping.getOffsetFor(pair.getType(graphLens)));
+ dest.putUleb128(mapping.getOffsetFor(pair.getType(graphLens, codeLens)));
dest.putUleb128(pair.addr);
- desugaredLibraryCodeToKeep.recordClass(pair.getType(graphLens));
+ desugaredLibraryCodeToKeep.recordClass(pair.getType(graphLens, codeLens));
}
if (hasCatchAll) {
dest.putUleb128(handler.catchAllAddr);
diff --git a/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java b/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
index b98df1c..1a2f918 100644
--- a/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
+++ b/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.graph.DexWritableCode;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.profile.startup.profile.StartupProfile;
import com.android.tools.r8.profile.startup.profile.StartupProfileClassRule;
@@ -124,7 +125,8 @@
methodReference.collectIndexedItems(appView, indexedItemCollection);
if (indexedItemCollection.addCode(method)) {
DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
- code.collectIndexedItems(appView, indexedItemCollection, method, rewriter);
+ GraphLens codeLens = code.getCodeLens(appView);
+ code.collectIndexedItems(appView, codeLens, indexedItemCollection, method, rewriter);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexCheckCast.java b/src/main/java/com/android/tools/r8/dex/code/DexCheckCast.java
index 224f94a..c0012cb 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexCheckCast.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexCheckCast.java
@@ -62,10 +62,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -77,7 +78,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = graphLens.lookupType(getType());
+ DexType rewritten = graphLens.lookupType(getType(), codeLens);
writeFirst(AA, dest);
write16BitReference(rewritten, dest, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexConstClass.java b/src/main/java/com/android/tools/r8/dex/code/DexConstClass.java
index b4a593e..0013063 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexConstClass.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexConstClass.java
@@ -62,10 +62,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -77,7 +78,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = graphLens.lookupType(getType());
+ DexType rewritten = graphLens.lookupType(getType(), codeLens);
writeFirst(AA, dest);
write16BitReference(rewritten, dest, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexConstMethodHandle.java b/src/main/java/com/android/tools/r8/dex/code/DexConstMethodHandle.java
index 7aa77db..f9ee91b 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexConstMethodHandle.java
@@ -95,6 +95,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexConstMethodType.java b/src/main/java/com/android/tools/r8/dex/code/DexConstMethodType.java
index 485b3da..bef8628 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexConstMethodType.java
@@ -91,6 +91,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexConstString.java b/src/main/java/com/android/tools/r8/dex/code/DexConstString.java
index b95b247..7ed956d 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexConstString.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexConstString.java
@@ -43,6 +43,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArray.java b/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArray.java
index 72fac38..d3815e8 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArray.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArray.java
@@ -46,10 +46,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -75,7 +76,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = graphLens.lookupType(getType());
+ DexType rewritten = graphLens.lookupType(getType(), codeLens);
writeFirst(A, G, dest);
write16BitReference(rewritten, dest, mapping);
write16BitValue(combineBytes(makeByte(F, E), makeByte(D, C)), dest);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArrayRange.java b/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArrayRange.java
index 436ec57..d26b547 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArrayRange.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFilledNewArrayRange.java
@@ -46,10 +46,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -75,7 +76,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = graphLens.lookupType(getType());
+ DexType rewritten = graphLens.lookupType(getType(), codeLens);
writeFirst(AA, dest);
write16BitReference(rewritten, dest, mapping);
write16BitValue(CCCC, dest);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat10t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat10t.java
index eaee763..1f1567c 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat10t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat10t.java
@@ -69,6 +69,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat10x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat10x.java
index 3071bfa..bdfca29 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat10x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat10x.java
@@ -46,6 +46,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat11n.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat11n.java
index 5796308..82c165e 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat11n.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat11n.java
@@ -79,6 +79,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat11x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat11x.java
index ef59bfb..cedd4a9 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat11x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat11x.java
@@ -69,6 +69,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat12x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat12x.java
index 05a6b22..12d53d2 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat12x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat12x.java
@@ -77,6 +77,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat20t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat20t.java
index d398e0d..d4d90c5 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat20t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat20t.java
@@ -69,6 +69,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat21h.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat21h.java
index 5dfec30..144d491 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat21h.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat21h.java
@@ -68,6 +68,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat21s.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat21s.java
index 8ccce8c..254efee 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat21s.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat21s.java
@@ -80,6 +80,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat21t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat21t.java
index 55eaac6..696b5bc 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat21t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat21t.java
@@ -98,6 +98,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat22b.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat22b.java
index d3bb2df..6334bc5 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat22b.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat22b.java
@@ -85,6 +85,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat22s.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat22s.java
index fc22957..f01a75b 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat22s.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat22s.java
@@ -85,6 +85,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat22t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat22t.java
index 00b22c1..bec44e3 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat22t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat22t.java
@@ -102,6 +102,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat22x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat22x.java
index 0dedb95..1077ce0 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat22x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat22x.java
@@ -79,6 +79,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat23x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat23x.java
index bcadc94..fab119f 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat23x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat23x.java
@@ -83,6 +83,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat30t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat30t.java
index 18c9137..a65da4f 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat30t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat30t.java
@@ -68,6 +68,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat31c.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat31c.java
index 695779e..9895905 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat31c.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat31c.java
@@ -77,6 +77,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat31i.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat31i.java
index d2eed2d..d0a2932 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat31i.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat31i.java
@@ -73,6 +73,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat31t.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat31t.java
index 2e7de21..28b16eb 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat31t.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat31t.java
@@ -88,6 +88,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat32x.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat32x.java
index dd6f6bf..fd8ae9d 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat32x.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat32x.java
@@ -81,6 +81,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
index a8935b6..6506871 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
@@ -102,13 +102,14 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
MethodLookupResult lookup =
appView
.graphLens()
- .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC);
+ .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC, codeLens);
assert lookup.getType() == InvokeType.POLYMORPHIC;
lookup.getReference().collectIndexedItems(appView, indexedItems);
@@ -130,7 +131,7 @@
assert rewriter.dexItemFactory().polymorphicMethods.isPolymorphicInvoke(getMethod());
assert getMethod()
== graphLens
- .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC)
+ .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC, codeLens)
.getReference();
DexProto rewrittenProto = rewriter.rewriteProto(getProto());
writeFirst(A, G, dest);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
index fcf77ed..0418db4 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
@@ -66,7 +66,7 @@
assert rewriter.dexItemFactory().polymorphicMethods.isPolymorphicInvoke(getMethod());
assert getMethod()
== graphLens
- .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC)
+ .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC, codeLens)
.getReference();
DexProto rewrittenProto = rewriter.rewriteProto(getProto());
writeFirst(AA, dest);
@@ -116,13 +116,14 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
MethodLookupResult lookup =
appView
.graphLens()
- .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC);
+ .lookupMethod(getMethod(), context.getReference(), InvokeType.POLYMORPHIC, codeLens);
assert lookup.getType() == InvokeType.POLYMORPHIC;
lookup.getReference().collectIndexedItems(appView, indexedItems);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat51l.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat51l.java
index a135f5b..bf29e4b 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat51l.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat51l.java
@@ -73,6 +73,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexIgetOrIput.java b/src/main/java/com/android/tools/r8/dex/code/DexIgetOrIput.java
index 8edfdf6..26330f6 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexIgetOrIput.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexIgetOrIput.java
@@ -25,10 +25,11 @@
@Override
public final void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexField rewritten = appView.graphLens().lookupField(getField());
+ DexField rewritten = appView.graphLens().lookupField(getField(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java b/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java
index 76a3289..47a4392 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java
@@ -49,12 +49,13 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
// We intentionally apply the graph lens first, and then the init class lens, using the fact
// that the init class lens maps classes in the final program to fields in the final program.
- DexType rewrittenClass = appView.graphLens().lookupType(clazz);
+ DexType rewrittenClass = appView.graphLens().lookupType(clazz, codeLens);
DexField clinitField = appView.initClassLens().getInitClassField(rewrittenClass);
clinitField.collectIndexedItems(appView, indexedItems);
}
@@ -123,7 +124,7 @@
LensCodeRewriterUtils rewriter) {
// We intentionally apply the graph lens first, and then the init class lens, using the fact
// that the init class lens maps classes in the final program to fields in the final program.
- DexType rewrittenClass = graphLens.lookupType(clazz);
+ DexType rewrittenClass = graphLens.lookupType(clazz, codeLens);
DexField clinitField = mapping.getClinitField(rewrittenClass);
writeFirst(dest, buffer, getOpcode(clinitField));
write16BitReference(clinitField, buffer, mapping);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInstanceOf.java b/src/main/java/com/android/tools/r8/dex/code/DexInstanceOf.java
index a85b4a3..386a942 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInstanceOf.java
@@ -57,10 +57,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -91,7 +92,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType lookup = graphLens.lookupType(getType());
+ DexType lookup = graphLens.lookupType(getType(), codeLens);
writeFirst(B, A, dest);
write16BitReference(lookup, dest, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInstruction.java b/src/main/java/com/android/tools/r8/dex/code/DexInstruction.java
index 12fc104..545528a 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInstruction.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInstruction.java
@@ -407,6 +407,7 @@
public abstract void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustom.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustom.java
index 21dd606..27f54c4 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustom.java
@@ -47,6 +47,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustomRange.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustomRange.java
index 3bc4796..93096bd 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustomRange.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeCustomRange.java
@@ -47,6 +47,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
index 763b823..2a31f06 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
@@ -27,13 +27,14 @@
@Override
public final void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
DexMethod rewritten =
appView
.graphLens()
- .lookupMethod(getMethod(), context.getReference(), getInvokeType())
+ .lookupMethod(getMethod(), context.getReference(), getInvokeType(), codeLens)
.getReference();
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -54,7 +55,7 @@
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
MethodLookupResult lookup =
- graphLens.lookupMethod(getMethod(), context.getReference(), getInvokeType());
+ graphLens.lookupMethod(getMethod(), context.getReference(), getInvokeType(), codeLens);
writeFirst(A, G, dest, lookup.getType().getDexOpcode());
write16BitReference(lookup.getReference(), dest, mapping);
write16BitValue(combineBytes(makeByte(F, E), makeByte(D, C)), dest);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
index 8809f06..9f53ea6 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
@@ -27,13 +27,14 @@
@Override
public final void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
DexMethod rewritten =
appView
.graphLens()
- .lookupMethod(getMethod(), context.getReference(), getInvokeType())
+ .lookupMethod(getMethod(), context.getReference(), getInvokeType(), codeLens)
.getReference();
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -54,7 +55,7 @@
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
MethodLookupResult lookup =
- graphLens.lookupMethod(getMethod(), context.getReference(), getInvokeType());
+ graphLens.lookupMethod(getMethod(), context.getReference(), getInvokeType(), codeLens);
writeFirst(AA, dest, lookup.getType().getDexOpcodeRange());
write16BitReference(lookup.getReference(), dest, mapping);
write16BitValue(CCCC, dest);
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/dex/code/DexItemBasedConstString.java
index d2adc25..88f47f8 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexItemBasedConstString.java
@@ -42,6 +42,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexNewArray.java b/src/main/java/com/android/tools/r8/dex/code/DexNewArray.java
index cad1490..e24cd52 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexNewArray.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexNewArray.java
@@ -47,10 +47,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -81,7 +82,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType lookup = graphLens.lookupType(getType());
+ DexType lookup = graphLens.lookupType(getType(), codeLens);
writeFirst(B, A, dest);
write16BitReference(lookup, dest, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexNewInstance.java b/src/main/java/com/android/tools/r8/dex/code/DexNewInstance.java
index 20067e5..f3885c6 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexNewInstance.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexNewInstance.java
@@ -53,10 +53,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = appView.graphLens().lookupType(getType());
+ DexType rewritten = appView.graphLens().lookupType(getType(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
@@ -68,7 +69,7 @@
GraphLens codeLens,
ObjectToOffsetMapping mapping,
LensCodeRewriterUtils rewriter) {
- DexType rewritten = graphLens.lookupType(getType());
+ DexType rewritten = graphLens.lookupType(getType(), codeLens);
writeFirst(AA, dest);
write16BitReference(rewritten, dest, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexNewUnboxedEnumInstance.java b/src/main/java/com/android/tools/r8/dex/code/DexNewUnboxedEnumInstance.java
index 0ef15d8..0e02d63 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexNewUnboxedEnumInstance.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexNewUnboxedEnumInstance.java
@@ -53,6 +53,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexRecordFieldValues.java b/src/main/java/com/android/tools/r8/dex/code/DexRecordFieldValues.java
index f7e4684..7fc116b 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexRecordFieldValues.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexRecordFieldValues.java
@@ -40,6 +40,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexSgetOrSput.java b/src/main/java/com/android/tools/r8/dex/code/DexSgetOrSput.java
index 3fe34b47..9e0b6be 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexSgetOrSput.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexSgetOrSput.java
@@ -26,10 +26,11 @@
@Override
public final void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
- DexField rewritten = appView.graphLens().lookupField(getField());
+ DexField rewritten = appView.graphLens().lookupField(getField(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
diff --git a/src/main/java/com/android/tools/r8/dump/DumpOptions.java b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
index 0bca3bd..ac46112 100644
--- a/src/main/java/com/android/tools/r8/dump/DumpOptions.java
+++ b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.dump;
+import com.android.tools.r8.AndroidResourceProvider;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.dex.Marker.Backend;
import com.android.tools.r8.dex.Marker.Tool;
@@ -75,7 +76,7 @@
private final Collection<StartupProfileProvider> startupProfileProviders;
private final boolean enableMissingLibraryApiModeling;
private final boolean isAndroidPlatformBuild;
-
+ private final AndroidResourceProvider androidResourceProvider;
private final Map<String, String> systemProperties;
// TraceReferences only.
@@ -107,7 +108,8 @@
boolean isAndroidPlatformBuild,
Map<String, String> systemProperties,
boolean dumpInputToFile,
- String traceReferencesConsumer) {
+ String traceReferencesConsumer,
+ AndroidResourceProvider androidResourceProvider) {
this.backend = backend;
this.tool = tool;
this.compilationMode = compilationMode;
@@ -131,6 +133,7 @@
this.systemProperties = systemProperties;
this.dumpInputToFile = dumpInputToFile;
this.traceReferencesConsumer = traceReferencesConsumer;
+ this.androidResourceProvider = androidResourceProvider;
}
public String getBuildPropertiesFileContent() {
@@ -333,6 +336,14 @@
return new Builder().setTool(tool);
}
+ public boolean hasAndroidResourcesProvider() {
+ return androidResourceProvider != null;
+ }
+
+ public AndroidResourceProvider getAndroidResourceProvider() {
+ return androidResourceProvider;
+ }
+
public static class Builder {
// Initialize backend to DEX for backwards compatibility.
private Backend backend = Backend.DEX;
@@ -354,6 +365,7 @@
private List<ProguardConfigurationRule> mainDexKeepRules;
private Collection<ArtProfileProvider> artProfileProviders;
private Collection<StartupProfileProvider> startupProfileProviders;
+ private AndroidResourceProvider androidResourceProvider;
private boolean enableMissingLibraryApiModeling = false;
private boolean isAndroidPlatformBuild = false;
@@ -530,7 +542,17 @@
isAndroidPlatformBuild,
systemProperties,
dumpInputToFile,
- traceReferencesConsumer);
+ traceReferencesConsumer,
+ androidResourceProvider);
+ }
+
+ public AndroidResourceProvider getAndroidResourceProvider() {
+ return androidResourceProvider;
+ }
+
+ public Builder setAndroidResourceProvider(AndroidResourceProvider androidResourceProvider) {
+ this.androidResourceProvider = androidResourceProvider;
+ return this;
}
}
}
diff --git a/src/main/java/com/android/tools/r8/features/FeatureSplitConfiguration.java b/src/main/java/com/android/tools/r8/features/FeatureSplitConfiguration.java
index c357177..af85bd2 100644
--- a/src/main/java/com/android/tools/r8/features/FeatureSplitConfiguration.java
+++ b/src/main/java/com/android/tools/r8/features/FeatureSplitConfiguration.java
@@ -16,9 +16,15 @@
public class FeatureSplitConfiguration {
private final List<FeatureSplit> featureSplits;
+ private final boolean isolatedSplits;
- public FeatureSplitConfiguration(List<FeatureSplit> featureSplits) {
+ public FeatureSplitConfiguration(List<FeatureSplit> featureSplits, boolean isolatedSplits) {
this.featureSplits = featureSplits;
+ this.isolatedSplits = isolatedSplits;
+ }
+
+ public static Builder builder() {
+ return new Builder();
}
public static class DataResourceProvidersAndConsumer {
@@ -67,4 +73,34 @@
public List<FeatureSplit> getFeatureSplits() {
return featureSplits;
}
+
+ public boolean isIsolatedSplitsEnabled() {
+ return isolatedSplits;
+ }
+
+ public static class Builder {
+
+ private List<FeatureSplit> featureSplits = new ArrayList<>();
+ private boolean isolatedSplits;
+
+ public Builder addFeatureSplit(FeatureSplit featureSplit) {
+ featureSplits.add(featureSplit);
+ return this;
+ }
+
+ public List<FeatureSplit> getFeatureSplits() {
+ return featureSplits;
+ }
+
+ public Builder setEnableIsolatedSplits(boolean isolatedSplits) {
+ this.isolatedSplits = isolatedSplits;
+ return this;
+ }
+
+ public FeatureSplitConfiguration build() {
+ return featureSplits.isEmpty()
+ ? null
+ : new FeatureSplitConfiguration(featureSplits, isolatedSplits);
+ }
+ }
}
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 f806710..d93fae1 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -751,7 +751,12 @@
return mainDexRootSet;
}
+ public boolean hasKeepInfo() {
+ return keepInfo != null;
+ }
+
public KeepInfoCollection getKeepInfo() {
+ assert hasKeepInfo();
return keepInfo;
}
@@ -768,6 +773,10 @@
return getKeepInfo().getClassInfo(clazz);
}
+ public KeepClassInfo getKeepInfoOrDefault(DexProgramClass clazz, KeepClassInfo defaultValue) {
+ return hasKeepInfo() ? getKeepInfo().getClassInfo(clazz) : defaultValue;
+ }
+
public KeepFieldInfo getKeepInfo(ProgramField field) {
return getKeepInfo().getFieldInfo(field);
}
@@ -1043,7 +1052,6 @@
// MemberRebindingIdentityLens.
GraphLens newMemberRebindingLens =
computeNewMemberRebindingLens(appView, appliedLens, firstUnappliedLens, timing);
-
firstUnappliedLens.withAlternativeParentLens(
newMemberRebindingLens,
() -> {
@@ -1178,7 +1186,8 @@
new ThreadTask() {
@Override
public void run(Timing threadTiming) {
- appView.resourceAnalysisResult.rewrittenWithLens(lens, threadTiming);
+ appView.resourceAnalysisResult.rewrittenWithLens(
+ lens, appliedLensInModifiedLens, threadTiming);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index fe5b2c4..e730dee 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -424,6 +424,7 @@
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
GraphLens graphLens = appView.graphLens();
+ GraphLens codeLens = getCodeLens(appView);
assert getOrComputeStackMapStatus(method, appView).isValidOrNotPresent()
: "Could not validate stack map frames";
DexItemFactory dexItemFactory = appView.dexItemFactory();
@@ -433,7 +434,15 @@
if (shouldAddParameterNames(method.getDefinition(), appView)) {
parameterLabel = new CfLabel();
parameterLabel.write(
- appView, method, dexItemFactory, graphLens, initClassLens, namingLens, rewriter, visitor);
+ appView,
+ method,
+ dexItemFactory,
+ graphLens,
+ codeLens,
+ initClassLens,
+ namingLens,
+ rewriter,
+ visitor);
}
boolean discardFrames =
classFileVersion.isLessThan(CfVersion.V1_6)
@@ -453,7 +462,15 @@
continue;
}
instruction.write(
- appView, method, dexItemFactory, graphLens, initClassLens, namingLens, rewriter, visitor);
+ appView,
+ method,
+ dexItemFactory,
+ graphLens,
+ codeLens,
+ initClassLens,
+ namingLens,
+ rewriter,
+ visitor);
}
visitor.visitEnd();
visitor.visitMaxs(maxStack, maxLocals);
@@ -462,7 +479,7 @@
Label end = tryCatch.end.getLabel();
for (int i = 0; i < tryCatch.guards.size(); i++) {
DexType guard = tryCatch.guards.get(i);
- DexType rewrittenGuard = graphLens.lookupType(guard);
+ DexType rewrittenGuard = graphLens.lookupType(guard, codeLens);
Label target = tryCatch.targets.get(i).getLabel();
visitor.visitTryCatchBlock(
start,
@@ -480,6 +497,7 @@
writeLocalVariableEntry(
visitor,
graphLens,
+ codeLens,
namingLens,
entry.getValue(),
parameterLabel,
@@ -489,7 +507,14 @@
} else {
for (LocalVariableInfo local : localVariables) {
writeLocalVariableEntry(
- visitor, graphLens, namingLens, local.local, local.start, local.end, local.index);
+ visitor,
+ graphLens,
+ codeLens,
+ namingLens,
+ local.local,
+ local.start,
+ local.end,
+ local.index);
}
}
}
@@ -497,12 +522,13 @@
private void writeLocalVariableEntry(
MethodVisitor visitor,
GraphLens graphLens,
+ GraphLens codeLens,
NamingLens namingLens,
DebugLocalInfo info,
CfLabel start,
CfLabel end,
int index) {
- DexType rewrittenType = graphLens.lookupType(info.type);
+ DexType rewrittenType = graphLens.lookupType(info.type, codeLens);
visitor.visitLocalVariable(
info.name.toString(),
namingLens.lookupDescriptor(rewrittenType).toString(),
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index 2974981..665a472 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -189,12 +189,13 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
DexMethod parentConstructor = getParentConstructor(context, rewriter.dexItemFactory());
MethodLookupResult lookupResult =
- appView.graphLens().lookupInvokeDirect(parentConstructor, context);
+ appView.graphLens().lookupInvokeDirect(parentConstructor, context, codeLens);
lookupResult.getReference().collectIndexedItems(appView, indexedItems);
}
@@ -398,8 +399,7 @@
LensCodeRewriterUtils lensCodeRewriter,
ObjectToOffsetMapping mapping) {
DexMethod parentConstructor = getParentConstructor(context, mapping.dexItemFactory());
- MethodLookupResult lookupResult = graphLens.lookupInvokeDirect(parentConstructor, context);
- new DexInvokeDirect(1, lookupResult.getReference(), 0, 0, 0, 0, 0)
+ new DexInvokeDirect(1, parentConstructor, 0, 0, 0, 0, 0)
.write(shortBuffer, context, graphLens, codeLens, mapping, lensCodeRewriter);
new DexReturnVoid().write(shortBuffer, context, graphLens, codeLens, mapping, lensCodeRewriter);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 2a80c0b..e61ec53 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -339,10 +339,6 @@
return methodCollection.allMethodsSorted();
}
- public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
- methodCollection.virtualizeMethods(privateInstanceMethods);
- }
-
/**
* For all annotations on the class and all annotations on its methods and fields apply the
* specified consumer.
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 00febce..95d19ee 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -749,13 +749,14 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
highestSortingString = null;
for (DexInstruction insn : instructions) {
assert !insn.isDexItemBasedConstString();
- insn.collectIndexedItems(appView, indexedItems, context, rewriter);
+ insn.collectIndexedItems(appView, codeLens, indexedItems, context, rewriter);
if (insn.isConstString()) {
updateHighestSortingString(insn.asConstString().getString());
} else if (insn.isConstStringJumbo()) {
@@ -763,10 +764,10 @@
}
}
if (debugInfo != null) {
- getDebugInfoForWriting().collectIndexedItems(appView, indexedItems);
+ getDebugInfoForWriting().collectIndexedItems(appView, codeLens, indexedItems);
}
for (TryHandler handler : handlers) {
- handler.collectIndexedItems(appView, indexedItems);
+ handler.collectIndexedItems(appView, codeLens, indexedItems);
}
}
@@ -996,9 +997,10 @@
return Equatable.equalsImpl(this, other);
}
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems) {
for (TypeAddrPair pair : pairs) {
- pair.collectIndexedItems(appView, indexedItems);
+ pair.collectIndexedItems(appView, codeLens, indexedItems);
}
}
@@ -1056,12 +1058,13 @@
return type;
}
- public DexType getType(GraphLens lens) {
- return lens.lookupType(type);
+ public DexType getType(GraphLens lens, GraphLens codeLens) {
+ return lens.lookupType(type, codeLens);
}
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
- DexType rewritten = getType(appView.graphLens());
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems) {
+ DexType rewritten = getType(appView.graphLens(), codeLens);
rewritten.collectIndexedItems(appView, indexedItems);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index ac495b4..5b4d625 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -24,7 +24,8 @@
public static final DexDebugEvent[] EMPTY_ARRAY = {};
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection collection) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection collection) {
// Empty by default.
}
@@ -74,9 +75,12 @@
}
public final void writeOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
assert isWritableEvent();
- internalWriteOn(writer, mapping, graphLens);
+ internalWriteOn(writer, mapping, graphLens, codeLens);
}
boolean isWritableEvent() {
@@ -84,7 +88,10 @@
}
void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
throw new Unreachable();
}
@@ -125,7 +132,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_ADVANCE_PC);
writer.putUleb128(delta);
}
@@ -180,7 +190,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_SET_PROLOGUE_END);
}
@@ -230,7 +243,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_SET_EPILOGUE_BEGIN);
}
@@ -291,7 +307,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_ADVANCE_LINE);
writer.putSleb128(delta);
}
@@ -364,25 +383,29 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(signature == null
? Constants.DBG_START_LOCAL
: Constants.DBG_START_LOCAL_EXTENDED);
writer.putUleb128(registerNum);
writer.putString(name);
- writer.putType(graphLens.lookupType(type));
+ writer.putType(graphLens.lookupType(type, codeLens));
if (signature != null) {
writer.putString(signature);
}
}
@Override
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection collection) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection collection) {
if (name != null) {
name.collectIndexedItems(collection);
}
if (type != null) {
- DexType rewritten = appView.graphLens().lookupType(type);
+ DexType rewritten = appView.graphLens().lookupType(type, codeLens);
rewritten.collectIndexedItems(appView, collection);
}
if (signature != null) {
@@ -440,7 +463,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_END_LOCAL);
writer.putUleb128(registerNum);
}
@@ -492,7 +518,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(Constants.DBG_RESTART_LOCAL);
writer.putUleb128(registerNum);
}
@@ -551,7 +580,8 @@
}
@Override
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection collection) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection collection) {
fileName.collectIndexedItems(collection);
}
@@ -682,7 +712,10 @@
@Override
public void internalWriteOn(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putByte(value);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index 3707fdf..24ee6d2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -152,7 +152,8 @@
}
@Override
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems) {
// No indexed items to collect.
}
@@ -172,15 +173,21 @@
@Override
public void write(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putUleb128(START_LINE);
writer.putUleb128(parameterCount);
for (int i = 0; i < parameterCount; i++) {
writer.putString(null);
}
- mapping.dexItemFactory().zeroChangeDefaultEvent.writeOn(writer, mapping, graphLens);
+ mapping.dexItemFactory().zeroChangeDefaultEvent.writeOn(writer, mapping, graphLens, codeLens);
for (int i = 0; i < maxPc; i++) {
- mapping.dexItemFactory().oneChangeDefaultEvent.writeOn(writer, mapping, graphLens);
+ mapping
+ .dexItemFactory()
+ .oneChangeDefaultEvent
+ .writeOn(writer, mapping, graphLens, codeLens);
}
writer.putByte(Constants.DBG_END_SEQUENCE);
}
@@ -263,14 +270,15 @@
return visitor.visit(this, other.asEventBasedInfo(), EventBasedDebugInfo::specify);
}
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems) {
for (DexString parameter : parameters) {
if (parameter != null) {
parameter.collectIndexedItems(indexedItems);
}
}
for (DexDebugEvent event : events) {
- event.collectIndexedItems(appView, indexedItems);
+ event.collectIndexedItems(appView, codeLens, indexedItems);
}
}
@@ -363,8 +371,9 @@
}
@Override
- public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
- super.collectIndexedItems(appView, indexedItems);
+ public void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems) {
+ super.collectIndexedItems(appView, codeLens, indexedItems);
}
@Override
@@ -385,14 +394,17 @@
@Override
public void write(
- DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens) {
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens) {
writer.putUleb128(startLine);
writer.putUleb128(parameters.length);
for (DexString name : parameters) {
writer.putString(name);
}
for (DexDebugEvent event : events) {
- event.writeOn(writer, mapping, graphLens);
+ event.writeOn(writer, mapping, graphLens, codeLens);
}
writer.putByte(Constants.DBG_END_SEQUENCE);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfoForWriting.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfoForWriting.java
index 67ab2aa..a01f2fb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfoForWriting.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfoForWriting.java
@@ -14,9 +14,14 @@
void collectMixedSectionItems(MixedSectionCollection collection);
- void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems);
+ void collectIndexedItems(
+ AppView<?> appView, GraphLens codeLens, IndexedItemCollection indexedItems);
int estimatedWriteSize();
- void write(DebugBytecodeWriter writer, ObjectToOffsetMapping mapping, GraphLens graphLens);
+ void write(
+ DebugBytecodeWriter writer,
+ ObjectToOffsetMapping mapping,
+ GraphLens graphLens,
+ GraphLens codeLens);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 730fb6c..40bdbe2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -761,8 +761,7 @@
@Override
public String toString() {
- checkIfObsolete();
- return "Encoded method " + getReference();
+ return toSourceString();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
index afe2afb..7cc7830 100644
--- a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
@@ -56,6 +56,7 @@
void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter);
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index 9afb69a..8e04491 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -208,33 +208,6 @@
}
@Override
- void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
- int vLen = virtualMethods.length;
- int dLen = directMethods.length;
- int mLen = privateInstanceMethods.size();
- assert mLen <= dLen;
-
- DexEncodedMethod[] newDirectMethods = new DexEncodedMethod[dLen - mLen];
- int index = 0;
- for (int i = 0; i < dLen; i++) {
- DexEncodedMethod encodedMethod = directMethods[i];
- if (!privateInstanceMethods.contains(encodedMethod)) {
- newDirectMethods[index++] = encodedMethod;
- }
- }
- assert index == dLen - mLen;
- setDirectMethods(newDirectMethods);
-
- DexEncodedMethod[] newVirtualMethods = new DexEncodedMethod[vLen + mLen];
- System.arraycopy(virtualMethods, 0, newVirtualMethods, 0, vLen);
- index = vLen;
- for (DexEncodedMethod encodedMethod : privateInstanceMethods) {
- newVirtualMethods[index++] = encodedMethod;
- }
- setVirtualMethods(newVirtualMethods);
- }
-
- @Override
DexEncodedMethod getDirectMethod(DexMethod method) {
for (DexEncodedMethod directMethod : directMethods) {
if (method.match(directMethod)) {
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index e14da8e..cc69b8e 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -367,11 +367,6 @@
backing.setVirtualMethods(methods);
}
- public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
- resetVirtualMethodCaches();
- backing.virtualizeMethods(privateInstanceMethods);
- }
-
public boolean hasAnnotations() {
return traverse(
method ->
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
index b270516..18a72a3 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -135,7 +135,4 @@
abstract DexEncodedMethod replaceDirectMethodWithVirtualMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement);
-
- abstract void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods);
-
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
index 0889c63..78cfebe8 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
@@ -323,13 +323,6 @@
}
@Override
- public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
- assert assertWriteEntry();
- super.virtualizeMethods(privateInstanceMethods);
- assert assertWriteExit();
- }
-
- @Override
public void useSortedBacking() {
assert assertWriteEntry();
super.useSortedBacking();
diff --git a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
index 84f114f..fa553d9 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -365,21 +365,6 @@
}
@Override
- void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
- // This is a no-op as the virtualizer has modified the encoded method bits.
- assert verifyVirtualizedMethods(privateInstanceMethods);
- }
-
- @SuppressWarnings("ReferenceEquality")
- private boolean verifyVirtualizedMethods(Set<DexEncodedMethod> methods) {
- for (DexEncodedMethod method : methods) {
- assert belongsToVirtualPool(method);
- assert methodMap.get(method.getSignature()) == method;
- }
- return true;
- }
-
- @Override
MethodMapBacking map(Function<DexEncodedMethod, DexEncodedMethod> fn) {
MethodMapBacking newBacking = new MethodMapBacking(isSorted, createMap(methodMap.size()));
methodMap.forEach((ignore, method) -> newBacking.addMethod(fn.apply(method)));
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 53e4ddc..9b4fa96 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -72,7 +72,8 @@
getReference().collectIndexedItems(appView, indexedItems);
if (definition.hasCode()) {
Code code = definition.getCode();
- code.asDexWritableCode().collectIndexedItems(appView, indexedItems, this, rewriter);
+ GraphLens codeLens = code.getCodeLens(appView);
+ code.asDexWritableCode().collectIndexedItems(appView, codeLens, indexedItems, this, rewriter);
}
definition.annotations().collectIndexedItems(appView, indexedItems);
definition.parameterAnnotationsList.collectIndexedItems(appView, indexedItems);
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java b/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
index dc2bbdc..7e359ec 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
@@ -79,9 +79,11 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
+ assert exceptionType.isIdenticalTo(appView.graphLens().lookupType(exceptionType, codeLens));
rewriter
.dexItemFactory()
.createInstanceInitializer(exceptionType)
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
index ddfbba1..48fe289 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
@@ -100,6 +100,7 @@
@Override
public void collectIndexedItems(
AppView<?> appView,
+ GraphLens codeLens,
IndexedItemCollection indexedItems,
ProgramMethod context,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
index ed61adb..950bff6 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
@@ -210,16 +210,15 @@
return resourceShrinkerState.getR8ResourceShrinkerModel();
}
- @SuppressWarnings("ReferenceEquality")
- public void rewrittenWithLens(GraphLens lens, Timing timing) {
+ public void rewrittenWithLens(GraphLens lens, GraphLens appliedLens, Timing timing) {
Map<DexType, DexType> changed = new IdentityHashMap<>();
for (DexType dexType : rClassFieldToValueStoreMap.keySet()) {
- DexType rewritten = lens.lookupClassType(dexType);
- if (rewritten != dexType) {
+ DexType rewritten = lens.lookupClassType(dexType, appliedLens);
+ if (rewritten.isNotIdenticalTo(dexType)) {
changed.put(dexType, rewritten);
}
}
- if (changed.size() > 0) {
+ if (!changed.isEmpty()) {
Map<DexType, RClassFieldToValueStore> rewrittenMap = new IdentityHashMap<>();
rClassFieldToValueStoreMap.forEach(
(type, map) -> {
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
index 64f8399..eff9aa9 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
@@ -414,6 +414,10 @@
return null;
}
+ public boolean isNumberUnboxerLens() {
+ return false;
+ }
+
public boolean isHorizontalClassMergerGraphLens() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
index d906b4c..63aa73a 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.utils.collections.EmptyBidirectionalOneToOneMap;
import java.util.Map;
import java.util.function.Function;
-import java.util.stream.Collectors;
/**
* GraphLens implementation with a parent lens where the mapping of types, methods and fields can be
@@ -291,24 +290,6 @@
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
- typeMap.forEach(
- (from, to) ->
- builder
- .append(from.getTypeName())
- .append(" -> ")
- .append(to.getTypeName())
- .append(System.lineSeparator()));
- fieldMap.forEachManyToOneMapping(
- (fromSet, to) -> {
- builder.append(
- fromSet.stream()
- .map(DexField::toSourceString)
- .collect(Collectors.joining("," + System.lineSeparator())));
- builder.append(" -> ");
- builder.append(to.toSourceString()).append(System.lineSeparator());
- });
- builder.append(getPrevious().toString());
- return builder.toString();
+ return getClass().getTypeName();
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLensWithCustomLensCodeRewriter.java b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLensWithCustomLensCodeRewriter.java
index 84599f0..e64f101 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLensWithCustomLensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLensWithCustomLensCodeRewriter.java
@@ -21,8 +21,10 @@
AppView<?> appView,
BidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap,
BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> methodMap,
- BidirectionalManyToManyRepresentativeMap<DexType, DexType> typeMap) {
+ BidirectionalManyToManyRepresentativeMap<DexType, DexType> typeMap,
+ CustomLensCodeRewriter customLensCodeRewriter) {
super(appView, fieldMap, methodMap, typeMap);
+ this.customLensCodeRewriter = customLensCodeRewriter;
}
public NestedGraphLensWithCustomLensCodeRewriter(
diff --git a/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java b/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
index 23df11c..3f628b9 100644
--- a/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
+++ b/src/main/java/com/android/tools/r8/graph/proto/RewrittenPrototypeDescription.java
@@ -33,7 +33,7 @@
private static final RewrittenPrototypeDescription NONE = new RewrittenPrototypeDescription();
- private final List<ExtraParameter> extraParameters;
+ private final List<? extends ExtraParameter> extraParameters;
private final ArgumentInfoCollection argumentInfoCollection;
private final RewrittenTypeInfo rewrittenReturnInfo;
@@ -44,7 +44,7 @@
}
private RewrittenPrototypeDescription(
- List<ExtraParameter> extraParameters,
+ List<? extends ExtraParameter> extraParameters,
RewrittenTypeInfo rewrittenReturnInfo,
ArgumentInfoCollection argumentsInfo) {
assert argumentsInfo != null;
@@ -55,7 +55,7 @@
}
public static RewrittenPrototypeDescription create(
- List<ExtraParameter> extraParameters,
+ List<? extends ExtraParameter> extraParameters,
RewrittenTypeInfo rewrittenReturnInfo,
ArgumentInfoCollection argumentsInfo) {
return extraParameters.isEmpty() && rewrittenReturnInfo == null && argumentsInfo.isEmpty()
@@ -116,7 +116,7 @@
return !extraParameters.isEmpty();
}
- public List<ExtraParameter> getExtraParameters() {
+ public List<? extends ExtraParameter> getExtraParameters() {
return extraParameters;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java
index e0f2b3b..8062a16 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
-import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneHashMap;
@@ -178,11 +177,10 @@
}
Iterator<DexProgramClass> candidateIterator = candidates.iterator();
DexProgramClass target = IterableUtils.first(candidates);
- KeepInfoCollection keepInfo = appView.getKeepInfo();
while (candidateIterator.hasNext()) {
DexProgramClass current = candidateIterator.next();
- if (keepInfo != null
- && keepInfo.getClassInfo(current).isMinificationAllowed(appView.options())) {
+ if (appView.hasKeepInfo()
+ && appView.getKeepInfo(current).isMinificationAllowed(appView.options())) {
target = current;
break;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
index cb443c4..eb6fe55 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NotMatchedByNoHorizontalClassMerging.java
@@ -19,7 +19,7 @@
@Override
public boolean canMerge(DexProgramClass clazz) {
- return !appView.appInfo().isNoHorizontalClassMergingOfType(clazz);
+ return appView.getKeepInfo(clazz).isHorizontalClassMergingAllowed(appView.options());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 712fa0d..e8e4799 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -54,6 +54,7 @@
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@@ -80,6 +81,9 @@
private final Map<DexProgramClass, ProgramFieldMap<AbstractValue>>
abstractFinalInstanceFieldValues = new ConcurrentHashMap<>();
+ private final Set<DexProgramClass> classesWithPrunedInstanceInitializers =
+ ConcurrentHashMap.newKeySet();
+
FieldAssignmentTracker(AppView<AppInfoWithLiveness> appView) {
this.abstractValueFactory = appView.abstractValueFactory();
this.appView = appView;
@@ -360,41 +364,49 @@
private void recordAllInstanceFieldPutsProcessed(
ProgramField field, OptimizationFeedbackDelayed feedback) {
- if (appView.appInfo().isInstanceFieldWrittenOnlyInInstanceInitializers(field)) {
- AbstractValue abstractValue = BottomValue.getInstance();
- DexProgramClass clazz = field.getHolder();
- for (DexEncodedMethod method : clazz.directMethods(DexEncodedMethod::isInstanceInitializer)) {
- InstanceFieldInitializationInfo fieldInitializationInfo =
- method
- .getOptimizationInfo()
- .getContextInsensitiveInstanceInitializerInfo()
- .fieldInitializationInfos()
- .get(field);
- if (fieldInitializationInfo.isSingleValue()) {
- abstractValue =
- appView
- .getAbstractValueFieldJoiner()
- .join(abstractValue, fieldInitializationInfo.asSingleValue(), field);
- if (abstractValue.isUnknown()) {
- break;
- }
- } else if (fieldInitializationInfo.isTypeInitializationInfo()) {
- // TODO(b/149732532): Not handled, for now.
- abstractValue = UnknownValue.getInstance();
- break;
- } else {
- assert fieldInitializationInfo.isArgumentInitializationInfo()
- || fieldInitializationInfo.isUnknown();
- abstractValue = UnknownValue.getInstance();
+ if (!appView.appInfo().isInstanceFieldWrittenOnlyInInstanceInitializers(field)) {
+ return;
+ }
+ DexProgramClass clazz = field.getHolder();
+ if (classesWithPrunedInstanceInitializers.contains(clazz)) {
+ // The current method is analyzing the instance-puts to the field in the instance initializers
+ // of the holder class. Due to single caller inlining of instance initializers some of the
+ // methods needed for the analysis may have been pruned from the app, in which case the
+ // analysis result will not be conservative.
+ return;
+ }
+ AbstractValue abstractValue = BottomValue.getInstance();
+ for (DexEncodedMethod method : clazz.directMethods(DexEncodedMethod::isInstanceInitializer)) {
+ InstanceFieldInitializationInfo fieldInitializationInfo =
+ method
+ .getOptimizationInfo()
+ .getContextInsensitiveInstanceInitializerInfo()
+ .fieldInitializationInfos()
+ .get(field);
+ if (fieldInitializationInfo.isSingleValue()) {
+ abstractValue =
+ appView
+ .getAbstractValueFieldJoiner()
+ .join(abstractValue, fieldInitializationInfo.asSingleValue(), field);
+ if (abstractValue.isUnknown()) {
break;
}
+ } else if (fieldInitializationInfo.isTypeInitializationInfo()) {
+ // TODO(b/149732532): Not handled, for now.
+ abstractValue = UnknownValue.getInstance();
+ break;
+ } else {
+ assert fieldInitializationInfo.isArgumentInitializationInfo()
+ || fieldInitializationInfo.isUnknown();
+ abstractValue = UnknownValue.getInstance();
+ break;
}
+ }
- assert !abstractValue.isBottom();
+ assert !abstractValue.isBottom();
- if (!abstractValue.isUnknown()) {
- feedback.recordFieldHasAbstractValue(field.getDefinition(), appView, abstractValue);
- }
+ if (!abstractValue.isUnknown()) {
+ feedback.recordFieldHasAbstractValue(field.getDefinition(), appView, abstractValue);
}
}
@@ -421,6 +433,16 @@
});
}
+ public void onMethodPruned(ProgramMethod method) {
+ onMethodCodePruned(method);
+ }
+
+ public void onMethodCodePruned(ProgramMethod method) {
+ if (method.getDefinition().isInstanceInitializer()) {
+ classesWithPrunedInstanceInitializers.add(method.getHolder());
+ }
+ }
+
public void waveDone(ProgramMethodSet wave, OptimizationFeedbackDelayed feedback) {
// This relies on the instance initializer info in the method optimization feedback. It is
// therefore important that the optimization info has been flushed in advance.
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index 0dcf961..5cbe158 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -315,17 +315,15 @@
AppView<? extends AppInfoWithClassHierarchy> appView,
SubtypingInfo subtypingInfo,
PredicateSet<DexType> alwaysClassInline,
- Set<DexType> neverMergeClassVertically,
- Set<DexType> neverMergeClassHorizontally,
Set<DexMethod> alwaysInline,
- Set<DexMethod> bypassClinitforInlining) {
+ Set<DexMethod> bypassClinitforInlining,
+ DependentMinimumKeepInfoCollection dependentMinimumKeepInfo) {
new RootSetExtension(
appView,
alwaysClassInline,
- neverMergeClassVertically,
- neverMergeClassHorizontally,
alwaysInline,
- bypassClinitforInlining)
+ bypassClinitforInlining,
+ dependentMinimumKeepInfo)
.extend(subtypingInfo);
}
@@ -444,26 +442,22 @@
private final ProtoReferences references;
private final PredicateSet<DexType> alwaysClassInline;
- private final Set<DexType> neverMergeClassVertically;
- private final Set<DexType> neverMergeClassHorizontally;
-
private final Set<DexMethod> alwaysInline;
private final Set<DexMethod> bypassClinitforInlining;
+ private final DependentMinimumKeepInfoCollection dependentMinimumKeepInfo;
RootSetExtension(
AppView<? extends AppInfoWithClassHierarchy> appView,
PredicateSet<DexType> alwaysClassInline,
- Set<DexType> neverMergeClassVertically,
- Set<DexType> neverMergeClassHorizontally,
Set<DexMethod> alwaysInline,
- Set<DexMethod> bypassClinitforInlining) {
+ Set<DexMethod> bypassClinitforInlining,
+ DependentMinimumKeepInfoCollection dependentMinimumKeepInfo) {
this.appView = appView;
this.references = appView.protoShrinker().references;
this.alwaysClassInline = alwaysClassInline;
- this.neverMergeClassVertically = neverMergeClassVertically;
- this.neverMergeClassHorizontally = neverMergeClassHorizontally;
this.alwaysInline = alwaysInline;
this.bypassClinitforInlining = bypassClinitforInlining;
+ this.dependentMinimumKeepInfo = dependentMinimumKeepInfo;
}
void extend(SubtypingInfo subtypingInfo) {
@@ -527,8 +521,11 @@
}
private void neverMergeClass(DexType type) {
- neverMergeClassVertically.add(type);
- neverMergeClassHorizontally.add(type);
+ dependentMinimumKeepInfo
+ .getOrCreateUnconditionalMinimumKeepInfoFor(type)
+ .asClassJoiner()
+ .disallowHorizontalClassMerging()
+ .disallowVerticalClassMerging();
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
index 3588346..0f6fb1f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
@@ -87,6 +87,13 @@
Instruction previous = previous();
assert previous == instruction;
}
+
+ default void addBeforeAndPositionAfterNewInstruction(Instruction instruction) {
+ previous();
+ add(instruction);
+ next();
+ }
+
/** See {@link #replaceCurrentInstruction(Instruction, Set)}. */
default void replaceCurrentInstruction(Instruction newInstruction) {
replaceCurrentInstruction(newInstruction, null);
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 2a10e4c..9a7b1e0 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
@@ -247,9 +247,11 @@
assert appView.rootSet() != null;
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
assumeInserter = new AssumeInserter(appViewWithLiveness);
+ this.lensCodeRewriter = new LensCodeRewriter(appViewWithLiveness);
+ this.inliner = new Inliner(appViewWithLiveness, this, lensCodeRewriter);
this.classInliner =
options.enableClassInlining && options.inlinerOptions().enableInlining
- ? new ClassInliner()
+ ? new ClassInliner(appViewWithLiveness, inliner)
: null;
this.dynamicTypeOptimization = new DynamicTypeOptimization(appViewWithLiveness);
this.fieldAccessAnalysis = new FieldAccessAnalysis(appViewWithLiveness);
@@ -259,8 +261,6 @@
: null;
this.enumUnboxer = EnumUnboxer.create(appViewWithLiveness);
this.numberUnboxer = NumberUnboxer.create(appViewWithLiveness);
- this.lensCodeRewriter = new LensCodeRewriter(appViewWithLiveness);
- this.inliner = new Inliner(appViewWithLiveness, this, lensCodeRewriter);
this.outliner = Outliner.create(appViewWithLiveness);
this.memberValuePropagation = new R8MemberValuePropagation(appViewWithLiveness);
this.methodOptimizationInfoCollector =
@@ -766,13 +766,11 @@
// lambda, it does not get collected by merger.
assert options.inlinerOptions().enableInlining && inliner != null;
classInliner.processMethodCode(
- appView.withLiveness(),
code.context(),
code,
feedback,
methodProcessor,
methodProcessingContext,
- inliner,
new LazyBox<>(
() ->
inliner.createDefaultOracle(
@@ -1152,6 +1150,7 @@
assert method.getHolder().lookupMethod(method.getReference()) == null;
appView.withArgumentPropagator(argumentPropagator -> argumentPropagator.onMethodPruned(method));
enumUnboxer.onMethodPruned(method);
+ fieldAccessAnalysis.fieldAssignmentTracker().onMethodPruned(method);
numberUnboxer.onMethodPruned(method);
outliner.onMethodPruned(method);
if (inliner != null) {
@@ -1170,6 +1169,7 @@
appView.withArgumentPropagator(
argumentPropagator -> argumentPropagator.onMethodCodePruned(method));
enumUnboxer.onMethodCodePruned(method);
+ fieldAccessAnalysis.fieldAssignmentTracker().onMethodCodePruned(method);
numberUnboxer.onMethodCodePruned(method);
outliner.onMethodCodePruned(method);
if (inliner != null) {
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 c48cb06..6880ed1 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
@@ -16,6 +16,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexItemBasedValueString;
@@ -50,6 +51,7 @@
import com.android.tools.r8.naming.dexitembasedstring.ClassNameComputationInfo;
import com.android.tools.r8.naming.dexitembasedstring.ClassNameComputationInfo.ClassNameMapping;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.KeepClassInfo;
import com.android.tools.r8.utils.Action;
import com.android.tools.r8.utils.IteratorUtils;
import com.google.common.collect.Maps;
@@ -177,7 +179,7 @@
Value value = put.value().getAliasedValue();
if (unnecessaryStaticPuts.contains(put)) {
if (fieldType == dexItemFactory.stringType) {
- fieldsWithStaticValues.put(field, getDexStringValue(value, context.getHolderType()));
+ fieldsWithStaticValues.put(field, getDexStringValue(value, context.getHolder()));
} else if (fieldType.isClassType() || fieldType.isArrayType()) {
if (value.isZero()) {
fieldsWithStaticValues.put(field, DexValueNull.NULL);
@@ -308,7 +310,7 @@
return new ClassInitializerDefaultsResult(fieldsWithStaticValues);
}
- private DexValue getDexStringValue(Value inValue, DexType holder) {
+ private DexValue getDexStringValue(Value inValue, DexProgramClass holder) {
if (inValue.isPhi()) {
return null;
}
@@ -337,25 +339,21 @@
}
@SuppressWarnings("ReferenceEquality")
- private DexValue getDexStringValueForInvoke(DexMethod invokedMethod, DexType holder) {
- DexClass clazz = appView.definitionFor(holder);
- if (clazz == null) {
- assert false;
- return null;
- }
-
- if (appView.enableWholeProgramOptimizations()
- && appView.withLiveness().appInfo().isMinificationAllowed(clazz)) {
+ private DexValue getDexStringValueForInvoke(DexMethod invokedMethod, DexProgramClass holder) {
+ if (appView
+ .getKeepInfoOrDefault(holder, KeepClassInfo.top())
+ .isMinificationAllowed(appView.options())) {
if (invokedMethod == dexItemFactory.classMethods.getName) {
- return new DexItemBasedValueString(holder, ClassNameComputationInfo.getInstance(NAME));
+ return new DexItemBasedValueString(
+ holder.getType(), ClassNameComputationInfo.getInstance(NAME));
}
if (invokedMethod == dexItemFactory.classMethods.getCanonicalName) {
return new DexItemBasedValueString(
- holder, ClassNameComputationInfo.getInstance(CANONICAL_NAME));
+ holder.getType(), ClassNameComputationInfo.getInstance(CANONICAL_NAME));
}
if (invokedMethod == dexItemFactory.classMethods.getSimpleName) {
return new DexItemBasedValueString(
- holder, ClassNameComputationInfo.getInstance(SIMPLE_NAME));
+ holder.getType(), ClassNameComputationInfo.getInstance(SIMPLE_NAME));
}
if (invokedMethod == dexItemFactory.classMethods.getTypeName) {
// TODO(b/119426668): desugar Type#getTypeName
@@ -375,7 +373,8 @@
// TODO(b/119426668): desugar Type#getTypeName
}
if (mapping != null) {
- return new DexValueString(mapping.map(holder.toDescriptorString(), clazz, dexItemFactory));
+ return new DexValueString(
+ mapping.map(holder.getType().toDescriptorString(), holder, dexItemFactory));
}
assert false;
return null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index 020390f..08ff606 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
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.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -42,9 +41,17 @@
NOT_ELIGIBLE
}
+ private final AppView<AppInfoWithLiveness> appView;
+ private final Inliner inliner;
+
private final ConcurrentHashMap<DexClass, EligibilityStatus> knownClasses =
new ConcurrentHashMap<>();
+ public ClassInliner(AppView<AppInfoWithLiveness> appView, Inliner inliner) {
+ this.appView = appView;
+ this.inliner = inliner;
+ }
+
// Process method code and inline eligible class instantiations, in short:
//
// - collect all 'new-instance' and 'static-get' instructions (called roots below) in
@@ -122,16 +129,13 @@
// }
// }
//
- public final void processMethodCode(
- AppView<AppInfoWithLiveness> appView,
+ public void processMethodCode(
ProgramMethod method,
IRCode code,
OptimizationFeedback feedback,
MethodProcessor methodProcessor,
MethodProcessingContext methodProcessingContext,
- Inliner inliner,
LazyBox<InliningOracle> defaultOracle) {
-
// Collect all the new-instance and static-get instructions in the code before inlining.
List<Instruction> roots =
Lists.newArrayList(code.instructions(insn -> insn.isNewInstance() || insn.isStaticGet()));
@@ -152,7 +156,6 @@
new InlineCandidateProcessor(
appView,
inliner,
- clazz -> isClassEligible(appView, clazz),
methodProcessor,
method,
root);
@@ -164,7 +167,7 @@
rootsIterator.remove();
continue;
}
- status = processor.isClassAndUsageEligible();
+ status = isClassEligible(processor.getEligibleClass());
if (status != EligibilityStatus.ELIGIBLE) {
// This root will never be inlined.
rootsIterator.remove();
@@ -247,15 +250,15 @@
new BranchSimplifier(appView)
.run(code, methodProcessor, methodProcessingContext, Timing.empty());
// If a method was inlined we may see more trivial computation/conversion of String.
- new StringOptimizer(appView).run(code, Timing.empty());
+ new StringOptimizer(appView)
+ .run(code, methodProcessor, methodProcessingContext, Timing.empty());
}
}
- private EligibilityStatus isClassEligible(
- AppView<AppInfoWithLiveness> appView, DexProgramClass clazz) {
+ private EligibilityStatus isClassEligible(DexProgramClass clazz) {
EligibilityStatus eligible = knownClasses.get(clazz);
if (eligible == null) {
- EligibilityStatus computed = computeClassEligible(appView, clazz);
+ EligibilityStatus computed = computeClassEligible(clazz);
EligibilityStatus existing = knownClasses.putIfAbsent(clazz, computed);
assert existing == null || existing == computed;
eligible = existing == null ? computed : existing;
@@ -263,27 +266,22 @@
return eligible;
}
- @SuppressWarnings("ReferenceEquality")
// Class is eligible for this optimization. Eligibility implementation:
// - is not an abstract class or interface
// - does not declare finalizer
// - does not trigger any static initializers except for its own
- private EligibilityStatus computeClassEligible(
- AppView<AppInfoWithLiveness> appView, DexProgramClass clazz) {
+ private EligibilityStatus computeClassEligible(DexProgramClass clazz) {
if (clazz == null
|| clazz.isAbstract()
|| clazz.isInterface()
- || !appView.appInfo().isClassInliningAllowed(clazz)) {
+ || !appView.getKeepInfo(clazz).isClassInliningAllowed(appView.options())) {
return EligibilityStatus.NOT_ELIGIBLE;
}
// Class must not define finalizer.
DexItemFactory dexItemFactory = appView.dexItemFactory();
- for (DexEncodedMethod method : clazz.virtualMethods()) {
- if (method.getReference().name == dexItemFactory.finalizeMethodName
- && method.getReference().proto == dexItemFactory.objectMembers.finalize.proto) {
- return EligibilityStatus.NOT_ELIGIBLE;
- }
+ if (clazz.lookupMethod(dexItemFactory.objectMembers.finalize) != null) {
+ return EligibilityStatus.NOT_ELIGIBLE;
}
// Check for static initializers in this class or any of interfaces it implements.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index afa1947..7935419 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -82,7 +82,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.Function;
final class InlineCandidateProcessor {
@@ -92,7 +91,6 @@
private final AppView<AppInfoWithLiveness> appView;
private final DexItemFactory dexItemFactory;
private final Inliner inliner;
- private final Function<DexProgramClass, EligibilityStatus> isClassEligible;
private final MethodProcessor methodProcessor;
private final ProgramMethod method;
private final Instruction root;
@@ -115,14 +113,12 @@
InlineCandidateProcessor(
AppView<AppInfoWithLiveness> appView,
Inliner inliner,
- Function<DexProgramClass, EligibilityStatus> isClassEligible,
MethodProcessor methodProcessor,
ProgramMethod method,
Instruction root) {
this.appView = appView;
this.dexItemFactory = appView.dexItemFactory();
this.inliner = inliner;
- this.isClassEligible = isClassEligible;
this.method = method;
this.root = root;
this.methodProcessor = methodProcessor;
@@ -200,21 +196,6 @@
return EligibilityStatus.ELIGIBLE;
}
- // Checks if the class is eligible and is properly used. Regarding general class
- // eligibility rules see comment on computeClassEligible(...).
- //
- // In addition to class being eligible this method also checks:
- // -- for 'new-instance' root:
- // * class itself does not have static initializer
- // -- for 'static-get' root:
- // * class does not have instance fields
- // * class is final
- // * class has class initializer marked as TrivialClassInitializer, and
- // class initializer initializes the field we are reading here.
- EligibilityStatus isClassAndUsageEligible() {
- return isClassEligible.apply(eligibleClass);
- }
-
/**
* Checks if the inlining candidate instance users are eligible, see comment on {@link
* ClassInliner#processMethodCode}.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
index ab1c629..9b95fb8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
@@ -330,9 +330,7 @@
for (SimpleStringFormatSpec.Part part : parsedSpec.parts) {
if (part.isPlaceholder()) {
Value paramValue = elementValues.get(part.placeholderIdx);
- if (paramValue == null || paramValue.isAlwaysNull(appView)) {
- // Save having to call isAlwaysNull() again.
- elementValues.set(part.placeholderIdx, null);
+ if (isArrayElementAlwaysNull(paramValue)) {
continue;
}
if (!isSupportedFormatType(part.formatChar, paramValue.getType())) {
@@ -388,7 +386,7 @@
appendMethod = dexItemFactory.stringBuilderMethods.appendString;
} else {
paramValue = elementValues.get(part.placeholderIdx);
- if (paramValue == null) {
+ if (isArrayElementAlwaysNull(paramValue)) {
ConstString constString =
ConstString.builder()
.setValue(dexItemFactory.createString(part.formatChar == 'b' ? "false" : "null"))
@@ -448,6 +446,10 @@
return instructionIterator;
}
+ private boolean isArrayElementAlwaysNull(Value value) {
+ return value == null || value.isAlwaysNull(appView);
+ }
+
private void optimizeValueOf(
IRCode code,
InstructionListIterator instructionIterator,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxer.java
index dbfb37a..b360857 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxer.java
@@ -34,7 +34,8 @@
public abstract void unboxNumbers(
PostMethodProcessor.Builder postMethodProcessorBuilder,
Timing timing,
- ExecutorService executorService);
+ ExecutorService executorService)
+ throws ExecutionException;
public abstract void onMethodPruned(ProgramMethod method);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerBoxingStatusResolution.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerBoxingStatusResolution.java
index 2f0a128..4a9cbfd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerBoxingStatusResolution.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerBoxingStatusResolution.java
@@ -7,12 +7,12 @@
import static com.android.tools.r8.ir.optimize.numberunboxer.NumberUnboxerBoxingStatusResolution.MethodBoxingStatusResult.BoxingStatusResult.NO_UNBOX;
import static com.android.tools.r8.ir.optimize.numberunboxer.NumberUnboxerBoxingStatusResolution.MethodBoxingStatusResult.BoxingStatusResult.TO_PROCESS;
import static com.android.tools.r8.ir.optimize.numberunboxer.NumberUnboxerBoxingStatusResolution.MethodBoxingStatusResult.BoxingStatusResult.UNBOX;
-import static com.android.tools.r8.utils.ListUtils.*;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.optimize.numberunboxer.NumberUnboxerBoxingStatusResolution.MethodBoxingStatusResult.BoxingStatusResult;
import com.android.tools.r8.ir.optimize.numberunboxer.TransitiveDependency.MethodArg;
import com.android.tools.r8.ir.optimize.numberunboxer.TransitiveDependency.MethodRet;
+import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.WorkList;
import java.util.Arrays;
@@ -72,6 +72,20 @@
public BoxingStatusResult[] getArgs() {
return args;
}
+
+ public boolean isNoneUnboxable() {
+ return ret == NO_UNBOX && ArrayUtils.all(args, NO_UNBOX);
+ }
+
+ public boolean shouldUnboxArg(int i) {
+ assert args[i] != TO_PROCESS;
+ return args[i] == UNBOX;
+ }
+
+ public boolean shouldUnboxRet() {
+ assert ret != TO_PROCESS;
+ return ret == UNBOX;
+ }
}
void markNoneUnboxable(DexMethod method) {
@@ -135,9 +149,14 @@
}
}
assert allProcessed();
+ clearNoneUnboxable();
return boxingStatusResultMap;
}
+ private void clearNoneUnboxable() {
+ boxingStatusResultMap.values().removeIf(MethodBoxingStatusResult::isNoneUnboxable);
+ }
+
private boolean allProcessed() {
boxingStatusResultMap.forEach(
(k, v) -> {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerImpl.java
index cf8f2ec..1e623e1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerImpl.java
@@ -43,13 +43,13 @@
public class NumberUnboxerImpl extends NumberUnboxer {
- private AppView<AppInfoWithLiveness> appView;
- private DexItemFactory factory;
- private Set<DexType> boxedTypes;
+ private final AppView<AppInfoWithLiveness> appView;
+ private final DexItemFactory factory;
+ private final Set<DexType> boxedTypes;
// Temporarily keep the information here, and not in the MethodOptimizationInfo as the
// optimization is developed and unfinished.
- private Map<DexMethod, MethodBoxingStatus> methodBoxingStatus = new ConcurrentHashMap<>();
+ private final Map<DexMethod, MethodBoxingStatus> methodBoxingStatus = new ConcurrentHashMap<>();
private Map<DexMethod, DexMethod> virtualMethodsRepresentative;
public NumberUnboxerImpl(AppView<AppInfoWithLiveness> appView) {
@@ -301,17 +301,28 @@
public void unboxNumbers(
PostMethodProcessor.Builder postMethodProcessorBuilder,
Timing timing,
- ExecutorService executorService) {
-
- Map<DexMethod, MethodBoxingStatusResult> result =
+ ExecutorService executorService)
+ throws ExecutionException {
+ Map<DexMethod, MethodBoxingStatusResult> unboxingResult =
new NumberUnboxerBoxingStatusResolution().resolve(methodBoxingStatus);
+ if (unboxingResult.isEmpty()) {
+ return;
+ }
- // TODO(b/307872552): The result encodes for each method which return value and parameter of
- // each method should be unboxed. We need here to implement the treefixer using it, and set up
- // correctly the reprocessing with a code rewriter similar to the enum unboxing code rewriter.
- // We should implement the optimization, so far, we just print out the result.
+ NumberUnboxerLens numberUnboxerLens =
+ new NumberUnboxerTreeFixer(appView, unboxingResult).fixupTree(executorService, timing);
+ appView.rewriteWithLens(numberUnboxerLens, executorService, timing);
+ new NumberUnboxerMethodReprocessingEnqueuer(appView, numberUnboxerLens)
+ .enqueueMethodsForReprocessing(postMethodProcessorBuilder, executorService, timing);
+
+ if (appView.testing().printNumberUnboxed) {
+ printNumberUnboxed(unboxingResult);
+ }
+ }
+
+ private void printNumberUnboxed(Map<DexMethod, MethodBoxingStatusResult> unboxingResult) {
StringBuilder stringBuilder = new StringBuilder();
- result.forEach(
+ unboxingResult.forEach(
(k, v) -> {
if (v.getRet() == UNBOX) {
stringBuilder
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerLens.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerLens.java
new file mode 100644
index 0000000..eeb1768
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerLens.java
@@ -0,0 +1,108 @@
+// Copyright (c) 2023, 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.ir.optimize.numberunboxer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.lens.NestedGraphLensWithCustomLensCodeRewriter;
+import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
+import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.graph.proto.RewrittenTypeInfo;
+import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
+import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
+import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NumberUnboxerLens extends NestedGraphLensWithCustomLensCodeRewriter {
+ private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod;
+
+ NumberUnboxerLens(
+ AppView<AppInfoWithLiveness> appView,
+ BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> renamedSignatures,
+ Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod,
+ NumberUnboxerRewriter numberUnboxerRewriter) {
+ super(appView, EMPTY_FIELD_MAP, renamedSignatures, EMPTY_TYPE_MAP, numberUnboxerRewriter);
+ this.prototypeChangesPerMethod = prototypeChangesPerMethod;
+ }
+
+ @Override
+ protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
+ RewrittenPrototypeDescription prototypeChanges, DexMethod method) {
+ RewrittenPrototypeDescription enumUnboxingPrototypeChanges =
+ prototypeChangesPerMethod.getOrDefault(method, RewrittenPrototypeDescription.none());
+ return prototypeChanges.combine(enumUnboxingPrototypeChanges);
+ }
+
+ @Override
+ public boolean isNumberUnboxerLens() {
+ return true;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod =
+ new IdentityHashMap<>();
+ private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
+ new BidirectionalOneToOneHashMap<>();
+
+ public RewrittenPrototypeDescription move(DexEncodedMethod fromEncoded, DexMethod to) {
+ DexMethod from = fromEncoded.getReference();
+ assert !from.isIdenticalTo(to);
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters =
+ ExtraUnusedNullParameter.computeExtraUnusedNullParameters(from, to);
+ RewrittenPrototypeDescription prototypeChanges =
+ computePrototypeChanges(from, to, fromEncoded.isStatic(), extraUnusedNullParameters);
+ synchronized (this) {
+ newMethodSignatures.put(from, to);
+ prototypeChangesPerMethod.put(to, prototypeChanges);
+ }
+ return prototypeChanges;
+ }
+
+ private RewrittenPrototypeDescription computePrototypeChanges(
+ DexMethod from,
+ DexMethod to,
+ boolean staticMethod,
+ List<ExtraUnusedNullParameter> extraUnusedNullParameters) {
+ assert from.getArity() + extraUnusedNullParameters.size() == to.getArity();
+ ArgumentInfoCollection.Builder builder =
+ ArgumentInfoCollection.builder()
+ .setArgumentInfosSize(from.getNumberOfArguments(staticMethod));
+ for (int i = 0; i < from.getParameters().size(); i++) {
+ DexType fromType = from.getParameter(i);
+ DexType toType = to.getParameter(i);
+ if (!fromType.isIdenticalTo(toType)) {
+ builder.addArgumentInfo(
+ i, RewrittenTypeInfo.builder().setOldType(fromType).setNewType(toType).build());
+ }
+ }
+ RewrittenTypeInfo returnInfo =
+ from.getReturnType().isIdenticalTo(to.getReturnType())
+ ? null
+ : RewrittenTypeInfo.builder()
+ .setOldType(from.getReturnType())
+ .setNewType(to.getReturnType())
+ .build();
+ return RewrittenPrototypeDescription.create(
+ extraUnusedNullParameters, returnInfo, builder.build());
+ }
+
+ public NumberUnboxerLens build(
+ AppView<AppInfoWithLiveness> appView, NumberUnboxerRewriter numberUnboxerRewriter) {
+ return new NumberUnboxerLens(
+ appView, newMethodSignatures, prototypeChangesPerMethod, numberUnboxerRewriter);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerMethodReprocessingEnqueuer.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerMethodReprocessingEnqueuer.java
new file mode 100644
index 0000000..a48a77f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerMethodReprocessingEnqueuer.java
@@ -0,0 +1,175 @@
+// Copyright (c) 2023, 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.ir.optimize.numberunboxer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DefaultUseRegistryWithResult;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.ir.conversion.PostMethodProcessor;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Timing;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+/** Finds the methods in the program that should be reprocessed due to number unboxing. */
+public class NumberUnboxerMethodReprocessingEnqueuer {
+
+ private final AppView<AppInfoWithLiveness> appView;
+ private final NumberUnboxerLens numberUnboxerLens;
+
+ public NumberUnboxerMethodReprocessingEnqueuer(
+ AppView<AppInfoWithLiveness> appView, NumberUnboxerLens numberUnboxerLens) {
+ this.appView = appView;
+ this.numberUnboxerLens = numberUnboxerLens;
+ }
+
+ public void enqueueMethodsForReprocessing(
+ PostMethodProcessor.Builder postMethodProcessorBuilder,
+ ExecutorService executorService,
+ Timing timing)
+ throws ExecutionException {
+ timing.begin("Enqueue methods for reprocessing due to the number unboxer");
+ assert appView.graphLens() == numberUnboxerLens;
+ postMethodProcessorBuilder.rewrittenWithLens(appView);
+ enqueueAffectedCallees(postMethodProcessorBuilder);
+ enqueueAffectedCallers(postMethodProcessorBuilder, executorService);
+ timing.end();
+ }
+
+ boolean shouldReprocess(DexMethod reference) {
+ return reference.isNotIdenticalTo(numberUnboxerLens.getPreviousMethodSignature(reference));
+ }
+
+ private void enqueueAffectedCallees(PostMethodProcessor.Builder postMethodProcessorBuilder) {
+ for (DexProgramClass clazz : appView.appInfo().classes()) {
+ clazz.forEachProgramMethodMatching(
+ DexEncodedMethod::hasCode,
+ method -> {
+ if (method.getDefinition().getCode().isSharedCodeObject()) {
+ return;
+ }
+ if (shouldReprocess(method.getReference())) {
+ assert !appView.appInfo().isNeverReprocessMethod(method);
+ postMethodProcessorBuilder.add(method, numberUnboxerLens);
+ }
+ });
+ }
+ }
+
+ // TODO(b/190154391): This could invalidate the @NeverReprocessMethod testing annotations (non
+ // critical). If @NeverReprocessMethod is used, we would need to scan the application to mark
+ // methods as unoptimizable prior to removing parameters from the application.
+ private void enqueueAffectedCallers(
+ PostMethodProcessor.Builder postMethodProcessorBuilder, ExecutorService executorService)
+ throws ExecutionException {
+ Collection<List<ProgramMethod>> methodsToReprocess =
+ ThreadUtils.processItemsWithResultsThatMatches(
+ appView.appInfo().classes(),
+ clazz -> {
+ List<ProgramMethod> methodsToReprocessInClass = new ArrayList<>();
+ clazz.forEachProgramMethodMatching(
+ DexEncodedMethod::hasCode,
+ method -> {
+ AffectedMembersGraphLensUseRegistry registry =
+ new AffectedMembersGraphLensUseRegistry(appView, method);
+ if (method.registerCodeReferencesWithResult(registry)) {
+ assert !method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite();
+ methodsToReprocessInClass.add(method);
+ }
+ });
+ return methodsToReprocessInClass;
+ },
+ res -> !res.isEmpty(),
+ appView.options().getThreadingModule(),
+ executorService);
+ methodsToReprocess.forEach(
+ methodsToReprocessInClass ->
+ postMethodProcessorBuilder.addAll(methodsToReprocessInClass, numberUnboxerLens));
+ }
+
+ public class AffectedMembersGraphLensUseRegistry
+ extends DefaultUseRegistryWithResult<Boolean, ProgramMethod> {
+
+ public AffectedMembersGraphLensUseRegistry(
+ AppView<AppInfoWithLiveness> appViewWithLiveness, ProgramMethod context) {
+ super(appViewWithLiveness, context, false);
+ }
+
+ private void markAffected() {
+ setResult(Boolean.TRUE);
+ }
+
+ @Override
+ public void registerInvokeDirect(DexMethod method) {
+ registerInvokeMethod(method, InvokeType.DIRECT);
+ }
+
+ @Override
+ public void registerInvokeInterface(DexMethod method) {
+ registerInvokeMethod(method, InvokeType.INTERFACE);
+ }
+
+ @Override
+ public void registerInvokeStatic(DexMethod method) {
+ registerInvokeMethod(method, InvokeType.STATIC);
+ }
+
+ @Override
+ public void registerInvokeSuper(DexMethod method) {
+ registerInvokeMethod(method, InvokeType.SUPER);
+ }
+
+ @Override
+ public void registerInvokeVirtual(DexMethod method) {
+ registerInvokeMethod(method, InvokeType.VIRTUAL);
+ }
+
+ private void registerInvokeMethod(DexMethod method, InvokeType invokeType) {
+ // TODO(b/314117865): This is assuming that there are no non-rebound method references.
+ DexMethod reference =
+ numberUnboxerLens
+ .lookupMethod(
+ method, getContext().getReference(), invokeType, numberUnboxerLens.getPrevious())
+ .getReference();
+ assert reference != null;
+ if (shouldReprocess(reference)) {
+ markAffected();
+ }
+ }
+
+ @Override
+ public void registerInstanceFieldRead(DexField field) {
+ registerFieldAccess(field);
+ }
+
+ @Override
+ public void registerInstanceFieldWrite(DexField field) {
+ registerFieldAccess(field);
+ }
+
+ @Override
+ public void registerStaticFieldRead(DexField field) {
+ registerFieldAccess(field);
+ }
+
+ @Override
+ public void registerStaticFieldWrite(DexField field) {
+ registerFieldAccess(field);
+ }
+
+ private void registerFieldAccess(DexField unused) {
+ // TODO(b/307872552): Deal with unboxed fields.
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerRewriter.java
new file mode 100644
index 0000000..83b1c96
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerRewriter.java
@@ -0,0 +1,189 @@
+// Copyright (c) 2023, 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.ir.optimize.numberunboxer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.proto.ArgumentInfo;
+import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.graph.proto.RewrittenTypeInfo;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.ir.code.InvokeVirtual;
+import com.android.tools.r8.ir.code.Phi;
+import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.Return;
+import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.optimize.CustomLensCodeRewriter;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class NumberUnboxerRewriter implements CustomLensCodeRewriter {
+
+ private final AppView<AppInfoWithLiveness> appView;
+
+ public NumberUnboxerRewriter(AppView<AppInfoWithLiveness> appView) {
+ this.appView = appView;
+ }
+
+ @Override
+ public Set<Phi> rewriteCode(
+ IRCode code,
+ MethodProcessor methodProcessor,
+ RewrittenPrototypeDescription prototypeChanges,
+ NonIdentityGraphLens graphLens) {
+ assert graphLens.isNumberUnboxerLens();
+ Set<Phi> affectedPhis = Sets.newIdentityHashSet();
+ rewriteArgs(code, prototypeChanges, affectedPhis);
+ InstructionListIterator iterator = code.instructionListIterator();
+ while (iterator.hasNext()) {
+ Instruction next = iterator.next();
+ if (next.isInvokeMethod()) {
+ InvokeMethod invokeMethod = next.asInvokeMethod();
+ // TODO(b/314117865): This is assuming that there are no non-rebound method references.
+ DexMethod rewrittenMethod =
+ graphLens
+ .lookupMethod(
+ invokeMethod.getInvokedMethod(),
+ code.context().getReference(),
+ invokeMethod.getType(),
+ graphLens.getPrevious())
+ .getReference();
+ assert rewrittenMethod != null;
+ RewrittenPrototypeDescription rewrittenPrototypeDescription =
+ graphLens.lookupPrototypeChangesForMethodDefinition(
+ rewrittenMethod, graphLens.getPrevious());
+ if (!rewrittenPrototypeDescription.isEmpty()) {
+ unboxInvokeValues(
+ code, iterator, invokeMethod, rewrittenPrototypeDescription, affectedPhis);
+ }
+ } else if (next.isReturn() && next.asReturn().hasReturnValue()) {
+ unboxReturnIfNeeded(code, iterator, next.asReturn(), prototypeChanges);
+ }
+ }
+ return affectedPhis;
+ }
+
+ private void unboxInvokeValues(
+ IRCode code,
+ InstructionListIterator iterator,
+ InvokeMethod invokeMethod,
+ RewrittenPrototypeDescription prototypeChanges,
+ Set<Phi> affectedPhis) {
+ assert prototypeChanges.getArgumentInfoCollection().numberOfRemovedArguments() == 0;
+ for (int inValueIndex = 0; inValueIndex < invokeMethod.inValues().size(); inValueIndex++) {
+ ArgumentInfo argumentInfo =
+ prototypeChanges.getArgumentInfoCollection().getArgumentInfo(inValueIndex);
+ if (argumentInfo.isRewrittenTypeInfo()) {
+ Value invokeArg = invokeMethod.getArgument(inValueIndex);
+ InvokeVirtual unboxOperation =
+ computeUnboxInvokeIfNeeded(
+ code, invokeArg, argumentInfo.asRewrittenTypeInfo(), invokeMethod.getPosition());
+ if (unboxOperation != null) {
+ iterator.addBeforeAndPositionAfterNewInstruction(unboxOperation);
+ invokeMethod.replaceValue(inValueIndex, unboxOperation.outValue());
+ }
+ }
+ }
+ if (invokeMethod.hasOutValue()) {
+ InvokeStatic boxOperation =
+ computeBoxInvokeIfNeeded(
+ code,
+ invokeMethod.outValue(),
+ prototypeChanges.getRewrittenReturnInfo(),
+ invokeMethod.getPosition());
+ if (boxOperation != null) {
+ iterator.add(boxOperation);
+ affectedPhis.addAll(boxOperation.outValue().uniquePhiUsers());
+ }
+ }
+ }
+
+ private void unboxReturnIfNeeded(
+ IRCode code,
+ InstructionListIterator iterator,
+ Return ret,
+ RewrittenPrototypeDescription prototypeChanges) {
+ InvokeVirtual unbox =
+ computeUnboxInvokeIfNeeded(
+ code, ret.returnValue(), prototypeChanges.getRewrittenReturnInfo(), ret.getPosition());
+ if (unbox != null) {
+ iterator.addBeforeAndPositionAfterNewInstruction(unbox);
+ ret.replaceValue(ret.returnValue(), unbox.outValue());
+ }
+ }
+
+ private InvokeVirtual computeUnboxInvokeIfNeeded(
+ IRCode code, Value input, RewrittenTypeInfo rewrittenTypeInfo, Position pos) {
+ if (rewrittenTypeInfo == null) {
+ return null;
+ }
+ assert rewrittenTypeInfo.getOldType().isReferenceType();
+ assert rewrittenTypeInfo.getNewType().isPrimitiveType();
+ assert appView.dexItemFactory().primitiveToBoxed.containsValue(rewrittenTypeInfo.getOldType());
+ return InvokeVirtual.builder()
+ .setMethod(appView.dexItemFactory().getUnboxPrimitiveMethod(rewrittenTypeInfo.getNewType()))
+ .setFreshOutValue(
+ code.valueNumberGenerator, rewrittenTypeInfo.getNewType().toTypeElement(appView))
+ .setArguments(ImmutableList.of(input))
+ .setPosition(pos)
+ .build();
+ }
+
+ private InvokeStatic computeBoxInvokeIfNeeded(
+ IRCode code, Value output, RewrittenTypeInfo rewrittenTypeInfo, Position pos) {
+ if (rewrittenTypeInfo == null) {
+ return null;
+ }
+ assert rewrittenTypeInfo.getOldType().isReferenceType();
+ assert rewrittenTypeInfo.getNewType().isPrimitiveType();
+ assert appView.dexItemFactory().primitiveToBoxed.containsValue(rewrittenTypeInfo.getOldType());
+ Value outValue = code.createValue(rewrittenTypeInfo.getOldType().toTypeElement(appView));
+ output.replaceUsers(outValue);
+ return InvokeStatic.builder()
+ .setOutValue(outValue)
+ .setMethod(appView.dexItemFactory().getBoxPrimitiveMethod(rewrittenTypeInfo.getNewType()))
+ .setSingleArgument(output)
+ .setPosition(pos)
+ .build();
+ }
+
+ private void rewriteArgs(
+ IRCode code, RewrittenPrototypeDescription prototypeChanges, Set<Phi> affectedPhis) {
+ List<InvokeStatic> boxingOperations = new ArrayList<>();
+ InstructionListIterator iterator = code.entryBlock().listIterator(code);
+ Position pos = iterator.peekNext().getPosition();
+ assert prototypeChanges.getArgumentInfoCollection().numberOfRemovedArguments() == 0;
+ int originalNumberOfArguments = code.getNumberOfArguments();
+ for (int argumentIndex = 0; argumentIndex < originalNumberOfArguments; argumentIndex++) {
+ ArgumentInfo argumentInfo =
+ prototypeChanges.getArgumentInfoCollection().getArgumentInfo(argumentIndex);
+ Instruction next = iterator.next();
+ assert next.isArgument();
+ if (argumentInfo.isRewrittenTypeInfo()) {
+ InvokeStatic boxOperation =
+ computeBoxInvokeIfNeeded(
+ code, next.outValue(), argumentInfo.asRewrittenTypeInfo(), pos);
+ if (boxOperation != null) {
+ boxingOperations.add(boxOperation);
+ }
+ }
+ }
+ assert !iterator.peekNext().isArgument();
+ for (InvokeStatic boxingOp : boxingOperations) {
+ iterator.add(boxingOp);
+ affectedPhis.addAll(boxingOp.outValue().uniquePhiUsers());
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerTreeFixer.java
new file mode 100644
index 0000000..166cccd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/numberunboxer/NumberUnboxerTreeFixer.java
@@ -0,0 +1,111 @@
+// Copyright (c) 2023, 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.ir.optimize.numberunboxer;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.fixup.ConcurrentMethodFixup;
+import com.android.tools.r8.graph.fixup.ConcurrentMethodFixup.ProgramClassFixer;
+import com.android.tools.r8.graph.fixup.MethodNamingUtility;
+import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.ir.optimize.numberunboxer.NumberUnboxerBoxingStatusResolution.MethodBoxingStatusResult;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ArrayUtils;
+import com.android.tools.r8.utils.OptionalBool;
+import com.android.tools.r8.utils.Timing;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+public class NumberUnboxerTreeFixer implements ProgramClassFixer {
+
+ private final Map<DexMethod, MethodBoxingStatusResult> unboxingResult;
+ private final AppView<AppInfoWithLiveness> appView;
+
+ private final NumberUnboxerLens.Builder lensBuilder = NumberUnboxerLens.builder();
+
+ public NumberUnboxerTreeFixer(
+ AppView<AppInfoWithLiveness> appView,
+ Map<DexMethod, MethodBoxingStatusResult> unboxingResult) {
+ this.unboxingResult = unboxingResult;
+ this.appView = appView;
+ }
+
+ public NumberUnboxerLens fixupTree(ExecutorService executorService, Timing timing)
+ throws ExecutionException {
+ // Take strongly connected components, for each merge data from call-sites and methods and
+ // unbox.
+ new ConcurrentMethodFixup(appView, this)
+ .fixupClassesConcurrentlyByConnectedProgramComponents(timing, executorService);
+ return lensBuilder.build(appView, new NumberUnboxerRewriter(appView));
+ }
+
+ @Override
+ public void fixupProgramClass(DexProgramClass clazz, MethodNamingUtility utility) {
+ clazz.getMethodCollection().replaceMethods(m -> fixupEncodedMethod(m, utility));
+ }
+
+ @Override
+ public boolean shouldReserveAsIfPinned(ProgramMethod method) {
+ // We don't reprocess dependencies of unchanged methods so we have to maintain them
+ // with the same signature.
+ return !unboxingResult.containsKey(method.getReference());
+ }
+
+ private DexEncodedMethod fixupEncodedMethod(
+ DexEncodedMethod method, MethodNamingUtility utility) {
+ if (!unboxingResult.containsKey(method.getReference())) {
+ assert method
+ .getReference()
+ .isIdenticalTo(
+ utility.nextUniqueMethod(
+ method, method.getProto(), appView.dexItemFactory().shortType));
+ return method;
+ }
+ MethodBoxingStatusResult methodBoxingStatus = unboxingResult.get(method.getReference());
+ assert !methodBoxingStatus.isNoneUnboxable();
+ DexProto newProto = fixupProto(method.getProto(), methodBoxingStatus);
+ DexMethod newMethod =
+ utility.nextUniqueMethod(method, newProto, appView.dexItemFactory().shortType);
+
+ RewrittenPrototypeDescription prototypeChanges = lensBuilder.move(method, newMethod);
+ return method.toTypeSubstitutedMethodAsInlining(
+ newMethod,
+ appView.dexItemFactory(),
+ builder ->
+ builder
+ .fixupOptimizationInfo(
+ appView, prototypeChanges.createMethodOptimizationInfoFixer())
+ .setCompilationState(method.getCompilationState())
+ .setIsLibraryMethodOverrideIf(
+ method.isNonPrivateVirtualMethod(), OptionalBool.FALSE));
+ }
+
+ private DexType fixupType(DexType type, boolean unbox) {
+ if (!unbox) {
+ return type;
+ }
+ DexType newType = appView.dexItemFactory().primitiveToBoxed.inverse().get(type);
+ assert newType != null;
+ return newType;
+ }
+
+ private DexProto fixupProto(DexProto proto, MethodBoxingStatusResult methodBoxingStatus) {
+ DexType[] argTypes = proto.getParameters().values;
+ DexType[] newArgTypes =
+ ArrayUtils.initialize(
+ new DexType[argTypes.length],
+ i -> fixupType(argTypes[i], methodBoxingStatus.shouldUnboxArg(i)));
+ DexType newReturnType = fixupType(proto.getReturnType(), methodBoxingStatus.shouldUnboxRet());
+ DexProto newProto = appView.dexItemFactory().createProto(newReturnType, newArgTypes);
+ assert newProto.isNotIdenticalTo(proto);
+ return newProto;
+ }
+}
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 f60a3fe..3eeaae6 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
@@ -35,6 +35,7 @@
import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
import com.android.tools.r8.ir.optimize.AffectedValues;
import com.android.tools.r8.naming.dexitembasedstring.ClassNameComputationInfo;
+import com.android.tools.r8.shaking.KeepClassInfo;
import java.io.UTFDataFormatException;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -308,8 +309,10 @@
continue;
}
boolean mayBeRenamed =
- appView.enableWholeProgramOptimizations()
- && appView.withLiveness().appInfo().isMinificationAllowed(holder);
+ holder.isProgramClass()
+ && appView
+ .getKeepInfoOrDefault(holder.asProgramClass(), KeepClassInfo.top())
+ .isMinificationAllowed(options);
// b/120138731: Filter out escaping uses. In such case, the result of this optimization will
// be stored somewhere, which can lead to a regression if the corresponding class is in a deep
// package hierarchy. For local cases, it is likely a one-time computation, but make sure the
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index 54a9c8c..056b7fa 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -373,6 +373,21 @@
.withAssert(c -> c.metadataMap == null);
}
+ protected LirCode(LirCode<EV> code) {
+ this(
+ code.irMetadata,
+ code.constants,
+ code.positionTable,
+ code.argumentCount,
+ code.instructions,
+ code.instructionCount,
+ code.tryCatchTable,
+ code.debugLocalInfoTable,
+ code.strategyInfo,
+ code.useDexEstimationStrategy,
+ code.metadataMap);
+ }
+
/** Should be constructed using {@link LirBuilder}. */
LirCode(
IRMetadata irMetadata,
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 71ff9e8..559d7f0 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -674,6 +674,11 @@
}
if (isInit) {
expect('>');
+ // There are some files that include identifier text after <clinit>, such as
+ // <clinit>$redex$opt as seen in b/309080420.
+ while (IdentifierUtils.isDexIdentifierPart(peekCodePoint())) {
+ nextCodePoint();
+ }
}
if (IdentifierUtils.isDexIdentifierPart(peekCodePoint())) {
throw new ParseException(
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index ea9d69a..0b947a3 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -131,7 +131,9 @@
methodState = MethodState.unknown();
}
- methodState = getMethodStateAfterUninstantiatedParameterRemoval(method, methodState);
+ if (appView.getKeepInfo(method).isArgumentPropagationAllowed(options)) {
+ methodState = getMethodStateAfterUninstantiatedParameterRemoval(method, methodState);
+ }
if (methodState.isUnknown()) {
// Nothing is known about the arguments to this method.
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 794ef20..f130874 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -166,13 +166,6 @@
private final Set<DexMethod> neverReprocess;
/** All types that should be inlined if possible due to a configuration directive. */
public final PredicateSet<DexType> alwaysClassInline;
- /** All types that *must* never be inlined due to a configuration directive (testing only). */
- private final Set<DexType> neverClassInline;
-
- private final Set<DexType> noClassMerging;
- private final Set<DexType> noHorizontalClassMerging;
- private final Set<DexType> noVerticalClassMerging;
-
/**
* Set of lock candidates (i.e., types whose class reference may flow to a monitor instruction).
*/
@@ -232,10 +225,6 @@
Set<DexMethod> reprocess,
Set<DexMethod> neverReprocess,
PredicateSet<DexType> alwaysClassInline,
- Set<DexType> neverClassInline,
- Set<DexType> noClassMerging,
- Set<DexType> noVerticalClassMerging,
- Set<DexType> noHorizontalClassMerging,
Set<DexMember<?, ?>> neverPropagateValue,
Object2BooleanMap<DexMember<?, ?>> identifierNameStrings,
Set<DexType> prunedTypes,
@@ -265,10 +254,6 @@
this.reprocess = reprocess;
this.neverReprocess = neverReprocess;
this.alwaysClassInline = alwaysClassInline;
- this.neverClassInline = neverClassInline;
- this.noClassMerging = noClassMerging;
- this.noVerticalClassMerging = noVerticalClassMerging;
- this.noHorizontalClassMerging = noHorizontalClassMerging;
this.neverPropagateValue = neverPropagateValue;
this.identifierNameStrings = identifierNameStrings;
this.prunedTypes = prunedTypes;
@@ -306,10 +291,6 @@
previous.reprocess,
previous.neverReprocess,
previous.alwaysClassInline,
- previous.neverClassInline,
- previous.noClassMerging,
- previous.noVerticalClassMerging,
- previous.noHorizontalClassMerging,
previous.neverPropagateValue,
previous.identifierNameStrings,
previous.prunedTypes,
@@ -348,10 +329,6 @@
pruneMethods(previous.reprocess, prunedItems, tasks),
pruneMethods(previous.neverReprocess, prunedItems, tasks),
previous.alwaysClassInline,
- pruneClasses(previous.neverClassInline, prunedItems, tasks),
- pruneClasses(previous.noClassMerging, prunedItems, tasks),
- pruneClasses(previous.noVerticalClassMerging, prunedItems, tasks),
- pruneClasses(previous.noHorizontalClassMerging, prunedItems, tasks),
pruneMembers(previous.neverPropagateValue, prunedItems, tasks),
pruneMapFromMembers(previous.identifierNameStrings, prunedItems, tasks),
prunedItems.hasRemovedClasses()
@@ -536,10 +513,6 @@
reprocess,
neverReprocess,
alwaysClassInline,
- neverClassInline,
- noClassMerging,
- noVerticalClassMerging,
- noHorizontalClassMerging,
neverPropagateValue,
identifierNameStrings,
prunedTypes,
@@ -614,10 +587,6 @@
this.reprocess = previous.reprocess;
this.neverReprocess = previous.neverReprocess;
this.alwaysClassInline = previous.alwaysClassInline;
- this.neverClassInline = previous.neverClassInline;
- this.noClassMerging = previous.noClassMerging;
- this.noVerticalClassMerging = previous.noVerticalClassMerging;
- this.noHorizontalClassMerging = previous.noHorizontalClassMerging;
this.neverPropagateValue = previous.neverPropagateValue;
this.identifierNameStrings = previous.identifierNameStrings;
this.prunedTypes = previous.prunedTypes;
@@ -1043,39 +1012,31 @@
return this;
}
- public boolean isClassInliningAllowed(DexProgramClass clazz) {
- return !isPinned(clazz) && !neverClassInline.contains(clazz.getType());
- }
-
+ @Deprecated
public boolean isMinificationAllowed(DexProgramClass clazz) {
return options().isMinificationEnabled()
&& keepInfo.getInfo(clazz).isMinificationAllowed(options());
}
+ @Deprecated
public boolean isMinificationAllowed(ProgramDefinition definition) {
return options().isMinificationEnabled()
&& keepInfo.getInfo(definition).isMinificationAllowed(options());
}
+ @Deprecated
public boolean isMinificationAllowed(DexDefinition definition) {
return options().isMinificationEnabled()
&& keepInfo.getInfo(definition, this).isMinificationAllowed(options());
}
+ @Deprecated
public boolean isMinificationAllowed(DexType reference) {
return options().isMinificationEnabled()
&& keepInfo.getClassInfo(reference, this).isMinificationAllowed(options());
}
- public boolean isAccessModificationAllowed(ProgramDefinition definition) {
- assert options().getProguardConfiguration().isAccessModificationAllowed();
- return keepInfo.getInfo(definition).isAccessModificationAllowed(options());
- }
-
public boolean isRepackagingAllowed(DexProgramClass clazz, AppView<?> appView) {
- if (!options().isRepackagingEnabled()) {
- return false;
- }
if (!keepInfo.getInfo(clazz).isRepackagingAllowed(options())) {
return false;
}
@@ -1086,19 +1047,23 @@
return applyMappingSeedMapper == null || !applyMappingSeedMapper.hasMapping(clazz.type);
}
+ @Deprecated
public boolean isPinnedWithDefinitionLookup(DexReference reference) {
assert checkIfObsolete();
return keepInfo.isPinnedWithDefinitionLookup(reference, options(), this);
}
+ @Deprecated
public boolean isPinned(DexDefinition definition) {
return keepInfo.isPinned(definition, options(), this);
}
+ @Deprecated
public boolean isPinned(DexProgramClass clazz) {
return keepInfo.isPinned(clazz, options());
}
+ @Deprecated
public boolean isPinned(Definition definition) {
assert definition != null;
return definition.isProgramDefinition()
@@ -1199,10 +1164,6 @@
lens.rewriteReferences(reprocess),
lens.rewriteReferences(neverReprocess),
alwaysClassInline.rewriteItems(lens::lookupType),
- lens.rewriteReferences(neverClassInline),
- lens.rewriteReferences(noClassMerging),
- lens.rewriteReferences(noVerticalClassMerging),
- lens.rewriteReferences(noHorizontalClassMerging),
lens.rewriteReferences(neverPropagateValue),
lens.rewriteReferenceKeys(identifierNameStrings),
// Don't rewrite pruned types - the removed types are identified by their original name.
@@ -1513,18 +1474,6 @@
return SubtypingInfo.create(this);
}
- /** Predicate on types that *must* never be merged horizontally. */
- public boolean isNoHorizontalClassMergingOfType(DexProgramClass clazz) {
- return noClassMerging.contains(clazz.getType())
- || noHorizontalClassMerging.contains(clazz.getType());
- }
-
- /** Predicate on types that *must* never be merged vertically. */
- public boolean isNoVerticalClassMergingOfType(DexProgramClass clazz) {
- return noClassMerging.contains(clazz.getType())
- || noVerticalClassMerging.contains(clazz.getType());
- }
-
public boolean verifyNoIteratingOverPrunedClasses() {
classes()
.forEach(
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index d1a2dda..30d6e81 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -10,6 +10,7 @@
import static com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.Flavor.ExcludeDexResources;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod;
+import static com.android.tools.r8.shaking.KeepInfo.Joiner.asClassJoinerOrNull;
import static com.android.tools.r8.shaking.KeepInfo.Joiner.asFieldJoinerOrNull;
import static com.android.tools.r8.utils.CovariantReturnTypeUtils.modelLibraryMethodsWithCovariantReturnTypes;
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
@@ -739,6 +740,16 @@
return keepInfo.getClassInfo(clazz);
}
+ public boolean hasMinimumKeepInfoThatMatches(
+ DexProgramClass clazz, Predicate<KeepClassInfo.Joiner> predicate) {
+ MinimumKeepInfoCollection minimumKeepInfoCollection =
+ dependentMinimumKeepInfo.getUnconditionalMinimumKeepInfoOrDefault(
+ MinimumKeepInfoCollection.empty());
+ KeepClassInfo.Joiner minimumKeepInfo =
+ asClassJoinerOrNull(minimumKeepInfoCollection.getOrDefault(clazz.getReference(), null));
+ return minimumKeepInfo != null && predicate.test(minimumKeepInfo);
+ }
+
public KeepFieldInfo getKeepInfo(ProgramField field) {
return keepInfo.getFieldInfo(field);
}
@@ -2225,8 +2236,8 @@
return;
}
- if (!appView.options().enableUnusedInterfaceRemoval
- || rootSet.noUnusedInterfaceRemoval.contains(type)
+ if (!options.enableUnusedInterfaceRemoval
+ || hasMinimumKeepInfoThatMatches(clazz, info -> !info.isUnusedInterfaceRemovalAllowed())
|| mode.isMainDexTracing()) {
markTypeAsLive(clazz, implementer);
return;
@@ -4309,10 +4320,6 @@
amendWithCompanionMethods(rootSet.reprocess),
amendWithCompanionMethods(rootSet.neverReprocess),
rootSet.alwaysClassInline,
- rootSet.neverClassInline,
- noClassMerging,
- rootSet.noVerticalClassMerging,
- rootSet.noHorizontalClassMerging,
rootSet.neverPropagateValue,
joinIdentifierNameStrings(rootSet.identifierNameStrings, identifierNameStrings),
emptySet(),
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepClassInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepClassInfo.java
index c199247..bd4cc3c 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepClassInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepClassInfo.java
@@ -15,11 +15,27 @@
// Requires all aspects of a class to be kept.
private static final KeepClassInfo TOP =
- new Builder().makeTop().disallowRepackaging().disallowPermittedSubclassesRemoval().build();
+ new Builder()
+ .makeTop()
+ .disallowClassInlining()
+ .disallowHorizontalClassMerging()
+ .disallowPermittedSubclassesRemoval()
+ .disallowRepackaging()
+ .disallowUnusedInterfaceRemoval()
+ .disallowVerticalClassMerging()
+ .build();
// Requires no aspects of a class to be kept.
private static final KeepClassInfo BOTTOM =
- new Builder().makeBottom().allowRepackaging().allowPermittedSubclassesRemoval().build();
+ new Builder()
+ .makeBottom()
+ .allowClassInlining()
+ .allowHorizontalClassMerging()
+ .allowPermittedSubclassesRemoval()
+ .allowRepackaging()
+ .allowUnusedInterfaceRemoval()
+ .allowVerticalClassMerging()
+ .build();
public static KeepClassInfo top() {
return TOP;
@@ -33,15 +49,23 @@
return bottom().joiner();
}
- private final boolean allowRepackaging;
- private final boolean checkEnumUnboxed;
+ private final boolean allowClassInlining;
+ private final boolean allowHorizontalClassMerging;
private final boolean allowPermittedSubclassesRemoval;
+ private final boolean allowRepackaging;
+ private final boolean allowUnusedInterfaceRemoval;
+ private final boolean allowVerticalClassMerging;
+ private final boolean checkEnumUnboxed;
private KeepClassInfo(Builder builder) {
super(builder);
- this.allowRepackaging = builder.isRepackagingAllowed();
- this.checkEnumUnboxed = builder.isCheckEnumUnboxedEnabled();
+ this.allowClassInlining = builder.isClassInliningAllowed();
+ this.allowHorizontalClassMerging = builder.isHorizontalClassMergingAllowed();
this.allowPermittedSubclassesRemoval = builder.isPermittedSubclassesRemovalAllowed();
+ this.allowRepackaging = builder.isRepackagingAllowed();
+ this.allowUnusedInterfaceRemoval = builder.isUnusedInterfaceRemovalAllowed();
+ this.allowVerticalClassMerging = builder.isVerticalClassMergingAllowed();
+ this.checkEnumUnboxed = builder.isCheckEnumUnboxedEnabled();
}
@Override
@@ -57,28 +81,24 @@
return checkEnumUnboxed;
}
- public Joiner joiner() {
- assert !isTop();
- return new Joiner(this);
+ public boolean isClassInliningAllowed(GlobalKeepInfoConfiguration configuration) {
+ return isOptimizationAllowed(configuration)
+ && isShrinkingAllowed(configuration)
+ && internalIsClassInliningAllowed();
}
- public boolean isPermittedSubclassesRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
- return !configuration.isKeepPermittedSubclassesEnabled()
- && internalIsPermittedSubclassesRemovalAllowed();
+ boolean internalIsClassInliningAllowed() {
+ return allowClassInlining;
}
- /**
- * True if an item may be repackaged.
- *
- * <p>This method requires knowledge of the global configuration as that can override the concrete
- * value on a given item.
- */
- public boolean isRepackagingAllowed(GlobalKeepInfoConfiguration configuration) {
- return configuration.isRepackagingEnabled() && internalIsRepackagingAllowed();
+ public boolean isHorizontalClassMergingAllowed(GlobalKeepInfoConfiguration configuration) {
+ return isOptimizationAllowed(configuration)
+ && isShrinkingAllowed(configuration)
+ && internalIsHorizontalClassMergingAllowed();
}
- boolean internalIsRepackagingAllowed() {
- return allowRepackaging;
+ boolean internalIsHorizontalClassMergingAllowed() {
+ return allowHorizontalClassMerging;
}
public boolean isKotlinMetadataRemovalAllowed(
@@ -101,10 +121,48 @@
|| !getClassInfo.apply(kotlinMetadataClass.asProgramClass()).isShrinkingAllowed(options);
}
+ public boolean isPermittedSubclassesRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
+ return !configuration.isKeepPermittedSubclassesEnabled()
+ && internalIsPermittedSubclassesRemovalAllowed();
+ }
+
boolean internalIsPermittedSubclassesRemovalAllowed() {
return allowPermittedSubclassesRemoval;
}
+ /**
+ * True if an item may be repackaged.
+ *
+ * <p>This method requires knowledge of the global configuration as that can override the concrete
+ * value on a given item.
+ */
+ public boolean isRepackagingAllowed(GlobalKeepInfoConfiguration configuration) {
+ return configuration.isRepackagingEnabled() && internalIsRepackagingAllowed();
+ }
+
+ boolean internalIsRepackagingAllowed() {
+ return allowRepackaging;
+ }
+
+ boolean internalIsUnusedInterfaceRemovalAllowed() {
+ return allowUnusedInterfaceRemoval;
+ }
+
+ public boolean isVerticalClassMergingAllowed(GlobalKeepInfoConfiguration configuration) {
+ return isOptimizationAllowed(configuration)
+ && isShrinkingAllowed(configuration)
+ && internalIsVerticalClassMergingAllowed();
+ }
+
+ boolean internalIsVerticalClassMergingAllowed() {
+ return allowVerticalClassMerging;
+ }
+
+ public Joiner joiner() {
+ assert !isTop();
+ return new Joiner(this);
+ }
+
@Override
public boolean isTop() {
return this.equals(top());
@@ -117,9 +175,13 @@
public static class Builder extends KeepInfo.Builder<Builder, KeepClassInfo> {
- private boolean allowRepackaging;
- private boolean checkEnumUnboxed;
+ private boolean allowClassInlining;
+ private boolean allowHorizontalClassMerging;
private boolean allowPermittedSubclassesRemoval;
+ private boolean allowRepackaging;
+ private boolean allowUnusedInterfaceRemoval;
+ private boolean allowVerticalClassMerging;
+ private boolean checkEnumUnboxed;
private Builder() {
super();
@@ -127,9 +189,13 @@
private Builder(KeepClassInfo original) {
super(original);
- allowRepackaging = original.internalIsRepackagingAllowed();
- checkEnumUnboxed = original.internalIsCheckEnumUnboxedEnabled();
+ allowClassInlining = original.internalIsClassInliningAllowed();
+ allowHorizontalClassMerging = original.internalIsHorizontalClassMergingAllowed();
allowPermittedSubclassesRemoval = original.internalIsPermittedSubclassesRemovalAllowed();
+ allowRepackaging = original.internalIsRepackagingAllowed();
+ allowUnusedInterfaceRemoval = original.internalIsUnusedInterfaceRemovalAllowed();
+ allowVerticalClassMerging = original.internalIsVerticalClassMergingAllowed();
+ checkEnumUnboxed = original.internalIsCheckEnumUnboxedEnabled();
}
// Check enum unboxed.
@@ -143,6 +209,73 @@
return self();
}
+ public Builder setCheckEnumUnboxed() {
+ return setCheckEnumUnboxed(true);
+ }
+
+ public Builder unsetCheckEnumUnboxed() {
+ return setCheckEnumUnboxed(false);
+ }
+
+ // Class inlining.
+
+ public Builder allowClassInlining() {
+ return setAllowClassInlining(true);
+ }
+
+ public boolean isClassInliningAllowed() {
+ return allowClassInlining;
+ }
+
+ private Builder setAllowClassInlining(boolean allowClassInlining) {
+ this.allowClassInlining = allowClassInlining;
+ return self();
+ }
+
+ public Builder disallowClassInlining() {
+ return setAllowClassInlining(false);
+ }
+
+ // Horizontal class merging.
+
+ public Builder allowHorizontalClassMerging() {
+ return setAllowHorizontalClassMerging(true);
+ }
+
+ public boolean isHorizontalClassMergingAllowed() {
+ return allowHorizontalClassMerging;
+ }
+
+ private Builder setAllowHorizontalClassMerging(boolean allowHorizontalClassMerging) {
+ this.allowHorizontalClassMerging = allowHorizontalClassMerging;
+ return self();
+ }
+
+ public Builder disallowHorizontalClassMerging() {
+ return setAllowHorizontalClassMerging(false);
+ }
+
+ // Permitted subclasses removal.
+
+ public Builder allowPermittedSubclassesRemoval() {
+ return setAllowPermittedSubclassesRemoval(true);
+ }
+
+ public boolean isPermittedSubclassesRemovalAllowed() {
+ return allowPermittedSubclassesRemoval;
+ }
+
+ private Builder setAllowPermittedSubclassesRemoval(boolean allowPermittedSubclassesRemoval) {
+ this.allowPermittedSubclassesRemoval = allowPermittedSubclassesRemoval;
+ return self();
+ }
+
+ public Builder disallowPermittedSubclassesRemoval() {
+ return setAllowPermittedSubclassesRemoval(false);
+ }
+
+ // Repackaging.
+
public boolean isRepackagingAllowed() {
return allowRepackaging;
}
@@ -160,29 +293,42 @@
return setAllowRepackaging(false);
}
- public Builder setCheckEnumUnboxed() {
- return setCheckEnumUnboxed(true);
+ // Unused interface removal.
+
+ public Builder allowUnusedInterfaceRemoval() {
+ return setAllowUnusedInterfaceRemoval(true);
}
- public Builder unsetCheckEnumUnboxed() {
- return setCheckEnumUnboxed(false);
+ public boolean isUnusedInterfaceRemovalAllowed() {
+ return allowUnusedInterfaceRemoval;
}
- public Builder allowPermittedSubclassesRemoval() {
- return setAllowPermittedSubclassesRemoval(true);
- }
-
- public boolean isPermittedSubclassesRemovalAllowed() {
- return allowPermittedSubclassesRemoval;
- }
-
- private Builder setAllowPermittedSubclassesRemoval(boolean allowPermittedSubclassesRemoval) {
- this.allowPermittedSubclassesRemoval = allowPermittedSubclassesRemoval;
+ private Builder setAllowUnusedInterfaceRemoval(boolean allowUnusedInterfaceRemoval) {
+ this.allowUnusedInterfaceRemoval = allowUnusedInterfaceRemoval;
return self();
}
- public Builder disallowPermittedSubclassesRemoval() {
- return setAllowPermittedSubclassesRemoval(false);
+ public Builder disallowUnusedInterfaceRemoval() {
+ return setAllowUnusedInterfaceRemoval(false);
+ }
+
+ // Vertical class merging.
+
+ public Builder allowVerticalClassMerging() {
+ return setAllowVerticalClassMerging(true);
+ }
+
+ public boolean isVerticalClassMergingAllowed() {
+ return allowVerticalClassMerging;
+ }
+
+ private Builder setAllowVerticalClassMerging(boolean allowVerticalClassMerging) {
+ this.allowVerticalClassMerging = allowVerticalClassMerging;
+ return self();
+ }
+
+ public Builder disallowVerticalClassMerging() {
+ return setAllowVerticalClassMerging(false);
}
@Override
@@ -208,10 +354,14 @@
@Override
boolean internalIsEqualTo(KeepClassInfo other) {
return super.internalIsEqualTo(other)
- && isRepackagingAllowed() == other.internalIsRepackagingAllowed()
&& isCheckEnumUnboxedEnabled() == other.internalIsCheckEnumUnboxedEnabled()
+ && isClassInliningAllowed() == other.internalIsClassInliningAllowed()
+ && isHorizontalClassMergingAllowed() == other.internalIsHorizontalClassMergingAllowed()
&& isPermittedSubclassesRemovalAllowed()
- == other.internalIsPermittedSubclassesRemovalAllowed();
+ == other.internalIsPermittedSubclassesRemovalAllowed()
+ && isRepackagingAllowed() == other.internalIsRepackagingAllowed()
+ && isUnusedInterfaceRemovalAllowed() == other.internalIsUnusedInterfaceRemovalAllowed()
+ && isVerticalClassMergingAllowed() == other.internalIsVerticalClassMergingAllowed();
}
@Override
@@ -222,17 +372,25 @@
@Override
public Builder makeTop() {
return super.makeTop()
- .unsetCheckEnumUnboxed()
+ .disallowClassInlining()
+ .disallowHorizontalClassMerging()
+ .disallowPermittedSubclassesRemoval()
.disallowRepackaging()
- .disallowPermittedSubclassesRemoval();
+ .disallowUnusedInterfaceRemoval()
+ .disallowVerticalClassMerging()
+ .unsetCheckEnumUnboxed();
}
@Override
public Builder makeBottom() {
return super.makeBottom()
- .unsetCheckEnumUnboxed()
+ .allowClassInlining()
+ .allowHorizontalClassMerging()
+ .allowPermittedSubclassesRemoval()
.allowRepackaging()
- .allowPermittedSubclassesRemoval();
+ .allowUnusedInterfaceRemoval()
+ .allowVerticalClassMerging()
+ .unsetCheckEnumUnboxed();
}
}
@@ -242,13 +400,13 @@
super(info.builder());
}
- public Joiner setCheckEnumUnboxed() {
- builder.setCheckEnumUnboxed();
+ public Joiner disallowClassInlining() {
+ builder.disallowClassInlining();
return self();
}
- public Joiner disallowRepackaging() {
- builder.disallowRepackaging();
+ public Joiner disallowHorizontalClassMerging() {
+ builder.disallowHorizontalClassMerging();
return self();
}
@@ -257,8 +415,27 @@
return self();
}
- public Joiner allowPermittedSubclassesRemoval() {
- builder.allowPermittedSubclassesRemoval();
+ public Joiner disallowRepackaging() {
+ builder.disallowRepackaging();
+ return self();
+ }
+
+ public Joiner disallowUnusedInterfaceRemoval() {
+ builder.disallowUnusedInterfaceRemoval();
+ return self();
+ }
+
+ public Joiner disallowVerticalClassMerging() {
+ builder.disallowVerticalClassMerging();
+ return self();
+ }
+
+ public boolean isUnusedInterfaceRemovalAllowed() {
+ return builder.isUnusedInterfaceRemovalAllowed();
+ }
+
+ public Joiner setCheckEnumUnboxed() {
+ builder.setCheckEnumUnboxed();
return self();
}
@@ -272,10 +449,20 @@
// Should be extended to merge the fields of this class in case any are added.
return super.merge(joiner)
.applyIf(joiner.builder.isCheckEnumUnboxedEnabled(), Joiner::setCheckEnumUnboxed)
- .applyIf(!joiner.builder.isRepackagingAllowed(), Joiner::disallowRepackaging)
+ .applyIf(!joiner.builder.isClassInliningAllowed(), Joiner::disallowClassInlining)
+ .applyIf(
+ !joiner.builder.isHorizontalClassMergingAllowed(),
+ Joiner::disallowHorizontalClassMerging)
.applyIf(
!joiner.builder.isPermittedSubclassesRemovalAllowed(),
- Joiner::disallowPermittedSubclassesRemoval);
+ Joiner::disallowPermittedSubclassesRemoval)
+ .applyIf(!joiner.builder.isRepackagingAllowed(), Joiner::disallowRepackaging)
+ .applyIf(
+ !joiner.builder.isUnusedInterfaceRemovalAllowed(),
+ Joiner::disallowUnusedInterfaceRemoval)
+ .applyIf(
+ !joiner.builder.isVerticalClassMergingAllowed(),
+ Joiner::disallowVerticalClassMerging);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
index fc0ec2d..e09ed70 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
@@ -502,6 +502,10 @@
return null;
}
+ public static KeepClassInfo.Joiner asClassJoinerOrNull(Joiner<?, ?, ?> joiner) {
+ return joiner != null ? joiner.asClassJoiner() : null;
+ }
+
public KeepFieldInfo.Joiner asFieldJoiner() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 1fcb8e6..e478be4 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -124,10 +124,6 @@
private final Set<DexMethod> reprocess = Sets.newIdentityHashSet();
private final Set<DexMethod> neverReprocess = Sets.newIdentityHashSet();
private final PredicateSet<DexType> alwaysClassInline = new PredicateSet<>();
- private final Set<DexType> neverClassInline = Sets.newIdentityHashSet();
- private final Set<DexType> noUnusedInterfaceRemoval = Sets.newIdentityHashSet();
- private final Set<DexType> noVerticalClassMerging = Sets.newIdentityHashSet();
- private final Set<DexType> noHorizontalClassMerging = Sets.newIdentityHashSet();
private final Set<DexMember<?, ?>> neverPropagateValue = Sets.newIdentityHashSet();
private final Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule =
new IdentityHashMap<>();
@@ -387,10 +383,9 @@
appView,
subtypingInfo,
alwaysClassInline,
- noVerticalClassMerging,
- noHorizontalClassMerging,
alwaysInline,
- bypassClinitforInlining);
+ bypassClinitforInlining,
+ dependentMinimumKeepInfo);
}
return new RootSet(
dependentMinimumKeepInfo,
@@ -402,10 +397,6 @@
reprocess,
neverReprocess,
alwaysClassInline,
- neverClassInline,
- noUnusedInterfaceRemoval,
- noVerticalClassMerging,
- noHorizontalClassMerging,
neverPropagateValue,
mayHaveSideEffects,
dependentKeepClassCompatRule,
@@ -473,8 +464,6 @@
ConsequentRootSet buildConsequentRootSet() {
return new ConsequentRootSet(
neverInlineDueToSingleCaller,
- neverClassInline,
- noHorizontalClassMerging,
dependentMinimumKeepInfo,
dependentKeepClassCompatRule,
Lists.newArrayList(delayedRootSetActionItems),
@@ -1221,10 +1210,13 @@
}
switch (classInlineRule.getType()) {
case ALWAYS:
- alwaysClassInline.addElement(item.asClass().getType());
+ alwaysClassInline.addElement(clazz.getType());
break;
case NEVER:
- neverClassInline.add(item.asClass().getType());
+ dependentMinimumKeepInfo
+ .getOrCreateUnconditionalMinimumKeepInfoFor(clazz.getType())
+ .asClassJoiner()
+ .disallowClassInlining();
break;
default:
throw new Unreachable();
@@ -1251,13 +1243,25 @@
.disallowRedundantFieldLoadElimination();
context.markAsUsed();
} else if (context instanceof NoUnusedInterfaceRemovalRule) {
- noUnusedInterfaceRemoval.add(item.asClass().type);
+ assert item.isProgramClass();
+ dependentMinimumKeepInfo
+ .getOrCreateUnconditionalMinimumKeepInfoFor(item.getReference())
+ .asClassJoiner()
+ .disallowUnusedInterfaceRemoval();
context.markAsUsed();
} else if (context instanceof NoVerticalClassMergingRule) {
- noVerticalClassMerging.add(item.asClass().type);
+ assert item.isProgramClass();
+ dependentMinimumKeepInfo
+ .getOrCreateUnconditionalMinimumKeepInfoFor(item.getReference())
+ .asClassJoiner()
+ .disallowVerticalClassMerging();
context.markAsUsed();
} else if (context instanceof NoHorizontalClassMergingRule) {
- noHorizontalClassMerging.add(item.asClass().type);
+ assert item.isProgramClass();
+ dependentMinimumKeepInfo
+ .getOrCreateUnconditionalMinimumKeepInfoFor(item.getReference())
+ .asClassJoiner()
+ .disallowHorizontalClassMerging();
context.markAsUsed();
} else if (context instanceof NoMethodStaticizingRule) {
assert item.isProgramMethod();
@@ -1793,8 +1797,6 @@
abstract static class RootSetBase {
final Set<DexMethod> neverInlineDueToSingleCaller;
- final Set<DexType> neverClassInline;
- final Set<DexType> noHorizontalClassMerging;
private final DependentMinimumKeepInfoCollection dependentMinimumKeepInfo;
final Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule;
final List<DelayedRootSetActionItem> delayedRootSetActionItems;
@@ -1802,15 +1804,11 @@
RootSetBase(
Set<DexMethod> neverInlineDueToSingleCaller,
- Set<DexType> neverClassInline,
- Set<DexType> noHorizontalClassMerging,
DependentMinimumKeepInfoCollection dependentMinimumKeepInfo,
Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule,
List<DelayedRootSetActionItem> delayedRootSetActionItems,
ProgramMethodMap<ProgramMethod> pendingMethodMoveInverse) {
this.neverInlineDueToSingleCaller = neverInlineDueToSingleCaller;
- this.neverClassInline = neverClassInline;
- this.noHorizontalClassMerging = noHorizontalClassMerging;
this.dependentMinimumKeepInfo = dependentMinimumKeepInfo;
this.dependentKeepClassCompatRule = dependentKeepClassCompatRule;
this.delayedRootSetActionItems = delayedRootSetActionItems;
@@ -1835,8 +1833,6 @@
public final Set<DexMethod> reprocess;
public final Set<DexMethod> neverReprocess;
public final PredicateSet<DexType> alwaysClassInline;
- public final Set<DexType> noUnusedInterfaceRemoval;
- public final Set<DexType> noVerticalClassMerging;
public final Set<DexMember<?, ?>> neverPropagateValue;
public final Map<DexReference, ProguardMemberRule> mayHaveSideEffects;
public final Set<DexMember<?, ?>> identifierNameStrings;
@@ -1852,10 +1848,6 @@
Set<DexMethod> reprocess,
Set<DexMethod> neverReprocess,
PredicateSet<DexType> alwaysClassInline,
- Set<DexType> neverClassInline,
- Set<DexType> noUnusedInterfaceRemoval,
- Set<DexType> noVerticalClassMerging,
- Set<DexType> noHorizontalClassMerging,
Set<DexMember<?, ?>> neverPropagateValue,
Map<DexReference, ProguardMemberRule> mayHaveSideEffects,
Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule,
@@ -1865,8 +1857,6 @@
ProgramMethodMap<ProgramMethod> pendingMethodMoveInverse) {
super(
neverInlineDueToSingleCaller,
- neverClassInline,
- noHorizontalClassMerging,
dependentMinimumKeepInfo,
dependentKeepClassCompatRule,
delayedRootSetActionItems,
@@ -1878,8 +1868,6 @@
this.reprocess = reprocess;
this.neverReprocess = neverReprocess;
this.alwaysClassInline = alwaysClassInline;
- this.noUnusedInterfaceRemoval = noUnusedInterfaceRemoval;
- this.noVerticalClassMerging = noVerticalClassMerging;
this.neverPropagateValue = neverPropagateValue;
this.mayHaveSideEffects = mayHaveSideEffects;
this.identifierNameStrings = Collections.unmodifiableSet(identifierNameStrings);
@@ -1911,8 +1899,6 @@
void addConsequentRootSet(ConsequentRootSet consequentRootSet) {
neverInlineDueToSingleCaller.addAll(consequentRootSet.neverInlineDueToSingleCaller);
- neverClassInline.addAll(consequentRootSet.neverClassInline);
- noHorizontalClassMerging.addAll(consequentRootSet.noHorizontalClassMerging);
consequentRootSet.dependentKeepClassCompatRule.forEach(
(type, rules) ->
dependentKeepClassCompatRule
@@ -1939,9 +1925,6 @@
getDependentMinimumKeepInfo().pruneDeadItems(definitions, enqueuer);
timing.end();
timing.begin("Prune others");
- pruneDeadReferences(noUnusedInterfaceRemoval, definitions, enqueuer);
- pruneDeadReferences(noVerticalClassMerging, definitions, enqueuer);
- pruneDeadReferences(noHorizontalClassMerging, definitions, enqueuer);
pruneDeadReferences(alwaysInline, definitions, enqueuer);
timing.end();
}
@@ -1997,10 +1980,6 @@
reprocess,
neverReprocess,
alwaysClassInline,
- neverClassInline,
- noUnusedInterfaceRemoval,
- noVerticalClassMerging,
- noHorizontalClassMerging,
neverPropagateValue,
mayHaveSideEffects,
dependentKeepClassCompatRule,
@@ -2238,16 +2217,12 @@
ConsequentRootSet(
Set<DexMethod> neverInlineDueToSingleCaller,
- Set<DexType> neverClassInline,
- Set<DexType> noHorizontalClassMerging,
DependentMinimumKeepInfoCollection dependentMinimumKeepInfo,
Map<DexType, Set<ProguardKeepRuleBase>> dependentKeepClassCompatRule,
List<DelayedRootSetActionItem> delayedRootSetActionItems,
ProgramMethodMap<ProgramMethod> pendingMethodMoveInverse) {
super(
neverInlineDueToSingleCaller,
- neverClassInline,
- noHorizontalClassMerging,
dependentMinimumKeepInfo,
dependentKeepClassCompatRule,
delayedRootSetActionItems,
@@ -2311,10 +2286,6 @@
Collections.emptySet(),
PredicateSet.empty(),
Collections.emptySet(),
- Collections.emptySet(),
- Collections.emptySet(),
- Collections.emptySet(),
- Collections.emptySet(),
emptyMap(),
emptyMap(),
Collections.emptySet(),
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index ac6c169..8bbf801 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -12,6 +12,8 @@
import static com.android.tools.r8.utils.ZipUtils.writeToZipStream;
import static java.nio.charset.StandardCharsets.UTF_8;
+import com.android.tools.r8.AndroidResourceInput;
+import com.android.tools.r8.AndroidResourceProvider;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.DataDirectoryResource;
@@ -99,18 +101,19 @@
private static final String dumpMainDexListResourceFileName = "main-dex-list.txt";
private static final String dumpMainDexRulesResourceFileName = "main-dex-rules.txt";
private static final String dumpProgramFileName = "program.jar";
+ private static final String dumpInputResourcesFileName = "app-res.ap_";
private static final String dumpClasspathFileName = "classpath.jar";
private static final String dumpLibraryFileName = "library.jar";
private static final String dumpConfigFileName = "proguard.config";
private static final String dumpInputConfigFileName = "proguard_input.config";
private static Map<FeatureSplit, String> dumpFeatureSplitFileNames(
- FeatureSplitConfiguration featureSplitConfiguration) {
+ FeatureSplitConfiguration featureSplitConfiguration, String postfix) {
Map<FeatureSplit, String> featureSplitFileNames = new IdentityHashMap<>();
if (featureSplitConfiguration != null) {
int i = 1;
for (FeatureSplit featureSplit : featureSplitConfiguration.getFeatureSplits()) {
- featureSplitFileNames.put(featureSplit, "feature-" + i + ".jar");
+ featureSplitFileNames.put(featureSplit, "feature-" + i + postfix);
i++;
}
}
@@ -550,6 +553,23 @@
if (dumpOptions.hasStartupProfileProviders()) {
dumpStartupProfileProviders(dumpOptions.getStartupProfileProviders(), options, out);
}
+ if (dumpOptions.hasAndroidResourcesProvider()) {
+ dumpAndroidResourcesProvider(
+ dumpOptions.getAndroidResourceProvider(), out, dumpInputResourcesFileName);
+ if (dumpOptions.getFeatureSplitConfiguration() != null) {
+ Map<FeatureSplit, String> featureSplitNameMap =
+ dumpFeatureSplitFileNames(dumpOptions.getFeatureSplitConfiguration(), ".ap_");
+ for (FeatureSplit featureSplit :
+ dumpOptions.getFeatureSplitConfiguration().getFeatureSplits()) {
+ if (featureSplit.getAndroidResourceProvider() != null) {
+ dumpAndroidResourcesProvider(
+ featureSplit.getAndroidResourceProvider(),
+ out,
+ featureSplitNameMap.get(featureSplit));
+ }
+ }
+ }
+ }
nextDexIndex =
dumpProgramResources(
dumpProgramFileName,
@@ -627,6 +647,23 @@
};
}
+ private void dumpAndroidResourcesProvider(
+ AndroidResourceProvider androidResourceProvider, ZipOutputStream out, String name)
+ throws IOException, ResourceException {
+ try (ByteArrayOutputStream archiveByteStream = new ByteArrayOutputStream()) {
+ try (ZipOutputStream archiveOutputStream = new ZipOutputStream(archiveByteStream)) {
+ for (AndroidResourceInput androidResource : androidResourceProvider.getAndroidResources()) {
+ writeToZipStream(
+ archiveOutputStream,
+ androidResource.getPath().location(),
+ androidResource.getByteStream().readAllBytes(),
+ ZipEntry.DEFLATED);
+ }
+ }
+ writeToZipStream(out, name, archiveByteStream.toByteArray(), ZipEntry.DEFLATED);
+ }
+ }
+
private int dumpProgramResources(
String archiveName,
FeatureSplitConfiguration featureSplitConfiguration,
@@ -635,7 +672,7 @@
InternalOptions options)
throws IOException, ResourceException {
Map<FeatureSplit, String> featureSplitArchiveNames =
- dumpFeatureSplitFileNames(featureSplitConfiguration);
+ dumpFeatureSplitFileNames(featureSplitConfiguration, ".jar");
Map<FeatureSplit, ByteArrayOutputStream> featureSplitArchiveByteStreams =
new IdentityHashMap<>();
Map<FeatureSplit, ZipOutputStream> featureSplitArchiveOutputStreams = new IdentityHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index ae6e72c..b71ad68 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -63,6 +63,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.analysis.ResourceAccessAnalysis;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider;
+import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.Policy;
@@ -2173,8 +2174,8 @@
public static class TestingOptions {
public boolean enableNumberUnboxer = false;
+ public boolean printNumberUnboxed = false;
public boolean roundtripThroughLir = false;
-
public boolean canUseLir(AppView<?> appView) {
return appView.enableWholeProgramOptimizations();
}
@@ -2218,6 +2219,19 @@
BytecodeMetadataProvider.empty(),
LirStrategy.getDefaultStrategy().getEncodingStrategy(),
appView.options());
+ // TODO(b/312890994): Setting a custom code lens is only needed until we convert
+ // code objects to LIR before we create the first code object with a custom code
+ // lens (horizontal class merging).
+ GraphLens codeLens = method.getDefinition().getCode().getCodeLens(appView);
+ if (codeLens != appView.codeLens()) {
+ lirCode =
+ new LirCode<>(lirCode) {
+ @Override
+ public GraphLens getCodeLens(AppView<?> appView) {
+ return codeLens;
+ }
+ };
+ }
method.setCode(lirCode, appView);
});
},
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
index 6cb5e12..0ffde6c 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
@@ -214,9 +214,8 @@
if (allocationInfo.isInstantiatedDirectly(sourceClass)
|| allocationInfo.isInterfaceWithUnknownSubtypeHierarchy(sourceClass)
|| allocationInfo.isImmediateInterfaceOfInstantiatedLambda(sourceClass)
- || appView.getKeepInfo(sourceClass).isPinned(options)
- || pinnedClasses.contains(sourceClass)
- || appView.appInfo().isNoVerticalClassMergingOfType(sourceClass)) {
+ || !appView.getKeepInfo(sourceClass).isVerticalClassMergingAllowed(options)
+ || pinnedClasses.contains(sourceClass)) {
return false;
}
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index d1eb192..2183979 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -34,7 +34,6 @@
import com.android.tools.r8.shaking.NoReturnTypeStrengtheningRule;
import com.android.tools.r8.shaking.NoUnusedInterfaceRemovalRule;
import com.android.tools.r8.shaking.NoVerticalClassMergingRule;
-import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.utils.AndroidApp;
@@ -147,25 +146,21 @@
class Box {
private List<ProguardConfigurationRule> syntheticProguardRules;
- private ProguardConfiguration proguardConfiguration;
}
Box box = new Box();
ToolHelper.addSyntheticProguardRulesConsumerForTesting(
builder, rules -> box.syntheticProguardRules = rules);
libraryDesugaringTestConfiguration.configure(builder);
builder.setEnableExperimentalMissingLibraryApiModeling(enableMissingLibraryApiModeling);
- ToolHelper.runAndBenchmarkR8WithoutResult(
- builder,
- optionsConsumer.andThen(
- options -> box.proguardConfiguration = options.getProguardConfiguration()),
- benchmarkResults);
+ StringBuilder pgConfOutput = wrapProguardConfigConsumer(builder);
+ ToolHelper.runAndBenchmarkR8WithoutResult(builder, optionsConsumer, benchmarkResults);
R8TestCompileResult compileResult =
new R8TestCompileResult(
getState(),
getOutputMode(),
libraryDesugaringTestConfiguration,
app.get(),
- box.proguardConfiguration,
+ pgConfOutput.toString(),
box.syntheticProguardRules,
proguardMapBuilder.toString(),
graphConsumer,
@@ -208,6 +203,20 @@
return compileResult;
}
+ private static StringBuilder wrapProguardConfigConsumer(Builder builder) {
+ StringBuilder pgConfOutput = new StringBuilder();
+ StringConsumer pgConfConsumer = builder.getProguardConfigurationConsumer();
+ builder.setProguardConfigurationConsumer(
+ new StringConsumer.ForwardingConsumer(pgConfConsumer) {
+ @Override
+ public void accept(String string, DiagnosticsHandler handler) {
+ super.accept(string, handler);
+ pgConfOutput.append(string);
+ }
+ });
+ return pgConfOutput;
+ }
+
public Builder getBuilder() {
return builder;
}
diff --git a/src/test/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
index 20b9f2d..25001ac 100644
--- a/src/test/java/com/android/tools/r8/R8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
import com.android.tools.r8.shaking.CollectingGraphConsumer;
-import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
@@ -35,7 +34,7 @@
public class R8TestCompileResult extends TestCompileResult<R8TestCompileResult, R8TestRunResult> {
- private final ProguardConfiguration proguardConfiguration;
+ private final String proguardConfiguration;
private final List<ProguardConfigurationRule> syntheticProguardRules;
private final String proguardMap;
private final CollectingGraphConsumer graphConsumer;
@@ -49,7 +48,7 @@
OutputMode outputMode,
LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration,
AndroidApp app,
- ProguardConfiguration proguardConfiguration,
+ String proguardConfiguration,
List<ProguardConfigurationRule> syntheticProguardRules,
String proguardMap,
CollectingGraphConsumer graphConsumer,
@@ -182,12 +181,11 @@
return new GraphInspector(graphConsumer, inspector());
}
- public ProguardConfiguration getProguardConfiguration() {
+ public String getProguardConfiguration() {
return proguardConfiguration;
}
- public R8TestCompileResult inspectProguardConfiguration(
- Consumer<ProguardConfiguration> consumer) {
+ public R8TestCompileResult inspectProguardConfiguration(Consumer<String> consumer) {
consumer.accept(getProguardConfiguration());
return self();
}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesDumpTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesDumpTest.java
new file mode 100644
index 0000000..f4ad013
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidResourcesDumpTest.java
@@ -0,0 +1,118 @@
+// Copyright (c) 2023, 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.androidresources;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.dump.CompilerDump;
+import com.android.tools.r8.utils.DumpInputFlags;
+import com.android.tools.r8.utils.ZipUtils;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidResourcesDumpTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection parameters() {
+ return getTestParameters().withDefaultDexRuntime().withMinimumApiLevel().build();
+ }
+
+ public static AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+ return new AndroidTestResourceBuilder()
+ .withSimpleManifestAndAppNameString()
+ .addStringValue("foo", "the foobar string")
+ .addXmlWithStringReference("file.xml", "foo")
+ .build(temp);
+ }
+
+ public static AndroidTestResource getFeatureTestResources(TemporaryFolder temp)
+ throws IOException {
+ return new AndroidTestResourceBuilder()
+ .withSimpleManifestAndAppNameString()
+ .addStringValue("feature_foo", "the feature string")
+ .addXmlWithStringReference("feature.xml", "feature_foo")
+ .build(temp);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Path dump = temp.newFile("with_resources.zip").toPath();
+ AndroidTestResource testResources = getTestResources(temp);
+ TemporaryFolder featureSplitTemp = ToolHelper.getTemporaryFolderForTest();
+ featureSplitTemp.create();
+ AndroidTestResource featureTestResources = getFeatureTestResources(featureSplitTemp);
+ try {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .addAndroidResources(testResources)
+ .addFeatureSplitAndroidResources(featureTestResources, "thefeature")
+ .addOptionsModification(
+ options -> options.setDumpInputFlags(DumpInputFlags.dumpToFile(dump)))
+ .setMinApi(parameters)
+ .compile();
+ fail("Expected to fail compilation");
+ } catch (CompilationFailedException ignored) {
+ }
+ CompilerDump compilerDump = CompilerDump.fromArchive(dump, temp.newFolder().toPath());
+ validateResourceEquality(
+ testResources,
+ ImmutableList.of("res/xml/file.xml", "AndroidManifest.xml", "resources.pb"),
+ compilerDump.getAndroidResources());
+ validateResourceEquality(
+ featureTestResources,
+ ImmutableList.of("res/xml/feature.xml", "AndroidManifest.xml", "resources.pb"),
+ compilerDump.getAndroidResourcesForFeature(1));
+ }
+
+ private static void validateResourceEquality(
+ AndroidTestResource testResources, List<String> fileEntries, Path dumpInput)
+ throws IOException {
+ int resourceFileCount = 0;
+ try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(dumpInput))) {
+ ZipEntry nextEntry = zipInputStream.getNextEntry();
+ Path resourceZip = testResources.getResourceZip();
+ while (nextEntry != null) {
+ resourceFileCount++;
+ String name = nextEntry.getName();
+ assertTrue(fileEntries.contains(name));
+ byte[] original = ZipUtils.readSingleEntry(resourceZip, name);
+ assertArrayEquals(original, ByteStreams.toByteArray(zipInputStream));
+ nextEntry = zipInputStream.getNextEntry();
+ }
+ }
+ assertEquals(resourceFileCount, fileEntries.size());
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {}
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java b/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
index f5b7bfe..6d9774b 100644
--- a/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
+++ b/src/test/java/com/android/tools/r8/dex/DebugByteCodeWriterTest.java
@@ -73,6 +73,7 @@
new DebugBytecodeWriter(
DexDebugInfo.convertToWritable(debugInfo),
emptyObjectTObjectMapping(),
+ GraphLens.getIdentityLens(),
GraphLens.getIdentityLens());
Assert.assertEquals(3, writer.generate().length);
}
diff --git a/src/main/java/com/android/tools/r8/dump/CompilerDump.java b/src/test/java/com/android/tools/r8/dump/CompilerDump.java
similarity index 88%
rename from src/main/java/com/android/tools/r8/dump/CompilerDump.java
rename to src/test/java/com/android/tools/r8/dump/CompilerDump.java
index 7febf31..46d5ec1 100644
--- a/src/main/java/com/android/tools/r8/dump/CompilerDump.java
+++ b/src/test/java/com/android/tools/r8/dump/CompilerDump.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// Copyright (c) 2023, 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.dump;
@@ -49,6 +49,14 @@
return Files.exists(directory.resolve("desugared-library.json"));
}
+ public Path getAndroidResources() {
+ return directory.resolve("app-res.ap_");
+ }
+
+ public Path getAndroidResourcesForFeature(int feature) {
+ return directory.resolve("feature-" + feature + ".ap_");
+ }
+
public Path getDesugaredLibraryFile() {
return directory.resolve("desugared-library.json");
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMappingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMappingTest.java
new file mode 100644
index 0000000..0f84aa8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingMappingTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2023, 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.enumunboxing;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EnumUnboxingMappingTest extends EnumUnboxingTestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public EnumUnboxingMappingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testEnumUnboxing() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepRules(EnumKeepRules.STUDIO.getKeepRules())
+ .addEnumUnboxingInspector(inspector -> inspector.assertUnboxed(MyEnum.class))
+ .enableNeverClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .allowDiagnosticMessages()
+ .setMinApi(parameters)
+ .compile()
+ .inspect(this::assertParameterTypes)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ "1", "2",
+ "DebugInfoForThisPrint", "1",
+ "DebugInfoForThisPrint", "2");
+ }
+
+ private void assertParameterTypes(CodeInspector codeInspector) {
+ ClassSubject main = codeInspector.clazz(Main.class);
+
+ MethodSubject debugInfoMethod = main.uniqueMethodWithOriginalName("debugInfoAfterUnboxing");
+ MethodSubject noDebugInfoMethod = main.uniqueMethodWithOriginalName("noDebugInfoAfterUnboxing");
+
+ assertEquals("int", debugInfoMethod.getFinalSignature().asMethodSignature().parameters[0]);
+ assertEquals("int", noDebugInfoMethod.getFinalSignature().asMethodSignature().parameters[0]);
+
+ assertEquals(MyEnum.class.getName(), debugInfoMethod.getOriginalSignature().parameters[0]);
+ // TODO(b/314076309): The original parameter should be MyEnum.class but is int.
+ assertEquals("int", noDebugInfoMethod.getOriginalSignature().parameters[0]);
+ }
+
+ @NeverClassInline
+ enum MyEnum {
+ A,
+ B
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(noDebugInfoAfterUnboxing(MyEnum.A));
+ System.out.println(noDebugInfoAfterUnboxing(null));
+ System.out.println(debugInfoAfterUnboxing(MyEnum.A));
+ System.out.println(debugInfoAfterUnboxing(null));
+ }
+
+ @NeverInline
+ private static int noDebugInfoAfterUnboxing(MyEnum e) {
+ return (e == null ? 1 : 0) + 1;
+ }
+
+ @NeverInline
+ private static int debugInfoAfterUnboxing(MyEnum e) {
+ System.out.println("DebugInfoForThisPrint");
+ return (e == null ? 1 : 0) + 1;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldsOnlyWrittenInInitializersWithSingleCallerPruningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldsOnlyWrittenInInitializersWithSingleCallerPruningTest.java
new file mode 100644
index 0000000..250dd0b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldsOnlyWrittenInInitializersWithSingleCallerPruningTest.java
@@ -0,0 +1,94 @@
+// Copyright (c) 2023, 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.ir.optimize.membervaluepropagation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class InstanceFieldsOnlyWrittenInInitializersWithSingleCallerPruningTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ assumeTrue(parameters.canInitNewInstanceUsingSuperclassConstructor());
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ // Ensure that A.<init>(String) is single caller inlined and removed from the application
+ // before processing the last instance field write to A.f.
+ .addOptionsModification(
+ options ->
+ options.testing.waveModifier =
+ waves -> {
+ int numberOfWaves = waves.size();
+ for (ProgramMethodSet wave : waves) {
+ boolean changed =
+ wave.removeIf(
+ method -> {
+ if (method.getHolder().getTypeName().equals(A.class.getTypeName())
+ && method.getDefinition().isInstanceInitializer()
+ && method.getParameters().isEmpty()) {
+ waves.addLast(ProgramMethodSet.create(method));
+ return true;
+ }
+ return false;
+ });
+ if (changed) {
+ break;
+ }
+ }
+ assertEquals(numberOfWaves + 1, waves.size());
+ })
+ .enableInliningAnnotations()
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+
+ static class Main {
+
+ public static void main(String[] args) {
+ System.out.print(new A());
+ System.out.println(new A(", world!"));
+ }
+ }
+
+ static class A {
+
+ String f;
+
+ @NeverInline
+ A() {
+ f = "Hello";
+ }
+
+ A(String f) {
+ this.f = f;
+ }
+
+ @Override
+ public String toString() {
+ return f;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java
index 4f1dc5f..94eb392 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.nonnull;
+import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
+@NeverClassInline
public class NonNullParamInterfaceImpl implements NonNullParamInterface {
@NeverInline
public int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
index 47613a0..414146d6 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionOnFieldTest.java
@@ -57,7 +57,7 @@
.compile()
.apply(
c -> {
- String rules = c.getProguardConfiguration().getParsedConfiguration();
+ String rules = c.getProguardConfiguration();
assertThat(rules, containsString("context: " + descriptor(A.class) + "foo()V"));
assertThat(rules, containsString("description: Keep the\\nstring-valued fields"));
})
diff --git a/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java b/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java
new file mode 100644
index 0000000..fdbe498
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2023, 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.keepanno.doctests;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.keepanno.annotations.KeepEdge;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.MethodAccessFlags;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MainMethodsDocumentationTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello I'm kept!");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDefaultRuntimes().withApiLevel(AndroidApiLevel.B).build();
+ }
+
+ public MainMethodsDocumentationTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClasses(getInputClasses())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testWithRuleExtraction() throws Exception {
+ testForR8(parameters.getBackend())
+ .enableExperimentalKeepAnnotations()
+ .addProgramClasses(getInputClasses())
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ public List<Class<?>> getInputClasses() {
+ return ImmutableList.of(TestClass.class, SomeClass.class);
+ }
+
+ /* INCLUDE DOC: KeepMainMethods
+ For example, to keep all main methods in the program one could use:
+ INCLUDE END */
+
+ static
+ // INCLUDE CODE: KeepMainMethods
+ @KeepEdge(
+ consequences = {
+ @KeepTarget(
+ kind = KeepItemKind.CLASS_AND_MEMBERS,
+ methodName = "main",
+ methodReturnType = "void",
+ methodParameters = {"java.lang.String[]"},
+ methodAccess = {MethodAccessFlags.PUBLIC, MethodAccessFlags.STATIC})
+ })
+ public class SomeClass {
+ // ...
+ }
+
+ // INCLUDE END
+
+ static class TestClass {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Hello I'm kept!");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
index f4fd1a8..6fd05eb 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.keepanno.utils;
+import static com.android.tools.r8.keepanno.utils.KeepItemAnnotationGenerator.quote;
+
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.keepanno.annotations.KeepBinding;
import com.android.tools.r8.keepanno.annotations.KeepCondition;
@@ -13,6 +15,7 @@
import com.android.tools.r8.keepanno.annotations.UsedByNative;
import com.android.tools.r8.keepanno.annotations.UsedByReflection;
import com.android.tools.r8.keepanno.annotations.UsesReflection;
+import com.android.tools.r8.keepanno.doctests.MainMethodsDocumentationTest;
import com.android.tools.r8.keepanno.doctests.UsesReflectionDocumentationTest;
import com.android.tools.r8.keepanno.utils.KeepItemAnnotationGenerator.Generator;
import com.android.tools.r8.utils.FileUtils;
@@ -22,9 +25,15 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public class KeepAnnoMarkdownGenerator {
@@ -39,6 +48,8 @@
private static String JAVADOC_URL =
"https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/";
+ private static final String TOC_MARKER = "[[[TOC]]]";
+
private static final String INCLUDE_MD_START = "[[[INCLUDE";
private static final String INCLUDE_MD_DOC_START = "[[[INCLUDE DOC";
private static final String INCLUDE_MD_CODE_START = "[[[INCLUDE CODE";
@@ -66,7 +77,8 @@
UsedByReflection.class,
UsedByNative.class,
KeepForApi.class);
- populateCodeAndDocReplacements(UsesReflectionDocumentationTest.class);
+ populateCodeAndDocReplacements(
+ UsesReflectionDocumentationTest.class, MainMethodsDocumentationTest.class);
}
private Map<String, String> getTypeLinkReplacements(Class<?>... classes) {
@@ -135,10 +147,17 @@
println("[comment]: <> (Changes should be made in " + template + ")");
println();
List<String> readAllLines = FileUtils.readAllLines(template);
+ TableEntry root = new TableEntry(0, "root", "root", null);
+ readAllLines = collectTableOfContents(readAllLines, root);
+
for (int i = 0; i < readAllLines.size(); i++) {
String line = readAllLines.get(i);
try {
- processLine(line, generator);
+ if (line.trim().equals(TOC_MARKER)) {
+ printTableOfContents(root);
+ } else {
+ processLine(line, generator);
+ }
} catch (Exception e) {
System.err.println("Parse error on line " + (i + 1) + ":");
System.err.println(line);
@@ -147,6 +166,70 @@
}
}
+ private void printTableOfContents(TableEntry root) {
+ println("## Table of contents");
+ println();
+ printTableSubEntries(root.subSections.values());
+ println();
+ }
+
+ private void printTableSubEntries(Collection<TableEntry> entries) {
+ for (TableEntry entry : entries) {
+ println("- " + entry.getHrefLink());
+ generator.withIndent(() -> printTableSubEntries(entry.subSections.values()));
+ }
+ }
+
+ private List<String> collectTableOfContents(List<String> lines, TableEntry root) {
+ Set<String> seen = new HashSet<>();
+ TableEntry current = root;
+ List<String> newLines = new ArrayList<>(lines.size());
+ Iterator<String> iterator = lines.iterator();
+ // Skip forward until the TOC insertion.
+ while (iterator.hasNext()) {
+ String line = iterator.next();
+ newLines.add(line);
+ if (line.trim().equals(TOC_MARKER)) {
+ break;
+ }
+ }
+ // Find TOC entries and replace the headings with links.
+ while (iterator.hasNext()) {
+ String line = iterator.next();
+ int headingDepth = 0;
+ for (int i = 0; i < line.length(); i++) {
+ char c = line.charAt(i);
+ if (c != '#') {
+ headingDepth = i;
+ break;
+ }
+ }
+ if (headingDepth == 0) {
+ newLines.add(line);
+ continue;
+ }
+ String headingPrefix = line.substring(0, headingDepth);
+ String headingContent = line.substring(headingDepth).trim();
+ int splitIndex = headingContent.indexOf("](");
+ if (splitIndex < 0 || !headingContent.startsWith("[") || !headingContent.endsWith(")")) {
+ throw new RuntimeException("Invalid heading format. Use [Heading Text](heading-id)");
+ }
+ String headingText = headingContent.substring(1, splitIndex);
+ String headingId = headingContent.substring(splitIndex + 2, headingContent.length() - 1);
+ if (!seen.add(headingId)) {
+ throw new RuntimeException("Duplicate heading id: " + headingText);
+ }
+ while (headingDepth <= current.depth) {
+ current = current.parent;
+ }
+ TableEntry entry = new TableEntry(headingDepth, headingText, headingId, current);
+ current.subSections.put(headingText, entry);
+ current = entry;
+ newLines.add(headingPrefix + " " + entry.getIdAnchor());
+ }
+ return newLines;
+ }
+
private String replaceCodeAndDocMarkers(String line) {
String originalLine = line;
line = line.trim();
@@ -190,25 +273,46 @@
private StringBuilder unindentLines(String replacement, StringBuilder builder) {
int shortestSpacePrefix = Integer.MAX_VALUE;
List<String> lines = StringUtils.split(replacement, '\n');
+ lines = trimEmptyLines(lines);
for (String line : lines) {
if (!line.isEmpty()) {
shortestSpacePrefix = Math.min(shortestSpacePrefix, findFirstNonSpaceIndex(line));
}
}
- if (shortestSpacePrefix > 0) {
- for (String line : lines) {
- if (!line.isEmpty()) {
- builder.append(line.substring(shortestSpacePrefix));
- }
- builder.append('\n');
+ for (String line : lines) {
+ if (!line.isEmpty()) {
+ builder.append(line.substring(shortestSpacePrefix));
}
- } else {
- builder.append(replacement);
builder.append('\n');
}
return builder;
}
+ private static List<String> trimEmptyLines(List<String> lines) {
+ int startLineIndex = 0;
+ int endLineIndex = lines.size() - 1;
+ while (true) {
+ String line = lines.get(startLineIndex);
+ if (line.trim().isEmpty()) {
+ startLineIndex++;
+ } else {
+ break;
+ }
+ }
+ while (true) {
+ String line = lines.get(endLineIndex);
+ if (line.trim().isEmpty()) {
+ --endLineIndex;
+ } else {
+ break;
+ }
+ }
+ if (startLineIndex != 0 || endLineIndex != lines.size() - 1) {
+ lines = lines.subList(startLineIndex, endLineIndex + 1);
+ }
+ return lines;
+ }
+
private int findFirstNonSpaceIndex(String line) {
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) != ' ') {
@@ -244,4 +348,27 @@
}
generator.println(line);
}
+
+ private static class TableEntry {
+ final int depth;
+ final String name;
+ final String id;
+ final TableEntry parent;
+ final Map<String, TableEntry> subSections = new LinkedHashMap<>();
+
+ public TableEntry(int depth, String name, String id, TableEntry parent) {
+ this.depth = depth;
+ this.name = name;
+ this.id = id;
+ this.parent = parent;
+ }
+
+ public String getHrefLink() {
+ return "[" + name + "](#" + id + ")";
+ }
+
+ public String getIdAnchor() {
+ return name + "<a id=" + quote(id) + "></a>";
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
index 005c344..d139b43 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
@@ -47,7 +47,7 @@
Generator.run();
}
- private static String quote(String str) {
+ public static String quote(String str) {
return "\"" + str + "\"";
}
@@ -218,7 +218,7 @@
this.writer = writer;
}
- private void withIndent(Runnable fn) {
+ public void withIndent(Runnable fn) {
indent += 2;
fn.run();
indent -= 2;
diff --git a/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringContextClassTest.java b/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringContextClassTest.java
new file mode 100644
index 0000000..4add73d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringContextClassTest.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2023, 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.adaptclassstrings;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.ProguardVersion;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.io.IOException;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AdaptClassStringContextClassTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public boolean isCompat;
+
+ @Parameter(2)
+ public ProguardVersion proguardVersion;
+
+ @Parameters(name = "{0}, isCompat: {1}, {2}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultCfRuntime().build(),
+ BooleanUtils.values(),
+ ProguardVersion.values());
+ }
+
+ @Test
+ public void testProguard() throws Exception {
+ assumeTrue(isCompat);
+ testForProguard(proguardVersion)
+ .addDontWarn(AdaptClassStringContextClassTest.class)
+ .apply(this::setUpTest)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ "com.android.tools.r8.naming.adaptclassstrings.a",
+ // PG 5 replaces in both contexts despite the filter.
+ proguardVersion == ProguardVersion.V5_2_1
+ ? "com.android.tools.r8.naming.adaptclassstrings.a"
+ : typeName(Foo.class))
+ .inspect(inspector -> assertThat(inspector.clazz(Foo.class), isPresentAndRenamed()));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeTrue(proguardVersion == ProguardVersion.getLatest());
+ (isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend()))
+ .setMinApi(AndroidApiLevel.B)
+ .apply(this::setUpTest)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ // TODO(b/313666380): R8 uses the class filter as which classes may adapt their names.
+ // The actual meaning of the class filter is in which contexts to allow adaption.
+ typeName(Foo.class), typeName(Foo.class))
+ .inspect(inspector -> assertThat(inspector.clazz(Foo.class), isPresentAndRenamed()));
+ }
+
+ private void setUpTest(TestShrinkerBuilder<?, ?, ?, ?, ?> builder) throws IOException {
+ builder
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepClassRulesWithAllowObfuscation(Foo.class)
+ .addKeepRules("-adaptclassstrings " + typeName(StringContainer1.class));
+ }
+
+ public static class Foo {}
+
+ public static class StringContainer1 {
+ static String getString() {
+ return "com.android.tools.r8.naming.adaptclassstrings.AdaptClassStringContextClassTest$Foo";
+ }
+ }
+
+ public static class StringContainer2 {
+ static String getString() {
+ return "com.android.tools.r8.naming.adaptclassstrings.AdaptClassStringContextClassTest$Foo";
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(StringContainer1.getString());
+ System.out.println(StringContainer2.getString());
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringPrefixTest.java b/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringPrefixTest.java
new file mode 100644
index 0000000..ecc0209
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/adaptclassstrings/AdaptClassStringPrefixTest.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2023, 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.adaptclassstrings;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.ProguardVersion;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.io.IOException;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AdaptClassStringPrefixTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public boolean isCompat;
+
+ @Parameter(2)
+ public ProguardVersion proguardVersion;
+
+ @Parameters(name = "{0}, isCompat: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultCfRuntime().build(),
+ BooleanUtils.values(),
+ ProguardVersion.values());
+ }
+
+ @Test
+ public void testProguard() throws Exception {
+ assumeTrue(isCompat);
+ testForProguard(proguardVersion)
+ .addDontWarn(AdaptClassStringPrefixTest.class)
+ .apply(this::setUpTest)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("com.android.tools.r8.naming.adaptclassstrings.a")
+ .inspect(inspector -> assertThat(inspector.clazz(Foo.class), isPresentAndRenamed()));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeTrue(proguardVersion == ProguardVersion.getLatest());
+ (isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend()))
+ .setMinApi(AndroidApiLevel.B)
+ .apply(this::setUpTest)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("a.a")
+ .inspect(inspector -> assertThat(inspector.clazz(Foo.class), isPresentAndRenamed()));
+ }
+
+ private void setUpTest(TestShrinkerBuilder<?, ?, ?, ?, ?> builder) throws IOException {
+ builder
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepRules("-keep,allowobfuscation class " + typeName(Foo.class))
+ .addKeepRules("-adaptclassstrings com.android.tools.r8.naming.**");
+ }
+
+ public static class Foo {}
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(
+ "com.android.tools.r8.naming.adaptclassstrings.AdaptClassStringPrefixTest$Foo");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/numberunboxing/SimpleNumberUnboxingTest.java b/src/test/java/com/android/tools/r8/numberunboxing/SimpleNumberUnboxingTest.java
index 755096b..ceaf904 100644
--- a/src/test/java/com/android/tools/r8/numberunboxing/SimpleNumberUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/numberunboxing/SimpleNumberUnboxingTest.java
@@ -4,10 +4,17 @@
package com.android.tools.r8.numberunboxing;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.Objects;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
@@ -36,9 +43,11 @@
.addKeepMainRule(Main.class)
.enableInliningAnnotations()
.addOptionsModification(opt -> opt.testing.enableNumberUnboxer = true)
+ .addOptionsModification(opt -> opt.testing.printNumberUnboxed = true)
.setMinApi(parameters)
.allowDiagnosticWarningMessages()
.compile()
+ .inspect(this::assertUnboxing)
.assertWarningMessageThatMatches(
CoreMatchers.containsString(
"Unboxing of arg 0 of void"
@@ -67,6 +76,33 @@
.assertSuccessWithOutputLines("32", "33", "42", "43", "51", "52", "2");
}
+ private void assertFirstParameterUnboxed(ClassSubject mainClass, String methodName) {
+ MethodSubject methodSubject = mainClass.uniqueMethodWithOriginalName(methodName);
+ assertThat(methodSubject, isPresent());
+ assertEquals("java.lang.Integer", methodSubject.getOriginalSignature().parameters[0]);
+ assertEquals("int", methodSubject.getFinalSignature().asMethodSignature().parameters[0]);
+ }
+
+ private void assertReturnUnboxed(ClassSubject mainClass, String methodName) {
+ MethodSubject methodSubject = mainClass.uniqueMethodWithOriginalName(methodName);
+ assertThat(methodSubject, isPresent());
+ assertEquals("java.lang.Integer", methodSubject.getOriginalSignature().type);
+ assertEquals("int", methodSubject.getFinalSignature().asMethodSignature().type);
+ }
+
+ private void assertUnboxing(CodeInspector codeInspector) {
+ ClassSubject mainClass = codeInspector.clazz(Main.class);
+ assertThat(mainClass, isPresent());
+
+ assertFirstParameterUnboxed(mainClass, "print");
+ assertFirstParameterUnboxed(mainClass, "forwardToPrint2");
+ assertFirstParameterUnboxed(mainClass, "directPrintUnbox");
+ assertFirstParameterUnboxed(mainClass, "forwardToPrint");
+
+ assertReturnUnboxed(mainClass, "get");
+ assertReturnUnboxed(mainClass, "forwardGet");
+ }
+
static class Main {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/retrace/InvalidMappingRangesB309080420Test.java b/src/test/java/com/android/tools/r8/retrace/InvalidMappingRangesB309080420Test.java
index 9e45fe5..09ca4e0 100644
--- a/src/test/java/com/android/tools/r8/retrace/InvalidMappingRangesB309080420Test.java
+++ b/src/test/java/com/android/tools/r8/retrace/InvalidMappingRangesB309080420Test.java
@@ -34,7 +34,9 @@
"a.x -> a.x:",
" 1:1:void a(com.example.Foo) -> a",
" 11:2:void a() -> a", // Unexpected line range [11:2] - interpreting as [2:11]
- " 12:21:void a(android.content.Intent) -> a");
+ " 12:21:void a(android.content.Intent) -> a",
+ // Allow identifier content to follow <init>/<clinit>.
+ " 22:41:void <clinit>$more$stuff() -> clinit$move$stuff");
@Test
public void test() throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesR8SpecificTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesR8SpecificTest.java
index 1079641..ccb56de 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesR8SpecificTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesR8SpecificTest.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,29 +45,17 @@
ProviderType.values());
}
- private static final String EXPECTED_A =
- StringUtils.lines(
- "-keep class A1 {", " <init>();", "}", "-keep class A2 {", " <init>();", "}");
+ private static final String EXPECTED_A = StringUtils.lines("-keep class A1", "-keep class A2");
- private static final String EXPECTED_B =
- StringUtils.lines(
- "-keep class B1 {", " <init>();", "}", "-keep class B2 {", " <init>();", "}");
+ private static final String EXPECTED_B = StringUtils.lines("-keep class B1", "-keep class B2");
- private static final String EXPECTED_C =
- StringUtils.lines(
- "-keep class C1 {", " <init>();", "}", "-keep class C2 {", " <init>();", "}");
+ private static final String EXPECTED_C = StringUtils.lines("-keep class C1", "-keep class C2");
- private static final String EXPECTED_D =
- StringUtils.lines(
- "-keep class D1 {", " <init>();", "}", "-keep class D2 {", " <init>();", "}");
+ private static final String EXPECTED_D = StringUtils.lines("-keep class D1", "-keep class D2");
- private static final String EXPECTED_E =
- StringUtils.lines(
- "-keep class E1 {", " <init>();", "}", "-keep class E2 {", " <init>();", "}");
+ private static final String EXPECTED_E = StringUtils.lines("-keep class E1", "-keep class E2");
- private static final String EXPECTED_X =
- StringUtils.lines(
- "-keep class X1 {", " <init>();", "}", "-keep class X2 {", " <init>();", "}");
+ private static final String EXPECTED_X = StringUtils.lines("-keep class X1", "-keep class X2");
private Path buildLibrary() throws Exception {
ZipBuilder jarBuilder =
@@ -144,7 +133,28 @@
.allowUnusedProguardConfigurationRules()
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals(expected, configuration.toString()));
+ configuration ->
+ assertEquals(
+ expected,
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
+ }
+
+ private static String stripCommentsAndInJars(String configuration, boolean expectOneInJar) {
+ int expectedInJars = expectOneInJar ? 1 : 0;
+ int foundInJars = 0;
+ List<String> lines = StringUtils.splitLines(configuration);
+ List<String> filtered = new ArrayList<>(lines.size());
+ for (String line : lines) {
+ if (line.trim().startsWith("-injars ")) {
+ if (++foundInJars > expectedInJars) {
+ fail("Unexpected: " + line);
+ }
+ } else if (!line.trim().startsWith("#")) {
+ filtered.add(line);
+ }
+ }
+ assertEquals(expectedInJars, foundInJars);
+ return StringUtils.lines(filtered);
}
@Test
@@ -222,9 +232,7 @@
}
Path library = buildLibrary();
testForR8(Backend.DEX)
- .applyIf(
- providerType == ProviderType.API,
- b -> b.addProgramFiles(library).addProgramFiles(library))
+ .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
.applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
.setMinApi(AndroidApiLevel.B)
.allowUnusedProguardConfigurationRules()
@@ -241,7 +249,7 @@
configuration ->
assertEquals(
StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_E.trim()),
- configuration.toString()));
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
@Test
@@ -257,7 +265,10 @@
.allowUnusedProguardConfigurationRules()
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals(EXPECTED_A, configuration.toString()));
+ configuration ->
+ assertEquals(
+ EXPECTED_A,
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
@Test
@@ -271,7 +282,10 @@
.allowUnusedProguardConfigurationRules()
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals(EXPECTED_X, configuration.toString()));
+ configuration ->
+ assertEquals(
+ EXPECTED_X,
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
@Test
@@ -284,7 +298,10 @@
.allowUnusedProguardConfigurationRules()
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals(EXPECTED_X, configuration.toString()));
+ configuration ->
+ assertEquals(
+ EXPECTED_X,
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
@Test
@@ -308,7 +325,10 @@
.setFakeCompilerVersion(SemanticVersion.create(1, 2, 3))
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals("", configuration.toString()));
+ configuration ->
+ assertEquals(
+ "",
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
}
@@ -332,7 +352,10 @@
.setMinApi(AndroidApiLevel.B)
.compile()
.inspectProguardConfiguration(
- configuration -> assertEquals("", configuration.toString()));
+ configuration ->
+ assertEquals(
+ "",
+ stripCommentsAndInJars(configuration, providerType == ProviderType.INJARS)));
}
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepRulePrintingTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepRulePrintingTest.java
index 9245a4d..925f70e 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepRulePrintingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepRulePrintingTest.java
@@ -39,7 +39,7 @@
.compile()
.apply(
r -> {
- assertThat(r.getProguardConfiguration().toString(), containsString("*** main(...);"));
+ assertThat(r.getProguardConfiguration(), containsString("*** main(...);"));
});
}