Implement try/catch/throw in optimizing.

- We currently don't run optimizations in the presence of a try/catch.
- We therefore implement Quick's mapping table.
- Also fix a missing null check on array-length.

Change-Id: I6917dfcb868e75c1cf6eff32b7cbb60b6cfbd68f
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 291b45f..631c4be 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -19,10 +19,13 @@
 
 namespace art {
 
-#define CHECK_REGS_CONTAIN_REFS(native_pc_offset, ...) do { \
+#define CHECK_REGS_CONTAIN_REFS(dex_pc, abort_if_not_found, ...) do { \
   int t[] = {__VA_ARGS__}; \
   int t_size = sizeof(t) / sizeof(*t); \
-  CheckReferences(t, t_size, m->NativeQuickPcOffset(m->ToNativeQuickPc(native_pc_offset))); \
+  uintptr_t native_quick_pc = m->ToNativeQuickPc(dex_pc, abort_if_not_found); \
+  if (native_quick_pc != UINTPTR_MAX) { \
+    CheckReferences(t, t_size, m->NativeQuickPcOffset(native_quick_pc)); \
+  } \
 } while (false);
 
 struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
@@ -40,31 +43,33 @@
     // we know the Dex registers with live reference values. Assert that what we
     // find is what is expected.
     if (m_name.compare("f") == 0) {
-      CHECK_REGS_CONTAIN_REFS(0x03U, 8);  // v8: this
-      CHECK_REGS_CONTAIN_REFS(0x06U, 8, 1);  // v8: this, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x08U, 8, 3, 1);  // v8: this, v3: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x0cU, 8, 3, 1);  // v8: this, v3: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x0eU, 8, 3, 1);  // v8: this, v3: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x10U, 8, 3, 1);  // v8: this, v3: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x03U, true, 8);  // v8: this
+      CHECK_REGS_CONTAIN_REFS(0x06U, true, 8, 1);  // v8: this, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x08U, true, 8, 3, 1);  // v8: this, v3: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x0cU, true, 8, 3, 1);  // v8: this, v3: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x0eU, true, 8, 3, 1);  // v8: this, v3: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x10U, true, 8, 3, 1);  // v8: this, v3: y, v1: x
       // v2 is added because of the instruction at DexPC 0024. Object merges with 0 is Object. See:
       //   0024: move-object v3, v2
       //   0025: goto 0013
       // Detaled dex instructions for ReferenceMap.java are at the end of this function.
       // CHECK_REGS_CONTAIN_REFS(8, 3, 2, 1);  // v8: this, v3: y, v2: y, v1: x
-      // We eliminate the non-live registers at a return, so only v3 is live:
-      CHECK_REGS_CONTAIN_REFS(0x13U);  // v3: y
-      CHECK_REGS_CONTAIN_REFS(0x18U, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
-      CHECK_REGS_CONTAIN_REFS(0x1aU, 8, 5, 2, 1, 0);  // v8: this, v5: x[1], v2: y, v1: x, v0: ex
-      CHECK_REGS_CONTAIN_REFS(0x1dU, 8, 5, 2, 1, 0);  // v8: this, v5: x[1], v2: y, v1: x, v0: ex
+      // We eliminate the non-live registers at a return, so only v3 is live.
+      // Note that it is OK for a compiler to not have a dex map at this dex PC because
+      // a return is not a safepoint.
+      CHECK_REGS_CONTAIN_REFS(0x13U, false);  // v3: y
+      CHECK_REGS_CONTAIN_REFS(0x18U, true, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
+      CHECK_REGS_CONTAIN_REFS(0x1aU, true, 8, 5, 2, 1, 0);  // v8: this, v5: x[1], v2: y, v1: x, v0: ex
+      CHECK_REGS_CONTAIN_REFS(0x1dU, true, 8, 5, 2, 1, 0);  // v8: this, v5: x[1], v2: y, v1: x, v0: ex
       // v5 is removed from the root set because there is a "merge" operation.
       // See 0015: if-nez v2, 001f.
-      CHECK_REGS_CONTAIN_REFS(0x1fU, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
-      CHECK_REGS_CONTAIN_REFS(0x21U, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
-      CHECK_REGS_CONTAIN_REFS(0x27U, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x29U, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x2cU, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x2fU, 8, 4, 3, 2, 1);  // v8: this, v4: ex, v3: y, v2: y, v1: x
-      CHECK_REGS_CONTAIN_REFS(0x32U, 8, 3, 2, 1, 0);  // v8: this, v3: y, v2: y, v1: x, v0: ex
+      CHECK_REGS_CONTAIN_REFS(0x1fU, true, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
+      CHECK_REGS_CONTAIN_REFS(0x21U, true, 8, 2, 1, 0);  // v8: this, v2: y, v1: x, v0: ex
+      CHECK_REGS_CONTAIN_REFS(0x27U, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x29U, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x2cU, true, 8, 4, 2, 1);  // v8: this, v4: ex, v2: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x2fU, true, 8, 4, 3, 2, 1);  // v8: this, v4: ex, v3: y, v2: y, v1: x
+      CHECK_REGS_CONTAIN_REFS(0x32U, true, 8, 3, 2, 1, 0);  // v8: this, v3: y, v2: y, v1: x, v0: ex
     }
 
     return true;
diff --git a/test/401-optimizing-compiler/src/Main.java b/test/401-optimizing-compiler/src/Main.java
index 07c407b..7c3fd25 100644
--- a/test/401-optimizing-compiler/src/Main.java
+++ b/test/401-optimizing-compiler/src/Main.java
@@ -94,6 +94,14 @@
       exception = e;
     }
 
+    // Test that we do NPE checks on array length.
+    exception = null;
+    try {
+      $opt$ArrayLengthOfNull(null);
+    } catch (NullPointerException e) {
+      exception = e;
+    }
+
     if (exception == null) {
       throw new Error("Missing NullPointerException");
     }
@@ -218,5 +226,9 @@
     return 42;
   }
 
+  public static int $opt$ArrayLengthOfNull(int[] array) {
+    return array.length;
+  }
+
   Object o;
 }
diff --git a/test/421-exceptions/expected.txt b/test/421-exceptions/expected.txt
new file mode 100644
index 0000000..94db350
--- /dev/null
+++ b/test/421-exceptions/expected.txt
@@ -0,0 +1,20 @@
+1
+3
+4
+1
+4
+1
+4
+1
+4
+Caught class java.lang.RuntimeException
+1
+2
+4
+1
+4
+1
+4
+1
+4
+Caught class java.lang.NullPointerException
diff --git a/test/421-exceptions/info.txt b/test/421-exceptions/info.txt
new file mode 100644
index 0000000..bdec67e
--- /dev/null
+++ b/test/421-exceptions/info.txt
@@ -0,0 +1 @@
+Simple test for try/catch/throw.
diff --git a/test/421-exceptions/src/Main.java b/test/421-exceptions/src/Main.java
new file mode 100644
index 0000000..6bf2377
--- /dev/null
+++ b/test/421-exceptions/src/Main.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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 $opt$bar() {
+    try {
+      $opt$foo(1);
+    } catch (NullPointerException e) {
+      $opt$foo(2);
+    } catch (RuntimeException e) {
+      $opt$foo(3);
+    } finally {
+      $opt$foo(4);
+    }
+  }
+
+  static int barState;
+  static int fooState;
+
+  public static void main(String[] args) {
+    fooState = 0;
+    $opt$runTest();
+    fooState = 1;
+    $opt$runTest();
+  }
+
+  public static void $opt$runTest() {
+    barState = 1;
+    $opt$bar();
+    barState = 2;
+    $opt$bar();
+    barState = 3;
+    $opt$bar();
+    barState = 4;
+    try {
+      $opt$bar();
+    } catch (RuntimeException e) {
+      System.out.println("Caught " + e.getClass());
+    }
+  }
+
+  public static void $opt$foo(int value) {
+    System.out.println(value);
+    if (value == barState) {
+      if (fooState == 0) {
+        throw new RuntimeException();
+      } else {
+        throw new NullPointerException();
+      }
+    }
+  }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 7d56271..269f2fb 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -312,26 +312,39 @@
   003-omnibus-opcodes \
   004-InterfaceTest \
   004-JniTest \
+  004-ReferenceMap \
+  004-SignalTest \
   004-StackWalk \
   004-UnsafeTest \
+  005-annotations \
   006-args \
   007-count10 \
+  008-exceptions \
   011-array-copy \
   013-math2 \
   016-intern \
   017-float \
   018-stack-overflow \
+  019-wrong-array-type \
   020-string \
+  021-string2 \
   022-interface \
   023-many-interfaces \
+  024-illegal-access \
   026-access \
   028-array-write \
+  029-assert \
   030-bad-finalizer \
   031-class-attributes \
   032-concrete-sub \
+  033-class-init-deadlock \
+  035-enum \
   036-finalizer \
   037-inherit \
   038-inner-null \
+  039-join-main \
+  040-miranda \
+  042-new-instance \
   043-privates \
   044-proxy \
   045-reflect-array \
@@ -342,9 +355,13 @@
   051-thread \
   052-verifier-fun \
   054-uncaught \
+  055-enum-performance \
   056-const-string-jumbo \
   061-out-of-memory \
   063-process-manager \
+  064-field-access \
+  065-mismatched-implements \
+  066-mismatched-super \
   067-preemptive-unpark \
   068-classloader \
   069-field-type \
@@ -352,16 +369,20 @@
   071-dexfile \
   072-precise-gc \
   074-gc-thrash \
+  075-verification-error \
   076-boolean-put \
   077-method-override \
+  078-polymorphic-virtual \
   079-phantom \
   080-oom-throw \
+  081-hot-exceptions \
   082-inline-execute \
   083-compiler-regressions \
   084-class-init \
   085-old-style-inner-class \
   086-null-super \
   087-gc-after-link \
+  088-monitor-verification \
   090-loop-formation \
   092-locale \
   093-serialization \
@@ -370,6 +391,7 @@
   097-duplicate-method \
   098-ddmc \
   100-reflect2 \
+  101-fibonacci \
   102-concurrent-gc \
   103-string-append \
   105-invoke \
@@ -377,20 +399,28 @@
   107-int-math2 \
   109-suspend-check \
   110-field-access \
+  111-unresolvable-exception \
   112-double-math \
   113-multidex \
   117-nopatchoat \
+  118-noimage-dex2oat \
+  119-noimage-patchoat \
   121-modifiers \
+  121-simple-suspend-check \
   122-npe \
   123-compiler-regressions-mt \
   124-missing-classes \
   125-gc-and-classloading \
   126-miranda-multidex \
+  201-built-in-exception-detail-messages \
+  202-thread-oome \
   300-package-override \
   301-abstract-protected \
   303-verification-stress \
   401-optimizing-compiler \
+  402-optimizing-control-flow \
   403-optimizing-long \
+  404-optimizing-allocator \
   405-optimizing-long-allocator \
   406-fields \
   407-arrays \
@@ -407,6 +437,7 @@
   418-const-string \
   419-long-parameter \
   420-const-class \
+  421-exceptions \
   422-type-conversion \
   700-LoadArgRegs \
   701-easy-div-rem \