Version 2.1.61
Cherry pick: Reproduce NPE from missing AppInfoWithLiveness rewriting
CL: https://r8-review.googlesource.com/c/r8/+/52765
Cherry pick: Rewrite AppInfoWithLiveness using LambdaRewriterLens
CL: https://r8-review.googlesource.com/c/r8/+/52766
This also cherry-picks part of 'Do not apply the graph lens to positions' at https://r8-review.googlesource.com/c/r8/+/52380, specifically the part that introduces LambdaRewriterLense in LambdaRewriter.java.
Bug: 161735546
Change-Id: I92ef83f646d6681956438917e5331bbbeed39d65
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 80f8371..e3becb5 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -700,7 +700,8 @@
executorService,
timing)
.withEnumValueInfoMaps(enumValueInfoMapCollection));
-
+ // Rerunning the enqueuer should not give rise to any method rewritings.
+ assert enqueuer.buildGraphLens(appView) == null;
appView.withGeneratedMessageLiteBuilderShrinker(
shrinker ->
shrinker.rewriteDeadBuilderReferencesFromDynamicMethods(
@@ -917,6 +918,14 @@
options.getProguardConfiguration().getDontWarnPatterns(),
executorService,
timing));
+ NestedGraphLense lens = enqueuer.buildGraphLens(appView);
+ if (lens != null) {
+ appView.setGraphLense(lens);
+ appViewWithLiveness.setAppInfo(
+ appViewWithLiveness
+ .appInfo()
+ .rewrittenWithLens(appView.appInfo().app().asDirect(), lens));
+ }
if (InternalOptions.assertionsEnabled()) {
// Register the dead proto types. These are needed to verify that no new missing types are
// reported and that no dead proto types are referenced in the generated application.
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 1f7c9d4..571ec73 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.1.60";
+ public static final String LABEL = "2.1.61";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index 8a7b983..0b83e0f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -7,10 +7,13 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexCallSite;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
@@ -29,6 +32,7 @@
import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -342,4 +346,34 @@
public Map<DexType, LambdaClass> getKnownLambdaClasses() {
return knownLambdaClasses;
}
+
+ public NestedGraphLense buildMappingLens(AppView<?> appView) {
+ if (originalMethodSignatures.isEmpty()) {
+ return null;
+ }
+ return new LambdaRewriterLens(
+ originalMethodSignatures, appView.graphLense(), appView.dexItemFactory());
+ }
+
+ static class LambdaRewriterLens extends NestedGraphLense {
+
+ public LambdaRewriterLens(
+ BiMap<DexMethod, DexMethod> originalMethodSignatures,
+ GraphLense graphLens,
+ DexItemFactory factory) {
+ super(
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ null,
+ originalMethodSignatures,
+ graphLens,
+ factory);
+ }
+
+ @Override
+ protected boolean isLegitimateToHaveEmptyMappings() {
+ return true;
+ }
+ }
}
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 08d6abf..fead6b8 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -57,6 +57,7 @@
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.LookupLambdaTarget;
import com.android.tools.r8.graph.LookupTarget;
@@ -2642,6 +2643,10 @@
return appInfoWithLiveness;
}
+ public NestedGraphLense buildGraphLens(AppView<?> appView) {
+ return lambdaRewriter != null ? lambdaRewriter.buildMappingLens(appView) : null;
+ }
+
public boolean isPinned(DexReference reference) {
return pinnedItems.contains(reference);
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/B161735546.java b/src/test/java/com/android/tools/r8/ir/optimize/B161735546.java
new file mode 100644
index 0000000..ce969b7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/B161735546.java
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class B161735546 extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public B161735546(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(B161735546.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("1", "2", "3");
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ new CounterUtils() {}.add(new Counter(), 3);
+ }
+ }
+
+ static class Counter {
+ int i = 0;
+ }
+
+ interface CounterConsumer {
+ void accept(Counter counter);
+ }
+
+ interface CounterUtils {
+ default void add(Counter counter, int i) {
+ if (i == 0) {
+ return;
+ }
+ CounterConsumer continuation =
+ c -> {
+ System.out.println(++counter.i);
+ add(counter, i - 1);
+ };
+ continuation.accept(counter);
+ }
+ }
+}