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 \