Fix null check elimination
The existing null check elimination mechanism suffered from the same
limitation as the SSA renaming: it took shortcuts that were valid in
a trace compilation world, but not in a method compilation world.
This CL replaces the old mechanism, and additionally takes advantage
of some the fact that "this" is always non-null, as are objects returned
from OP_NEW_* (thanks Ian!).
Two test cases added. The one for ensuring that unnecessary null checks
are elminated requires manual inspection. The other - that we don't
eliminate a necessary null check - is disabled until exceptions are working.
Change-Id: I2a9b72741f56617bf609e4d7c20244796c988f28
diff --git a/test/ExceptionTest/ExceptionTest.java b/test/ExceptionTest/ExceptionTest.java
new file mode 100644
index 0000000..13ef058
--- /dev/null
+++ b/test/ExceptionTest/ExceptionTest.java
@@ -0,0 +1,158 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+class ExceptionTest {
+
+ public int ifoo;
+
+ /* Test requires visual inspection of object code to verify */
+ int noThrow(ExceptionTest nonNullA,
+ ExceptionTest nonNullB,
+ ExceptionTest nonNullC) {
+
+ // "this" check should be eliminated on both IGET/IPUT
+ ifoo++;
+
+ // "this" check should be eliminated on both IGET/IPUT
+ if (ifoo != 321) {
+ // Check not eliminated
+ nonNullA.ifoo = 12;
+ // Check not eliminated
+ nonNullB.ifoo = 21;
+ } else {
+ // Check not eliminated
+ nonNullA.ifoo = 12;
+ }
+
+ // Check eliminated
+ nonNullA.ifoo = 13;
+
+ // Check not eliminated
+ nonNullB.ifoo = 21;
+
+ nonNullC = nonNullB;
+
+ // Check eliminated
+ nonNullC.ifoo = 32;
+
+ // All null checks eliminated
+ return ifoo + nonNullA.ifoo + nonNullB.ifoo + nonNullC.ifoo;
+ }
+
+ /* Test to ensure we don't remove necessary null checks */
+ int checkThrow(ExceptionTest nonNullA,
+ ExceptionTest nonNullB,
+ ExceptionTest nonNullC,
+ ExceptionTest nullA,
+ ExceptionTest nullB,
+ ExceptionTest nullC) {
+
+ // "this" check should be eliminated on both IGET/IPUT
+ ifoo++;
+
+ try {
+ nullA.ifoo = 12;
+ // Should not be reached
+ return -1;
+ } catch (NullPointerException npe) {
+ ifoo++;
+ }
+ try {
+ nullB.ifoo = 13;
+ // Should not be reached
+ return -2;
+ } catch (NullPointerException npe) {
+ ifoo++;
+ }
+ try {
+ nullC.ifoo = 14;
+ // Should not be reached
+ return -3;
+ } catch (NullPointerException npe) {
+ ifoo++;
+ }
+
+ // "this" check should be eliminated
+ if (ifoo != 321) {
+ // Check not eliminated
+ nonNullA.ifoo = 12;
+ // Check not eliminated
+ nonNullB.ifoo = 21;
+ // Should throw here
+ try {
+ nullA.ifoo = 11;
+ return -4;
+ } catch (NullPointerException npe) {
+ }
+ } else {
+ // Check not eliminated
+ nonNullA.ifoo = 12;
+ // Should throw here
+ try {
+ nullA.ifoo = 11;
+ return -5;
+ } catch (NullPointerException npe) {
+ }
+ }
+
+ // Check not eliminated
+ nonNullA.ifoo = 13;
+
+ // Check not eliminated
+ nonNullB.ifoo = 21;
+
+ nonNullC = nonNullB;
+
+ // Check eliminated
+ nonNullC.ifoo = 32;
+
+ // Should throw here
+ try {
+ nullA.ifoo = 13;
+ return -6;
+ } catch (NullPointerException npe) {
+ }
+
+ return ifoo + nonNullA.ifoo + nonNullB.ifoo + nonNullC.ifoo;
+ }
+
+
+ static int nullCheckTestNoThrow(int x) {
+ ExceptionTest base = new ExceptionTest();
+ ExceptionTest a = new ExceptionTest();
+ ExceptionTest b = new ExceptionTest();
+ ExceptionTest c = new ExceptionTest();
+ base.ifoo = x;
+ return base.noThrow(a,b,c);
+ }
+
+ static int nullCheckTestThrow(int x) {
+ ExceptionTest base = new ExceptionTest();
+ ExceptionTest a = new ExceptionTest();
+ ExceptionTest b = new ExceptionTest();
+ ExceptionTest c = new ExceptionTest();
+ ExceptionTest d = null;
+ ExceptionTest e = null;
+ ExceptionTest f = null;
+ base.ifoo = x;
+ return base.checkThrow(a,b,c,d,e,f);
+ }
+
+
+ public static void main(String[] args) {
+ int res;
+
+ res = nullCheckTestNoThrow(1976);
+ if (res == 2054) {
+ System.out.println("nullCheckTestNoThrow PASSED");
+ } else {
+ System.out.println("nullCheckTestNoThrow FAILED: " + res);
+ }
+
+ res = nullCheckTestThrow(1976);
+ if (res == 2057) {
+ System.out.println("nullCheckTestNoThrow PASSED");
+ } else {
+ System.out.println("nullCheckTestNoThrow FAILED: " + res);
+ }
+ }
+}