Revert "Remove methods from definitionsFor cache."
This reverts commit 8ec568330915a0e5f522a0954c55fb87ee5d53f7.
Bug: 151878901
Change-Id: Id6c902f5e527c2f8b1eea029611b281d7f67102e
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index a41e119..2ddba3f 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -31,15 +31,11 @@
private final DexApplication app;
private final DexItemFactory dexItemFactory;
-
- // TODO(b/151804585): Remove this cache.
- private final ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache =
- new ConcurrentHashMap<>();
-
+ private final ConcurrentHashMap<DexType, Map<DexMember<?, ?>, DexEncodedMember<?, ?>>>
+ definitions = new ConcurrentHashMap<>();
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
- private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses =
- new ConcurrentHashMap<>();
+ final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses = new ConcurrentHashMap<>();
// Set when a new AppInfo replaces a previous one. All public methods should verify that the
// current instance is not obsolete, to ensure that we almost use the most recent AppInfo.
@@ -54,7 +50,7 @@
assert !previous.isObsolete();
this.app = previous.app;
this.dexItemFactory = app.dexItemFactory;
- this.fieldDefinitionsCache.putAll(previous.fieldDefinitionsCache);
+ this.definitions.putAll(previous.definitions);
copyMetadataFromPrevious(previous);
}
@@ -98,7 +94,7 @@
assert checkIfObsolete();
assert clazz.type.isD8R8SynthesizedClassType();
DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
- invalidateFieldCacheFor(clazz.type);
+ invalidateTypeCacheFor(clazz.type);
assert previous == null || previous == clazz;
}
@@ -107,11 +103,12 @@
return Collections.unmodifiableCollection(synthesizedClasses.values());
}
- private Map<DexField, DexEncodedField> computeFieldDefinitions(DexType type) {
- Builder<DexField, DexEncodedField> builder = ImmutableMap.builder();
+ private Map<DexMember<?, ?>, DexEncodedMember<?, ?>> computeDefinitions(DexType type) {
+ Builder<DexMember<?, ?>, DexEncodedMember<?, ?>> builder = ImmutableMap.builder();
DexClass clazz = definitionFor(type);
if (clazz != null) {
- clazz.forEachField(field -> builder.put(field.field, field));
+ clazz.forEachMethod(method -> builder.put(method.toReference(), method));
+ clazz.forEachField(field -> builder.put(field.toReference(), field));
}
return builder.build();
}
@@ -176,29 +173,35 @@
@Override
public DexEncodedMethod definitionFor(DexMethod method) {
assert checkIfObsolete();
- assert method.holder.isClassType();
- if (!method.holder.isClassType()) {
- return null;
+ DexType holderType = method.holder;
+ DexEncodedMethod cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
+ if (cached != null && cached.isObsolete()) {
+ definitions.remove(holderType);
+ cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
}
- DexClass clazz = definitionFor(method.holder);
- if (clazz == null) {
- return null;
- }
- return clazz.getMethodCollection().getMethod(method);
+ return cached;
}
@Override
public DexEncodedField definitionFor(DexField field) {
assert checkIfObsolete();
- return getFieldDefinitions(field.holder).get(field);
+ return (DexEncodedField) getDefinitions(field.holder).get(field);
}
- private Map<DexField, DexEncodedField> getFieldDefinitions(DexType type) {
- return fieldDefinitionsCache.computeIfAbsent(type, this::computeFieldDefinitions);
+ private Map<DexMember<?, ?>, DexEncodedMember<?, ?>> getDefinitions(DexType type) {
+ Map<DexMember<?, ?>, DexEncodedMember<?, ?>> typeDefinitions = definitions.get(type);
+ if (typeDefinitions != null) {
+ return typeDefinitions;
+ }
+
+ typeDefinitions = computeDefinitions(type);
+ Map<DexMember<?, ?>, DexEncodedMember<?, ?>> existing =
+ definitions.putIfAbsent(type, typeDefinitions);
+ return existing != null ? existing : typeDefinitions;
}
- public void invalidateFieldCacheFor(DexType type) {
- fieldDefinitionsCache.remove(type);
+ public void invalidateTypeCacheFor(DexType type) {
+ definitions.remove(type);
}
// TODO(b/147578480): Temporary API since most of the code base use a type instead
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 c43b1f9..d4545b3 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2527,6 +2527,7 @@
for (ProgramMethod bridge : syntheticInterfaceMethodBridges.values()) {
DexProgramClass holder = bridge.getHolder();
DexEncodedMethod method = bridge.getMethod();
+ appView.appInfo().invalidateTypeCacheFor(holder.type);
holder.addVirtualMethod(method);
targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
liveMethods.add(holder, method, graphReporter.fakeReportShouldNotBeUsed());