1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import java.lang.reflect.Method;
18 import java.lang.reflect.InvocationTargetException;
19 
20 public class Main {
21   // Workaround for b/18051191.
22   class Inner {}
23 
assertIsInterpreted()24   public static native void assertIsInterpreted();
ensureJitCompiled(Class<?> cls, String methodName)25   public static native void ensureJitCompiled(Class<?> cls, String methodName);
26 
assertEqual(String expected, String actual)27   public static void assertEqual(String expected, String actual) {
28     if (!expected.equals(actual)) {
29       throw new Error("Assertion failed: " + expected + " != " + actual);
30     }
31   }
32 
assertEqual(byte[] expected, String actual)33   public static void assertEqual(byte[] expected, String actual) throws Exception {
34     String str = new String(expected, "UTF8");
35     if (!str.equals(actual)) {
36       throw new Error("Assertion failed: " + str + " != " + actual);
37     }
38   }
39 
main(String[] args)40   public static void main(String[] args) throws Throwable {
41     System.loadLibrary(args[0]);
42     Class<?> c = Class.forName("TestCase");
43     String testString = "Hello world";
44     byte[] testData = testString.getBytes("UTF8");
45 
46     {
47       Method m = c.getMethod("vregAliasing", byte[].class);
48       String result = (String) m.invoke(null, new Object[] { testData });
49       assertEqual(testString, result);
50     }
51 
52     {
53       c.getMethod("compareNewInstance").invoke(null, (Object[]) null);
54     }
55 
56     {
57       // If the JIT is enabled, ensure it has compiled the method to force the deopt.
58       ensureJitCompiled(c, "deoptimizeNewInstance");
59       Method m = c.getMethod("deoptimizeNewInstance", int[].class, byte[].class);
60       try {
61         m.invoke(null, new Object[] { new int[] { 1, 2, 3 }, testData });
62       } catch (InvocationTargetException ex) {
63         if (ex.getCause() instanceof ArrayIndexOutOfBoundsException) {
64           // Expected.
65         } else {
66           throw ex.getCause();
67         }
68       }
69     }
70 
71     {
72       Method m = c.getMethod("removeNewInstance", byte[].class);
73       String result = (String) m.invoke(null, new Object[] { testData });
74       assertEqual(testString, result);
75     }
76 
77     {
78       Method m = c.getMethod("irreducibleLoopAndStringInit1", byte[].class, boolean.class);
79       String result = (String) m.invoke(null, new Object[] { testData, true });
80       assertEqual(testString, result);
81       result = (String) m.invoke(null, new Object[] { testData, false });
82       assertEqual(testString, result);
83     }
84     {
85       Method m = c.getMethod("irreducibleLoopAndStringInit2", byte[].class, boolean.class);
86       String result = (String) m.invoke(null, new Object[] { testData, true });
87       assertEqual(testString, result);
88       result = (String) m.invoke(null, new Object[] { testData, false });
89       assertEqual(testString, result);
90     }
91     {
92       Method m = c.getMethod("irreducibleLoopAndStringInit3", byte[].class, boolean.class);
93       String result = (String) m.invoke(null, new Object[] { testData, true });
94       assertEqual(testString, result);
95       result = (String) m.invoke(null, new Object[] { testData, false });
96       assertEqual(testString, result);
97     }
98     {
99       Method m = c.getMethod("loopAndStringInit", byte[].class, boolean.class);
100       String result = (String) m.invoke(null, new Object[] { testData, true });
101       assertEqual(testString, result);
102       result = (String) m.invoke(null, new Object[] { testData, false });
103       assertEqual(testString, result);
104     }
105     {
106       Method m = c.getMethod("loopAndStringInitAlias", byte[].class, boolean.class);
107       String result = (String) m.invoke(null, new Object[] { testData, true });
108       assertEqual(testString, result);
109       result = (String) m.invoke(null, new Object[] { testData, false });
110       assertEqual(testString, result);
111     }
112     {
113       Method m = c.getMethod("loopAndStringInitAndTest", byte[].class, boolean.class);
114       String result = (String) m.invoke(null, new Object[] { testData, true });
115       assertEqual(testString, result);
116       result = (String) m.invoke(null, new Object[] { testData, false });
117       assertEqual(testString, result);
118     }
119     {
120       // If the JIT is enabled, ensure it has compiled the method to force the deopt.
121       ensureJitCompiled(c, "deoptimizeNewInstanceAfterLoop");
122       Method m = c.getMethod(
123           "deoptimizeNewInstanceAfterLoop", int[].class, byte[].class, int.class);
124       try {
125         m.invoke(null, new Object[] { new int[] { 1, 2, 3 }, testData, 0 });
126       } catch (InvocationTargetException ex) {
127         if (ex.getCause() instanceof ArrayIndexOutOfBoundsException) {
128           // Expected.
129         } else {
130           throw ex.getCause();
131         }
132       }
133     }
134     {
135       Method m = c.getMethod("loopAndStringInitAndPhi", byte[].class, boolean.class);
136       String result = (String) m.invoke(null, new Object[] { testData, true });
137       assertEqual(testString, result);
138       result = (String) m.invoke(null, new Object[] { testData, false });
139       assertEqual(testString, result);
140     }
141     {
142       Method m =
143           c.getMethod("loopAndTwoStringInitAndPhi", byte[].class, boolean.class, boolean.class);
144       String result = (String) m.invoke(null, new Object[] { testData, false, false });
145       assertEqual(testString, result);
146       result = (String) m.invoke(null, new Object[] { testData, false, true });
147       assertEqual(testString, result);
148     }
149     {
150       Method m = c.getMethod("stringAndCatch", byte[].class, boolean.class);
151       String result = (String) m.invoke(null, new Object[] { testData, false });
152       assertEqual(testString, result);
153     }
154     {
155       Method m = c.getMethod("stringAndCatch2", byte[].class, boolean.class);
156       String result = (String) m.invoke(null, new Object[] { testData, false });
157       assertEqual(testString, result);
158     }
159     {
160       Method m = c.getMethod("stringAndCatch3", byte[].class, boolean.class);
161       String result = (String) m.invoke(null, new Object[] { testData, false });
162       assertEqual(testString, result);
163     }
164   }
165 
166   public static boolean doThrow = false;
167 
$noinline$HiddenNull()168   public static Object $noinline$HiddenNull() {
169     if (doThrow) { throw new Error(); }
170     return null;
171   }
172 }
173