Add a test for b/62688874.

The crash in that bug showed we could also leak references with
garbage (0xEBADDE09), because mterp uses the same code between
RETURN and RETURN_OBJECT.

bug: 62688874
bug: 62536525
Test: 656-loop-deopt
Change-Id: Ic54009a505dc6e845f5d6c8fedcfe8c10783023c
diff --git a/test/656-loop-deopt/src/Main.java b/test/656-loop-deopt/src/Main.java
index c99cccf..20e6d72 100644
--- a/test/656-loop-deopt/src/Main.java
+++ b/test/656-loop-deopt/src/Main.java
@@ -32,6 +32,15 @@
     $noinline$loopIncrement(new Main());
     ensureJitCompiled(Main.class, "$noinline$loopIncrement");
     $noinline$loopIncrement(new SubMain());
+
+    $noinline$objectReturned(new Main());
+    ensureJitCompiled(Main.class, "$noinline$objectReturned");
+    Object o = $noinline$objectReturned(new SubMain());
+    // We used to get 0xebadde09 in 'o' here and therefore crash
+    // both interpreter and compiled code.
+    if (o instanceof Cloneable) {
+      System.out.println("Unexpected object type " + o.getClass());
+    }
   }
 
   public boolean doCheck() {
@@ -59,7 +68,7 @@
   public static void $noinline$objectUpdate(Main m) {
     Object o = new Object();
     // We used to kill 'o' when the inline cache of 'doCheck' only
-    // contains 'Main' (which makes the only branch using 'a' dead).
+    // contains 'Main' (which makes the only branch using 'o' dead).
     // So the deoptimization at the inline cache was incorrectly assuming
     // 'o' was dead.
     // This lead to a NPE on the 'toString' call just after deoptimizing.
@@ -82,8 +91,8 @@
     // 'k' was 5000.
     for (int i = 0; i < 5000; i++, k++) {
       if (m.doCheck()) {
-        // We make this branch the only true user of the 'a' phi. All other uses
-        // of 'a' are phi updates.
+        // We make this branch the only true user of the 'k' phi. All other uses
+        // of 'k' are phi updates.
         myIntStatic = k;
       }
     }
@@ -92,6 +101,28 @@
     }
   }
 
+  public static Object $noinline$objectReturned(Main m) {
+    Object o = new Object();
+    // We used to kill 'o' when the inline cache of 'doCheck' only
+    // contains 'Main' (which makes the only branch using 'o' dead).
+    // So the deoptimization at the inline cache was incorrectly assuming
+    // 'o' was dead.
+    // We also need to make 'o' escape through a return instruction, as mterp
+    // executes the same code for return and return-object, and the 0xebadde09
+    // sentinel for dead value is only pushed to non-object dex registers.
+    Object myReturnValue = null;
+    for (int i = 0; i < 5000; i++) {
+      if (m.doCheck()) {
+        // We make this branch the only true user of the 'o' phi. All other uses
+        // of 'o' are phi updates.
+        myReturnValue = o;
+      } else if (myIntStatic == 42) {
+        o = m;
+      }
+    }
+    return myReturnValue;
+  }
+
   public static int myIntStatic = 0;
 
   public static native void ensureJitCompiled(Class<?> itf, String name);