blob: 8032ce911670b162bdff28e7e834ab2c2e47c446 [file] [log] [blame]
Mingyao Yangf711f2c2016-05-23 12:29:39 -07001/*
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
17import java.lang.reflect.Method;
18import java.util.Arrays;
19import java.util.Comparator;
20import java.util.HashMap;
21
22class DummyObject {
23 public static boolean sHashCodeInvoked = false;
24 private int i;
25
26 public DummyObject(int i) {
27 this.i = i;
28 }
29
30 public boolean equals(Object obj) {
31 return (obj instanceof DummyObject) && (i == ((DummyObject)obj).i);
32 }
33
34 public int hashCode() {
35 sHashCodeInvoked = true;
36 Main.assertIsManaged();
37 Main.deoptimizeAll();
38 Main.assertIsInterpreted();
39 Main.assertCallerIsManaged(); // Caller is from framework code HashMap.
40 return i % 64;
41 }
42}
43
44public class Main {
45 static boolean sFlag = false;
46
47 public static native void deoptimizeAll();
48 public static native void undeoptimizeAll();
49 public static native void assertIsInterpreted();
50 public static native void assertIsManaged();
51 public static native void assertCallerIsInterpreted();
52 public static native void assertCallerIsManaged();
53
54 public static void execute(Runnable runnable) throws Exception {
55 Thread t = new Thread(runnable);
56 t.start();
57 t.join();
58 }
59
60 public static void main(String[] args) throws Exception {
61 System.loadLibrary(args[0]);
62 final HashMap<DummyObject, Long> map = new HashMap<DummyObject, Long>();
63
64 // Single-frame deoptimization that covers partial fragment.
65 execute(new Runnable() {
66 public void run() {
67 int[] arr = new int[3];
68 assertIsManaged();
69 int res = $noinline$run1(arr);
70 assertIsManaged(); // Only single frame is deoptimized.
71 if (res != 79) {
72 System.out.println("Failure 1!");
73 System.exit(0);
74 }
75 }
76 });
77
78 // Single-frame deoptimization that covers a full fragment.
79 execute(new Runnable() {
80 public void run() {
81 try {
82 int[] arr = new int[3];
83 assertIsManaged();
84 // Use reflection to call $noinline$run2 so that it does
85 // full-fragment deoptimization since that is an upcall.
86 Class<?> cls = Class.forName("Main");
87 Method method = cls.getDeclaredMethod("$noinline$run2", int[].class);
88 double res = (double)method.invoke(Main.class, arr);
89 assertIsManaged(); // Only single frame is deoptimized.
90 if (res != 79.3d) {
91 System.out.println("Failure 2!");
92 System.exit(0);
93 }
94 } catch (Exception e) {
95 e.printStackTrace();
96 }
97 }
98 });
99
100 // Full-fragment deoptimization.
101 execute(new Runnable() {
102 public void run() {
103 assertIsManaged();
104 float res = $noinline$run3B();
105 assertIsInterpreted(); // Every deoptimizeable method is deoptimized.
106 if (res != 0.034f) {
107 System.out.println("Failure 3!");
108 System.exit(0);
109 }
110 }
111 });
112
113 undeoptimizeAll(); // Make compiled code useable again.
114
115 // Partial-fragment deoptimization.
116 execute(new Runnable() {
117 public void run() {
118 try {
119 assertIsManaged();
120 map.put(new DummyObject(10), Long.valueOf(100));
121 assertIsInterpreted(); // Every deoptimizeable method is deoptimized.
122 } catch (Exception e) {
123 e.printStackTrace();
124 }
125 }
126 });
127
128 undeoptimizeAll(); // Make compiled code useable again.
129
130 if (!DummyObject.sHashCodeInvoked) {
131 System.out.println("hashCode() method not invoked!");
132 }
133 if (map.get(new DummyObject(10)) != 100) {
134 System.out.println("Wrong hashmap value!");
135 }
136 System.out.println("Finishing");
137 }
138
139 public static int $noinline$run1(int[] arr) {
140 assertIsManaged();
141 // Prevent inlining.
142 if (sFlag) {
143 throw new Error();
144 }
145 boolean caught = false;
146 // BCE will use deoptimization for the code below.
147 try {
148 arr[0] = 1;
149 arr[1] = 1;
150 arr[2] = 1;
151 // This causes AIOOBE and triggers deoptimization from compiled code.
152 arr[3] = 1;
153 } catch (ArrayIndexOutOfBoundsException e) {
154 assertIsInterpreted(); // Single-frame deoptimization triggered.
155 caught = true;
156 }
157 if (!caught) {
158 System.out.println("Expected exception");
159 }
160 assertIsInterpreted();
161 return 79;
162 }
163
164 public static double $noinline$run2(int[] arr) {
165 assertIsManaged();
166 // Prevent inlining.
167 if (sFlag) {
168 throw new Error();
169 }
170 boolean caught = false;
171 // BCE will use deoptimization for the code below.
172 try {
173 arr[0] = 1;
174 arr[1] = 1;
175 arr[2] = 1;
176 // This causes AIOOBE and triggers deoptimization from compiled code.
177 arr[3] = 1;
178 } catch (ArrayIndexOutOfBoundsException e) {
179 assertIsInterpreted(); // Single-frame deoptimization triggered.
180 caught = true;
181 }
182 if (!caught) {
183 System.out.println("Expected exception");
184 }
185 assertIsInterpreted();
186 return 79.3d;
187 }
188
189 public static float $noinline$run3A() {
190 assertIsManaged();
191 // Prevent inlining.
192 if (sFlag) {
193 throw new Error();
194 }
195 // Deoptimize callers.
196 deoptimizeAll();
197 assertIsInterpreted();
198 assertCallerIsInterpreted(); // $noinline$run3B is deoptimizeable.
199 return 0.034f;
200 }
201
202 public static float $noinline$run3B() {
203 assertIsManaged();
204 // Prevent inlining.
205 if (sFlag) {
206 throw new Error();
207 }
208 float res = $noinline$run3A();
209 assertIsInterpreted();
210 return res;
211 }
212}