ART: Monitor-stack merging should not be handled as throwing

Mismatched stacks and other issues on merging register lines should
not be handled as a pending runtime exception. Actual exceptions
will be thrown at monitor-enter/exit and return sites. Both are
already covered: the former by being annotated kThrow, the latter
by explicit checks for the stack (and end of control flow).

Thus, Fail() with pending_exc set to false in register line merging.
This still triggers lock verification at runtime.

Bug: 121245951
Test: m test-art-host
Change-Id: I06acca2920110e3de2a2bed7bae6695788f77449
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index 1bbf5a6..b69267c 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -442,7 +442,7 @@
   }
   if (monitors_.size() > 0 || incoming_line->monitors_.size() > 0) {
     if (monitors_.size() != incoming_line->monitors_.size()) {
-      verifier->Fail(VERIFY_ERROR_LOCKING);
+      verifier->Fail(VERIFY_ERROR_LOCKING, /*pending_exc=*/ false);
       if (kDumpLockFailures) {
         VLOG(verifier) << "mismatched stack depths (depth=" << MonitorStackDepth()
                        << ", incoming depth=" << incoming_line->MonitorStackDepth() << ") in "
@@ -476,7 +476,7 @@
               !FindLockAliasedRegister(idx,
                                        incoming_line->reg_to_lock_depths_,
                                        reg_to_lock_depths_)) {
-            verifier->Fail(VERIFY_ERROR_LOCKING);
+            verifier->Fail(VERIFY_ERROR_LOCKING, /*pending_exc=*/ false);
             if (kDumpLockFailures) {
               VLOG(verifier) << "mismatched stack depths for register v" << idx
                              << ": " << depths  << " != " << incoming_depths << " in "
@@ -517,7 +517,7 @@
                                          incoming_line->reg_to_lock_depths_,
                                          reg_to_lock_depths_)) {
               // No aliases for both current and incoming, we'll lose information.
-              verifier->Fail(VERIFY_ERROR_LOCKING);
+              verifier->Fail(VERIFY_ERROR_LOCKING, /*pending_exc=*/ false);
               if (kDumpLockFailures) {
                 VLOG(verifier) << "mismatched lock levels for register v" << idx << ": "
                                << std::hex << locked_levels << std::dec  << " != "
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index 88dc054..fbf10bb 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -77,4 +77,7 @@
 b/122501785
 b/134061982
 b/134061982 (2)
+b/121245951
+b/121245951 (2)
+b/121245951 (3)
 Done!
diff --git a/test/800-smali/smali/b_121245951.smali b/test/800-smali/smali/b_121245951.smali
new file mode 100644
index 0000000..4faaf67
--- /dev/null
+++ b/test/800-smali/smali/b_121245951.smali
@@ -0,0 +1,26 @@
+.class public LB121245951;
+
+.super Ljava/lang/Object;
+
+.method public static run(ZLjava/lang/Object;)V
+  .registers 3
+
+  # Create an unequal lock stack.
+
+  if-eqz v1, :LfalseBranch
+
+:LtrueBranch
+  monitor-enter v2
+  monitor-enter v2
+  goto :Ljoin
+
+:LfalseBranch
+  monitor-enter v2
+  goto :Ljoin
+
+:Ljoin
+  monitor-exit v2
+
+  # Should throw here.
+  return-void
+.end method
diff --git a/test/800-smali/smali/b_121245951_2.smali b/test/800-smali/smali/b_121245951_2.smali
new file mode 100644
index 0000000..0750bb0
--- /dev/null
+++ b/test/800-smali/smali/b_121245951_2.smali
@@ -0,0 +1,30 @@
+.class public LB121245951_2;
+
+.super Ljava/lang/Object;
+
+.method public static run(ZLjava/lang/Object;)V
+  .registers 3
+
+  # Create an unequal lock stack.
+
+  if-eqz v1, :LfalseBranch
+
+:LtrueBranch
+  monitor-enter v2
+  monitor-enter v2
+  const/4 v0, 0x0
+  goto :Ljoin
+
+:LfalseBranch
+  monitor-enter v2
+  move-object v0, v2
+  goto :Ljoin
+
+:Ljoin
+  monitor-exit v2
+
+  # This should fail the class
+  add-int/lit8 v0, v0, 0x1
+
+  return-void
+.end method
diff --git a/test/800-smali/smali/b_121245951_3.smali b/test/800-smali/smali/b_121245951_3.smali
new file mode 100644
index 0000000..b6e7b1c
--- /dev/null
+++ b/test/800-smali/smali/b_121245951_3.smali
@@ -0,0 +1,33 @@
+.class public LB121245951_3;
+
+.super Ljava/lang/Object;
+
+.method public static run(Ljava/lang/Object;)V
+  .registers 3
+
+  const/4 v1, 0x1
+
+:LcatchStart
+
+  monitor-enter v2
+
+  # Possibly throwing to merge v1 into catch handler as int.
+  sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+  move-object v1, v2
+
+  # This should cause a runtime failure, and not merge into the
+  # catch handler.
+  return-void
+
+:LcatchEnd
+:LcatchHandler
+  move-exception v0
+  # If the lock fail at the return-void above merged into the catch
+  # handler, this will fail the class.
+  add-int/lit8 v1, v1, 0x1
+  throw v0
+
+.catchall {:LcatchStart .. :LcatchEnd} :LcatchHandler
+
+.end method
\ No newline at end of file
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index ce7426f..90476b3 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -201,6 +201,12 @@
                 new NullPointerException(), 0));
         testCases.add(new TestCase("b/134061982 (2)", "B134061982_2", "run", new Object[] { 0 },
                 new VerifyError(), 0));
+        testCases.add(new TestCase("b/121245951", "B121245951", "run", new Object[] { true,
+                new Object() }, new IllegalMonitorStateException(), 0));
+        testCases.add(new TestCase("b/121245951 (2)", "B121245951_2", "run", new Object[] { true,
+                new Object() }, new VerifyError(), 0));
+        testCases.add(new TestCase("b/121245951 (3)", "B121245951_3", "run", new Object[] {
+                new Object() }, new IllegalMonitorStateException(), 0));
     }
 
     public void runTests() {