Fix recording of synthetic $r8$classId field accesses
Change-Id: I2df11ba6e6c784b457fa337b5c2eb092d31b9556
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 535c08f..b0d84f9 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -57,10 +57,15 @@
return false;
}
+ public boolean isHorizontalClassMergingCode() {
+ return false;
+ }
+
public boolean isOutlineCode() {
return false;
}
+
/** Estimate the number of IR instructions emitted by buildIR(). */
public int estimatedSizeForInlining() {
return Integer.MAX_VALUE;
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 1547891..2a6ebf5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -185,6 +185,16 @@
predicate, method -> consumer.accept(new ProgramMethod(this, method)));
}
+ public void forEachProgramInstanceInitializer(Consumer<ProgramMethod> consumer) {
+ forEachProgramInstanceInitializerMatching(alwaysTrue(), consumer);
+ }
+
+ public void forEachProgramInstanceInitializerMatching(
+ Predicate<DexEncodedMethod> predicate, Consumer<ProgramMethod> consumer) {
+ forEachProgramDirectMethodMatching(
+ method -> method.isInstanceInitializer() && predicate.test(method), consumer);
+ }
+
public void forEachProgramVirtualMethod(Consumer<ProgramMethod> consumer) {
forEachProgramVirtualMethodMatching(alwaysTrue(), consumer);
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index b48d8ce..0a6a9b9 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -27,7 +27,6 @@
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.google.common.base.Equivalence.Wrapper;
@@ -59,7 +58,6 @@
private final ClassInitializerSynthesizedCode classInitializerSynthesizedCode;
private final HorizontalClassMergerGraphLens.Builder lensBuilder;
private final HorizontallyMergedClasses.Builder mergedClassesBuilder;
- private final FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder;
private final ClassMethodsBuilder classMethodsBuilder = new ClassMethodsBuilder();
private final Reference2IntMap<DexType> classIdentifiers = new Reference2IntOpenHashMap<>();
@@ -72,7 +70,6 @@
AppView<AppInfoWithLiveness> appView,
HorizontalClassMergerGraphLens.Builder lensBuilder,
HorizontallyMergedClasses.Builder mergedClassesBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
MergeGroup group,
Collection<VirtualMethodMerger> virtualMethodMergers,
Collection<ConstructorMerger> constructorMergers,
@@ -80,7 +77,6 @@
this.appView = appView;
this.lensBuilder = lensBuilder;
this.mergedClassesBuilder = mergedClassesBuilder;
- this.fieldAccessChangesBuilder = fieldAccessChangesBuilder;
this.group = group;
this.virtualMethodMergers = virtualMethodMergers;
this.constructorMergers = constructorMergers;
@@ -187,16 +183,13 @@
merger.merge(
classMethodsBuilder,
lensBuilder,
- fieldAccessChangesBuilder,
classIdentifiers,
syntheticArgumentClass));
}
void mergeVirtualMethods() {
virtualMethodMergers.forEach(
- merger ->
- merger.merge(
- classMethodsBuilder, lensBuilder, fieldAccessChangesBuilder, classIdentifiers));
+ merger -> merger.merge(classMethodsBuilder, lensBuilder, classIdentifiers));
group.forEachSource(clazz -> clazz.getMethodCollection().clearVirtualMethods());
}
@@ -329,8 +322,7 @@
public ClassMerger build(
HorizontallyMergedClasses.Builder mergedClassesBuilder,
- HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder) {
+ HorizontalClassMergerGraphLens.Builder lensBuilder) {
setup();
List<VirtualMethodMerger> virtualMethodMergers =
new ArrayList<>(virtualMethodMergerBuilders.size());
@@ -356,7 +348,6 @@
appView,
lensBuilder,
mergedClassesBuilder,
- fieldAccessChangesBuilder,
group,
virtualMethodMergers,
constructorMergers,
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java
index 7d250bb..bbce62b 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorEntryPointSynthesizedCode.java
@@ -45,4 +45,9 @@
registry.registerInvokeDirect(typeConstructor);
}
}
+
+ @Override
+ public boolean isHorizontalClassMergingCode() {
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
index 01d5771..b4e9887 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ConstructorMerger.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.structural.Ordered;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
@@ -139,7 +138,6 @@
void merge(
ClassMethodsBuilder classMethodsBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
Reference2IntMap<DexType> classIdentifiers,
SyntheticArgumentClass syntheticArgumentClass) {
// Tree map as must be sorted.
@@ -216,8 +214,5 @@
lensBuilder.recordNewMethodSignature(bridgeConstructorReference, newConstructorReference);
classMethodsBuilder.addDirectMethod(newConstructor);
-
- fieldAccessChangesBuilder.fieldWrittenByMethod(
- group.getClassIdField(), newConstructorReference);
}
}
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 09b975b..fd9fa86 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -80,15 +80,12 @@
new HorizontallyMergedClasses.Builder();
HorizontalClassMergerGraphLens.Builder lensBuilder =
new HorizontalClassMergerGraphLens.Builder();
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder =
- new FieldAccessInfoCollectionModifier.Builder();
MainDexTracingResult.Builder mainDexTracingResultBuilder =
mainDexTracingResult.extensionBuilder(appView.appInfo());
// Set up a class merger for each group.
List<ClassMerger> classMergers =
- initializeClassMergers(
- mergedClassesBuilder, lensBuilder, fieldAccessChangesBuilder, groups);
+ initializeClassMergers(mergedClassesBuilder, lensBuilder, groups);
Iterable<DexProgramClass> allMergeClasses =
Iterables.concat(
Iterables.transform(classMergers, classMerger -> classMerger.getGroup().getClasses()));
@@ -104,14 +101,30 @@
HorizontallyMergedClasses mergedClasses = mergedClassesBuilder.build();
appView.setHorizontallyMergedClasses(mergedClasses);
HorizontalClassMergerGraphLens lens =
- createLens(mergedClasses, lensBuilder, fieldAccessChangesBuilder, syntheticArgumentClass);
+ createLens(mergedClasses, lensBuilder, syntheticArgumentClass);
// Prune keep info.
KeepInfoCollection keepInfo = appView.appInfo().getKeepInfo();
keepInfo.mutate(mutator -> mutator.removeKeepInfoForPrunedItems(mergedClasses.getSources()));
return new HorizontalClassMergerResult(
- fieldAccessChangesBuilder.build(), lens, mainDexTracingResultBuilder.build());
+ createFieldAccessInfoCollectionModifier(groups), lens, mainDexTracingResultBuilder.build());
+ }
+
+ private FieldAccessInfoCollectionModifier createFieldAccessInfoCollectionModifier(
+ Collection<MergeGroup> groups) {
+ FieldAccessInfoCollectionModifier.Builder builder =
+ new FieldAccessInfoCollectionModifier.Builder();
+ for (MergeGroup group : groups) {
+ DexProgramClass target = group.getTarget();
+ target.forEachProgramInstanceInitializerMatching(
+ definition -> definition.getCode().isHorizontalClassMergingCode(),
+ method -> builder.recordFieldWrittenInContext(group.getClassIdField(), method));
+ target.forEachProgramVirtualMethodMatching(
+ definition -> definition.getCode().isHorizontalClassMergingCode(),
+ method -> builder.recordFieldReadInContext(group.getClassIdField(), method));
+ }
+ return builder.build();
}
private List<Policy> getPolicies(
@@ -157,7 +170,6 @@
private List<ClassMerger> initializeClassMergers(
HorizontallyMergedClasses.Builder mergedClassesBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
Collection<MergeGroup> groups) {
List<ClassMerger> classMergers = new ArrayList<>();
@@ -165,8 +177,7 @@
for (MergeGroup group : groups) {
assert !group.isEmpty();
ClassMerger merger =
- new ClassMerger.Builder(appView, group)
- .build(mergedClassesBuilder, lensBuilder, fieldAccessChangesBuilder);
+ new ClassMerger.Builder(appView, group).build(mergedClassesBuilder, lensBuilder);
classMergers.add(merger);
}
@@ -188,10 +199,8 @@
private HorizontalClassMergerGraphLens createLens(
HorizontallyMergedClasses mergedClasses,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
SyntheticArgumentClass syntheticArgumentClass) {
- return new TreeFixer(
- appView, mergedClasses, lensBuilder, fieldAccessChangesBuilder, syntheticArgumentClass)
+ return new TreeFixer(appView, mergedClasses, lensBuilder, syntheticArgumentClass)
.fixupTypeReferences();
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
index 551d229..c66d5de 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
@@ -20,7 +20,6 @@
import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
import com.android.tools.r8.shaking.AnnotationFixer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.OptionalBool;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
@@ -40,7 +39,6 @@
class TreeFixer extends TreeFixerBase {
private final HorizontallyMergedClasses mergedClasses;
private final HorizontalClassMergerGraphLens.Builder lensBuilder;
- private final FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder;
private final AppView<AppInfoWithLiveness> appView;
private final DexItemFactory dexItemFactory;
private final SyntheticArgumentClass syntheticArgumentClass;
@@ -51,13 +49,11 @@
AppView<AppInfoWithLiveness> appView,
HorizontallyMergedClasses mergedClasses,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
SyntheticArgumentClass syntheticArgumentClass) {
super(appView);
this.appView = appView;
this.mergedClasses = mergedClasses;
this.lensBuilder = lensBuilder;
- this.fieldAccessChangesBuilder = fieldAccessChangesBuilder;
this.syntheticArgumentClass = syntheticArgumentClass;
this.dexItemFactory = appView.dexItemFactory();
}
@@ -126,7 +122,6 @@
subtypingForrest.traverseNodeDepthFirst(root, HashBiMap.create(), this::fixupProgramClass);
}
HorizontalClassMergerGraphLens lens = lensBuilder.build(appView, mergedClasses);
- fieldAccessChangesBuilder.fixup(this::fixupMethodReference);
new AnnotationFixer(lens).run(appView.appInfo().classes());
return lens;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodEntryPointSynthesizedCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodEntryPointSynthesizedCode.java
index 7428b92..a1aaa6b 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodEntryPointSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodEntryPointSynthesizedCode.java
@@ -38,4 +38,9 @@
registry.registerInvokeDirect(mappedMethod);
}
}
+
+ @Override
+ public boolean isHorizontalClassMergingCode() {
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index e4060fe..24a1b84 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.structural.Ordered;
@@ -200,7 +199,6 @@
public void merge(
ClassMethodsBuilder classMethodsBuilder,
HorizontalClassMergerGraphLens.Builder lensBuilder,
- FieldAccessInfoCollectionModifier.Builder fieldAccessChangesBuilder,
Reference2IntMap<DexType> classIdentifiers) {
assert !methods.isEmpty();
@@ -275,7 +273,5 @@
lensBuilder.recordNewMethodSignature(bridgeMethodReference, newMethodReference);
classMethodsBuilder.addVirtualMethod(newMethod);
-
- fieldAccessChangesBuilder.fieldReadByMethod(group.getClassIdField(), newMethodReference);
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java b/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
index 591ef6d..f656a56 100644
--- a/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
+++ b/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
@@ -6,94 +6,57 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.ProgramMethod;
-import java.util.ArrayList;
-import java.util.Collection;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
public class FieldAccessInfoCollectionModifier {
static class FieldReferences {
- final List<DexMethod> writeContexts = new ArrayList<>();
- final List<DexMethod> readContexts = new ArrayList<>();
-
- void fixUpMethods(List<DexMethod> methods, Function<DexMethod, DexMethod> fixUpMethod) {
- for (int i = 0; i < methods.size(); i++) {
- DexMethod method = methods.get(i);
- DexMethod newMethod = fixUpMethod.apply(method);
- if (method != newMethod) {
- methods.set(i, newMethod);
- }
- }
- }
-
- void fixup(Function<DexMethod, DexMethod> fixUpMethod) {
- fixUpMethods(writeContexts, fixUpMethod);
- fixUpMethods(readContexts, fixUpMethod);
- }
+ private final ProgramMethodSet writeContexts = ProgramMethodSet.create();
+ private final ProgramMethodSet readContexts = ProgramMethodSet.create();
}
- final Map<DexField, FieldReferences> newFieldAccesses;
+ private final Map<DexField, FieldReferences> newFieldAccesses;
FieldAccessInfoCollectionModifier(Map<DexField, FieldReferences> newFieldAccesses) {
this.newFieldAccesses = newFieldAccesses;
}
- void forEachFieldAccess(
- AppView<?> appView,
- Collection<DexMethod> methods,
- DexField field,
- BiConsumer<DexField, ProgramMethod> record) {
- for (DexMethod method : methods) {
- ProgramMethod programMethod =
- appView.definitionFor(method.holder).asProgramClass().lookupProgramMethod(method);
- record.accept(field, programMethod);
- }
- }
-
public void modify(AppView<AppInfoWithLiveness> appView) {
FieldAccessInfoCollectionImpl impl = appView.appInfo().getMutableFieldAccessInfoCollection();
newFieldAccesses.forEach(
(field, info) -> {
FieldAccessInfoImpl fieldAccessInfo = new FieldAccessInfoImpl(field);
- forEachFieldAccess(appView, info.readContexts, field, fieldAccessInfo::recordRead);
- forEachFieldAccess(appView, info.writeContexts, field, fieldAccessInfo::recordWrite);
+ info.readContexts.forEach(context -> fieldAccessInfo.recordRead(field, context));
+ info.writeContexts.forEach(context -> fieldAccessInfo.recordWrite(field, context));
impl.extend(field, fieldAccessInfo);
});
}
public static class Builder {
- final Map<DexField, FieldReferences> newFieldAccesses = new IdentityHashMap<>();
+
+ private final Map<DexField, FieldReferences> newFieldAccesses = new IdentityHashMap<>();
public Builder() {}
- public void fixup(Function<DexMethod, DexMethod> fixupMethod) {
- for (FieldReferences fieldReferences : newFieldAccesses.values()) {
- fieldReferences.fixup(fixupMethod);
- }
+ private FieldReferences getFieldReferences(DexField field) {
+ return newFieldAccesses.computeIfAbsent(field, ignore -> new FieldReferences());
+ }
+
+ public void recordFieldReadInContext(DexField field, ProgramMethod context) {
+ getFieldReferences(field).readContexts.add(context);
+ }
+
+ public void recordFieldWrittenInContext(DexField field, ProgramMethod context) {
+ getFieldReferences(field).writeContexts.add(context);
}
public FieldAccessInfoCollectionModifier build() {
return new FieldAccessInfoCollectionModifier(newFieldAccesses);
}
-
- FieldReferences getFieldReferences(DexField field) {
- return newFieldAccesses.computeIfAbsent(field, ignore -> new FieldReferences());
- }
-
- public void fieldReadByMethod(DexField field, DexMethod method) {
- getFieldReferences(field).readContexts.add(method);
- }
-
- public void fieldWrittenByMethod(DexField field, DexMethod method) {
- getFieldReferences(field).writeContexts.add(method);
- }
}
}