Support for inlining methods that call/throw.

Mostly fixes here and there to make it working.

Change-Id: I1b535e895105d78b65634636d675b818551f783e
diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java
index 1e2a91b..782f51d 100644
--- a/test/004-StackWalk/src/Main.java
+++ b/test/004-StackWalk/src/Main.java
@@ -2,9 +2,14 @@
   public Main() {
   }
 
-  int f() {
+  int f() throws Exception {
     g(1);
     g(2);
+
+    // This loop currently defeats inlining of `f`.
+    for (int i = 0; i < 10; i++) {
+      Thread.sleep(0);
+    }
     return 0;
   }
 
@@ -86,7 +91,7 @@
     System.loadLibrary("arttest");
   }
 
-  public static void main(String[] args) {
+  public static void main(String[] args) throws Exception {
     Main st = new Main();
     st.f();
   }
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index c40de7e..97afe1c 100644
--- a/test/004-StackWalk/stack_walk_jni.cc
+++ b/test/004-StackWalk/stack_walk_jni.cc
@@ -45,11 +45,11 @@
     if (m_name == "f") {
       if (gJava_StackWalk_refmap_calls == 1) {
         CHECK_EQ(1U, GetDexPc());
-        CHECK_REGS(1);
+        CHECK_REGS(4);
       } else {
         CHECK_EQ(gJava_StackWalk_refmap_calls, 2);
         CHECK_EQ(5U, GetDexPc());
-        CHECK_REGS(1);
+        CHECK_REGS(4);
       }
     } else if (m_name == "g") {
       if (gJava_StackWalk_refmap_calls == 1) {
diff --git a/test/466-get-live-vreg/src/Main.java b/test/466-get-live-vreg/src/Main.java
index 3118085..851506b 100644
--- a/test/466-get-live-vreg/src/Main.java
+++ b/test/466-get-live-vreg/src/Main.java
@@ -53,18 +53,30 @@
   }
 
   public static void main(String[] args) {
-    if (testLiveArgument(42) != 42) {
-      throw new Error("Expected 42");
+    if (testLiveArgument(staticField3) != staticField3) {
+      throw new Error("Expected " + staticField3);
     }
 
-    if (testLiveArgument(42) != 42) {
-      throw new Error("Expected 42");
+    if (testLiveArgument(staticField3) != staticField3) {
+      throw new Error("Expected " + staticField3);
     }
 
-    testIntervalHole(1, true);
-    testIntervalHole(1, false);
+    testWrapperIntervalHole(1, true);
+    testWrapperIntervalHole(1, false);
+  }
+
+  // Wrapper method to avoid inlining, which affects liveness
+  // of dex registers.
+  static void testWrapperIntervalHole(int arg, boolean test) {
+    try {
+      Thread.sleep(0);
+      testIntervalHole(arg, test);
+    } catch (Exception e) {
+      throw new Error(e);
+    }
   }
 
   static int staticField1;
   static int staticField2;
+  static int staticField3 = 42;
 }
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index d5592aa..51be912 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -167,7 +167,7 @@
     static void invokeStaticNotInlined() {
       // The invocation of invokeStaticNotInlined triggers the
       // initialization of ClassWithClinit4, meaning that the
-      // hereinbelow call to staticMethod does not need a clinit
+      // call to staticMethod below does not need a clinit
       // check.
       staticMethod();
     }
diff --git a/test/487-checker-inline-calls/expected.txt b/test/487-checker-inline-calls/expected.txt
new file mode 100644
index 0000000..2230482
--- /dev/null
+++ b/test/487-checker-inline-calls/expected.txt
@@ -0,0 +1,6 @@
+java.lang.Error
+	at Main.inline3(Main.java:48)
+	at Main.inline2(Main.java:44)
+	at Main.inline1(Main.java:40)
+	at Main.doTopCall(Main.java:36)
+	at Main.main(Main.java:21)
diff --git a/test/487-checker-inline-calls/info.txt b/test/487-checker-inline-calls/info.txt
new file mode 100644
index 0000000..9f5df8b
--- /dev/null
+++ b/test/487-checker-inline-calls/info.txt
@@ -0,0 +1 @@
+Checker test for ensuring inlining preserves stack traces.
diff --git a/test/487-checker-inline-calls/src/Main.java b/test/487-checker-inline-calls/src/Main.java
new file mode 100644
index 0000000..70384d5
--- /dev/null
+++ b/test/487-checker-inline-calls/src/Main.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      doTopCall();
+    } catch (Error e) {
+      e.printStackTrace();
+    }
+  }
+
+  // We check that some inlining happened by checking the
+  // method index of the called method.
+
+  /// CHECK-START: void Main.doTopCall() inliner (before)
+  /// CHECK:     InvokeStaticOrDirect dex_file_index:2
+
+  /// CHECK-START: void Main.doTopCall() inliner (after)
+  /// CHECK:     InvokeStaticOrDirect dex_file_index:4
+  public static void doTopCall() {
+    inline1();
+  }
+
+  public static void inline1() {
+    inline2();
+  }
+
+  public static void inline2() {
+    inline3();
+  }
+
+  public static void inline3() {
+    throw new Error();
+  }
+}
diff --git a/test/488-checker-inline-recursive-calls/expected.txt b/test/488-checker-inline-recursive-calls/expected.txt
new file mode 100644
index 0000000..f615d3a
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/expected.txt
@@ -0,0 +1,7 @@
+java.lang.Error
+	at Main.inline3(Main.java:51)
+	at Main.doTopCall(Main.java:37)
+	at Main.inline2(Main.java:47)
+	at Main.inline1(Main.java:43)
+	at Main.doTopCall(Main.java:34)
+	at Main.main(Main.java:21)
diff --git a/test/488-checker-inline-recursive-calls/info.txt b/test/488-checker-inline-recursive-calls/info.txt
new file mode 100644
index 0000000..9abd93c
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/info.txt
@@ -0,0 +1 @@
+Checker test for inlining calls that in turn call the outer method.
diff --git a/test/488-checker-inline-recursive-calls/src/Main.java b/test/488-checker-inline-recursive-calls/src/Main.java
new file mode 100644
index 0000000..c1f25b3
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/src/Main.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      doTopCall(true);
+    } catch (Error e) {
+      e.printStackTrace();
+    }
+  }
+
+  /// CHECK-START: void Main.doTopCall(boolean) inliner (before)
+  /// CHECK-NOT:   InvokeStaticOrDirect recursive:true
+
+  /// CHECK-START: void Main.doTopCall(boolean) inliner (after)
+  /// CHECK:       InvokeStaticOrDirect recursive:true
+  public static void doTopCall(boolean first_call) {
+    if (first_call) {
+      inline1();
+    } else {
+      while (true) {
+        inline3();
+      }
+    }
+  }
+
+  public static void inline1() {
+    inline2();
+  }
+
+  public static void inline2() {
+    doTopCall(false);
+  }
+
+  public static void inline3() {
+    throw new Error();
+  }
+}