Fix conversion to dex when instance initializers need lens rewriting
Bug: 230430794
Change-Id: I872b29b465eced07d6e5c772815279504aa20c08
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 6671b6a..3608975 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -127,7 +127,7 @@
? new SyntheticArgumentClass.Builder(appView.withLiveness()).build(groups)
: null;
SyntheticInitializerConverter.Builder syntheticInitializerConverterBuilder =
- SyntheticInitializerConverter.builder(appView, codeProvider);
+ SyntheticInitializerConverter.builder(appView, codeProvider, mode);
List<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfos = new ArrayList<>();
PrunedItems prunedItems =
applyClassMergers(
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
index 7912f4c..a31760b 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/SyntheticInitializerConverter.java
@@ -6,15 +6,19 @@
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
import com.android.tools.r8.horizontalclassmerging.IRCodeProvider;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -26,22 +30,28 @@
private final AppView<?> appView;
private final IRCodeProvider codeProvider;
+ private final Mode mode;
+
private final List<ProgramMethod> classInitializers;
- private final List<ProgramMethod> instanceInitializers;
+
+ // Classes with one or more instance initializers that need to have their code processed into dex.
+ private final Set<DexProgramClass> instanceInitializers;
private SyntheticInitializerConverter(
AppView<?> appView,
IRCodeProvider codeProvider,
+ Mode mode,
List<ProgramMethod> classInitializers,
- List<ProgramMethod> instanceInitializers) {
+ Set<DexProgramClass> instanceInitializers) {
this.appView = appView;
this.codeProvider = codeProvider;
+ this.mode = mode;
this.classInitializers = classInitializers;
this.instanceInitializers = instanceInitializers;
}
- public static Builder builder(AppView<?> appView, IRCodeProvider codeProvider) {
- return new Builder(appView, codeProvider);
+ public static Builder builder(AppView<?> appView, IRCodeProvider codeProvider, Mode mode) {
+ return new Builder(appView, codeProvider, mode);
}
public void convertClassInitializers(ExecutorService executorService) throws ExecutionException {
@@ -57,10 +67,23 @@
if (!instanceInitializers.isEmpty()) {
IRConverter converter = new IRConverter(createAppViewForConversion(), Timing.empty());
ThreadUtils.processItems(
- instanceInitializers, method -> processMethod(method, converter), executorService);
+ instanceInitializers,
+ clazz -> processInstanceInitializers(clazz, converter),
+ executorService);
}
}
+ private void processInstanceInitializers(DexProgramClass clazz, IRConverter converter) {
+ assert appView.options().isGeneratingDex();
+ assert mode.isFinal();
+ clazz.forEachProgramInstanceInitializerMatching(
+ method -> !method.getCode().isDexCode(),
+ method -> {
+ processMethod(method, converter);
+ assert method.getDefinition().getCode().isDexCode();
+ });
+ }
+
private AppView<AppInfo> createAppViewForConversion() {
// At this point the code rewritings described by repackaging and synthetic finalization have
// not been applied to the code objects. These code rewritings will be applied in the
@@ -88,12 +111,15 @@
private final AppView<?> appView;
private final IRCodeProvider codeProvider;
- private final List<ProgramMethod> classInitializers = new ArrayList<>();
- private final List<ProgramMethod> instanceInitializers = new ArrayList<>();
+ private final Mode mode;
- private Builder(AppView<?> appView, IRCodeProvider codeProvider) {
+ private final List<ProgramMethod> classInitializers = new ArrayList<>();
+ private final Set<DexProgramClass> instanceInitializers = Sets.newIdentityHashSet();
+
+ private Builder(AppView<?> appView, IRCodeProvider codeProvider, Mode mode) {
this.appView = appView;
this.codeProvider = codeProvider;
+ this.mode = mode;
}
public Builder addClassInitializer(ProgramMethod method) {
@@ -102,13 +128,16 @@
}
public Builder addInstanceInitializer(ProgramMethod method) {
- this.instanceInitializers.add(method);
+ // Record that the holder has an instance initializer that needs processing to dex. We avoid
+ // storing the collection of exact initializers that need processing, since that requires lens
+ // code rewriting after the fixup has been made.
+ this.instanceInitializers.add(method.getHolder());
return this;
}
public SyntheticInitializerConverter build() {
return new SyntheticInitializerConverter(
- appView, codeProvider, classInitializers, instanceInitializers);
+ appView, codeProvider, mode, classInitializers, instanceInitializers);
}
}
}