Strengthen type of staticizer's referencedFrom
Change-Id: Icc5ef11d463d8697c1a6f72bd8e9a4b4044df61d
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 675e8f4..041cf09 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -35,12 +35,12 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
-import com.android.tools.r8.utils.collections.ProgramMethodSetOrBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -69,7 +69,6 @@
final AtomicInteger fieldWrites = new AtomicInteger();
// Number of instances created.
final AtomicInteger instancesCreated = new AtomicInteger();
- ProgramMethodSetOrBuilder referencedFrom = new LongLivedProgramMethodSetBuilder();
final AtomicReference<DexEncodedMethod> constructor = new AtomicReference<>();
final AtomicReference<DexEncodedMethod> getter = new AtomicReference<>();
@@ -103,6 +102,9 @@
}
}
+ final Map<CandidateInfo, LongLivedProgramMethodSetBuilder> referencedFrom =
+ new IdentityHashMap<>();
+
// The map storing all the potential candidates for staticizing.
final ConcurrentHashMap<DexType, CandidateInfo> candidates = new ConcurrentHashMap<>();
@@ -289,7 +291,9 @@
}
// Ignore just read instruction.
}
- candidateInfo.referencedFrom.asLongLivedBuilder().add(method);
+ referencedFrom
+ .computeIfAbsent(candidateInfo, ignore -> new LongLivedProgramMethodSetBuilder())
+ .add(method);
}
continue;
}
@@ -309,7 +313,9 @@
// Check the field being read: make sure all usages are valid.
CandidateInfo info = processStaticFieldRead(instruction.asStaticGet());
if (info != null) {
- info.referencedFrom.asLongLivedBuilder().add(method);
+ referencedFrom
+ .computeIfAbsent(info, ignore -> new LongLivedProgramMethodSetBuilder())
+ .add(method);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -323,7 +329,9 @@
// Check if it is a static singleton getter.
CandidateInfo info = processInvokeStatic(instruction.asInvokeStatic());
if (info != null) {
- info.referencedFrom.asLongLivedBuilder().add(method);
+ referencedFrom
+ .computeIfAbsent(info, ignore -> new LongLivedProgramMethodSetBuilder())
+ .add(method);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 9e1b0f8..1e7fb3c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -94,10 +94,11 @@
final void run(OptimizationFeedback feedback, ExecutorService executorService)
throws ExecutionException {
// Filter out candidates based on the information we collected while examining methods.
- finalEligibilityCheck();
+ Map<CandidateInfo, ProgramMethodSet> materializedReferencedFromCollections =
+ finalEligibilityCheck();
// Prepare interim data.
- prepareCandidates();
+ prepareCandidates(materializedReferencedFromCollections);
// Enqueue all host class initializers (only remove instantiations).
ProgramMethodSet hostClassInitMethods = ProgramMethodSet.create();
@@ -147,11 +148,12 @@
classStaticizer.candidates.clear();
}
- private void finalEligibilityCheck() {
+ private Map<CandidateInfo, ProgramMethodSet> finalEligibilityCheck() {
+ Map<CandidateInfo, ProgramMethodSet> materializedReferencedFromCollections =
+ new IdentityHashMap<>();
Set<Phi> visited = Sets.newIdentityHashSet();
Set<Phi> trivialPhis = Sets.newIdentityHashSet();
- Iterator<Entry<DexType, CandidateInfo>> it =
- classStaticizer.candidates.entrySet().iterator();
+ Iterator<Entry<DexType, CandidateInfo>> it = classStaticizer.candidates.entrySet().iterator();
while (it.hasNext()) {
Entry<DexType, CandidateInfo> entry = it.next();
DexType candidateType = entry.getKey();
@@ -222,8 +224,13 @@
continue;
}
- ProgramMethodSet referencedFrom = info.referencedFrom.asLongLivedBuilder().build(appView);
- info.referencedFrom = referencedFrom;
+ ProgramMethodSet referencedFrom;
+ if (classStaticizer.referencedFrom.containsKey(info)) {
+ referencedFrom = classStaticizer.referencedFrom.remove(info).build(appView);
+ materializedReferencedFromCollections.put(info, referencedFrom);
+ } else {
+ referencedFrom = ProgramMethodSet.empty();
+ }
// CHECK: references to field read usages are fixable.
boolean fixableFieldReads = true;
@@ -275,9 +282,11 @@
continue;
}
}
+ return materializedReferencedFromCollections;
}
- private void prepareCandidates() {
+ private void prepareCandidates(
+ Map<CandidateInfo, ProgramMethodSet> materializedReferencedFromCollections) {
Set<DexEncodedMethod> removedInstanceMethods = Sets.newIdentityHashSet();
for (CandidateInfo candidate : classStaticizer.candidates.values()) {
@@ -304,7 +313,8 @@
if (getter != null) {
singletonGetters.put(getter.method, candidate);
}
- ProgramMethodSet referencedFrom = candidate.referencedFrom.asSet();
+ ProgramMethodSet referencedFrom =
+ materializedReferencedFromCollections.getOrDefault(candidate, ProgramMethodSet.empty());
assert validMethods(referencedFrom);
referencingExtraMethods.addAll(referencedFrom);
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java b/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java
index 269b24d..b76c14c 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java
@@ -12,7 +12,7 @@
import com.google.common.collect.Sets;
import java.util.Set;
-public class LongLivedProgramMethodSetBuilder implements ProgramMethodSetOrBuilder {
+public class LongLivedProgramMethodSetBuilder {
private Set<DexMethod> methods = Sets.newIdentityHashSet();
@@ -39,14 +39,4 @@
public boolean isEmpty() {
return methods.isEmpty();
}
-
- @Override
- public boolean isLongLivedBuilder() {
- return true;
- }
-
- @Override
- public LongLivedProgramMethodSetBuilder asLongLivedBuilder() {
- return this;
- }
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
index d288177..1795899 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
@@ -18,7 +18,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
-public class ProgramMethodSet implements ProgramMethodSetOrBuilder, Iterable<ProgramMethod> {
+public class ProgramMethodSet implements Iterable<ProgramMethod> {
private static final ProgramMethodSet EMPTY = new ProgramMethodSet(ImmutableMap.of());
@@ -68,11 +68,6 @@
backing.putAll(methods.backing);
}
- @Override
- public ProgramMethodSet asSet() {
- return this;
- }
-
public boolean createAndAdd(DexProgramClass clazz, DexEncodedMethod definition) {
return add(new ProgramMethod(clazz, definition));
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java
deleted file mode 100644
index f7298be..0000000
--- a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2020, 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.utils.collections;
-
-public interface ProgramMethodSetOrBuilder {
-
- default boolean isLongLivedBuilder() {
- return false;
- }
-
- default LongLivedProgramMethodSetBuilder asLongLivedBuilder() {
- return null;
- }
-
- default ProgramMethodSet asSet() {
- return null;
- }
-}