Reland "Remove methods from definitionsFor cache."
This reverts commit f58b55990d3fca2b3a4acf67ecba721cdc9c0262.
Bug: 151878901
Change-Id: I3e94ffdd1c3a7ddb9826adcc2af405dff57e8001
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 2ddba3f..a41e119 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -31,11 +31,15 @@
private final DexApplication app;
private final DexItemFactory dexItemFactory;
- private final ConcurrentHashMap<DexType, Map<DexMember<?, ?>, DexEncodedMember<?, ?>>>
- definitions = new ConcurrentHashMap<>();
+
+ // TODO(b/151804585): Remove this cache.
+ private final ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache =
+ new ConcurrentHashMap<>();
+
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
- final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses = new ConcurrentHashMap<>();
+ private 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.
@@ -50,7 +54,7 @@
assert !previous.isObsolete();
this.app = previous.app;
this.dexItemFactory = app.dexItemFactory;
- this.definitions.putAll(previous.definitions);
+ this.fieldDefinitionsCache.putAll(previous.fieldDefinitionsCache);
copyMetadataFromPrevious(previous);
}
@@ -94,7 +98,7 @@
assert checkIfObsolete();
assert clazz.type.isD8R8SynthesizedClassType();
DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
- invalidateTypeCacheFor(clazz.type);
+ invalidateFieldCacheFor(clazz.type);
assert previous == null || previous == clazz;
}
@@ -103,12 +107,11 @@
return Collections.unmodifiableCollection(synthesizedClasses.values());
}
- private Map<DexMember<?, ?>, DexEncodedMember<?, ?>> computeDefinitions(DexType type) {
- Builder<DexMember<?, ?>, DexEncodedMember<?, ?>> builder = ImmutableMap.builder();
+ private Map<DexField, DexEncodedField> computeFieldDefinitions(DexType type) {
+ Builder<DexField, DexEncodedField> builder = ImmutableMap.builder();
DexClass clazz = definitionFor(type);
if (clazz != null) {
- clazz.forEachMethod(method -> builder.put(method.toReference(), method));
- clazz.forEachField(field -> builder.put(field.toReference(), field));
+ clazz.forEachField(field -> builder.put(field.field, field));
}
return builder.build();
}
@@ -173,35 +176,29 @@
@Override
public DexEncodedMethod definitionFor(DexMethod method) {
assert checkIfObsolete();
- 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);
+ assert method.holder.isClassType();
+ if (!method.holder.isClassType()) {
+ return null;
}
- return cached;
+ DexClass clazz = definitionFor(method.holder);
+ if (clazz == null) {
+ return null;
+ }
+ return clazz.getMethodCollection().getMethod(method);
}
@Override
public DexEncodedField definitionFor(DexField field) {
assert checkIfObsolete();
- return (DexEncodedField) getDefinitions(field.holder).get(field);
+ return getFieldDefinitions(field.holder).get(field);
}
- 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;
+ private Map<DexField, DexEncodedField> getFieldDefinitions(DexType type) {
+ return fieldDefinitionsCache.computeIfAbsent(type, this::computeFieldDefinitions);
}
- public void invalidateTypeCacheFor(DexType type) {
- definitions.remove(type);
+ public void invalidateFieldCacheFor(DexType type) {
+ fieldDefinitionsCache.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 d4545b3..c43b1f9 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2527,7 +2527,6 @@
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());