Merge "Add support for sharding tests"
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index ff330e1..9dff882 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -581,7 +581,8 @@
               // target.
               return;
             }
-            if (!dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
+            if (guard != dexItemFactory.catchAllType
+                && !dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
               // TODO(christofferqa): Consider updating previous dominator tree instead of
               // rebuilding it from scratch.
               DominatorTree dominatorTree = new DominatorTree(code, MAY_HAVE_UNREACHABLE_BLOCKS);
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index a35ce71..34955b6 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -894,7 +894,7 @@
               "lang.String.getBytesLjava_lang_String.String_getBytes_A14",
               match(artRuntimesUpTo(Runtime.ART_V7_0_0)))
           .put("lang.String.splitLjava_lang_String.String_split_A01", any())
-          .put("lang.String.getBytesII_BI.String_getBytes_A03", any())
+          .put("lang.String.getBytesII_BI.String_getBytes_A03", anyDexVm())
           .put("lang.String.getBytesII_BI.String_getBytes_A02", anyDexVm())
           .put("lang.String.toLowerCaseLjava_util_Locale.String_toLowerCase_A01", any())
           .put("lang.String.Constructor_BIILjava_nio_charset_Charset.String_Constructor_A01", any())
@@ -1690,6 +1690,54 @@
               "lang.String.replaceAllLjava_lang_StringLjava_lang_String.String_replaceAll_A01",
               cf())
           .put("lang.System.inheritedChannel.System_inheritedChannel_A01", cf())
+          // TODO(b/124842490): Failing with change to JDK 9 for the classfile backend.
+          .put("lang.Character.isSpaceCharC.Character_isSpaceChar_A01", cf())
+          .put("lang.Character.isSpaceCharI.Character_isSpaceChar_A01", cf())
+          .put("lang.Character.isWhitespaceI.Character_isWhitespace_A01", cf())
+          .put("lang.Class.getConstructors.Class_getConstructors_A01", cf())
+          .put("lang.Class.getPackage.Class_getPackage_A01", cf())
+          .put(
+              "lang.Class.getResourceAsStreamLjava_lang_String.Class_getResourceAsStream_A01", cf())
+          .put("lang.Class.getResourceLjava_lang_String.Class_getResource_A01", cf())
+          .put(
+              "lang.ClassLoader.defineClassLjava_lang_StringLjava_nio_ByteBufferLjava_security_ProtectionDomain.ClassLoader_defineClass_A01",
+              cf())
+          .put(
+              "lang.ClassLoader.defineClassLjava_lang_String_BII.ClassLoader_defineClass_A01", cf())
+          .put(
+              "lang.ClassLoader.defineClassLjava_lang_String_BIILjava_security_ProtectionDomain.ClassLoader_defineClass_A01",
+              cf())
+          .put("lang.ClassLoader.defineClass_BII.ClassLoader_defineClass_A01", cf())
+          .put(
+              "lang.ClassLoader.definePackageLjava_lang_String6Ljava_net_URL.ClassLoader_definePackage_A03",
+              cf())
+          .put("lang.ClassLoader.getPackages.ClassLoader_getPackages_A01", cf())
+          .put("lang.Package.getImplementationVersion.Package_getImplementationVersion_A01", cf())
+          .put(
+              "lang.SecurityManager.checkAwtEventQueueAccess.SecurityManager_checkAwtEventQueueAccess_A01",
+              cf())
+          .put(
+              "lang.SecurityManager.checkSystemClipboardAccess.SecurityManager_checkSystemClipboardAccess_A01",
+              cf())
+          .put(
+              "lang.SecurityManager.checkTopLevelWindowLjava_lang_Object.SecurityManager_checkTopLevelWindow_A01",
+              cf())
+          .put("lang.StrictMath.toDegreesD.StrictMath_toDegrees_A01", cf())
+          .put("lang.StrictMath.toRadiansD.StrictMath_toRadians_A01", cf())
+          .put("lang.String.matchesLjava_lang_String.String_matches_A01", cf())
+          .put("lang.StringBuffer.append_CII.StringBuffer_append_A03", cf())
+          .put("lang.System.getProperties.System_getProperties_A02", cf())
+          .put("lang.System.getPropertyLjava_lang_String.System_getProperty_A02", cf())
+          .put(
+              "lang.System.getPropertyLjava_lang_StringLjava_lang_String.System_getProperty_A02",
+              cf())
+          .put("lang.Throwable.serialization.Throwable_serialization_A01", cf())
+          .put("lang.ref.ReferenceQueue.poll.ReferenceQueue_poll_A01", cf())
+          .put("lang.ref.ReferenceQueue.remove.ReferenceQueue_remove_A01", cf())
+          .put("lang.ref.ReferenceQueue.removeJ.ReferenceQueue_remove_A01", cf())
+          .put("lang.reflect.Constructor.toGenericString.Constructor_toGenericString_A01", cf())
+          .put("lang.reflect.Field.getGenericType.Field_getGenericType_A01", cf())
+          .put("lang.reflect.Field.toGenericString.Field_toGenericString_A01", cf())
           .build(); // end of failuresToTriage
 
   public static final Multimap<String, TestCondition> flakyWhenRun =
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
new file mode 100644
index 0000000..f082098
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/uninstantiatedtypes/SynchronizedMethodTest.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2019, 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.ir.optimize.uninstantiatedtypes;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Test;
+
+public class SynchronizedMethodTest extends TestBase {
+
+  @Test
+  public void test() throws Exception {
+    String expectedOutput = StringUtils.lines("In A.m()", "Got NullPointerException");
+    CodeInspector inspector =
+        testForR8(Backend.DEX)
+            .addInnerClasses(SynchronizedMethodTest.class)
+            .addKeepMainRule(TestClass.class)
+            .enableInliningAnnotations()
+            .enableMergeAnnotations()
+            .run(TestClass.class)
+            .assertSuccessWithOutput(expectedOutput)
+            .inspector();
+
+    ClassSubject clazz = inspector.clazz(A.class);
+    MethodSubject method = clazz.uniqueMethodWithName("m");
+
+    // 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.
+    List<InstructionSubject> throwInstructions =
+        method
+            .streamInstructions()
+            .filter(InstructionSubject::isThrow)
+            .collect(Collectors.toList());
+    assertEquals(2, 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));
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      try {
+        test(new A());
+      } catch (NullPointerException e) {
+        System.out.println("Got NullPointerException");
+      }
+    }
+
+    @NeverInline
+    private static void test(A obj) {
+      obj.m();
+    }
+  }
+
+  static class A {
+
+    @NeverInline
+    static Uninstantiated createUninstantiated() {
+      return null;
+    }
+
+    @NeverInline
+    public synchronized void m() {
+      System.out.println("In A.m()");
+      A.createUninstantiated().m();
+    }
+  }
+
+  static class Uninstantiated {
+    public void m() {
+      System.out.println("In Uninstantiated.m()");
+    }
+  }
+}