Make FieldAccessInfo and FieldAccessInfoCollection immutable
Optimizations that need to update FieldAccessInfo get access to a new MutableFieldAccessInfoCollection and MutableFieldAccessInfo.
No optimizations other than the Enqueuer should have access to the underlying implementation, FieldAccessInfoCollectionImpl and FieldAccessInfoImpl.
Change-Id: I36a4e395ed2a32b170294a9c6b6e20976e9634b9
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 78c7d8c..c9be529 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -506,10 +506,12 @@
if (options.getTestingOptions().enableMemberRebindingAnalysis) {
new MemberRebindingAnalysis(appViewWithLiveness).run(executorService);
- } else {
- appViewWithLiveness.appInfo().getFieldAccessInfoCollection().flattenAccessContexts();
}
- appViewWithLiveness.appInfo().notifyMemberRebindingFinished(appViewWithLiveness);
+ appViewWithLiveness.appInfo().getMutableFieldAccessInfoCollection().flattenAccessContexts();
+ appViewWithLiveness
+ .appInfo()
+ .getMutableFieldAccessInfoCollection()
+ .restrictToProgram(appView);
assert ArtProfileCompletenessChecker.verify(appView);
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
index 126a0d0..357f02b 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
@@ -4,22 +4,17 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.analysis.proto.ProtoReferences;
import java.util.function.Consumer;
import java.util.function.Predicate;
/** Provides immutable access to {@link FieldAccessInfoImpl}. */
public interface FieldAccessInfo {
- FieldAccessInfoImpl asMutable();
-
DexField getField();
int getNumberOfWriteContexts();
- AbstractAccessContexts getReadsWithContexts();
-
- AbstractAccessContexts getWritesWithContexts();
-
boolean hasKnownReadContexts();
boolean hasKnownWriteContexts();
@@ -32,8 +27,6 @@
boolean hasReflectiveAccess();
- boolean hasReflectiveRead();
-
boolean hasReflectiveWrite();
default boolean isAccessedFromMethodHandle() {
@@ -48,14 +41,12 @@
boolean isReadFromMethodHandle();
- boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate);
+ boolean isReadOnlyInFindLiteExtensionByNumberMethod(ProtoReferences references);
boolean isWritten();
boolean isWrittenFromMethodHandle();
- boolean isWrittenInMethodSatisfying(Predicate<ProgramMethod> predicate);
-
boolean isWrittenOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate);
boolean isWrittenOutside(DexEncodedMethod method);
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollection.java
index b3f9c25..86394be 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollection.java
@@ -4,23 +4,16 @@
package com.android.tools.r8.graph;
-import java.util.function.BiPredicate;
import java.util.function.Consumer;
/** Provides immutable access to {@link FieldAccessInfoCollectionImpl}. */
public interface FieldAccessInfoCollection<T extends FieldAccessInfo> {
- void destroyAccessContexts();
-
- void flattenAccessContexts();
-
- boolean contains(DexField field);
+ default boolean contains(DexField field) {
+ return get(field) != null;
+ }
T get(DexField field);
void forEach(Consumer<T> consumer);
-
- void removeIf(BiPredicate<DexField, FieldAccessInfoImpl> predicate);
-
- void restrictToProgram(DexDefinitionSupplier definitions);
}
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
index 24b9d33..92ac34d 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
@@ -17,7 +17,8 @@
import java.util.function.Function;
public class FieldAccessInfoCollectionImpl
- implements FieldAccessInfoCollection<FieldAccessInfoImpl> {
+ implements MutableFieldAccessInfoCollection<
+ FieldAccessInfoCollectionImpl, FieldAccessInfoImpl> {
private final Map<DexField, FieldAccessInfoImpl> infos;
@@ -45,15 +46,11 @@
}
@Override
- public boolean contains(DexField field) {
- return infos.containsKey(field);
- }
-
- @Override
public FieldAccessInfoImpl get(DexField field) {
return infos.get(field);
}
+ @Override
public FieldAccessInfoImpl extend(DexField field, FieldAccessInfoImpl info) {
assert !infos.containsKey(field);
infos.put(field, info);
@@ -81,6 +78,7 @@
removeIf((field, info) -> !definitions.definitionForHolder(field).isProgramClass());
}
+ @Override
public FieldAccessInfoCollectionImpl rewrittenWithLens(
DexDefinitionSupplier definitions, GraphLens lens, Timing timing) {
timing.begin("Rewrite FieldAccessInfoCollectionImpl");
@@ -105,6 +103,7 @@
return true;
}
+ @Override
public FieldAccessInfoCollectionImpl withoutPrunedItems(PrunedItems prunedItems) {
Iterator<Entry<DexField, FieldAccessInfoImpl>> iterator = infos.entrySet().iterator();
while (iterator.hasNext()) {
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
index a09751b..31d875c 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AbstractAccessContexts.ConcreteAccessContexts;
import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.ir.analysis.proto.ProtoReferences;
import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind;
import com.android.tools.r8.utils.timing.Timing;
import com.google.common.collect.Sets;
@@ -19,7 +20,7 @@
*
* <p>The information is generated by the {@link com.android.tools.r8.shaking.Enqueuer}.
*/
-public class FieldAccessInfoImpl implements FieldAccessInfo {
+public class FieldAccessInfoImpl implements MutableFieldAccessInfo {
public static final FieldAccessInfoImpl MISSING_FIELD_ACCESS_INFO = new FieldAccessInfoImpl(null);
@@ -74,16 +75,10 @@
}
@Override
- public FieldAccessInfoImpl asMutable() {
- return this;
- }
-
- @Override
public DexField getField() {
return field;
}
- @Override
public AbstractAccessContexts getReadsWithContexts() {
return readsWithContexts;
}
@@ -92,7 +87,6 @@
this.readsWithContexts = readsWithContexts;
}
- @Override
public AbstractAccessContexts getWritesWithContexts() {
return writesWithContexts;
}
@@ -162,13 +156,16 @@
return hasReflectiveRead() || hasReflectiveWrite();
}
- @Override
public boolean hasReflectiveRead() {
return (flags & FLAG_HAS_REFLECTIVE_READ) != 0;
}
- public void setHasReflectiveRead() {
- flags |= FLAG_HAS_REFLECTIVE_READ;
+ public boolean setHasReflectiveRead() {
+ if (!hasReflectiveRead()) {
+ flags |= FLAG_HAS_REFLECTIVE_READ;
+ return true;
+ }
+ return false;
}
@Override
@@ -176,8 +173,12 @@
return (flags & FLAG_HAS_REFLECTIVE_WRITE) != 0;
}
- public void setHasReflectiveWrite() {
- flags |= FLAG_HAS_REFLECTIVE_WRITE;
+ public boolean setHasReflectiveWrite() {
+ if (!hasReflectiveWrite()) {
+ flags |= FLAG_HAS_REFLECTIVE_WRITE;
+ return true;
+ }
+ return false;
}
/** Returns true if this field is read by the program. */
@@ -236,12 +237,11 @@
flags &= ~FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC;
}
- /**
- * Returns true if this field is only read by methods for which {@param predicate} returns true.
- */
@Override
- public boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) {
- return readsWithContexts.isAccessedOnlyInMethodSatisfying(predicate) && !isReadIndirectly();
+ public boolean isReadOnlyInFindLiteExtensionByNumberMethod(ProtoReferences references) {
+ return !isReadIndirectly()
+ && readsWithContexts.isAccessedOnlyInMethodSatisfying(
+ references::isFindLiteExtensionByNumberMethod);
}
/** Returns true if this field is written by the program. */
@@ -270,7 +270,6 @@
/**
* Returns true if this field is written by a method for which {@param predicate} returns true.
*/
- @Override
public boolean isWrittenInMethodSatisfying(Predicate<ProgramMethod> predicate) {
return writesWithContexts.isAccessedInMethodSatisfying(predicate);
}
@@ -312,6 +311,7 @@
return false;
}
+ @Override
public void clearReads() {
assert !hasReflectiveAccess();
assert !isReadFromAnnotation();
@@ -320,6 +320,7 @@
clearReadFromRecordInvokeDynamic();
}
+ @Override
public void clearWrites() {
writesWithContexts = AbstractAccessContexts.empty();
}
diff --git a/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfo.java b/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfo.java
new file mode 100644
index 0000000..ee1d85b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfo.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2025, 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.graph;
+
+public interface MutableFieldAccessInfo extends FieldAccessInfo {
+
+ void clearReads();
+
+ void clearWrites();
+}
diff --git a/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfoCollection.java
new file mode 100644
index 0000000..17a8c35
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/MutableFieldAccessInfoCollection.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2025, 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.graph;
+
+import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.utils.timing.Timing;
+import java.util.function.BiPredicate;
+
+public interface MutableFieldAccessInfoCollection<
+ S extends MutableFieldAccessInfoCollection<S, T>, T extends MutableFieldAccessInfo>
+ extends FieldAccessInfoCollection<T> {
+
+ void destroyAccessContexts();
+
+ T extend(DexField field, FieldAccessInfoImpl info);
+
+ void flattenAccessContexts();
+
+ void removeIf(BiPredicate<DexField, FieldAccessInfoImpl> predicate);
+
+ void restrictToProgram(DexDefinitionSupplier definitions);
+
+ S rewrittenWithLens(DexDefinitionSupplier definitions, GraphLens lens, Timing timing);
+
+ S withoutPrunedItems(PrunedItems prunedItems);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
index 8138996..1279d85 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.MutableFieldAccessInfoCollection;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
@@ -169,15 +170,16 @@
}
private void clearReadsAndWritesFromFieldsOfInterest(AppInfoWithLiveness appInfo) {
- FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
+ MutableFieldAccessInfoCollection<?, ?> fieldAccessInfoCollection =
+ appInfo.getMutableFieldAccessInfoCollection();
for (DexEncodedField field : constantFields) {
- fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
+ fieldAccessInfoCollection.get(field.getReference()).clearReads();
}
for (DexEncodedField field : readFields.keySet()) {
- fieldAccessInfoCollection.get(field.getReference()).asMutable().clearWrites();
+ fieldAccessInfoCollection.get(field.getReference()).clearWrites();
}
for (DexEncodedField field : writtenFields.keySet()) {
- fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
+ fieldAccessInfoCollection.get(field.getReference()).clearReads();
}
}
@@ -242,7 +244,8 @@
}
private void processFieldsNeverRead(AppInfoWithLiveness appInfo) {
- FieldAccessInfoCollection<?> fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
+ MutableFieldAccessInfoCollection<?, ?> fieldAccessInfoCollection =
+ appInfo.getMutableFieldAccessInfoCollection();
writtenFields
.entrySet()
.removeIf(
@@ -253,7 +256,7 @@
writtenFields.forEach(
(field, contexts) -> {
assert !readFields.containsKey(field);
- fieldAccessInfoCollection.get(field.getReference()).asMutable().clearReads();
+ fieldAccessInfoCollection.get(field.getReference()).clearReads();
methodsToReprocess.addAll(
contexts.asConcrete().getAccessesWithContexts().values().iterator().next());
methodsToReprocess.addAll(dependencies.getOrDefault(field, ProgramMethodSet.empty()));
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
index ae7191d..45afec6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
@@ -103,7 +103,10 @@
*/
public TreePrunerConfiguration run(Enqueuer.Mode mode) {
forEachDeadProtoExtensionField(field -> recordDeadProtoExtensionField(field, mode));
- appView.appInfo().getFieldAccessInfoCollection().removeIf((field, info) -> wasRemoved(field));
+ appView
+ .appInfo()
+ .getMutableFieldAccessInfoCollection()
+ .removeIf((field, info) -> wasRemoved(field));
return createTreePrunerConfiguration(mode);
}
@@ -274,8 +277,7 @@
}
// Multiple GeneratedExtensionRegistries exist in Chrome; 1 per feature split.
- return fieldAccessInfo.isReadOnlyInMethodSatisfying(
- references::isFindLiteExtensionByNumberMethod);
+ return fieldAccessInfo.isReadOnlyInFindLiteExtensionByNumberMethod(references);
}
private void forEachDeadProtoExtensionField(Consumer<DexField> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index 7300dd7..29bce4e 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -116,7 +116,7 @@
new IdentifierMinifier(appView).rewriteDexItemBasedConstStringInStaticFields(executorService);
// The field access info collection is not maintained during IR processing.
- appView.appInfo().withLiveness().getFieldAccessInfoCollection().destroyAccessContexts();
+ appView.appInfoWithLiveness().getMutableFieldAccessInfoCollection().destroyAccessContexts();
// Assure that no more optimization feedback left after primary processing.
assert feedback.noUpdatesLeft();
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index f16d405..b20df20 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -360,11 +360,9 @@
}
public void run(ExecutorService executorService) throws ExecutionException {
- AppInfoWithLiveness appInfo = appView.appInfo();
Map<InvokeType, NonReboundMethodAccessCollection> nonReboundMethodAccessCollections =
computeNonReboundMethodAccessCollections(executorService);
computeMethodRebinding(nonReboundMethodAccessCollections);
- appInfo.getFieldAccessInfoCollection().flattenAccessContexts();
MemberRebindingLens memberRebindingLens = lensBuilder.build();
appView.setGraphLens(memberRebindingLens);
eventConsumer.finished(appView, memberRebindingLens);
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 3d5de3b..577626e 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -33,13 +33,14 @@
import com.android.tools.r8.graph.DispatchTargetLookupResult;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.InstantiatedSubTypeInfo;
import com.android.tools.r8.graph.LookupMethodTarget;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
import com.android.tools.r8.graph.LookupTarget;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
+import com.android.tools.r8.graph.MutableFieldAccessInfo;
+import com.android.tools.r8.graph.MutableFieldAccessInfoCollection;
import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.ProgramField;
@@ -132,7 +133,8 @@
* a given field is read/written by the program, and it also includes all indirect accesses to
* each field. The latter is used, for example, during member rebinding.
*/
- private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;
+ private final MutableFieldAccessInfoCollection<?, ? extends MutableFieldAccessInfo>
+ fieldAccessInfoCollection;
/** Information about instantiated classes and their allocation sites. */
private final ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection;
@@ -202,7 +204,8 @@
Set<DexMethod> bootstrapMethods,
Set<DexMethod> virtualMethodsTargetedByInvokeDirect,
Set<DexMethod> liveMethods,
- FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
+ MutableFieldAccessInfoCollection<?, ? extends MutableFieldAccessInfo>
+ fieldAccessInfoCollection,
ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
Map<DexCallSite, ProgramMethodSet> callSites,
KeepInfoCollection keepInfo,
@@ -401,10 +404,6 @@
return map;
}
- public void notifyMemberRebindingFinished(AppView<AppInfoWithLiveness> appView) {
- getFieldAccessInfoCollection().restrictToProgram(appView);
- }
-
@Override
public void notifyMinifierFinished() {
liveMethods = ThrowingSet.get();
@@ -745,7 +744,8 @@
return fieldAccessInfoCollection;
}
- FieldAccessInfoCollectionImpl getMutableFieldAccessInfoCollection() {
+ public MutableFieldAccessInfoCollection<?, ? extends MutableFieldAccessInfo>
+ getMutableFieldAccessInfoCollection() {
return fieldAccessInfoCollection;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLivenessModifier.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLivenessModifier.java
index bf91868..305d864 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLivenessModifier.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLivenessModifier.java
@@ -6,8 +6,8 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
-import com.android.tools.r8.graph.FieldAccessInfoImpl;
+import com.android.tools.r8.graph.MutableFieldAccessInfo;
+import com.android.tools.r8.graph.MutableFieldAccessInfoCollection;
import com.android.tools.r8.utils.SetUtils;
import java.util.Set;
@@ -37,11 +37,11 @@
appInfo.mutateObjectAllocationInfoCollection(
mutator -> noLongerInstantiatedClasses.forEach(mutator::markNoLongerInstantiated));
// Written fields.
- FieldAccessInfoCollectionImpl fieldAccessInfoCollection =
- appInfo.getMutableFieldAccessInfoCollection();
+ MutableFieldAccessInfoCollection<?, ? extends MutableFieldAccessInfo>
+ fieldAccessInfoCollection = appInfo.getMutableFieldAccessInfoCollection();
noLongerWrittenFields.forEach(
field -> {
- FieldAccessInfoImpl fieldAccessInfo = fieldAccessInfoCollection.get(field);
+ MutableFieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field);
if (fieldAccessInfo != null) {
fieldAccessInfo.clearWrites();
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index ca00c0c..5e9c0fd 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1228,20 +1228,10 @@
return false;
}
if (isReflective) {
- if (isRead) {
- if (!info.hasReflectiveRead()) {
- info.setHasReflectiveRead();
- return true;
- }
- } else {
- if (!info.hasReflectiveWrite()) {
- info.setHasReflectiveWrite();
- return true;
- }
- }
- return false;
+ return isRead ? info.setHasReflectiveRead() : info.setHasReflectiveWrite();
+ } else {
+ return isRead ? info.recordRead(field, context) : info.recordWrite(field, context);
}
- return isRead ? info.recordRead(field, context) : info.recordWrite(field, context);
}
void traceCallSite(
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
index 6a0cf10..3cbf5ae 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
+import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
@@ -162,7 +163,7 @@
assert enqueuer.getKeepInfo(field).isBottom();
assert !enqueuer.getKeepInfo(field).isPinned(options) || options.isOptimizedResourceShrinking();
- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
+ FieldAccessInfoImpl info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
if (info.hasReflectiveAccess()
|| info.isAccessedFromMethodHandle()
|| info.isReadFromAnnotation()
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index eda1979..5ff3b75 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfo;
+import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
@@ -843,7 +844,7 @@
@Override
public void enqueueTraceReflectiveFieldAccessAction(ProgramField field, ProgramMethod context) {
- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
+ FieldAccessInfoImpl info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
if (info == null || !info.hasReflectiveRead() || !info.hasReflectiveWrite()) {
queue.add(new TraceReflectiveFieldAccessAction(field, context));
}
@@ -851,7 +852,7 @@
@Override
public void enqueueTraceReflectiveFieldReadAction(ProgramField field, ProgramMethod context) {
- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
+ FieldAccessInfoImpl info = enqueuer.getFieldAccessInfoCollection().get(field.getReference());
if (info == null || !info.hasReflectiveRead()) {
queue.add(
new TraceReflectiveFieldAccessAction(
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 a05a33b..2dadd07 100644
--- a/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
+++ b/src/main/java/com/android/tools/r8/shaking/FieldAccessInfoCollectionModifier.java
@@ -8,8 +8,9 @@
import com.android.tools.r8.graph.AbstractAccessContexts.ConcreteAccessContexts;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
+import com.android.tools.r8.graph.MutableFieldAccessInfo;
+import com.android.tools.r8.graph.MutableFieldAccessInfoCollection;
import com.android.tools.r8.graph.ProgramMethod;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -66,13 +67,14 @@
}
public void modify(AppView<AppInfoWithLiveness> appView) {
- FieldAccessInfoCollectionImpl impl = appView.appInfo().getMutableFieldAccessInfoCollection();
+ MutableFieldAccessInfoCollection<?, ? extends MutableFieldAccessInfo>
+ mutableFieldAccessInfoCollection = appView.appInfo().getMutableFieldAccessInfoCollection();
newFieldAccessContexts.forEach(
(field, accessContexts) -> {
FieldAccessInfoImpl fieldAccessInfo = new FieldAccessInfoImpl(field);
fieldAccessInfo.setReadsWithContexts(accessContexts.readsWithContexts);
fieldAccessInfo.setWritesWithContexts(accessContexts.writesWithContexts);
- impl.extend(field, fieldAccessInfo);
+ mutableFieldAccessInfoCollection.extend(field, fieldAccessInfo);
});
}