Update class inliner to check if method is eligible for force inlining

Change-Id: I93fffb195153196f1f8961bc4f3cc6f3ebbd1055
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 769923d..38b0b5f 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
@@ -23,7 +23,6 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
-import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
 import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
@@ -48,7 +47,6 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.Inliner;
-import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
 import com.android.tools.r8.ir.optimize.Inliner.InliningInfo;
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
 import com.android.tools.r8.ir.optimize.InliningOracle;
@@ -1171,15 +1169,12 @@
 
     // Check if the method is inline-able by standard inliner.
     InliningOracle oracle = defaultOracle.get();
-    InlineAction inlineAction =
-        oracle.computeInlining(
-            invoke,
-            resolutionResult,
-            singleTarget,
-            method,
-            ClassInitializationAnalysis.trivial(),
-            NopWhyAreYouNotInliningReporter.getInstance());
-    if (inlineAction == null) {
+    if (!oracle.passesInliningConstraints(
+        invoke,
+        resolutionResult,
+        singleTarget,
+        Reason.SIMPLE,
+        NopWhyAreYouNotInliningReporter.getInstance())) {
       return false;
     }
 
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
index 6f3c8f8..dbc83c8 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceCollisionTest.java
@@ -99,6 +99,7 @@
     }
   }
 
+  @NeverClassInline
   public static class C extends Parent implements I {
     @Override
     @NeverInline
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
index 627838f..169a59b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/TreeFixerInterfaceFixedCollisionTest.java
@@ -99,6 +99,7 @@
     }
   }
 
+  @NeverClassInline
   public static class C extends Parent implements I {
     @Override
     @NeverInline
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
index 635ec43..11164b1 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideAbstractMethodWithDefaultTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestParameters;
@@ -15,6 +16,7 @@
 import org.junit.Test;
 
 public class OverrideAbstractMethodWithDefaultTest extends HorizontalClassMergingTestBase {
+
   public OverrideAbstractMethodWithDefaultTest(
       TestParameters parameters, boolean enableHorizontalClassMerging) {
     super(parameters, enableHorizontalClassMerging);
@@ -29,6 +31,7 @@
             options ->
                 options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
         .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .setMinApi(parameters.getApiLevel())
         .addHorizontallyMergedClassesInspectorIf(
@@ -73,8 +76,10 @@
     }
   }
 
+  @NeverClassInline
   static class C1 extends B1 implements J {}
 
+  @NeverClassInline
   static class C2 extends B2 {}
 
   static class Main {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
index 0e3a098..15ca564 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultMethodTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestParameters;
@@ -29,6 +30,7 @@
             options ->
                 options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
         .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .setMinApi(parameters.getApiLevel())
         .addHorizontallyMergedClassesInspectorIf(
@@ -52,8 +54,10 @@
     }
   }
 
+  @NeverClassInline
   public static class A implements I {}
 
+  @NeverClassInline
   public static class B implements I {
     @NeverInline
     @Override
@@ -69,6 +73,7 @@
     }
   }
 
+  @NeverClassInline
   public static class C extends A implements J {}
 
   public static class Main {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
index fa2dcb2..2aea3d0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/dispatch/OverrideDefaultOnSuperMethodTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoUnusedInterfaceRemoval;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -30,6 +31,7 @@
             options ->
                 options.horizontalClassMergerOptions().enableIf(enableHorizontalClassMerging))
         .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
         .enableNoUnusedInterfaceRemovalAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .setMinApi(parameters.getApiLevel())
@@ -58,8 +60,10 @@
 
   public static class Parent implements I {}
 
+  @NeverClassInline
   public static class A extends Parent {}
 
+  @NeverClassInline
   public static class B extends Parent {
     @NeverInline
     @Override
@@ -68,6 +72,7 @@
     }
   }
 
+  @NeverClassInline
   @NoUnusedInterfaceRemoval
   @NoVerticalClassMerging
   interface J extends I {
@@ -76,6 +81,7 @@
     }
   }
 
+  @NeverClassInline
   public static class C extends A implements J {}
 
   public static class Main {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
index f489112..209f9f9 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/InterfaceMethodTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -48,6 +49,7 @@
             .addInnerClasses(InterfaceMethodTest.class)
             .addKeepMainRule(TestClass.class)
             .enableInliningAnnotations()
+            .enableNeverClassInliningAnnotations()
             .enableNoVerticalClassMergingAnnotations()
             .enableNoHorizontalClassMergingAnnotations()
             .run(TestClass.class)
@@ -84,6 +86,7 @@
     Uninstantiated m();
   }
 
+  @NeverClassInline
   static class A implements I {
 
     @NeverInline
@@ -97,6 +100,7 @@
   // The purpose of this class is merely to avoid that the invoke-interface instruction in
   // TestClass.test() gets devirtualized to an invoke-virtual instruction. Otherwise the method
   // I.m() would not be present in the output.
+  @NeverClassInline
   @NoHorizontalClassMerging
   static class B implements I {
 
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/NestedInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/NestedInterfaceMethodTest.java
index 7890640..3cbaed0 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/NestedInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/NestedInterfaceMethodTest.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestBase;
@@ -49,6 +50,7 @@
             .addInnerClasses(NestedInterfaceMethodTest.class)
             .addKeepMainRule(TestClass.class)
             .enableInliningAnnotations()
+            .enableNeverClassInliningAnnotations()
             .enableNoVerticalClassMergingAnnotations()
             .addOptionsModification(
                 options -> {
@@ -91,6 +93,7 @@
   @NoVerticalClassMerging
   interface J extends I {}
 
+  @NeverClassInline
   static class A implements J {
 
     @Override
@@ -100,11 +103,13 @@
     }
   }
 
+  @NeverClassInline
   static class B extends A {}
 
   // The purpose of this class is merely to avoid that the invoke-interface instruction in
   // TestClass.test() gets devirtualized to an invoke-virtual instruction. Otherwise the method
   // I.m() would not be present in the output.
+  @NeverClassInline
   static class C extends A {}
 
   static class Uninstantiated {}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/SynchronizedMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/SynchronizedMethodTest.java
index 88459a5..a04df37 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/SynchronizedMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/SynchronizedMethodTest.java
@@ -4,11 +4,17 @@
 
 package com.android.tools.r8.ir.optimize.uninstantiatedtypes;
 
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -18,23 +24,41 @@
 import java.util.List;
 import java.util.stream.Collectors;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class SynchronizedMethodTest extends TestBase {
 
+  private final TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public SynchronizedMethodTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
   @Test
   public void test() throws Exception {
     String expectedOutput = StringUtils.lines("In A.m()", "Got NullPointerException");
     CodeInspector inspector =
-        testForR8(Backend.DEX)
+        testForR8(parameters.getBackend())
             .addInnerClasses(SynchronizedMethodTest.class)
             .addKeepMainRule(TestClass.class)
             .enableInliningAnnotations()
-            .run(TestClass.class)
+            .enableNeverClassInliningAnnotations()
+            .setMinApi(parameters.getApiLevel())
+            .run(parameters.getRuntime(), TestClass.class)
             .assertSuccessWithOutput(expectedOutput)
             .inspector();
 
     ClassSubject clazz = inspector.clazz(A.class);
     MethodSubject method = clazz.uniqueMethodWithName("m");
+    assertThat(method, isPresent());
 
     // The invoke on the uninstantiated turns into a "throw null", and the synchronized method
     // already have a throw instruction in the catch all handler ensuring monitor exit is called.
@@ -43,24 +67,30 @@
             .streamInstructions()
             .filter(InstructionSubject::isThrow)
             .collect(Collectors.toList());
-    assertEquals(2, throwInstructions.size());
+    assertEquals(1 + BooleanUtils.intValue(parameters.isDexRuntime()), throwInstructions.size());
 
-    // The inserted "throw null" should still be covered by the catch all to ensure monitor exit
-    // is called.
-    List<InstructionSubject> catchAllCoveredInstructions = new ArrayList<>();
-    method.iterateTryCatches().forEachRemaining(tryCatchSubject -> {
-      if (tryCatchSubject.hasCatchAll()) {
-        catchAllCoveredInstructions.addAll(
-        throwInstructions
-            .stream()
-            .filter(
-                throwInstruction ->
-                    tryCatchSubject.getRange().includes(throwInstruction.getOffset(method)))
-            .collect(Collectors.toList()));
-      }
-    });
-    assertEquals(1, catchAllCoveredInstructions.size());
-    assertSame(throwInstructions.get(0), catchAllCoveredInstructions.get(0));
+    if (parameters.isDexRuntime()) {
+      // The inserted "throw null" should still be covered by the catch all to ensure monitor exit
+      // is called.
+      List<InstructionSubject> catchAllCoveredInstructions = new ArrayList<>();
+      method
+          .iterateTryCatches()
+          .forEachRemaining(
+              tryCatchSubject -> {
+                if (tryCatchSubject.hasCatchAll()) {
+                  catchAllCoveredInstructions.addAll(
+                      throwInstructions.stream()
+                          .filter(
+                              throwInstruction ->
+                                  tryCatchSubject
+                                      .getRange()
+                                      .includes(throwInstruction.getOffset(method)))
+                          .collect(Collectors.toList()));
+                }
+              });
+      assertEquals(1, catchAllCoveredInstructions.size());
+      assertSame(throwInstructions.get(0), catchAllCoveredInstructions.get(0));
+    }
   }
 
   static class TestClass {
@@ -79,6 +109,7 @@
     }
   }
 
+  @NeverClassInline
   static class A {
 
     @NeverInline
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/unusedinterfaces/UnusedInterfaceWithDefaultMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/unusedinterfaces/UnusedInterfaceWithDefaultMethodTest.java
index 52131b3..768fbd6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/unusedinterfaces/UnusedInterfaceWithDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/unusedinterfaces/UnusedInterfaceWithDefaultMethodTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestBase;
@@ -40,6 +41,7 @@
         .addInnerClasses(UnusedInterfaceWithDefaultMethodTest.class)
         .addKeepMainRule(TestClass.class)
         .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .setMinApi(parameters.getApiLevel())
         .compile()
@@ -94,5 +96,6 @@
     }
   }
 
+  @NeverClassInline
   static class A implements J {}
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
index ace926f..9246164 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnTargetedMethodTest.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.shaking.annotations;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoHorizontalClassMerging;
 import com.android.tools.r8.NoVerticalClassMerging;
@@ -55,6 +56,7 @@
         .addKeepMainRule(TestClass.class)
         .addKeepRuntimeVisibleAnnotations()
         .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
         .enableNoHorizontalClassMergingAnnotations()
         .enableNoVerticalClassMergingAnnotations()
         .noMinification()
@@ -94,6 +96,7 @@
     void targetedMethod();
   }
 
+  @NeverClassInline
   @NoHorizontalClassMerging
   static class InterfaceImpl implements Interface {
 
@@ -104,6 +107,7 @@
     }
   }
 
+  @NeverClassInline
   @NoHorizontalClassMerging
   static class OtherInterfaceImpl implements Interface {
 
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
index 5bb8e48..035ddf7 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByTwoMethods.java
@@ -5,6 +5,7 @@
 
 import static com.android.tools.r8.references.Reference.methodFromMethod;
 
+import com.android.tools.r8.NeverClassInline;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoVerticalClassMerging;
 import com.android.tools.r8.TestBase;
@@ -31,6 +32,7 @@
     }
   }
 
+  @NeverClassInline
   @NoVerticalClassMerging
   public static class B extends A {
     // Intermediate to A.
@@ -72,6 +74,7 @@
     GraphInspector inspector =
         testForR8(parameters.getBackend())
             .enableGraphInspector()
+            .enableNeverClassInliningAnnotations()
             .enableNoVerticalClassMergingAnnotations()
             .enableInliningAnnotations()
             .addKeepMainRule(TestClass.class)