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());
+ }
}