Fix may-have-finalize-method cache
Change-Id: Iaf5f11841f211ed69b0901bd581c1c8121d2d04e
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 9befcc6..ec90464 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.OptionalBool;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.origin.Origin;
@@ -48,10 +47,6 @@
// Caching what interfaces this type is implementing. This includes super-interface hierarchy.
Set<DexType> implementedInterfaces = null;
- // Caches which static types that may store an object that has a non-default finalize() method.
- // E.g., `java.lang.Object -> TRUE` if there is a subtype of Object that overrides finalize().
- Map<DexType, Boolean> mayHaveFinalizeMethodDirectlyOrIndirectlyCache = new IdentityHashMap<>();
-
public TypeInfo(DexType type) {
this.type = type;
}
@@ -114,17 +109,6 @@
ensureDirectSubTypeSet();
directSubtypes.add(type);
}
-
- synchronized OptionalBool mayHaveFinalizeMethodDirectlyOrIndirectly() {
- Boolean cache = mayHaveFinalizeMethodDirectlyOrIndirectlyCache.get(type);
- return cache != null ? OptionalBool.of(cache.booleanValue()) : OptionalBool.unknown();
- }
-
- synchronized boolean cacheMayHaveFinalizeMethodDirectlyOrIndirectly(boolean value) {
- assert mayHaveFinalizeMethodDirectlyOrIndirectlyCache.getOrDefault(type, value) == value;
- mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, value);
- return value;
- }
}
// Set of missing classes, discovered during subtypeMap computation.
@@ -140,6 +124,11 @@
// Map from types to their subtyping information.
private final Map<DexType, TypeInfo> typeInfo;
+ // Caches which static types that may store an object that has a non-default finalize() method.
+ // E.g., `java.lang.Object -> TRUE` if there is a subtype of Object that overrides finalize().
+ private final Map<DexType, Boolean> mayHaveFinalizeMethodDirectlyOrIndirectlyCache =
+ new ConcurrentHashMap<>();
+
public AppInfoWithSubtyping(DexApplication application) {
super(application);
typeInfo = Collections.synchronizedMap(new IdentityHashMap<>());
@@ -733,33 +722,37 @@
private boolean computeMayHaveFinalizeMethodDirectlyOrIndirectlyIfAbsent(
DexType type, boolean lookUpwards) {
assert type.isClassType();
- TypeInfo typeInfo = getTypeInfo(type);
- OptionalBool result = typeInfo.mayHaveFinalizeMethodDirectlyOrIndirectly();
- if (!result.isUnknown()) {
- return result.isTrue();
+ Boolean cache = mayHaveFinalizeMethodDirectlyOrIndirectlyCache.get(type);
+ if (cache != null) {
+ return cache;
}
DexClass clazz = definitionFor(type);
if (clazz == null) {
- return typeInfo.cacheMayHaveFinalizeMethodDirectlyOrIndirectly(true);
+ mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
+ return true;
}
if (clazz.isProgramClass()) {
if (lookUpwards) {
DexEncodedMethod resolutionResult =
resolveMethod(type, dexItemFactory().objectMethods.finalize).asSingleTarget();
if (resolutionResult != null && resolutionResult.isProgramMethod(this)) {
- return typeInfo.cacheMayHaveFinalizeMethodDirectlyOrIndirectly(true);
+ mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
+ return true;
}
} else {
if (clazz.lookupVirtualMethod(dexItemFactory().objectMethods.finalize) != null) {
- return typeInfo.cacheMayHaveFinalizeMethodDirectlyOrIndirectly(true);
+ mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
+ return true;
}
}
}
for (DexType subtype : allImmediateSubtypes(type)) {
if (computeMayHaveFinalizeMethodDirectlyOrIndirectlyIfAbsent(subtype, false)) {
- return typeInfo.cacheMayHaveFinalizeMethodDirectlyOrIndirectly(true);
+ mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
+ return true;
}
}
- return typeInfo.cacheMayHaveFinalizeMethodDirectlyOrIndirectly(false);
+ mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, false);
+ return false;
}
}