Merge commit '9e1b041d190874407fea685fe7dc6e4701d5d79e' into dev-release
diff --git a/infra/config/global/generated/cr-buildbucket.cfg b/infra/config/global/generated/cr-buildbucket.cfg
index ebe76f2..73e65b4 100644
--- a/infra/config/global/generated/cr-buildbucket.cfg
+++ b/infra/config/global/generated/cr-buildbucket.cfg
@@ -24,7 +24,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -53,7 +53,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -82,7 +82,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -118,7 +118,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -156,7 +156,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -190,7 +190,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -222,7 +222,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -255,7 +255,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -292,7 +292,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -329,7 +329,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -366,7 +366,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -403,7 +403,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -440,7 +440,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -477,7 +477,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -514,7 +514,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -551,7 +551,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -588,7 +588,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -625,7 +625,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -662,7 +662,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -699,7 +699,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -736,7 +736,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -773,7 +773,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -810,7 +810,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -847,7 +847,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -884,7 +884,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -921,7 +921,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -958,7 +958,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -995,7 +995,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1031,7 +1031,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1067,7 +1067,7 @@
dimensions: "cores:2"
dimensions: "cpu:x86-64"
dimensions: "internal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1100,7 +1100,7 @@
dimensions: "cores:2"
dimensions: "cpu:x86-64"
dimensions: "internal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1133,7 +1133,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1169,7 +1169,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1205,7 +1205,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1241,7 +1241,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1277,7 +1277,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1313,7 +1313,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1349,7 +1349,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1385,7 +1385,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1420,7 +1420,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1457,7 +1457,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1495,7 +1495,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1531,7 +1531,7 @@
dimensions: "cores:8"
dimensions: "cpu:x86-64"
dimensions: "normal:true"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1566,7 +1566,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
@@ -1598,7 +1598,7 @@
swarming_tags: "vpython:native-python-wrapper"
dimensions: "cores:8"
dimensions: "cpu:x86-64"
- dimensions: "os:Ubuntu-16.04"
+ dimensions: "os:Ubuntu-18.04"
dimensions: "pool:luci.r8.ci"
exe {
cipd_package: "infra_internal/recipe_bundles/chrome-internal.googlesource.com/chrome/tools/build_limited/scripts/slave"
diff --git a/infra/config/global/main.star b/infra/config/global/main.star
index 73e0802..8574aa5 100755
--- a/infra/config/global/main.star
+++ b/infra/config/global/main.star
@@ -170,7 +170,7 @@
if windows:
dimensions["os"] = "Windows-10"
else:
- dimensions["os"] = "Ubuntu-16.04"
+ dimensions["os"] = "Ubuntu-18.04"
if internal:
dimensions["internal"] = "true"
if normal:
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 9c659f5..dc99fda 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -35,7 +35,6 @@
import com.android.tools.r8.optimize.argumentpropagation.ArgumentPropagator;
import com.android.tools.r8.optimize.interfaces.collection.OpenClosedInterfacesCollection;
import com.android.tools.r8.profile.art.ArtProfileCollection;
-import com.android.tools.r8.retrace.internal.RetraceUtils;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.AssumeInfoCollection;
import com.android.tools.r8.shaking.KeepClassInfo;
@@ -983,9 +982,7 @@
}
public void addPrunedClassSourceFile(DexType prunedType, String sourceFile) {
- if (!RetraceUtils.hasPredictableSourceFileName(prunedType.toSourceString(), sourceFile)) {
- sourceFileForPrunedTypes.put(prunedType, sourceFile);
- }
+ sourceFileForPrunedTypes.put(prunedType, sourceFile);
}
public String getPrunedClassSourceFileInfo(DexType dexType) {
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 188211d..46d91ef 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -386,6 +386,26 @@
return false;
}
+ // Predicate to see if a method definition is only changed by repackaging or synthetic
+ // finalization indicating that it is a simple renaming.
+ public final boolean isSimpleRenaming(DexMethod method) {
+ DexMethod methodToCompareAgainst = method;
+ DexMethod original = method;
+ GraphLens current = this;
+ while (current.isNonIdentityLens()) {
+ NonIdentityGraphLens nonIdentityLens = current.asNonIdentityLens();
+ original = nonIdentityLens.getPreviousMethodSignature(original);
+ if (current.isSimpleRenamingLens()) {
+ methodToCompareAgainst = original;
+ } else if (methodToCompareAgainst != original) {
+ return false;
+ }
+ assert nonIdentityLens.getPrevious() != null;
+ current = nonIdentityLens.getPrevious();
+ }
+ return true;
+ }
+
public abstract String lookupPackageName(String pkg);
public DexType lookupClassType(DexType type) {
@@ -572,6 +592,10 @@
return false;
}
+ public boolean isSimpleRenamingLens() {
+ return false;
+ }
+
public abstract boolean isIdentityLens();
public boolean isMemberRebindingLens() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java
new file mode 100644
index 0000000..65f23dc
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2021, 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.desugar;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * If an invoke-virtual targets a private method in the current class overriding will not apply (see
+ * JVM 11 spec on method selection 5.4.6. In previous jvm specs this was not explicitly stated, but
+ * derived from method resolution 5.4.3.3 and overriding 5.4.5).
+ *
+ * <p>An invoke-interface can in the same way target a private method.
+ *
+ * <p>For desugaring we use invoke-direct instead. We need to do this as the Android Runtime will
+ * not allow invoke-virtual of a private method.
+ */
+public class InvokeToPrivateRewriter implements CfInstructionDesugaring {
+
+ @Override
+ public Collection<CfInstruction> desugarInstruction(
+ CfInstruction instruction,
+ FreshLocalProvider freshLocalProvider,
+ LocalStackAllocator localStackAllocator,
+ CfInstructionDesugaringEventConsumer eventConsumer,
+ ProgramMethod context,
+ MethodProcessingContext methodProcessingContext,
+ CfInstructionDesugaringCollection desugaringCollection,
+ DexItemFactory dexItemFactory) {
+ if (!instruction.isInvokeVirtual() && !instruction.isInvokeInterface()) {
+ return null;
+ }
+ CfInvoke invoke = instruction.asInvoke();
+ DexMethod method = invoke.getMethod();
+ DexEncodedMethod privateMethod = privateMethodInvokedOnSelf(invoke, context);
+ if (privateMethod == null) {
+ return null;
+ }
+ return ImmutableList.of(new CfInvoke(Opcodes.INVOKESPECIAL, method, invoke.isInterface()));
+ }
+
+ @Override
+ public boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
+ if (!instruction.isInvokeVirtual() && !instruction.isInvokeInterface()) {
+ return false;
+ }
+ return isInvokingPrivateMethodOnSelf(instruction.asInvoke(), context);
+ }
+
+ private DexEncodedMethod privateMethodInvokedOnSelf(CfInvoke invoke, ProgramMethod context) {
+ DexMethod method = invoke.getMethod();
+ if (method.getHolderType() != context.getHolderType()) {
+ return null;
+ }
+ DexEncodedMethod directTarget = context.getHolder().lookupDirectMethod(method);
+ if (directTarget != null && !directTarget.isStatic()) {
+ assert method.holder == directTarget.getHolderType();
+ return directTarget;
+ }
+ return null;
+ }
+
+ private boolean isInvokingPrivateMethodOnSelf(CfInvoke invoke, ProgramMethod context) {
+ return privateMethodInvokedOnSelf(invoke, context) != null;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 4ee8f70..aa8ca78 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -121,6 +121,9 @@
desugarings.add(new LambdaInstructionDesugaring(appView));
desugarings.add(new ConstantDynamicInstructionDesugaring(appView));
desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
+ if (appView.options().rewriteInvokeToPrivateInDesugar) {
+ desugarings.add(new InvokeToPrivateRewriter());
+ }
desugarings.add(new StringConcatInstructionDesugaring(appView));
desugarings.add(new BufferCovariantReturnTypeRewriter(appView));
if (backportedMethodRewriter.hasBackports()) {
@@ -358,7 +361,8 @@
// identification is explicitly non-overlapping and remove the exceptions below.
assert !alsoApplicable
|| (appliedDesugaring instanceof InterfaceMethodRewriter
- && desugaring instanceof NestBasedAccessDesugaring)
+ && (desugaring instanceof InvokeToPrivateRewriter
+ || desugaring instanceof NestBasedAccessDesugaring))
|| (appliedDesugaring instanceof TwrInstructionDesugaring
&& desugaring instanceof InterfaceMethodRewriter)
: "Desugaring of "
diff --git a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
index 5b0abaa..0b872f0 100644
--- a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
+++ b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
@@ -88,8 +88,11 @@
throw new MappingComposeException(
"Composition of mapping files supported from map version 2.2.");
}
- if (currentMapVersion == null || currentMapVersion.getMapVersion().isLessThan(newMapVersion)) {
+ if (currentMapVersion == null) {
currentMapVersion = newMapVersionInfo;
+ } else {
+ currentMapVersion =
+ newMapVersionInfo.compose(currentMapVersion).asMapVersionMappingInformation();
}
for (ClassNamingForNameMapper classMapping : classNameMapper.getClassNameMappings().values()) {
compose(classNameMapper, classMapping);
@@ -829,7 +832,8 @@
List<MappedRange> existingMappedRanges,
ComputedOutlineInformation computedOutlineInformation,
int lastStartingMinifiedFrom,
- int position) {
+ int position)
+ throws MappingComposeException {
Range existingRange = existingMappedRanges.get(0).minifiedRange;
assert existingMappedRanges.stream().allMatch(x -> x.minifiedRange.equals(existingRange));
Range newMinifiedRange = new Range(lastStartingMinifiedFrom, position);
@@ -883,19 +887,33 @@
}
/***
- * Populates newMappingInformation with existingMappingInformation, prioritizing new mapping
- * information if new mapping information does not allow existing information.
+ * Populates newMappingInformation with existingMappingInformation.
*/
private void composeMappingInformation(
List<MappingInformation> newMappingInformation,
List<MappingInformation> existingMappingInformation,
- Consumer<MappingInformation> consumer) {
- List<MappingInformation> existingMappingCopy = new ArrayList<>(existingMappingInformation);
- for (MappingInformation newMappingInfo : newMappingInformation) {
- existingMappingCopy.removeIf(otherInfo -> !newMappingInfo.allowOther(otherInfo));
+ Consumer<MappingInformation> consumer)
+ throws MappingComposeException {
+ Set<MappingInformation> nonCompasableNewInfos = Sets.newIdentityHashSet();
+ for (MappingInformation existingInfo : existingMappingInformation) {
+ boolean hasBeenComposed = false;
+ for (MappingInformation newInfo : newMappingInformation) {
+ if (newInfo.shouldCompose(existingInfo)) {
+ nonCompasableNewInfos.add(newInfo);
+ consumer.accept(newInfo.compose(existingInfo));
+ hasBeenComposed = true;
+ }
+ }
+ if (!hasBeenComposed) {
+ consumer.accept(existingInfo);
+ }
}
- existingMappingCopy.forEach(consumer);
- newMappingInformation.forEach(consumer);
+ newMappingInformation.forEach(
+ info -> {
+ if (!nonCompasableNewInfos.contains(info)) {
+ consumer.accept(info);
+ }
+ });
}
private boolean isInlineMappedRange(List<MappedRange> mappedRanges, int index) {
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
index 7f82be1..b1d1eff 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.naming.mappinginformation;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
@@ -47,6 +48,12 @@
}
@Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ // There is no difference between taking the existing or new so we just do a consistent choice.
+ return existing;
+ }
+
+ @Override
public boolean allowOther(MappingInformation information) {
return !information.isCompilerSynthesizedMappingInformation();
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
index e4f3490..828b5d8 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
@@ -42,6 +43,12 @@
}
@Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ // Always take the first mapping.
+ return existing;
+ }
+
+ @Override
public boolean allowOther(MappingInformation information) {
return !information.isFileNameInformation();
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MapVersionMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MapVersionMappingInformation.java
index 32f11f4..f061912 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MapVersionMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MapVersionMappingInformation.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics.noKeyForObjectWithId;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
@@ -40,6 +41,13 @@
}
@Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ assert existing.isMapVersionMappingInformation();
+ MapVersionMappingInformation existingMapVersionInfo = existing.asMapVersionMappingInformation();
+ return mapVersion.isLessThanOrEqualTo(existingMapVersionInfo.getMapVersion()) ? existing : this;
+ }
+
+ @Override
public boolean allowOther(MappingInformation information) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
index 25bb1f3..c62d4e6 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualFieldSignatureMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualMethodSignatureMappingInformation;
import com.google.gson.JsonElement;
@@ -96,6 +97,13 @@
return null;
}
+ public boolean shouldCompose(MappingInformation existing) {
+ return !allowOther(existing);
+ }
+
+ public abstract MappingInformation compose(MappingInformation existing)
+ throws MappingComposeException;
+
public boolean isGlobalMappingInformation() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
index 4bcfe95..b38d707 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.MethodReferenceUtils;
import com.google.gson.JsonElement;
@@ -68,6 +69,11 @@
return this;
}
+ @Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ throw new MappingComposeException("Unable to compose " + ID);
+ }
+
public int rewritePosition(int originalPosition) {
return positions.getOrDefault(originalPosition, originalPosition);
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
index 54c392b..09c60d9 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.naming.mappinginformation;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
@@ -32,8 +33,14 @@
}
@Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ // It does not matter which one we take so just take the first one.
+ return existing;
+ }
+
+ @Override
public boolean allowOther(MappingInformation information) {
- return true;
+ return !information.isOutlineMappingInformation();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
index 9d6ac63..1c94da9 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -114,6 +115,13 @@
public ResidualMethodSignatureMappingInformation asResidualMethodSignatureMappingInformation() {
return this;
}
+
+ @Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ // Always take the newest residual mapping
+ assert existing.isResidualMethodSignatureMappingInformation();
+ return this;
+ }
}
public static class ResidualFieldSignatureMappingInformation
@@ -148,5 +156,12 @@
public ResidualFieldSignatureMappingInformation asResidualFieldSignatureMappingInformation() {
return this;
}
+
+ @Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ // Always take the newest residual mapping.
+ assert existing.isResidualFieldSignatureMappingInformation();
+ return this;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
index 00eb800..da0c1f3 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.naming.MapVersion;
+import com.android.tools.r8.naming.MappingComposeException;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.internal.RetraceStackTraceContextImpl;
@@ -105,6 +106,11 @@
return this;
}
+ @Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ throw new MappingComposeException("Unable to compose " + ID);
+ }
+
public static RewriteFrameMappingInformation.Builder builder() {
return new Builder();
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
index 848919b..3348063 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.naming.mappinginformation;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.naming.MappingComposeException;
import com.google.gson.JsonObject;
import java.util.function.Consumer;
@@ -47,6 +48,11 @@
return this;
}
+ @Override
+ public MappingInformation compose(MappingInformation existing) throws MappingComposeException {
+ throw new MappingComposeException("Unable to compose unknown json mapping information");
+ }
+
public static void deserialize(
String id, JsonObject object, Consumer<MappingInformation> onMappingInfo) {
onMappingInfo.accept(new UnknownJsonMappingInformation(id, object.toString()));
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
index 64fe0eb..8b4ad76 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingLens.java
@@ -66,6 +66,11 @@
this::isSimpleTypeRenamingOrEqual);
}
+ @Override
+ public boolean isSimpleRenamingLens() {
+ return true;
+ }
+
private boolean isSimpleTypeRenamingOrEqual(DexType from, DexType to) {
return from == to || newTypes.get(from) == to;
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceUtils.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceUtils.java
index 7c884e2..0180960 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceUtils.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceUtils.java
@@ -56,11 +56,6 @@
return sb.toString();
}
- public static boolean hasPredictableSourceFileName(String originalClassName, String sourceFile) {
- String synthesizedSourceFileName = getOuterClassSimpleName(originalClassName) + ".java";
- return synthesizedSourceFileName.equals(sourceFile);
- }
-
private static String getOuterClassSimpleName(String clazz) {
int lastIndexOfPeriod = clazz.lastIndexOf(DescriptorUtils.JAVA_PACKAGE_SEPARATOR);
// Check if we can find a subclass separator.
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 0d767c6..54ef01b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -101,6 +101,11 @@
public boolean isSyntheticFinalizationGraphLens() {
return true;
}
+
+ @Override
+ public boolean isSimpleRenamingLens() {
+ return true;
+ }
}
private static class Builder {
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index cbad6e6..cd7460b 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -77,6 +77,10 @@
return DexVersion.getDexVersion(this);
}
+ public boolean isPlatform() {
+ return this == ANDROID_PLATFORM;
+ }
+
public static List<AndroidApiLevel> getAndroidApiLevelsSorted() {
return Arrays.asList(AndroidApiLevel.values());
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
index 06c4094..7369593 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -94,7 +94,7 @@
// running with boot class path as min api and all definitions are accessible at runtime.
if (!androidApiLevelCompute.isEnabled()) {
assert !options.apiModelingOptions().enableLibraryApiModeling;
- return options.isAndroidPlatformBuild();
+ return options.isAndroidPlatformBuildOrMinApiPlatform();
}
assert options.apiModelingOptions().enableLibraryApiModeling;
ComputedApiLevel apiLevel =
@@ -113,7 +113,7 @@
}
public static boolean isApiSafeForReference(LibraryDefinition definition, AppView<?> appView) {
- if (appView.options().isAndroidPlatformBuild()) {
+ if (appView.options().isAndroidPlatformBuildOrMinApiPlatform()) {
assert definition != null;
return true;
}
@@ -177,7 +177,7 @@
}
if (!appView.options().apiModelingOptions().isApiCallerIdentificationEnabled()) {
// Conservatively bail out if we don't have api modeling.
- return false;
+ return appView.options().isAndroidPlatformBuildOrMinApiPlatform();
}
LibraryClass newBaseLibraryClass = newBaseClass.asLibraryClass();
if (isApiSafeForReference(newBaseLibraryClass, appView)) {
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 41cc946..3939dd5 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -272,13 +272,15 @@
public void configureAndroidPlatformBuild(boolean isAndroidPlatformBuild) {
assert !androidPlatformBuild;
+ if (isAndroidPlatformBuildOrMinApiPlatform()) {
+ apiModelingOptions().disableApiModeling();
+ }
if (!isAndroidPlatformBuild) {
return;
}
- androidPlatformBuild = isAndroidPlatformBuild;
// Configure options according to platform build assumptions.
// See go/r8platformflag and b/232073181.
- apiModelingOptions().disableApiModeling();
+ androidPlatformBuild = isAndroidPlatformBuild;
enableBackportMethods = false;
}
@@ -286,6 +288,10 @@
return androidPlatformBuild;
}
+ public boolean isAndroidPlatformBuildOrMinApiPlatform() {
+ return androidPlatformBuild || minApiLevel.isPlatform();
+ }
+
public boolean printTimes = System.getProperty("com.android.tools.r8.printtimes") != null;
// To print memory one also have to enable printtimes.
public boolean printMemory = System.getProperty("com.android.tools.r8.printmemory") != null;
@@ -416,6 +422,11 @@
public boolean createSingletonsForStatelessLambdas =
System.getProperty("com.android.tools.r8.createSingletonsForStatelessLambdas") != null;
+ // Flag to control the representation of stateless lambdas.
+ // See b/222081665 for context.
+ public boolean rewriteInvokeToPrivateInDesugar =
+ System.getProperty("com.android.tools.r8.rewriteInvokeToPrivateInDesugar") != null;
+
// Flag to allow record annotations in DEX. See b/231930852 for context.
public boolean emitRecordAnnotationsInDex =
System.getProperty("com.android.tools.r8.emitRecordAnnotationsInDex") != null;
@@ -1856,6 +1867,7 @@
public boolean roundtripThroughLIR = false;
private boolean hasReadCheckDeterminism = false;
private DeterminismChecker determinismChecker = null;
+ public boolean usePcEncodingInCfForTesting = false;
// Testing options to analyse locality of items in DEX files when they are generated.
public boolean calculateItemUseCountInDex = false;
diff --git a/src/main/java/com/android/tools/r8/utils/SegmentTree.java b/src/main/java/com/android/tools/r8/utils/SegmentTree.java
index 9962b1c..c68a0c2 100644
--- a/src/main/java/com/android/tools/r8/utils/SegmentTree.java
+++ b/src/main/java/com/android/tools/r8/utils/SegmentTree.java
@@ -85,6 +85,9 @@
if (internalTree.remove(start) != null) {
size = size - 1;
}
+ if (size == 0) {
+ internalTree.clear();
+ }
}
public void visitSegments(Consumer<V> consumer) {
diff --git a/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java b/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
index b84e916..cd6efb7 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/ClassFilePositionToMappedRangeMapper.java
@@ -7,10 +7,13 @@
import static com.android.tools.r8.utils.positions.PositionUtils.remapAndAdd;
import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.utils.Pair;
import java.util.ArrayList;
import java.util.List;
@@ -29,6 +32,18 @@
boolean hasOverloads,
boolean canUseDexPc,
int pcEncodingCutoff) {
+ return appView.options().getTestingOptions().usePcEncodingInCfForTesting
+ ? getPcEncodedPositions(method, positionRemapper)
+ : getMappedPositionsRemapped(method, positionRemapper);
+ }
+
+ @Override
+ public void updateDebugInfoInCodeObjects() {
+ // Intentionally empty.
+ }
+
+ private List<MappedPosition> getMappedPositionsRemapped(
+ ProgramMethod method, PositionRemapper positionRemapper) {
List<MappedPosition> mappedPositions = new ArrayList<>();
// Do the actual processing for each method.
CfCode oldCode = method.getDefinition().getCode().asCfCode();
@@ -36,8 +51,8 @@
List<CfInstruction> newInstructions = new ArrayList<>(oldInstructions.size());
for (CfInstruction oldInstruction : oldInstructions) {
CfInstruction newInstruction;
- if (oldInstruction instanceof CfPosition) {
- CfPosition cfPosition = (CfPosition) oldInstruction;
+ if (oldInstruction.isPosition()) {
+ CfPosition cfPosition = oldInstruction.asPosition();
newInstruction =
new CfPosition(
cfPosition.getLabel(),
@@ -59,8 +74,64 @@
return mappedPositions;
}
- @Override
- public void updateDebugInfoInCodeObjects() {
- // Intentionally empty.
+ private List<MappedPosition> getPcEncodedPositions(
+ ProgramMethod method, PositionRemapper positionRemapper) {
+ List<MappedPosition> mappedPositions = new ArrayList<>();
+ // Do the actual processing for each method.
+ CfCode oldCode = method.getDefinition().getCode().asCfCode();
+ List<CfInstruction> oldInstructions = oldCode.getInstructions();
+ List<CfInstruction> newInstructions = new ArrayList<>(oldInstructions.size() * 3);
+ Position currentPosition = null;
+ boolean isFirstEntry = false;
+ for (CfInstruction oldInstruction : oldInstructions) {
+ if (oldInstruction.isPosition()) {
+ CfPosition cfPosition = oldInstruction.asPosition();
+ currentPosition = cfPosition.getPosition();
+ isFirstEntry = true;
+ } else {
+ if (currentPosition != null) {
+ Pair<Position, Position> remappedPosition =
+ positionRemapper.createRemappedPosition(currentPosition);
+ Position oldPosition = remappedPosition.getFirst();
+ Position newPosition = remappedPosition.getSecond();
+ if (isFirstEntry) {
+ mappedPositions.add(
+ new MappedPosition(
+ oldPosition.getMethod(),
+ oldPosition.getLine(),
+ oldPosition.getCallerPosition(),
+ newPosition.getLine(),
+ oldPosition.isOutline(),
+ oldPosition.getOutlineCallee(),
+ oldPosition.getOutlinePositions()));
+ } else {
+ mappedPositions.add(
+ new MappedPosition(
+ oldPosition.getMethod(),
+ oldPosition.getLine(),
+ oldPosition.getCallerPosition(),
+ newPosition.getLine(),
+ false,
+ null,
+ null));
+ }
+ CfPosition position = new CfPosition(new CfLabel(), newPosition);
+ newInstructions.add(position);
+ newInstructions.add(position.getLabel());
+ }
+ isFirstEntry = false;
+ newInstructions.add(oldInstruction);
+ }
+ }
+ method.setCode(
+ new CfCode(
+ method.getHolderType(),
+ oldCode.getMaxStack(),
+ oldCode.getMaxLocals(),
+ newInstructions,
+ oldCode.getTryCatchRanges(),
+ oldCode.getLocalVariables()),
+ appView);
+ return mappedPositions;
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index 5c23d90..2b51ed8 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -41,7 +41,6 @@
import com.android.tools.r8.naming.mappinginformation.RewriteFrameMappingInformation.ThrowsCondition;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.retrace.internal.RetraceUtils;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
@@ -108,7 +107,6 @@
assert appView.appInfo().definitionForWithoutExistenceAssert(holder) == null;
String typeName = holder.toSourceString();
String sourceFile = entry.getValue();
- assert !RetraceUtils.hasPredictableSourceFileName(typeName, sourceFile);
classNameMapperBuilder
.classNamingBuilder(
typeName, typeName, com.android.tools.r8.position.Position.UNKNOWN)
@@ -150,11 +148,9 @@
// Check if source file should be added to the map
DexString originalSourceFile = originalSourceFiles.getOriginalSourceFile(clazz);
if (originalSourceFile != null) {
- String sourceFile = originalSourceFile.toString();
- if (!RetraceUtils.hasPredictableSourceFileName(clazz.toSourceString(), sourceFile)) {
- getBuilder()
- .addMappingInformation(FileNameInformation.build(sourceFile), Unreachable::raise);
- }
+ getBuilder()
+ .addMappingInformation(
+ FileNameInformation.build(originalSourceFile.toSourceString()), Unreachable::raise);
}
return this;
}
@@ -219,13 +215,12 @@
|| appView.isCfByteCodePassThrough(definition);
return this;
}
- // TODO(b/169953605): Ensure we emit the residual signature information.
if (mapFileVersion.isGreaterThan(MapVersion.MAP_VERSION_2_1)
- && originalMethod != method.getReference()) {
+ && originalMethod != method.getReference()
+ && !appView.graphLens().isSimpleRenaming(residualMethod)) {
methodMappingInfo.add(
ResidualMethodSignatureMappingInformation.fromDexMethod(residualMethod));
}
-
MethodSignature residualSignature = MethodSignature.fromDexMethod(residualMethod);
MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
@@ -234,9 +229,7 @@
// Add simple "a() -> b" mapping if we won't have any other with concrete line numbers
if (mappedPositions.isEmpty()) {
MappedRange range =
- getBuilder()
- .addMappedRange(
- null, originalSignature, null, residualSignature.getName().toString());
+ getBuilder().addMappedRange(null, originalSignature, null, residualSignature.getName());
methodMappingInfo.forEach(info -> range.addMappingInformation(info, Unreachable::raise));
return this;
}
@@ -495,6 +488,10 @@
return this == OUT_OF_RANGE;
}
+ private boolean isSameDelta() {
+ return this == SAME_DELTA;
+ }
+
public MappedPositionRange canAddNextMappingToRange(
MappedPosition lastPosition, MappedPosition currentPosition) {
if (isOutOfRange()) {
@@ -508,9 +505,12 @@
boolean hasSameRightHandSide =
lastPosition.getOriginalLine() == currentPosition.getOriginalLine();
if (hasSameRightHandSide) {
+ if (isSameDelta()) {
+ return OUT_OF_RANGE;
+ }
boolean hasSameLeftHandSide =
lastPosition.getObfuscatedLine() == currentPosition.getObfuscatedLine();
- return hasSameLeftHandSide ? SINGLE_LINE : RANGE_TO_SINGLE;
+ return (hasSameLeftHandSide && isSingleLine()) ? SINGLE_LINE : RANGE_TO_SINGLE;
}
if (isRangeToSingle()) {
// We cannot recover a delta encoding if we have had range to single encoding.
diff --git a/src/test/java/com/android/tools/r8/desugar/InterfaceInvokePrivateTest.java b/src/test/java/com/android/tools/r8/desugar/InterfaceInvokePrivateTest.java
index 9cb8615..4055ea0 100644
--- a/src/test/java/com/android/tools/r8/desugar/InterfaceInvokePrivateTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/InterfaceInvokePrivateTest.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import org.junit.Test;
@@ -29,11 +30,16 @@
@Parameter(1)
public CfVersion inputCfVersion;
- @Parameterized.Parameters(name = "{0}, Input CfVersion = {1}")
+ @Parameter(2)
+ public boolean rewriteInvokeToPrivateInDesugar;
+
+ @Parameterized.Parameters(
+ name = "{0}, Input CfVersion = {1}, rewriteInvokeToPrivateInDesugar = {2}")
public static Iterable<?> data() {
return buildParameters(
getTestParameters().withCfRuntimes().withDexRuntimes().withAllApiLevelsAlsoForCf().build(),
- CfVersion.rangeInclusive(CfVersion.V1_8, CfVersion.V15));
+ CfVersion.rangeInclusive(CfVersion.V1_8, CfVersion.V15),
+ BooleanUtils.values());
}
private static final String EXPECTED_OUTPUT = StringUtils.unixLines("Hello, world!", "21", "6");
@@ -47,6 +53,7 @@
public void testReference() throws Exception {
assumeTrue(parameters.getRuntime().isCf());
assumeTrue(parameters.getApiLevel().isEqualTo(AndroidApiLevel.B));
+ assumeTrue(rewriteInvokeToPrivateInDesugar);
testForJvm()
.addProgramClassFileData(transformIToPrivate(inputCfVersion))
@@ -69,7 +76,9 @@
@Test
public void testDesugar() throws Exception {
- testForDesugaring(parameters)
+ testForDesugaring(
+ parameters,
+ options -> options.rewriteInvokeToPrivateInDesugar = rewriteInvokeToPrivateInDesugar)
.addProgramClassFileData(transformIToPrivate(inputCfVersion))
.addProgramClasses(TestRunner.class)
.run(parameters.getRuntime(), TestRunner.class)
@@ -91,7 +100,8 @@
parameters.getRuntime().isCf()
&& parameters.getRuntime().asCf().isOlderThan(CfVm.JDK11)
&& (DesugarTestConfiguration.isNotDesugared(c)
- || parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)),
+ || (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
+ && !rewriteInvokeToPrivateInDesugar)),
r -> r.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class),
// All other conditions succeed.
r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT));
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/R8WithCfPcEncodingTest.java b/src/test/java/com/android/tools/r8/mappingcompose/R8WithCfPcEncodingTest.java
new file mode 100644
index 0000000..99ea77c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/R8WithCfPcEncodingTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.mappingcompose.testclasses.MainWithHelloWorld;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import com.android.tools.r8.retrace.RetracedMethodReference;
+import com.android.tools.r8.retrace.Retracer;
+import com.android.tools.r8.utils.codeinspector.LineNumberTable;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableSet;
+import java.util.HashSet;
+import java.util.OptionalInt;
+import java.util.Set;
+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 R8WithCfPcEncodingTest extends TestBase {
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntimes().build();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(MainWithHelloWorld.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(MainWithHelloWorld.class)
+ .addKeepAttributeLineNumberTable()
+ .addOptionsModification(
+ options -> options.getTestingOptions().usePcEncodingInCfForTesting = true)
+ .run(parameters.getRuntime(), MainWithHelloWorld.class)
+ .assertSuccessWithOutputLines("Hello World!")
+ .inspect(
+ inspector -> {
+ MethodSubject subject = inspector.clazz(MainWithHelloWorld.class).mainMethod();
+ assertThat(subject, isPresent());
+ LineNumberTable lineNumberTable = subject.getLineNumberTable();
+ Set<Integer> lines = new HashSet<>(lineNumberTable.getLines());
+ assertEquals(ImmutableSet.of(1, 2, 3, 4), lines);
+ Retracer retracer = inspector.getRetracer();
+ MethodReference methodReference = subject.getFinalReference();
+ Set<Integer> retracedLines = new HashSet<>();
+ lines.forEach(
+ line -> {
+ retracer
+ .retraceFrame(
+ RetraceStackTraceContext.empty(), OptionalInt.of(line), methodReference)
+ .forEach(
+ element -> {
+ element.forEachRewritten(
+ singleFrame -> {
+ RetracedMethodReference retracedReference =
+ singleFrame.getMethodReference();
+ assertTrue(retracedReference.isKnown());
+ assertEquals(
+ methodReference,
+ retracedReference.asKnown().getMethodReference());
+ retracedLines.add(
+ retracedReference.getOriginalPositionOrDefault(-1));
+ });
+ });
+ });
+ assertEquals(ImmutableSet.of(10), retracedLines);
+ });
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/testclasses/MainWithHelloWorld.java b/src/test/java/com/android/tools/r8/mappingcompose/testclasses/MainWithHelloWorld.java
new file mode 100644
index 0000000..853dbee
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/testclasses/MainWithHelloWorld.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, 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.mappingcompose.testclasses;
+
+public class MainWithHelloWorld {
+
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+}
diff --git a/tools/compare_apk_sizes.py b/tools/compare_apk_sizes.py
index 1890283..ad75024 100755
--- a/tools/compare_apk_sizes.py
+++ b/tools/compare_apk_sizes.py
@@ -25,6 +25,10 @@
def parse_options():
result = optparse.OptionParser(usage=USAGE)
+ result.add_option('--no-build',
+ help='Run without building first',
+ default=False,
+ action='store_true')
result.add_option('--temp',
help='Temporary directory to store extracted classes in')
result.add_option('--use_code_size',
@@ -47,12 +51,14 @@
if not os.path.exists(f):
raise Exception('%s does not exist' % f)
-def extract_classes(input, output):
+def extract_classes(input, output, options):
if os.path.exists(output):
shutil.rmtree(output)
os.makedirs(output)
args = ['--file-per-class',
'--output', output]
+ if options.no_build:
+ args.extend(['--no-build'])
args.extend(input)
if toolhelper.run('d8', args) is not 0:
raise Exception('Failed running d8')
@@ -183,8 +189,8 @@
app1_classes_dir = os.path.join(output, 'app1_classes')
app2_classes_dir = os.path.join(output, 'app2_classes')
- extract_classes(app1_input, app1_classes_dir)
- extract_classes(app2_input, app2_classes_dir)
+ extract_classes(app1_input, app1_classes_dir, options)
+ extract_classes(app2_input, app2_classes_dir, options)
compare(app1_classes_dir, app2_classes_dir, app1, app2, options)
if __name__ == '__main__':