RewritePrefix flag in Machine specification
Bug: 184026720
Change-Id: I37bb23bc4626823af55ce6257e48e8e44b11dfa7
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 3b3e48e..ad3e92b 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -168,8 +168,7 @@
private static AppView<AppInfo> readApp(
AndroidApp inputApp, InternalOptions options, ExecutorService executor, Timing timing)
throws IOException {
- PrefixRewritingMapper rewritePrefix =
- options.desugaredLibrarySpecification.getPrefixRewritingMapper();
+ PrefixRewritingMapper rewritePrefix = options.getPrefixRewritingMapper();
ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
LazyLoadedDexApplication app = applicationReader.read(executor);
AppInfo appInfo = AppInfo.createInitialAppInfo(app, applicationReader.readMainDexClasses(app));
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index c3bf91f..9ba6c7f 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -166,8 +166,7 @@
LazyLoadedDexApplication lazyApp =
new ApplicationReader(inputApp, options, timing).read(executor);
- PrefixRewritingMapper rewritePrefix =
- options.desugaredLibrarySpecification.getPrefixRewritingMapper();
+ PrefixRewritingMapper rewritePrefix = options.getPrefixRewritingMapper();
DexApplication app = new L8TreePruner(options).prune(lazyApp, rewritePrefix);
return AppView.createForL8(AppInfo.createInitialAppInfo(app), rewritePrefix);
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 c2316e4..14b0ded 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -160,7 +160,7 @@
private static <T extends AppInfo> PrefixRewritingMapper defaultPrefixRewritingMapper(T appInfo) {
InternalOptions options = appInfo.options();
- return options.desugaredLibrarySpecification.getPrefixRewritingMapper();
+ return options.getPrefixRewritingMapper();
}
public static <T extends AppInfo> AppView<T> createForD8(T appInfo) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index ee7f8e1..49ad698 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -100,8 +100,7 @@
public static List<DexMethod> generateListOfBackportedMethods(
AndroidApp androidApp, InternalOptions options, ExecutorService executor) throws IOException {
List<DexMethod> methods = new ArrayList<>();
- PrefixRewritingMapper rewritePrefix =
- options.desugaredLibrarySpecification.getPrefixRewritingMapper();
+ PrefixRewritingMapper rewritePrefix = options.getPrefixRewritingMapper();
AppInfo appInfo = null;
if (androidApp != null) {
DexApplication app =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
index f5861d7..bf96b67 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
@@ -220,6 +221,55 @@
}
}
+ public static class MachineDesugarPrefixRewritingMapper extends PrefixRewritingMapper {
+
+ private final PrefixRewritingMapper mapper;
+ private final Map<DexType, DexType> rewriteType;
+ private final Map<DexType, DexType> rewriteDerivedTypeOnly;
+
+ public MachineDesugarPrefixRewritingMapper(
+ PrefixRewritingMapper mapper, MachineRewritingFlags flags) {
+ this.mapper = mapper;
+ this.rewriteType = new ConcurrentHashMap<>(flags.getRewriteType());
+ rewriteDerivedTypeOnly = flags.getRewriteDerivedTypeOnly();
+ }
+
+ @Override
+ public DexType rewrittenType(DexType type, AppView<?> appView) {
+ assert mapper.rewrittenType(type, appView) == rewriteType.get(type);
+ return rewriteType.get(type);
+ }
+
+ @Override
+ public DexType rewrittenContextType(DexType context, AppView<?> appView) {
+ if (rewriteType.containsKey(context)) {
+ return rewriteType.get(context);
+ }
+ return rewriteDerivedTypeOnly.get(context);
+ }
+
+ @Override
+ public void rewriteType(DexType type, DexType rewrittenType) {
+ mapper.rewriteType(type, rewrittenType);
+ rewriteType.compute(
+ type,
+ (t, val) -> {
+ assert val == null || val == rewrittenType;
+ return rewrittenType;
+ });
+ }
+
+ @Override
+ public boolean isRewriting() {
+ return true;
+ }
+
+ @Override
+ public void forAllRewrittenTypes(Consumer<DexType> consumer) {
+ rewriteType.keySet().forEach(consumer);
+ }
+ }
+
public static class EmptyPrefixRewritingMapper extends PrefixRewritingMapper {
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
index db17cf5..4077e4b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.google.common.collect.ImmutableMap;
+import java.util.IdentityHashMap;
import java.util.Map;
public class MachineRewritingFlags {
@@ -16,16 +17,25 @@
}
MachineRewritingFlags(
+ Map<DexType, DexType> rewriteType,
+ Map<DexType, DexType> rewriteDerivedTypeOnly,
Map<DexMethod, DexMethod> staticRetarget,
Map<DexMethod, DexMethod> nonEmulatedVirtualRetarget,
Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedVirtualRetarget,
Map<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces) {
+ this.rewriteType = rewriteType;
+ this.rewriteDerivedTypeOnly = rewriteDerivedTypeOnly;
this.staticRetarget = staticRetarget;
this.nonEmulatedVirtualRetarget = nonEmulatedVirtualRetarget;
this.emulatedVirtualRetarget = emulatedVirtualRetarget;
this.emulatedInterfaces = emulatedInterfaces;
}
+ // Rewrites all the references to the keys as well as synthetic types derived from any key.
+ private final Map<DexType, DexType> rewriteType;
+ // Rewrites only synthetic types derived from any key.
+ private final Map<DexType, DexType> rewriteDerivedTypeOnly;
+
// Static methods to retarget, duplicated to library boundaries.
private final Map<DexMethod, DexMethod> staticRetarget;
@@ -43,6 +53,14 @@
// Emulated interface descriptors.
private final Map<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces;
+ public Map<DexType, DexType> getRewriteType() {
+ return rewriteType;
+ }
+
+ public Map<DexType, DexType> getRewriteDerivedTypeOnly() {
+ return rewriteDerivedTypeOnly;
+ }
+
public Map<DexMethod, DexMethod> getStaticRetarget() {
return staticRetarget;
}
@@ -63,6 +81,8 @@
Builder() {}
+ private final Map<DexType, DexType> rewriteType = new IdentityHashMap<>();
+ private final Map<DexType, DexType> rewriteDerivedTypeOnly = new IdentityHashMap<>();
private final ImmutableMap.Builder<DexMethod, DexMethod> staticRetarget =
ImmutableMap.builder();
private final ImmutableMap.Builder<DexMethod, DexMethod> nonEmulatedVirtualRetarget =
@@ -72,6 +92,14 @@
private final ImmutableMap.Builder<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces =
ImmutableMap.builder();
+ public void rewriteType(DexType src, DexType target) {
+ rewriteType.put(src, target);
+ }
+
+ public void rewriteDerivedTypeOnly(DexType src, DexType target) {
+ rewriteDerivedTypeOnly.put(src, target);
+ }
+
public void putStaticRetarget(DexMethod src, DexMethod dest) {
staticRetarget.put(src, dest);
}
@@ -90,6 +118,8 @@
public MachineRewritingFlags build() {
return new MachineRewritingFlags(
+ rewriteType,
+ rewriteDerivedTypeOnly,
staticRetarget.build(),
nonEmulatedVirtualRetarget.build(),
emulatedVirtualRetarget.build(),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
new file mode 100644
index 0000000..69c409a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachinePrefixConverter.java
@@ -0,0 +1,112 @@
+// 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.ir.desugar.desugaredlibrary.specificationconversion;
+
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+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.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+public class HumanToMachinePrefixConverter {
+
+ private final AppInfoWithClassHierarchy appInfo;
+
+ public HumanToMachinePrefixConverter(AppInfoWithClassHierarchy appInfo) {
+ this.appInfo = appInfo;
+ }
+
+ private DexString toDescriptorPrefix(String prefix) {
+ return appInfo
+ .dexItemFactory()
+ .createString("L" + DescriptorUtils.getBinaryNameFromJavaType(prefix));
+ }
+
+ public void convertPrefixFlags(
+ HumanRewritingFlags rewritingFlags,
+ MachineRewritingFlags.Builder builder,
+ String synthesizedPrefix) {
+ Map<DexString, DexString> descriptorPrefix = convertRewritePrefix(rewritingFlags);
+ rewriteClasses(descriptorPrefix, builder);
+ rewriteValues(descriptorPrefix, builder, rewritingFlags.getRetargetCoreLibMember());
+ rewriteValues(descriptorPrefix, builder, rewritingFlags.getCustomConversions());
+ rewriteEmulatedInterface(builder, rewritingFlags.getEmulateLibraryInterface());
+ rewriteRetargetKeys(builder, rewritingFlags.getRetargetCoreLibMember(), synthesizedPrefix);
+ }
+
+ public DexType convertJavaNameToDesugaredLibrary(DexType type, String prefix) {
+ String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(prefix);
+ String interfaceType = type.toString();
+ int firstPackage = interfaceType.indexOf('.');
+ return appInfo
+ .dexItemFactory()
+ .createType(
+ DescriptorUtils.javaTypeToDescriptor(
+ convertedPrefix + interfaceType.substring(firstPackage + 1)));
+ }
+
+ private void rewriteRetargetKeys(
+ MachineRewritingFlags.Builder builder, Map<DexMethod, DexType> retarget, String prefix) {
+ for (DexMethod dexMethod : retarget.keySet()) {
+ DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder, prefix);
+ builder.rewriteDerivedTypeOnly(dexMethod.holder, type);
+ }
+ }
+
+ private void rewriteEmulatedInterface(
+ MachineRewritingFlags.Builder builder, Map<DexType, DexType> emulateLibraryInterface) {
+ emulateLibraryInterface.forEach(builder::rewriteDerivedTypeOnly);
+ }
+
+ private void rewriteValues(
+ Map<DexString, DexString> descriptorPrefix,
+ MachineRewritingFlags.Builder builder,
+ Map<?, DexType> flags) {
+ for (DexType type : flags.values()) {
+ DexType rewrittenType = rewrittenType(descriptorPrefix, type);
+ builder.rewriteType(type, rewrittenType);
+ }
+ }
+
+ private void rewriteClasses(
+ Map<DexString, DexString> descriptorPrefix, MachineRewritingFlags.Builder builder) {
+ for (DexProgramClass clazz : appInfo.classes()) {
+ DexType type = clazz.type;
+ DexType rewrittenType = rewrittenType(descriptorPrefix, type);
+ if (rewrittenType == null) {
+ continue;
+ }
+ builder.rewriteType(type, rewrittenType);
+ }
+ }
+
+ private DexType rewrittenType(Map<DexString, DexString> descriptorPrefix, DexType type) {
+ DexString prefixToMatch = type.descriptor.withoutArray(appInfo.dexItemFactory());
+ for (DexString prefix : descriptorPrefix.keySet()) {
+ if (prefixToMatch.startsWith(prefix)) {
+ DexString rewrittenTypeDescriptor =
+ type.descriptor.withNewPrefix(
+ prefix, descriptorPrefix.get(prefix), appInfo.dexItemFactory());
+ return appInfo.dexItemFactory().createType(rewrittenTypeDescriptor);
+ }
+ }
+ return null;
+ }
+
+ private ImmutableMap<DexString, DexString> convertRewritePrefix(
+ HumanRewritingFlags rewritingFlags) {
+ Map<String, String> rewritePrefix = rewritingFlags.getRewritePrefix();
+ ImmutableMap.Builder<DexString, DexString> mapBuilder = ImmutableMap.builder();
+ for (String key : rewritePrefix.keySet()) {
+ mapBuilder.put(toDescriptorPrefix(key), toDescriptorPrefix(rewritePrefix.get(key)));
+ }
+ return mapBuilder.build();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
index 69ae2e2..af380d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineSpecificationConverter.java
@@ -29,17 +29,24 @@
DexApplication app = readApp(androidLib, options);
AppView<?> appView = AppView.createForD8(AppInfo.createInitialAppInfo(app));
MachineRewritingFlags machineRewritingFlags =
- convertRewritingFlags(humanSpec.getRewritingFlags(), appView.appInfoForDesugaring());
+ convertRewritingFlags(
+ humanSpec.getSynthesizedLibraryClassesPackagePrefix(),
+ humanSpec.getRewritingFlags(),
+ appView.appInfoForDesugaring());
return new MachineDesugaredLibrarySpecification(
humanSpec.isLibraryCompilation(), machineRewritingFlags);
}
private MachineRewritingFlags convertRewritingFlags(
- HumanRewritingFlags rewritingFlags, AppInfoWithClassHierarchy appInfo) {
+ String synthesizedPrefix,
+ HumanRewritingFlags rewritingFlags,
+ AppInfoWithClassHierarchy appInfo) {
MachineRewritingFlags.Builder builder = MachineRewritingFlags.builder();
new HumanToMachineRetargetConverter(appInfo).convertRetargetFlags(rewritingFlags, builder);
new HumanToMachineEmulatedInterfaceConverter(appInfo)
.convertEmulatedInterfaces(rewritingFlags, appInfo, builder);
+ new HumanToMachinePrefixConverter(appInfo)
+ .convertPrefixFlags(rewritingFlags, builder, synthesizedPrefix);
return builder.build();
}
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 c1dc2c9..58cdf7e 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -53,6 +53,8 @@
import com.android.tools.r8.horizontalclassmerging.Policy;
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
+import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.MachineDesugarPrefixRewritingMapper;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.nest.Nest;
@@ -892,6 +894,15 @@
public LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
LegacyDesugaredLibrarySpecification.empty();
+ public PrefixRewritingMapper getPrefixRewritingMapper() {
+ if (testing.machineDesugaredLibrarySpecification != null) {
+ return new MachineDesugarPrefixRewritingMapper(
+ desugaredLibrarySpecification.getPrefixRewritingMapper(),
+ testing.machineDesugaredLibrarySpecification.getRewritingFlags());
+ }
+ return desugaredLibrarySpecification.getPrefixRewritingMapper();
+ }
+
public boolean relocatorCompilation = false;
// If null, no keep rules are recorded.