Reland "Remove legacy debugging code from class inliner"
This reverts commit bf6add1bf9d798b1fdf46cfbed9f1c431f933172.
Change-Id: Icbc6942f0f258e21913804acb6f1e3add788d624
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index f172fa9..6f945bd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -27,64 +27,25 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.inliner.InliningIRProvider;
import com.android.tools.r8.ir.optimize.string.StringOptimizer;
-import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
-import com.google.common.collect.Streams;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
public final class ClassInliner {
enum EligibilityStatus {
- // Used by InlineCandidateProcessor#isInstanceEligible
- NON_CLASS_TYPE,
- NOT_A_SINGLETON_FIELD,
- RETRIEVAL_MAY_HAVE_SIDE_EFFECTS,
- UNKNOWN_TYPE,
- UNUSED_INSTANCE,
-
- // Used by isClassEligible
- NON_PROGRAM_CLASS,
- ABSTRACT_OR_INTERFACE,
- NEVER_CLASS_INLINE,
- IS_PINNED_TYPE,
- HAS_FINALIZER,
- TRIGGER_CLINIT,
-
- // Used by InlineCandidateProcessor#isClassAndUsageEligible
- HAS_CLINIT,
- HAS_INSTANCE_FIELDS,
- NON_FINAL_TYPE,
- NOT_INITIALIZED_AT_INIT,
- PINNED_FIELD,
-
- ELIGIBLE
+ ELIGIBLE,
+ NOT_ELIGIBLE
}
private final ConcurrentHashMap<DexClass, EligibilityStatus> knownClasses =
new ConcurrentHashMap<>();
- private void logEligibilityStatus(
- DexEncodedMethod context, Instruction root, EligibilityStatus status) {
- if (Log.ENABLED && Log.isLoggingEnabledFor(ClassInliner.class)) {
- Log.info(getClass(), "At %s,", context.toSourceString());
- Log.info(getClass(), "ClassInlining eligibility of `%s`: %s.", root, status);
- }
- }
-
- private void logIneligibleUser(
- DexEncodedMethod context, Instruction root, InstructionOrPhi ineligibleUser) {
- if (Log.ENABLED && Log.isLoggingEnabledFor(ClassInliner.class)) {
- Log.info(getClass(), "At %s,", context.toSourceString());
- Log.info(getClass(), "Ineligible user of `%s`: `%s`.", root, ineligibleUser);
- }
- }
-
// Process method code and inline eligible class instantiations, in short:
//
// - collect all 'new-instance' and 'static-get' instructions (called roots below) in
@@ -176,9 +137,7 @@
// Collect all the new-instance and static-get instructions in the code before inlining.
List<Instruction> roots =
- Streams.stream(code.instructionIterator())
- .filter(insn -> insn.isNewInstance() || insn.isStaticGet())
- .collect(Collectors.toList());
+ Lists.newArrayList(code.instructions(insn -> insn.isNewInstance() || insn.isStaticGet()));
// We loop inlining iterations until there was no inlining, but still use same set
// of roots to avoid infinite inlining. Looping makes possible for some roots to
@@ -204,13 +163,11 @@
// Assess eligibility of instance and class.
EligibilityStatus status = processor.isInstanceEligible();
if (status != EligibilityStatus.ELIGIBLE) {
- logEligibilityStatus(code.method(), root, status);
// This root will never be inlined.
rootsIterator.remove();
continue;
}
status = processor.isClassAndUsageEligible();
- logEligibilityStatus(code.method(), root, status);
if (status != EligibilityStatus.ELIGIBLE) {
// This root will never be inlined.
rootsIterator.remove();
@@ -221,7 +178,6 @@
InstructionOrPhi ineligibleUser = processor.areInstanceUsersEligible(defaultOracle);
if (ineligibleUser != null) {
// This root may succeed if users change in future.
- logIneligibleUser(code.method(), root, ineligibleUser);
continue;
}
@@ -309,7 +265,8 @@
}
}
- private EligibilityStatus isClassEligible(AppView<AppInfoWithLiveness> appView, DexClass clazz) {
+ private EligibilityStatus isClassEligible(
+ AppView<AppInfoWithLiveness> appView, DexProgramClass clazz) {
EligibilityStatus eligible = knownClasses.get(clazz);
if (eligible == null) {
EligibilityStatus computed = computeClassEligible(appView, clazz);
@@ -325,21 +282,12 @@
// - does not declare finalizer
// - does not trigger any static initializers except for its own
private EligibilityStatus computeClassEligible(
- AppView<AppInfoWithLiveness> appView, DexClass clazz) {
- if (clazz == null) {
- return EligibilityStatus.UNKNOWN_TYPE;
- }
- if (clazz.isNotProgramClass()) {
- return EligibilityStatus.NON_PROGRAM_CLASS;
- }
- if (clazz.isAbstract() || clazz.isInterface()) {
- return EligibilityStatus.ABSTRACT_OR_INTERFACE;
- }
- if (appView.appInfo().neverClassInline.contains(clazz.type)) {
- return EligibilityStatus.NEVER_CLASS_INLINE;
- }
- if (appView.appInfo().isPinned(clazz.type)) {
- return EligibilityStatus.IS_PINNED_TYPE;
+ AppView<AppInfoWithLiveness> appView, DexProgramClass clazz) {
+ if (clazz == null
+ || clazz.isAbstract()
+ || clazz.isInterface()
+ || !appView.appInfo().isClassInliningAllowed(clazz)) {
+ return EligibilityStatus.NOT_ELIGIBLE;
}
// Class must not define finalizer.
@@ -347,13 +295,13 @@
for (DexEncodedMethod method : clazz.virtualMethods()) {
if (method.method.name == dexItemFactory.finalizeMethodName
&& method.method.proto == dexItemFactory.objectMembers.finalize.proto) {
- return EligibilityStatus.HAS_FINALIZER;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
}
// Check for static initializers in this class or any of interfaces it implements.
if (clazz.initializationOfParentTypesMayHaveSideEffects(appView)) {
- return EligibilityStatus.TRIGGER_CLINIT;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
return EligibilityStatus.ELIGIBLE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index f597582..c8cc00e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -95,7 +94,7 @@
private final AppView<AppInfoWithLiveness> appView;
private final DexItemFactory dexItemFactory;
private final Inliner inliner;
- private final Function<DexClass, EligibilityStatus> isClassEligible;
+ private final Function<DexProgramClass, EligibilityStatus> isClassEligible;
private final MethodProcessor methodProcessor;
private final ProgramMethod method;
private final Instruction root;
@@ -122,7 +121,7 @@
InlineCandidateProcessor(
AppView<AppInfoWithLiveness> appView,
Inliner inliner,
- Function<DexClass, EligibilityStatus> isClassEligible,
+ Function<DexProgramClass, EligibilityStatus> isClassEligible,
MethodProcessor methodProcessor,
ProgramMethod method,
Instruction root) {
@@ -157,20 +156,20 @@
EligibilityStatus isInstanceEligible() {
eligibleInstance = root.outValue();
if (eligibleInstance == null) {
- return EligibilityStatus.UNUSED_INSTANCE;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
if (root.isNewInstance()) {
eligibleClass = asProgramClassOrNull(appView.definitionFor(root.asNewInstance().clazz));
if (eligibleClass == null) {
- return EligibilityStatus.UNKNOWN_TYPE;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
if (eligibleClass.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of the current context are guaranteed to be initialized.
type -> appView.isSubtype(method.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet())) {
- return EligibilityStatus.HAS_CLINIT;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
return EligibilityStatus.ELIGIBLE;
}
@@ -179,19 +178,19 @@
StaticGet staticGet = root.asStaticGet();
if (staticGet.instructionMayHaveSideEffects(appView, method)) {
- return EligibilityStatus.RETRIEVAL_MAY_HAVE_SIDE_EFFECTS;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
DexEncodedField field = appView.appInfo().resolveField(staticGet.getField()).getResolvedField();
FieldOptimizationInfo optimizationInfo = field.getOptimizationInfo();
ClassTypeElement dynamicLowerBoundType = optimizationInfo.getDynamicLowerBoundType();
if (dynamicLowerBoundType == null
|| !dynamicLowerBoundType.equals(optimizationInfo.getDynamicUpperBoundType())) {
- return EligibilityStatus.NOT_A_SINGLETON_FIELD;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
eligibleClass =
asProgramClassOrNull(appView.definitionFor(dynamicLowerBoundType.getClassType()));
if (eligibleClass == null) {
- return EligibilityStatus.UNKNOWN_TYPE;
+ return EligibilityStatus.NOT_ELIGIBLE;
}
return EligibilityStatus.ELIGIBLE;
}
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 d5bc317..7c6d911 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -905,6 +905,10 @@
return this;
}
+ public boolean isClassInliningAllowed(DexProgramClass clazz) {
+ return !isPinned(clazz) && !neverClassInline.contains(clazz.getType());
+ }
+
public boolean isMinificationAllowed(DexReference reference) {
return options().isMinificationEnabled()
&& keepInfo.getInfo(reference, this).isMinificationAllowed(options());
@@ -938,6 +942,11 @@
return keepInfo.isPinned(reference, this);
}
+ public boolean isPinned(DexDefinition definition) {
+ assert definition != null;
+ return isPinned(definition.toReference());
+ }
+
public boolean hasPinnedInstanceInitializer(DexType type) {
assert type.isClassType();
DexProgramClass clazz = asProgramClassOrNull(definitionFor(type));