Add test for superfluous monitor instructions
* Add getNode() helper for testing
* Always disable desugaring for CF backend
Bug: 73921688
Change-Id: I633138ab79e3df5bec414daea0ad41646c3c2e67
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 7004d5f..9a61a9f 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -319,6 +319,9 @@
assert getProgramConsumer() != null;
+ boolean desugaring =
+ (getProgramConsumer() instanceof ClassFileConsumer) ? false : !getDisableDesugaring();
+
R8Command command =
new R8Command(
getAppBuilder().build(),
@@ -329,7 +332,7 @@
getMode(),
getMinApiLevel(),
reporter,
- !getDisableDesugaring(),
+ desugaring,
configuration.isShrinking(),
configuration.isObfuscating(),
forceProguardCompatibility,
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 62dc43f..16edb7a 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -60,6 +60,11 @@
context.codeList.add(this);
}
+ public MethodNode getNode() {
+ triggerDelayedParsingIfNeccessary();
+ return node;
+ }
+
@Override
public boolean isJarCode() {
return true;
diff --git a/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTest.java b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTest.java
new file mode 100644
index 0000000..c1d079e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTest.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, 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.cf;
+
+public class SynchronizedNoopTest {
+ public static synchronized void noop() {
+ System.out.println("Foo");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java
new file mode 100644
index 0000000..20acb9f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018, 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.cf;
+
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.JarCode;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidAppConsumers;
+import com.android.tools.r8.utils.DexInspector;
+import java.util.ArrayList;
+import java.util.Collections;
+import org.junit.Test;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.MethodNode;
+
+public class SynchronizedNoopTestRunner {
+ private byte[] data;
+ static final Class CLASS = SynchronizedNoopTest.class;
+
+ @Test
+ public void testSynchronizedNoop() throws Exception {
+ AndroidAppConsumers a = new AndroidAppConsumers();
+ R8.run(
+ R8Command.builder()
+ .addClassProgramData(ToolHelper.getClassAsBytes(CLASS), Origin.unknown())
+ .addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()))
+ .setProgramConsumer(a.wrapClassFileConsumer(null))
+ .build());
+ DexInspector inspector = new DexInspector(a.build());
+ DexEncodedMethod method =
+ inspector.clazz(CLASS).method("void", "noop", Collections.emptyList()).getMethod();
+ ArrayList<AbstractInsnNode> insns = new ArrayList<>();
+ JarCode jarCode = method.getCode().asJarCode();
+ MethodNode node = jarCode.getNode();
+ assert node != null;
+ InsnList asmInsns = node.instructions;
+ for (int i = 0; i < asmInsns.size(); i++) {
+ insns.add(asmInsns.get(i));
+ }
+ boolean hasMonitor =
+ insns
+ .stream()
+ .anyMatch(
+ insn ->
+ insn.getOpcode() == Opcodes.MONITORENTER
+ || insn.getOpcode() == Opcodes.MONITOREXIT);
+ // TODO(b/73921688): Should not have monitor instruction here
+ assert hasMonitor;
+ }
+}