Merge "Add isZero to Value"
diff --git a/build.gradle b/build.gradle
index 63513ce..7362238 100644
--- a/build.gradle
+++ b/build.gradle
@@ -565,6 +565,7 @@
             executable file("third_party/kotlin/kotlinc/bin/kotlinc");
         }
         args "-include-runtime"
+        args "-nowarn"
         args "-d"
         args "build/test/${kotlinHostJar}"
         args fileTree(dir: kotlinResourcesDir, include: '**/*.kt')
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
index 03c614a..5d382a3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
@@ -134,8 +134,7 @@
       return (sort == Type.OBJECT && otherSort == Type.ARRAY)
           || (sort == Type.ARRAY && otherSort == Type.OBJECT)
           || (sort == Type.OBJECT && otherSort == Type.OBJECT)
-          || (sort == Type.ARRAY && otherSort == Type.ARRAY
-              && isReferenceCompatible(getArrayElementType(type), getArrayElementType(other)));
+          || (sort == Type.ARRAY && otherSort == Type.ARRAY);
     }
   }
 
diff --git a/src/test/debugTestResources/Locals.java b/src/test/debugTestResources/Locals.java
index 109c43e..56613b3 100644
--- a/src/test/debugTestResources/Locals.java
+++ b/src/test/debugTestResources/Locals.java
@@ -300,6 +300,14 @@
     return -1;
   }
 
+  public static String regression65039701(boolean createIntNotLong) {
+    Object a = createIntNotLong ? new int[1] : new long[1];
+    if (a instanceof int []) {
+      ((int [])a)[0] = 0;
+    }
+    return "OK";
+  }
+
   public static void main(String[] args) {
     noLocals();
     unusedLocals();
@@ -318,5 +326,6 @@
     argumentLiveAtReturn(-1);
     switchRewriteToIfs(1);
     switchRewriteToSwitches(1);
+    regression65039701(true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index b2b77bc..7635e52 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -886,100 +886,6 @@
       setState(State.WaitForEvent);
     }
 
-    private boolean installBreakpoint(BreakpointInfo breakpointInfo) {
-      String classSignature = getClassSignature(breakpointInfo.className);
-      byte typeTag = TypeTag.CLASS;
-      long classId = getMirror().getClassID(classSignature);
-      if (classId == -1) {
-        // Is it an interface ?
-        classId = getMirror().getInterfaceID(classSignature);
-        typeTag = TypeTag.INTERFACE;
-      }
-      if (classId == -1) {
-        // The class is not ready yet. Request a CLASS_PREPARE to delay the installation of the
-        // breakpoint.
-        ReplyPacket replyPacket = getMirror().setClassPrepared(breakpointInfo.className);
-        int classPrepareRequestId = replyPacket.getNextValueAsInt();
-        assertAllDataRead(replyPacket);
-        events.put(Integer.valueOf(classPrepareRequestId),
-            new ClassPrepareHandler(breakpointInfo, classPrepareRequestId));
-        return false;
-      } else {
-        // Find the method.
-        long breakpointMethodId = findMethod(classId, breakpointInfo.methodName,
-            breakpointInfo.methodSignature);
-        long index = getMethodFirstCodeIndex(classId, breakpointMethodId);
-        Assert.assertTrue("No code in method", index >= 0);
-        // Install the breakpoint.
-        ReplyPacket replyPacket = getMirror()
-            .setBreakpoint(new Location(typeTag, classId, breakpointMethodId, index),
-                SuspendPolicy.ALL);
-        checkReplyPacket(replyPacket, "Breakpoint");
-        int breakpointId = replyPacket.getNextValueAsInt();
-        // Nothing to do on breakpoint
-        events.put(Integer.valueOf(breakpointId), new DefaultEventHandler());
-        return true;
-      }
-    }
-
-    private long findMethod(long classId, String methodName, String methodSignature) {
-      class MethodInfo {
-
-        final long methodId;
-        final String methodName;
-        final String methodSignature;
-
-        MethodInfo(long methodId, String methodName, String methodSignature) {
-          this.methodId = methodId;
-          this.methodName = methodName;
-          this.methodSignature = methodSignature;
-        }
-      }
-
-      boolean withGenericSignature = true;
-      CommandPacket commandPacket = new CommandPacket(ReferenceTypeCommandSet.CommandSetID,
-          ReferenceTypeCommandSet.MethodsWithGenericCommand);
-      commandPacket.setNextValueAsReferenceTypeID(classId);
-      ReplyPacket replyPacket = getMirror().performCommand(commandPacket);
-      if (replyPacket.getErrorCode() != Error.NONE) {
-        // Retry with older command ReferenceType.Methods
-        withGenericSignature = false;
-        commandPacket.setCommand(ReferenceTypeCommandSet.MethodsCommand);
-        replyPacket = getMirror().performCommand(commandPacket);
-        assert replyPacket.getErrorCode() == Error.NONE;
-      }
-
-      int methodsCount = replyPacket.getNextValueAsInt();
-      List<MethodInfo> methodInfos = new ArrayList<>(methodsCount);
-      for (int i = 0; i < methodsCount; ++i) {
-        long currentMethodId = replyPacket.getNextValueAsMethodID();
-        String currentMethodName = replyPacket.getNextValueAsString();
-        String currentMethodSignature = replyPacket.getNextValueAsString();
-        if (withGenericSignature) {
-          replyPacket.getNextValueAsString(); // skip generic signature
-        }
-        replyPacket.getNextValueAsInt(); // skip modifiers
-        methodInfos
-            .add(new MethodInfo(currentMethodId, currentMethodName, currentMethodSignature));
-      }
-      Assert.assertTrue(replyPacket.isAllDataRead());
-
-      // Only keep methods with the expected name.
-      methodInfos = methodInfos.stream()
-          .filter(m -> m.methodName.equals(methodName)).collect(
-              Collectors.toList());
-      if (methodSignature != null) {
-        methodInfos = methodInfos.stream()
-            .filter(m -> methodSignature.equals(m.methodSignature)).collect(
-                Collectors.toList());
-      }
-      Assert.assertFalse("No method named " + methodName + " found", methodInfos.isEmpty());
-      // There must be only one matching method
-      Assert.assertEquals("More than 1 method found: please specify a signature", 1,
-          methodInfos.size());
-      return methodInfos.get(0).methodId;
-    }
-
     private long getMethodFirstCodeIndex(long classId, long breakpointMethodId) {
       ReplyPacket replyPacket = getMirror().getLineTable(classId, breakpointMethodId);
       checkReplyPacket(replyPacket, "Failed to get method line table");
@@ -1019,6 +925,7 @@
         private final String className;
         private final String methodName;
         private final String methodSignature;
+        private boolean requestedClassPrepare = false;
 
         public BreakpointCommand(String className, String methodName,
             String methodSignature) {
@@ -1031,7 +938,90 @@
 
         @Override
         public void perform(JUnit3Wrapper testBase) {
-          testBase.installBreakpoint(new BreakpointInfo(className, methodName, methodSignature));
+          VmMirror mirror = testBase.getMirror();
+          String classSignature = getClassSignature(className);
+          byte typeTag = TypeTag.CLASS;
+          long classId = mirror.getClassID(classSignature);
+          if (classId == -1) {
+            // Is it an interface ?
+            classId = mirror.getInterfaceID(classSignature);
+            typeTag = TypeTag.INTERFACE;
+          }
+          if (classId == -1) {
+            // The class is not ready yet. Request a CLASS_PREPARE to delay the installation of the
+            // breakpoint.
+            assert requestedClassPrepare == false : "Already requested class prepare";
+            requestedClassPrepare = true;
+            ReplyPacket replyPacket = mirror.setClassPrepared(className);
+            final int classPrepareRequestId = replyPacket.getNextValueAsInt();
+            testBase.events.put(Integer.valueOf(classPrepareRequestId), wrapper -> {
+              // Remove the CLASS_PREPARE
+              wrapper.events.remove(Integer.valueOf(classPrepareRequestId));
+              wrapper.getMirror().clearEvent(JDWPConstants.EventKind.CLASS_PREPARE,
+                  classPrepareRequestId);
+
+              // Breakpoint then resume. Note: we add them at the beginning of the queue (to be the
+              // next commands to be processed), thus they need to be pushed in reverse order.
+              wrapper.commandsQueue.addFirst(new JUnit3Wrapper.Command.RunCommand());
+              wrapper.commandsQueue.addFirst(BreakpointCommand.this);
+
+              // Set wrapper ready to process next command.
+              wrapper.setState(State.ProcessCommand);
+            });
+          } else {
+            // The class is available: lookup the method then set the breakpoint.
+            long breakpointMethodId = findMethod(mirror, classId, methodName, methodSignature);
+            long index = testBase.getMethodFirstCodeIndex(classId, breakpointMethodId);
+            Assert.assertTrue("No code in method", index >= 0);
+            ReplyPacket replyPacket = testBase.getMirror().setBreakpoint(
+                new Location(typeTag, classId, breakpointMethodId, index), SuspendPolicy.ALL);
+            assert replyPacket.getErrorCode() == Error.NONE;
+            int breakpointId = replyPacket.getNextValueAsInt();
+            testBase.events.put(Integer.valueOf(breakpointId), new DefaultEventHandler());
+          }
+        }
+
+        private static long findMethod(VmMirror mirror, long classId, String methodName,
+            String methodSignature) {
+
+          boolean withGenericSignature = true;
+          CommandPacket commandPacket = new CommandPacket(ReferenceTypeCommandSet.CommandSetID,
+              ReferenceTypeCommandSet.MethodsWithGenericCommand);
+          commandPacket.setNextValueAsReferenceTypeID(classId);
+          ReplyPacket replyPacket = mirror.performCommand(commandPacket);
+          if (replyPacket.getErrorCode() != Error.NONE) {
+            // Retry with older command ReferenceType.Methods
+            withGenericSignature = false;
+            commandPacket.setCommand(ReferenceTypeCommandSet.MethodsCommand);
+            replyPacket = mirror.performCommand(commandPacket);
+            assert replyPacket.getErrorCode() == Error.NONE;
+          }
+
+          int methodsCount = replyPacket.getNextValueAsInt();
+          List<Long> matchingMethodIds = new ArrayList<>();
+          for (int i = 0; i < methodsCount; ++i) {
+            long currentMethodId = replyPacket.getNextValueAsMethodID();
+            String currentMethodName = replyPacket.getNextValueAsString();
+            String currentMethodSignature = replyPacket.getNextValueAsString();
+            if (withGenericSignature) {
+              replyPacket.getNextValueAsString(); // skip generic signature
+            }
+            replyPacket.getNextValueAsInt(); // skip modifiers
+
+            // Filter methods based on name (and signature if there is).
+            if (methodName.equals(currentMethodName)) {
+              if (methodSignature == null || methodSignature.equals(currentMethodSignature)) {
+                matchingMethodIds.add(Long.valueOf(currentMethodId));
+              }
+            }
+          }
+          Assert.assertTrue(replyPacket.isAllDataRead());
+
+          Assert.assertFalse("No method named " + methodName + " found", matchingMethodIds.isEmpty());
+          // There must be only one matching method
+          Assert.assertEquals("More than 1 method found: please specify a signature", 1,
+              matchingMethodIds.size());
+          return matchingMethodIds.get(0);
         }
 
         @Override
@@ -1178,47 +1168,6 @@
       }
     }
 
-    private static class BreakpointInfo {
-
-      private final String className;
-      private final String methodName;
-      private final String methodSignature;
-
-      private BreakpointInfo(String className, String methodName, String methodSignature) {
-        this.className = className;
-        this.methodName = methodName;
-        this.methodSignature = methodSignature;
-      }
-    }
-
-    /**
-     * CLASS_PREPARE signals us that we can install a breakpoint
-     */
-    private static class ClassPrepareHandler implements EventHandler {
-
-      private final BreakpointInfo breakpointInfo;
-      private final int classPrepareRequestId;
-
-      private ClassPrepareHandler(BreakpointInfo breakpointInfo, int classPrepareRequestId) {
-        this.breakpointInfo = breakpointInfo;
-        this.classPrepareRequestId = classPrepareRequestId;
-      }
-
-      @Override
-      public void handle(JUnit3Wrapper testBase) {
-        // Remove the CLASS_PREPARE
-        testBase.events.remove(Integer.valueOf(classPrepareRequestId));
-        testBase.getMirror().clearEvent(JDWPConstants.EventKind.CLASS_PREPARE,
-            classPrepareRequestId);
-
-        // Install breakpoint now.
-        boolean success = testBase.installBreakpoint(breakpointInfo);
-        Assert.assertTrue("Failed to insert breakpoint after class has been prepared", success);
-
-        // Resume now
-        testBase.resume();
-      }
-    }
   }
 
   //
diff --git a/src/test/java/com/android/tools/r8/debug/LocalsTest.java b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
index 60db262..926e84a 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalsTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
@@ -528,4 +528,22 @@
         checkNoLocal("t"),
         run());
   }
+
+  @Test
+  public void regression65039701() throws Throwable {
+    runDebugTest(
+        "Locals",
+        breakpoint("Locals", "regression65039701"),
+        run(),
+        checkLine(SOURCE_FILE, 304),
+        checkLocal("createIntNotLong", Value.createBoolean(true)),
+        stepOver(),
+        checkLine(SOURCE_FILE, 305),
+        checkLocal("a"),
+        stepOver(),
+        checkLine(SOURCE_FILE, 306),
+        stepOver(),
+        checkLine(SOURCE_FILE, 308),
+        run());
+  }
 }