Fix NullPointerException when inlining outline

Bug: b/514117718
Change-Id: Iafcc8cfc8a95576d8c53927a7a829192c855dea2
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 91739b4..ace93b2 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -241,6 +241,21 @@
           translatedPosition = result;
         }
       }
+      // Translation can fail for non-throwing outline instructions. In this case, pick the best
+      // position.
+      if (translatedPosition == null) {
+        int bestLine = Integer.MAX_VALUE;
+        Position bestPosition = null;
+        for (int i = 0; i < translation.size(); i++) {
+          int currentLine = translation.getKey(i);
+          Position currentPosition = translation.getValue(i);
+          if (outlineLine < currentLine && currentLine < bestLine && currentPosition != null) {
+            bestLine = currentLine;
+            bestPosition = currentPosition;
+          }
+        }
+        translatedPosition = bestPosition;
+      }
       assert translatedPosition != null;
       // If the caller has outer frames compose them with the translated position.
       if (callerPosition.hasCallerPosition()) {
diff --git a/src/main/java/com/android/tools/r8/utils/Int2StructuralItemArrayMap.java b/src/main/java/com/android/tools/r8/utils/Int2StructuralItemArrayMap.java
index 8f5f5d3..05c00c3 100644
--- a/src/main/java/com/android/tools/r8/utils/Int2StructuralItemArrayMap.java
+++ b/src/main/java/com/android/tools/r8/utils/Int2StructuralItemArrayMap.java
@@ -32,6 +32,14 @@
     return this;
   }
 
+  public int getKey(int index) {
+    return keys[index];
+  }
+
+  public T getValue(int index) {
+    return values.get(index);
+  }
+
   @Override
   public StructuralMapping<Int2StructuralItemArrayMap<T>> getStructuralMapping() {
     return Int2StructuralItemArrayMap::specify;
@@ -57,6 +65,10 @@
     }
   }
 
+  public int size() {
+    return keys.length;
+  }
+
   @SuppressWarnings("unchecked")
   @Override
   public boolean equals(Object other) {
diff --git a/src/test/java8/ir/com/android/tools/r8/ir/optimize/inliner/SingleCallerInlineOutlineWithNonThrowingPreludeTest.java b/src/test/java8/ir/com/android/tools/r8/ir/optimize/inliner/SingleCallerInlineOutlineWithNonThrowingPreludeTest.java
index 3e90293..700ca3e 100644
--- a/src/test/java8/ir/com/android/tools/r8/ir/optimize/inliner/SingleCallerInlineOutlineWithNonThrowingPreludeTest.java
+++ b/src/test/java8/ir/com/android/tools/r8/ir/optimize/inliner/SingleCallerInlineOutlineWithNonThrowingPreludeTest.java
@@ -11,7 +11,6 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.utils.codeinspector.AssertUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.android.tools.r8.utils.internal.BooleanUtils;
@@ -39,62 +38,57 @@
 
   @Test
   public void test() throws Exception {
-    AssertUtils.assertFailsCompilationIf(
-        allowInliningOfOutlines,
-        () ->
-            testForR8(parameters)
-                .addInnerClasses(getClass())
-                .addKeepMainRule(Main.class)
-                .addOptionsModification(
-                    options -> {
-                      options.outline.threshold = 2;
-                      options.outline.minSize = 2;
-                      options.getTestingOptions().allowInliningOfOutlines = allowInliningOfOutlines;
-                    })
-                .collectSyntheticItems()
-                .enableInliningAnnotations()
-                .compile()
-                .inspectWithSyntheticItems(
-                    (inspector, syntheticItems) -> {
-                      ClassSubject printerClassSubject = inspector.clazz(Printer.class);
-                      assertThat(printerClassSubject, isPresent());
+    testForR8(parameters)
+        .addInnerClasses(getClass())
+        .addKeepMainRule(Main.class)
+        .addOptionsModification(
+            options -> {
+              options.outline.threshold = 2;
+              options.outline.minSize = 2;
+              options.getTestingOptions().allowInliningOfOutlines = allowInliningOfOutlines;
+            })
+        .collectSyntheticItems()
+        .enableInliningAnnotations()
+        .compile()
+        .inspectWithSyntheticItems(
+            (inspector, syntheticItems) -> {
+              ClassSubject printerClassSubject = inspector.clazz(Printer.class);
+              assertThat(printerClassSubject, isPresent());
 
-                      MethodSubject helloMethodSubject =
-                          printerClassSubject.uniqueMethodWithOriginalName("hello");
-                      assertThat(helloMethodSubject, isPresent());
+              MethodSubject helloMethodSubject =
+                  printerClassSubject.uniqueMethodWithOriginalName("hello");
+              assertThat(helloMethodSubject, isPresent());
 
-                      MethodSubject worldMethodSubject =
-                          printerClassSubject.uniqueMethodWithOriginalName("world");
-                      assertThat(worldMethodSubject, isPresent());
+              MethodSubject worldMethodSubject =
+                  printerClassSubject.uniqueMethodWithOriginalName("world");
+              assertThat(worldMethodSubject, isPresent());
 
-                      ClassSubject mainClassSubject = inspector.clazz(Main.class);
-                      assertThat(mainClassSubject, isPresent());
+              ClassSubject mainClassSubject = inspector.clazz(Main.class);
+              assertThat(mainClassSubject, isPresent());
 
-                      MethodSubject outlineCandidateMethodSubject =
-                          mainClassSubject.uniqueMethodWithOriginalName("outlineCandidate");
-                      assertThat(outlineCandidateMethodSubject, isPresent());
+              MethodSubject outlineCandidateMethodSubject =
+                  mainClassSubject.uniqueMethodWithOriginalName("outlineCandidate");
+              assertThat(outlineCandidateMethodSubject, isPresent());
 
-                      ClassSubject outlineClassSubject =
-                          inspector.clazz(syntheticItems.syntheticOutlineClass(Main.class, 0));
-                      // Note that the outline class is present even when `allowInliningOfOutlines`
-                      // is true, since we do not run another round of tree shaking after the single
-                      // caller inliner pass.
-                      assertThat(outlineClassSubject, isPresent());
+              ClassSubject outlineClassSubject =
+                  inspector.clazz(syntheticItems.syntheticOutlineClass(Main.class, 0));
+              // Note that the outline class is present even when `allowInliningOfOutlines`
+              // is true, since we do not run another round of tree shaking after the single
+              // caller inliner pass.
+              assertThat(outlineClassSubject, isPresent());
 
-                      if (allowInliningOfOutlines) {
-                        assertThat(
-                            outlineCandidateMethodSubject,
-                            allOf(
-                                invokesMethod(helloMethodSubject),
-                                invokesMethod(worldMethodSubject)));
-                      } else {
-                        assertThat(
-                            outlineCandidateMethodSubject,
-                            invokesMethod(outlineClassSubject.uniqueMethod()));
-                      }
-                    })
-                .run(parameters.getRuntime(), Main.class)
-                .assertSuccessWithOutputLines("Hello 3.0, world!"));
+              if (allowInliningOfOutlines) {
+                assertThat(
+                    outlineCandidateMethodSubject,
+                    allOf(invokesMethod(helloMethodSubject), invokesMethod(worldMethodSubject)));
+              } else {
+                assertThat(
+                    outlineCandidateMethodSubject,
+                    invokesMethod(outlineClassSubject.uniqueMethod()));
+              }
+            })
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello 3.0, world!");
   }
 
   static class Main {