1 /*
2  * Copyright (C) 2017 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 package art;
18 
19 import java.lang.reflect.Executable;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.util.Base64;
23 import java.util.EnumSet;
24 import java.util.concurrent.CountDownLatch;
25 import java.util.function.Consumer;
26 
27 import static art.SuspendEvents.setupTest;
28 import static art.SuspendEvents.setupSuspendBreakpointFor;
29 import static art.SuspendEvents.clearSuspendBreakpointFor;
30 import static art.SuspendEvents.setupSuspendSingleStepAt;
31 import static art.SuspendEvents.setupFieldSuspendFor;
32 import static art.SuspendEvents.setupSuspendMethodEvent;
33 import static art.SuspendEvents.setupSuspendExceptionEvent;
34 import static art.SuspendEvents.setupSuspendPopFrameEvent;
35 import static art.SuspendEvents.EVENT_TYPE_CLASS_LOAD;
36 import static art.SuspendEvents.EVENT_TYPE_CLASS_PREPARE;
37 import static art.SuspendEvents.setupSuspendClassEvent;
38 
39 public class Test1953 {
40   private static boolean IS_ART = System.getProperty("java.vm.name").equals("Dalvik");
41   public final boolean canRunClassLoadTests;
doNothing()42   public static void doNothing() {}
43 
44   public interface TestRunnable extends Runnable {
getBaseCallCount()45     public int getBaseCallCount();
getCalledMethod()46     public Method getCalledMethod() throws Exception;
getCallingMethod()47     public default Method getCallingMethod() throws Exception {
48       return this.getClass().getMethod("run");
49     };
50   }
51 
52   public static interface TestSuspender {
setup(Thread thr)53     public void setup(Thread thr);
waitForSuspend(Thread thr)54     public void waitForSuspend(Thread thr);
cleanup(Thread thr)55     public void cleanup(Thread thr);
56   }
57 
run(Thread thr)58   public static interface ThreadRunnable { public void run(Thread thr); }
makeSuspend(final ThreadRunnable setup, final ThreadRunnable clean)59   public static TestSuspender makeSuspend(final ThreadRunnable setup, final ThreadRunnable clean) {
60     return new TestSuspender() {
61       public void setup(Thread thr) { setup.run(thr); }
62       public void waitForSuspend(Thread thr) { SuspendEvents.waitForSuspendHit(thr); }
63       public void cleanup(Thread thr) { clean.run(thr); }
64     };
65   }
66 
67   public void runTestOn(TestRunnable testObj, ThreadRunnable su, ThreadRunnable cl) throws
68       Exception {
69     runTestOn(testObj, makeSuspend(su, cl));
70   }
71 
72   private static void SafePrintStackTrace(StackTraceElement st[]) {
73     for (StackTraceElement e : st) {
74       System.out.println("\t" + e.getClassName() + "." + e.getMethodName() + "(" +
75           (e.isNativeMethod() ? "Native Method" : e.getFileName()) + ")");
76       if (e.getClassName().equals("art.Test1953") && e.getMethodName().equals("runTests")) {
77         System.out.println("\t<Additional frames hidden>");
78         break;
79       }
80     }
81   }
82 
83   public void runTestOn(TestRunnable testObj, TestSuspender su) throws Exception {
84     System.out.println("Single call with PopFrame on " + testObj + " base-call-count: " +
85         testObj.getBaseCallCount());
86     final CountDownLatch continue_latch = new CountDownLatch(1);
87     final CountDownLatch startup_latch = new CountDownLatch(1);
88     Runnable await = () -> {
89       try {
90         startup_latch.countDown();
91         continue_latch.await();
92       } catch (Exception e) {
93         throw new Error("Failed to await latch", e);
94       }
95     };
96     Thread thr = new Thread(() -> { await.run(); testObj.run(); });
97     thr.start();
98 
99     // Wait until the other thread is started.
100     startup_latch.await();
101 
102     // Do any final setup.
103     preTest.accept(testObj);
104 
105     // Setup suspension method on the thread.
106     su.setup(thr);
107 
108     // Let the other thread go.
109     continue_latch.countDown();
110 
111     // Wait for the other thread to hit the breakpoint/watchpoint/whatever and suspend itself
112     // (without re-entering java)
113     su.waitForSuspend(thr);
114 
115     // Cleanup the breakpoint/watchpoint/etc.
116     su.cleanup(thr);
117 
118     try {
119       // Pop the frame.
120       popFrame(thr);
121     } catch (Exception e) {
122       System.out.println("Failed to pop frame due to " + e);
123       SafePrintStackTrace(e.getStackTrace());
124     }
125 
126     // Start the other thread going again.
127     Suspension.resume(thr);
128 
129     // Wait for the other thread to finish.
130     thr.join();
131 
132     // See how many times calledFunction was called.
133     System.out.println("result is " + testObj + " base-call count: " + testObj.getBaseCallCount());
134   }
135 
136   public static abstract class AbstractTestObject implements TestRunnable {
137     public int callerCnt;
138 
139     public AbstractTestObject() {
140       callerCnt = 0;
141     }
142 
143     public int getBaseCallCount() {
144       return callerCnt;
145     }
146 
147     public void run() {
148       callerCnt++;
149       // This function should be re-executed by the popFrame.
150       calledFunction();
151     }
152 
153     public Method getCalledMethod() throws Exception {
154       return this.getClass().getMethod("calledFunction");
155     }
156 
157     public abstract void calledFunction();
158   }
159 
160   public static class RedefineTestObject extends AbstractTestObject implements Runnable {
161     public static enum RedefineState { ORIGINAL, REDEFINED, };
162     /* public static class RedefineTestObject extends AbstractTestObject implements Runnable {
163      *   public static final byte[] CLASS_BYTES;
164      *   public static final byte[] DEX_BYTES;
165      *   static {
166      *     CLASS_BYTES = null;
167      *     DEX_BYTES = null;
168      *   }
169      *
170      *   public EnumSet<RedefineState> redefine_states;
171      *   public RedefineTestObject() {
172      *     super();
173      *     redefine_states = EnumSet.noneOf(RedefineState.class);
174      *   }
175      *   public String toString() {
176      *     return "RedefineTestObject { states: " + redefine_states.toString()
177      *                                            + " current: REDEFINED }";
178      *   }
179      *   public void calledFunction() {
180      *     redefine_states.add(RedefineState.REDEFINED);  // line +0
181      *     // We will trigger the redefinition using a breakpoint on the next line.
182      *     doNothing();                                   // line +2
183      *   }
184      * }
185      */
186     public static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
187       "yv66vgAAADUATQoADQAjBwAkCgAlACYJAAwAJwoAJQAoEgAAACwJAAIALQoAJQAuCgAvADAJAAwA" +
188       "MQkADAAyBwAzBwA0BwA2AQASUmVkZWZpbmVUZXN0T2JqZWN0AQAMSW5uZXJDbGFzc2VzAQANUmVk" +
189       "ZWZpbmVTdGF0ZQEAC0NMQVNTX0JZVEVTAQACW0IBAAlERVhfQllURVMBAA9yZWRlZmluZV9zdGF0" +
190       "ZXMBABNMamF2YS91dGlsL0VudW1TZXQ7AQAJU2lnbmF0dXJlAQBETGphdmEvdXRpbC9FbnVtU2V0" +
191       "PExhcnQvVGVzdDE5NTMkUmVkZWZpbmVUZXN0T2JqZWN0JFJlZGVmaW5lU3RhdGU7PjsBAAY8aW5p" +
192       "dD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAIdG9TdHJpbmcBABQoKUxqYXZhL2xh" +
193       "bmcvU3RyaW5nOwEADmNhbGxlZEZ1bmN0aW9uAQAIPGNsaW5pdD4BAApTb3VyY2VGaWxlAQANVGVz" +
194       "dDE5NTMuamF2YQwAGQAaAQAtYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmlu" +
195       "ZVN0YXRlBwA3DAA4ADkMABUAFgwAHQAeAQAQQm9vdHN0cmFwTWV0aG9kcw8GADoIADsMADwAPQwA" +
196       "PgA/DABAAEEHAEIMAEMAGgwAEgATDAAUABMBAB9hcnQvVGVzdDE5NTMkUmVkZWZpbmVUZXN0T2Jq" +
197       "ZWN0AQAfYXJ0L1Rlc3QxOTUzJEFic3RyYWN0VGVzdE9iamVjdAEAEkFic3RyYWN0VGVzdE9iamVj" +
198       "dAEAEmphdmEvbGFuZy9SdW5uYWJsZQEAEWphdmEvdXRpbC9FbnVtU2V0AQAGbm9uZU9mAQAmKExq" +
199       "YXZhL2xhbmcvQ2xhc3M7KUxqYXZhL3V0aWwvRW51bVNldDsKAEQARQEAM1JlZGVmaW5lVGVzdE9i" +
200       "amVjdCB7IHN0YXRlczogASBjdXJyZW50OiBSRURFRklORUQgfQEAF21ha2VDb25jYXRXaXRoQ29u" +
201       "c3RhbnRzAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAlSRURFRklO" +
202       "RUQBAC9MYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmluZVN0YXRlOwEAA2Fk" +
203       "ZAEAFShMamF2YS9sYW5nL09iamVjdDspWgEADGFydC9UZXN0MTk1MwEACWRvTm90aGluZwcARgwA" +
204       "PABJAQAkamF2YS9sYW5nL2ludm9rZS9TdHJpbmdDb25jYXRGYWN0b3J5BwBLAQAGTG9va3VwAQCY" +
205       "KExqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwO0xqYXZhL2xhbmcvU3RyaW5n" +
206       "O0xqYXZhL2xhbmcvaW52b2tlL01ldGhvZFR5cGU7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xh" +
207       "bmcvT2JqZWN0OylMamF2YS9sYW5nL2ludm9rZS9DYWxsU2l0ZTsHAEwBACVqYXZhL2xhbmcvaW52" +
208       "b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwAQAeamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVz" +
209       "ACEADAANAAEADgADABkAEgATAAAAGQAUABMAAAABABUAFgABABcAAAACABgABAABABkAGgABABsA" +
210       "AAAuAAIAAQAAAA4qtwABKhICuAADtQAEsQAAAAEAHAAAAA4AAwAAACEABAAiAA0AIwABAB0AHgAB" +
211       "ABsAAAAlAAEAAQAAAA0qtAAEtgAFugAGAACwAAAAAQAcAAAABgABAAAAJQABAB8AGgABABsAAAAv" +
212       "AAIAAQAAAA8qtAAEsgAHtgAIV7gACbEAAAABABwAAAAOAAMAAAApAAsAKwAOACwACAAgABoAAQAb" +
213       "AAAAKQABAAAAAAAJAbMACgGzAAuxAAAAAQAcAAAADgADAAAAGwAEABwACAAdAAMAIQAAAAIAIgAQ" +
214       "AAAAIgAEAAwALwAPAAkAAgAMABFAGQANAC8ANQQJAEcASgBIABkAKQAAAAgAAQAqAAEAKw==");
215     public static final byte[] DEX_BYTES = Base64.getDecoder().decode(
216       "ZGV4CjAzNQAaR23N6WpunLRVX+BexSuzzNNiHNOvQpFoBwAAcAAAAHhWNBIAAAAAAAAAAKQGAAAq" +
217       "AAAAcAAAABEAAAAYAQAABQAAAFwBAAAEAAAAmAEAAAwAAAC4AQAAAQAAABgCAAAwBQAAOAIAACID" +
218       "AAA5AwAAQwMAAEsDAABPAwAAXAMAAGcDAABqAwAAbgMAAJEDAADCAwAA5QMAAPUDAAAZBAAAOQQA" +
219       "AFwEAAB7BAAAjgQAAKIEAAC4BAAAzAQAAOcEAAD8BAAAEQUAABwFAAAwBQAATwUAAF4FAABhBQAA" +
220       "ZAUAAGgFAABsBQAAeQUAAH4FAACGBQAAlgUAAKEFAACnBQAArwUAAMAFAADKBQAA0QUAAAgAAAAJ" +
221       "AAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAGwAAABwA" +
222       "AAAeAAAABgAAAAsAAAAAAAAABwAAAAwAAAAMAwAABwAAAA0AAAAUAwAAGwAAAA4AAAAAAAAAHQAA" +
223       "AA8AAAAcAwAAAQABABcAAAACABAABAAAAAIAEAAFAAAAAgANACYAAAAAAAMAAgAAAAIAAwABAAAA" +
224       "AgADAAIAAAACAAMAIgAAAAIAAAAnAAAAAwADACMAAAAMAAMAAgAAAAwAAQAhAAAADAAAACcAAAAN" +
225       "AAQAIAAAAA0AAgAlAAAADQAAACcAAAACAAAAAQAAAAAAAAAEAwAAGgAAAIwGAABRBgAAAAAAAAQA" +
226       "AQACAAAA+gIAAB0AAABUMAMAbhALAAAADAAiAQwAcBAGAAEAGgIZAG4gBwAhAG4gBwABABoAAABu" +
227       "IAcAAQBuEAgAAQAMABEAAAABAAAAAAAAAPQCAAAGAAAAEgBpAAEAaQACAA4AAgABAAEAAADuAgAA" +
228       "DAAAAHAQAAABABwAAQBxEAoAAAAMAFsQAwAOAAMAAQACAAAA/gIAAAsAAABUIAMAYgEAAG4gCQAQ" +
229       "AHEABQAAAA4AIQAOPIcAGwAOPC0AJQAOACkADnk8AAEAAAAKAAAAAQAAAAsAAAABAAAACAAAAAEA" +
230       "AAAJABUgY3VycmVudDogUkVERUZJTkVEIH0ACDxjbGluaXQ+AAY8aW5pdD4AAj47AAtDTEFTU19C" +
231       "WVRFUwAJREVYX0JZVEVTAAFMAAJMTAAhTGFydC9UZXN0MTk1MyRBYnN0cmFjdFRlc3RPYmplY3Q7" +
232       "AC9MYXJ0L1Rlc3QxOTUzJFJlZGVmaW5lVGVzdE9iamVjdCRSZWRlZmluZVN0YXRlOwAhTGFydC9U" +
233       "ZXN0MTk1MyRSZWRlZmluZVRlc3RPYmplY3Q7AA5MYXJ0L1Rlc3QxOTUzOwAiTGRhbHZpay9hbm5v" +
234       "dGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ACFM" +
235       "ZGFsdmlrL2Fubm90YXRpb24vTWVtYmVyQ2xhc3NlczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWdu" +
236       "YXR1cmU7ABFMamF2YS9sYW5nL0NsYXNzOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5n" +
237       "L1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7" +
238       "ABNMamF2YS91dGlsL0VudW1TZXQ7ABNMamF2YS91dGlsL0VudW1TZXQ8AAlSRURFRklORUQAElJl" +
239       "ZGVmaW5lVGVzdE9iamVjdAAdUmVkZWZpbmVUZXN0T2JqZWN0IHsgc3RhdGVzOiAADVRlc3QxOTUz" +
240       "LmphdmEAAVYAAVoAAlpMAAJbQgALYWNjZXNzRmxhZ3MAA2FkZAAGYXBwZW5kAA5jYWxsZWRGdW5j" +
241       "dGlvbgAJZG9Ob3RoaW5nAARuYW1lAAZub25lT2YAD3JlZGVmaW5lX3N0YXRlcwAIdG9TdHJpbmcA" +
242       "BXZhbHVlAFt+fkQ4eyJtaW4tYXBpIjoxLCJzaGEtMSI6IjUyNzNjM2RmZWUxMDQ2NzIwYWY0MjVm" +
243       "YTg1NTMxNmM5OWM4NmM4ZDIiLCJ2ZXJzaW9uIjoiMS4zLjE4LWRldiJ9AAIHASgcAxcWFwkXAwIE" +
244       "ASgYAwIFAh8ECSQXGAIGASgcARgBAgECAgEZARkDAQGIgASEBQGBgASgBQMByAUBAbgEAAAAAAAB" +
245       "AAAALgYAAAMAAAA6BgAAQAYAAEkGAAB8BgAAAQAAAAAAAAAAAAAAAwAAAHQGAAAQAAAAAAAAAAEA" +
246       "AAAAAAAAAQAAACoAAABwAAAAAgAAABEAAAAYAQAAAwAAAAUAAABcAQAABAAAAAQAAACYAQAABQAA" +
247       "AAwAAAC4AQAABgAAAAEAAAAYAgAAASAAAAQAAAA4AgAAAyAAAAQAAADuAgAAARAAAAQAAAAEAwAA" +
248       "AiAAACoAAAAiAwAABCAAAAQAAAAuBgAAACAAAAEAAABRBgAAAxAAAAMAAABwBgAABiAAAAEAAACM" +
249       "BgAAABAAAAEAAACkBgAA");
250 
251     public EnumSet<RedefineState> redefine_states;
252     public RedefineTestObject() {
253       super();
254       redefine_states = EnumSet.noneOf(RedefineState.class);
255     }
256 
257     public String toString() {
258       return "RedefineTestObject { states: " + redefine_states.toString() + " current: ORIGINAL }";
259     }
260 
261     public void calledFunction() {
262       redefine_states.add(RedefineState.ORIGINAL);  // line +0
263       // We will trigger the redefinition using a breakpoint on the next line.
264       doNothing();                                  // line +2
265     }
266   }
267 
268   public static class ClassLoadObject implements TestRunnable {
269     public int cnt;
270     public int baseCallCnt;
271 
272     public static final String[] CLASS_NAMES = new String[] {
273       "Lart/Test1953$ClassLoadObject$TC0;",
274       "Lart/Test1953$ClassLoadObject$TC1;",
275       "Lart/Test1953$ClassLoadObject$TC2;",
276       "Lart/Test1953$ClassLoadObject$TC3;",
277       "Lart/Test1953$ClassLoadObject$TC4;",
278       "Lart/Test1953$ClassLoadObject$TC5;",
279       "Lart/Test1953$ClassLoadObject$TC6;",
280       "Lart/Test1953$ClassLoadObject$TC7;",
281       "Lart/Test1953$ClassLoadObject$TC8;",
282       "Lart/Test1953$ClassLoadObject$TC9;",
283     };
284 
285     private static int curClass = 0;
286 
287     private static class TC0 { public static int foo; static { foo = 1; } }
288     private static class TC1 { public static int foo; static { foo = 2; } }
289     private static class TC2 { public static int foo; static { foo = 3; } }
290     private static class TC3 { public static int foo; static { foo = 4; } }
291     private static class TC4 { public static int foo; static { foo = 5; } }
292     private static class TC5 { public static int foo; static { foo = 6; } }
293     private static class TC6 { public static int foo; static { foo = 7; } }
294     private static class TC7 { public static int foo; static { foo = 8; } }
295     private static class TC8 { public static int foo; static { foo = 9; } }
296     private static class TC9 { public static int foo; static { foo = 10; } }
297 
298     public ClassLoadObject() {
299       super();
300       cnt = 0;
301       baseCallCnt = 0;
302     }
303 
304     public int getBaseCallCount() {
305       return baseCallCnt;
306     }
307 
308     public void run() {
309       baseCallCnt++;
310       if (curClass == 0) {
311         $noprecompile$calledFunction0();
312       } else if (curClass == 1) {
313         $noprecompile$calledFunction1();
314       } else if (curClass == 2) {
315         $noprecompile$calledFunction2();
316       } else if (curClass == 3) {
317         $noprecompile$calledFunction3();
318       } else if (curClass == 4) {
319         $noprecompile$calledFunction4();
320       } else if (curClass == 5) {
321         $noprecompile$calledFunction5();
322       } else if (curClass == 6) {
323         $noprecompile$calledFunction6();
324       } else if (curClass == 7) {
325         $noprecompile$calledFunction7();
326       } else if (curClass == 8) {
327         $noprecompile$calledFunction8();
328       } else if (curClass == 9) {
329         $noprecompile$calledFunction9();
330       }
331       curClass++;
332     }
333 
334     public Method getCalledMethod() throws Exception {
335       return this.getClass().getMethod("jnoprecompile$calledFunction" + curClass);
336     }
337 
338     // Give these all a tag to prevent 1954 from compiling them (and loading the class as a
339     // consequence).
340     public void $noprecompile$calledFunction0() {
341       cnt++;
342       System.out.println("TC0.foo == " + TC0.foo);
343     }
344 
345     public void $noprecompile$calledFunction1() {
346       cnt++;
347       System.out.println("TC1.foo == " + TC1.foo);
348     }
349 
350     public void $noprecompile$calledFunction2() {
351       cnt++;
352       System.out.println("TC2.foo == " + TC2.foo);
353     }
354 
355     public void $noprecompile$calledFunction3() {
356       cnt++;
357       System.out.println("TC3.foo == " + TC3.foo);
358     }
359 
360     public void $noprecompile$calledFunction4() {
361       cnt++;
362       System.out.println("TC4.foo == " + TC4.foo);
363     }
364 
365     public void $noprecompile$calledFunction5() {
366       cnt++;
367       System.out.println("TC5.foo == " + TC5.foo);
368     }
369 
370     public void $noprecompile$calledFunction6() {
371       cnt++;
372       System.out.println("TC6.foo == " + TC6.foo);
373     }
374 
375     public void $noprecompile$calledFunction7() {
376       cnt++;
377       System.out.println("TC7.foo == " + TC7.foo);
378     }
379 
380     public void $noprecompile$calledFunction8() {
381       cnt++;
382       System.out.println("TC8.foo == " + TC8.foo);
383     }
384 
385     public void $noprecompile$calledFunction9() {
386       cnt++;
387       System.out.println("TC9.foo == " + TC9.foo);
388     }
389 
390     public String toString() {
391       return "ClassLoadObject { cnt: " + cnt + ", curClass: " + curClass + "}";
392     }
393   }
394 
395   public static class FieldBasedTestObject extends AbstractTestObject implements Runnable {
396     public int cnt;
397     public int TARGET_FIELD;
398     public FieldBasedTestObject() {
399       super();
400       cnt = 0;
401       TARGET_FIELD = 0;
402     }
403 
404     public void calledFunction() {
405       cnt++;
406       // We put a watchpoint here and PopFrame when we are at it.
407       TARGET_FIELD += 10;
408       if (cnt == 1) { System.out.println("FAILED: No pop on first call!"); }
409     }
410 
411     public String toString() {
412       return "FieldBasedTestObject { cnt: " + cnt + ", TARGET_FIELD: " + TARGET_FIELD + " }";
413     }
414   }
415 
416   public static class StandardTestObject extends AbstractTestObject implements Runnable {
417     public int cnt;
418     public final boolean check;
419 
420     public StandardTestObject(boolean check) {
421       super();
422       cnt = 0;
423       this.check = check;
424     }
425 
426     public StandardTestObject() {
427       this(true);
428     }
429 
430     public void calledFunction() {
431       cnt++;       // line +0
432       // We put a breakpoint here and PopFrame when we are at it.
433       doNothing(); // line +2
434       if (check && cnt == 1) { System.out.println("FAILED: No pop on first call!"); }
435     }
436 
437     public String toString() {
438       return "StandardTestObject { cnt: " + cnt + " }";
439     }
440   }
441 
442   public static class SynchronizedFunctionTestObject extends AbstractTestObject implements Runnable {
443     public int cnt;
444 
445     public SynchronizedFunctionTestObject() {
446       super();
447       cnt = 0;
448     }
449 
450     public synchronized void calledFunction() {
451       cnt++;               // line +0
452       // We put a breakpoint here and PopFrame when we are at it.
453       doNothing();         // line +2
454     }
455 
456     public String toString() {
457       return "SynchronizedFunctionTestObject { cnt: " + cnt + " }";
458     }
459   }
460   public static class SynchronizedTestObject extends AbstractTestObject implements Runnable {
461     public int cnt;
462     public final Object lock;
463 
464     public SynchronizedTestObject() {
465       this(new Object());
466     }
467 
468     public SynchronizedTestObject(Object l) {
469       super();
470       cnt = 0;
471       lock = l;
472     }
473 
474     public void calledFunction() {
475       synchronized (lock) {  // line +0
476         cnt++;               // line +1
477         // We put a breakpoint here and PopFrame when we are at it.
478         doNothing();         // line +3
479       }
480     }
481 
482     public String toString() {
483       return "SynchronizedTestObject { cnt: " + cnt + " }";
484     }
485   }
486 
487   public static class ExceptionCatchTestObject extends AbstractTestObject implements Runnable {
488     public static class TestError extends Error {}
489 
490     public int cnt;
491     public ExceptionCatchTestObject() {
492       super();
493       cnt = 0;
494     }
495 
496     public void calledFunction() {
497       cnt++;
498       try {
499         doThrow();
500       } catch (TestError e) {
501         System.out.println(e.getClass().getName() + " caught in called function.");
502       }
503     }
504 
505     public void doThrow() {
506       throw new TestError();
507     }
508 
509     public String toString() {
510       return "ExceptionCatchTestObject { cnt: " + cnt + " }";
511     }
512   }
513 
514   public static class ExceptionThrowFarTestObject implements TestRunnable {
515     public static class TestError extends Error {}
516 
517     public int cnt;
518     public int baseCallCnt;
519     public final boolean catchInCalled;
520     public ExceptionThrowFarTestObject(boolean catchInCalled) {
521       super();
522       cnt = 0;
523       baseCallCnt = 0;
524       this.catchInCalled = catchInCalled;
525     }
526 
527     public int getBaseCallCount() {
528       return baseCallCnt;
529     }
530 
531     public void run() {
532       baseCallCnt++;
533       try {
534         callingFunction();
535       } catch (TestError e) {
536         System.out.println(e.getClass().getName() + " thrown and caught!");
537       }
538     }
539 
540     public void callingFunction() {
541       calledFunction();
542     }
543     public void calledFunction() {
544       cnt++;
545       if (catchInCalled) {
546         try {
547           throw new TestError(); // We put a watch here.
548         } catch (TestError e) {
549           System.out.println(e.getClass().getName() + " caught in same function.");
550         }
551       } else {
552         throw new TestError(); // We put a watch here.
553       }
554     }
555 
556     public Method getCallingMethod() throws Exception {
557       return this.getClass().getMethod("callingFunction");
558     }
559 
560     public Method getCalledMethod() throws Exception {
561       return this.getClass().getMethod("calledFunction");
562     }
563 
564     public String toString() {
565       return "ExceptionThrowFarTestObject { cnt: " + cnt + " }";
566     }
567   }
568 
569   public static class ExceptionOnceObject extends AbstractTestObject {
570     public static final class TestError extends Error {}
571     public int cnt;
572     public final boolean throwInSub;
573     public ExceptionOnceObject(boolean throwInSub) {
574       super();
575       cnt = 0;
576       this.throwInSub = throwInSub;
577     }
578 
579     public void calledFunction() {
580       cnt++;
581       if (cnt == 1) {
582         if (throwInSub) {
583           doThrow();
584         } else {
585           throw new TestError();
586         }
587       }
588     }
589 
590     public void doThrow() {
591       throw new TestError();
592     }
593 
594     public String toString() {
595       return "ExceptionOnceObject { cnt: " + cnt + ", throwInSub: " + throwInSub + " }";
596     }
597   }
598 
599   public static class ExceptionThrowTestObject implements TestRunnable {
600     public static class TestError extends Error {}
601 
602     public int cnt;
603     public int baseCallCnt;
604     public final boolean catchInCalled;
605     public ExceptionThrowTestObject(boolean catchInCalled) {
606       super();
607       cnt = 0;
608       baseCallCnt = 0;
609       this.catchInCalled = catchInCalled;
610     }
611 
612     public int getBaseCallCount() {
613       return baseCallCnt;
614     }
615 
616     public void run() {
617       baseCallCnt++;
618       try {
619         calledFunction();
620       } catch (TestError e) {
621         System.out.println(e.getClass().getName() + " thrown and caught!");
622       }
623     }
624 
625     public void calledFunction() {
626       cnt++;
627       if (catchInCalled) {
628         try {
629           throw new TestError(); // We put a watch here.
630         } catch (TestError e) {
631           System.out.println(e.getClass().getName() + " caught in same function.");
632         }
633       } else {
634         throw new TestError(); // We put a watch here.
635       }
636     }
637 
638     public Method getCalledMethod() throws Exception {
639       return this.getClass().getMethod("calledFunction");
640     }
641 
642     public String toString() {
643       return "ExceptionThrowTestObject { cnt: " + cnt + " }";
644     }
645   }
646 
647   public static class NativeCalledObject extends AbstractTestObject {
648     public int cnt = 0;
649 
650     public native void calledFunction();
651 
652     public String toString() {
653       return "NativeCalledObject { cnt: " + cnt + " }";
654     }
655   }
656 
657   public static class NativeCallerObject implements TestRunnable {
658     public int baseCnt = 0;
659     public int cnt = 0;
660 
661     public int getBaseCallCount() {
662       return baseCnt;
663     }
664 
665     public native void run();
666 
667     public void calledFunction() {
668       cnt++;
669       // We will stop using a MethodExit event.
670     }
671 
672     public Method getCalledMethod() throws Exception {
673       return this.getClass().getMethod("calledFunction");
674     }
675 
676     public String toString() {
677       return "NativeCallerObject { cnt: " + cnt + " }";
678     }
679   }
680   public static class SuspendSuddenlyObject extends AbstractTestObject {
681     public volatile boolean stop_spinning = false;
682     public volatile boolean is_spinning = false;
683     public int cnt = 0;
684 
685     public void calledFunction() {
686       cnt++;
687       while (!stop_spinning) {
688         is_spinning = true;
689       }
690     }
691 
692     public String toString() {
693       return "SuspendSuddenlyObject { cnt: " + cnt + " }";
694     }
695   }
696 
697   public static void run(boolean canRunClassLoadTests) throws Exception {
698     new Test1953(canRunClassLoadTests, (x)-> {}).runTests();
699   }
700 
701   // This entrypoint is used by CTS only. */
702   public static void run() throws Exception {
703     /* TODO: Due to the way that CTS tests are verified we cannot run class-load-tests since the
704      *       verifier will be delayed until runtime and then load the classes all at once. This
705      *       makes the test impossible to run.
706      */
707     run(/*canRunClassLoadTests*/ false);
708   }
709 
710   public Test1953(boolean canRunClassLoadTests, Consumer<TestRunnable> preTest) {
711     this.canRunClassLoadTests = canRunClassLoadTests;
712     this.preTest = preTest;
713   }
714 
715   private Consumer<TestRunnable> preTest;
716 
717   public void runTests() throws Exception {
718     setupTest();
719 
720     final Method calledFunction = StandardTestObject.class.getDeclaredMethod("calledFunction");
721     final Method doNothingMethod = Test1953.class.getDeclaredMethod("doNothing");
722     // Add a breakpoint on the second line after the start of the function
723     final int line = Breakpoint.locationToLine(calledFunction, 0) + 2;
724     final long loc = Breakpoint.lineToLocation(calledFunction, line);
725     System.out.println("Test stopped using breakpoint");
726     runTestOn(new StandardTestObject(),
727         (thr) -> setupSuspendBreakpointFor(calledFunction, loc, thr),
728         SuspendEvents::clearSuspendBreakpointFor);
729 
730     final Method syncFunctionCalledFunction =
731         SynchronizedFunctionTestObject.class.getDeclaredMethod("calledFunction");
732     // Add a breakpoint on the second line after the start of the function
733     // Annoyingly r8 generally has the first instruction (a monitor enter) not be marked as being
734     // on any line but javac has it marked as being on the first line of the function. Just use the
735     // second entry on the line-number table to get the breakpoint. This should be good for both.
736     final long syncFunctionLoc =
737         Breakpoint.getLineNumberTable(syncFunctionCalledFunction)[1].location;
738     System.out.println("Test stopped using breakpoint with declared synchronized function");
739     runTestOn(new SynchronizedFunctionTestObject(),
740         (thr) -> setupSuspendBreakpointFor(syncFunctionCalledFunction, syncFunctionLoc, thr),
741         SuspendEvents::clearSuspendBreakpointFor);
742 
743     final Method syncCalledFunction =
744         SynchronizedTestObject.class.getDeclaredMethod("calledFunction");
745     // Add a breakpoint on the second line after the start of the function
746     final int syncLine = Breakpoint.locationToLine(syncCalledFunction, 0) + 3;
747     final long syncLoc = Breakpoint.lineToLocation(syncCalledFunction, syncLine);
748     System.out.println("Test stopped using breakpoint with synchronized block");
749     Object lock = new Object();
750     synchronized (lock) {}
751     runTestOn(new SynchronizedTestObject(lock),
752         (thr) -> setupSuspendBreakpointFor(syncCalledFunction, syncLoc, thr),
753         SuspendEvents::clearSuspendBreakpointFor);
754     synchronized (lock) {}
755 
756     System.out.println("Test stopped on single step");
757     runTestOn(new StandardTestObject(),
758         (thr) -> setupSuspendSingleStepAt(calledFunction, loc, thr),
759         SuspendEvents::clearSuspendSingleStepFor);
760 
761     final Field target_field = FieldBasedTestObject.class.getDeclaredField("TARGET_FIELD");
762     System.out.println("Test stopped on field access");
763     runTestOn(new FieldBasedTestObject(),
764         (thr) -> setupFieldSuspendFor(FieldBasedTestObject.class, target_field, true, thr),
765         SuspendEvents::clearFieldSuspendFor);
766 
767     System.out.println("Test stopped on field modification");
768     runTestOn(new FieldBasedTestObject(),
769         (thr) -> setupFieldSuspendFor(FieldBasedTestObject.class, target_field, false, thr),
770         SuspendEvents::clearFieldSuspendFor);
771 
772     System.out.println("Test stopped during Method Exit of doNothing");
773     runTestOn(new StandardTestObject(false),
774         (thr) -> setupSuspendMethodEvent(doNothingMethod, /*enter*/ false, thr),
775         SuspendEvents::clearSuspendMethodEvent);
776 
777     // NB We need another test to make sure the MethodEntered event is triggered twice.
778     System.out.println("Test stopped during Method Enter of doNothing");
779     runTestOn(new StandardTestObject(false),
780         (thr) -> setupSuspendMethodEvent(doNothingMethod, /*enter*/ true, thr),
781         SuspendEvents::clearSuspendMethodEvent);
782 
783     System.out.println("Test stopped during Method Exit of calledFunction");
784     runTestOn(new StandardTestObject(false),
785         (thr) -> setupSuspendMethodEvent(calledFunction, /*enter*/ false, thr),
786         SuspendEvents::clearSuspendMethodEvent);
787 
788     System.out.println("Test stopped during Method Enter of calledFunction");
789     runTestOn(new StandardTestObject(false),
790         (thr) -> setupSuspendMethodEvent(calledFunction, /*enter*/ true, thr),
791         SuspendEvents::clearSuspendMethodEvent);
792 
793     final Method exceptionOnceCalledMethod =
794         ExceptionOnceObject.class.getDeclaredMethod("calledFunction");
795     System.out.println("Test stopped during Method Exit due to exception thrown in same function");
796     runTestOn(new ExceptionOnceObject(/*throwInSub*/ false),
797         (thr) -> setupSuspendMethodEvent(exceptionOnceCalledMethod, /*enter*/ false, thr),
798         SuspendEvents::clearSuspendMethodEvent);
799 
800     System.out.println("Test stopped during Method Exit due to exception thrown in subroutine");
801     runTestOn(new ExceptionOnceObject(/*throwInSub*/ true),
802         (thr) -> setupSuspendMethodEvent(exceptionOnceCalledMethod, /*enter*/ false, thr),
803         SuspendEvents::clearSuspendMethodEvent);
804 
805     final Method exceptionThrowCalledMethod =
806         ExceptionThrowTestObject.class.getDeclaredMethod("calledFunction");
807     final Method exceptionCatchThrowMethod =
808         ExceptionCatchTestObject.class.getDeclaredMethod("doThrow");
809     // Disable more often then we technically need to in order to avoid the need
810     // for a huge number of possible results and allow the test to be easily
811     // used in CTS.
812     if (IS_ART && canRunClassLoadTests && CanRunClassLoadingTests()) {
813       System.out.println("Test stopped during notifyFramePop without exception on pop of calledFunction");
814       runTestOn(new StandardTestObject(false),
815           (thr) -> setupSuspendPopFrameEvent(1, doNothingMethod, thr),
816           SuspendEvents::clearSuspendPopFrameEvent);
817 
818       System.out.println("Test stopped during notifyFramePop without exception on pop of doNothing");
819       runTestOn(new StandardTestObject(false),
820           (thr) -> setupSuspendPopFrameEvent(0, doNothingMethod, thr),
821           SuspendEvents::clearSuspendPopFrameEvent);
822 
823       System.out.println("Test stopped during notifyFramePop with exception on pop of calledFunction");
824       runTestOn(new ExceptionThrowTestObject(false),
825           (thr) -> setupSuspendPopFrameEvent(0, exceptionThrowCalledMethod, thr),
826           SuspendEvents::clearSuspendPopFrameEvent);
827 
828       System.out.println("Test stopped during notifyFramePop with exception on pop of doThrow");
829       runTestOn(new ExceptionCatchTestObject(),
830           (thr) -> setupSuspendPopFrameEvent(0, exceptionCatchThrowMethod, thr),
831           SuspendEvents::clearSuspendPopFrameEvent);
832     }
833 
834     System.out.println("Test stopped during ExceptionCatch event of calledFunction " +
835         "(catch in called function, throw in called function)");
836     runTestOn(new ExceptionThrowTestObject(true),
837         (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ true, thr),
838         SuspendEvents::clearSuspendExceptionEvent);
839 
840     final Method exceptionCatchCalledMethod =
841         ExceptionCatchTestObject.class.getDeclaredMethod("calledFunction");
842     System.out.println("Test stopped during ExceptionCatch event of calledFunction " +
843         "(catch in called function, throw in subroutine)");
844     runTestOn(new ExceptionCatchTestObject(),
845         (thr) -> setupSuspendExceptionEvent(exceptionCatchCalledMethod, /*catch*/ true, thr),
846         SuspendEvents::clearSuspendExceptionEvent);
847 
848     System.out.println("Test stopped during Exception event of calledFunction " +
849         "(catch in calling function)");
850     runTestOn(new ExceptionThrowTestObject(false),
851         (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ false, thr),
852         SuspendEvents::clearSuspendExceptionEvent);
853 
854     System.out.println("Test stopped during Exception event of calledFunction " +
855         "(catch in called function)");
856     runTestOn(new ExceptionThrowTestObject(true),
857         (thr) -> setupSuspendExceptionEvent(exceptionThrowCalledMethod, /*catch*/ false, thr),
858         SuspendEvents::clearSuspendExceptionEvent);
859 
860     final Method exceptionThrowFarCalledMethod =
861         ExceptionThrowFarTestObject.class.getDeclaredMethod("calledFunction");
862     System.out.println("Test stopped during Exception event of calledFunction " +
863         "(catch in parent of calling function)");
864     runTestOn(new ExceptionThrowFarTestObject(false),
865         (thr) -> setupSuspendExceptionEvent(exceptionThrowFarCalledMethod, /*catch*/ false, thr),
866         SuspendEvents::clearSuspendExceptionEvent);
867 
868     System.out.println("Test stopped during Exception event of calledFunction " +
869         "(catch in called function)");
870     runTestOn(new ExceptionThrowFarTestObject(true),
871         (thr) -> setupSuspendExceptionEvent(exceptionThrowFarCalledMethod, /*catch*/ false, thr),
872         SuspendEvents::clearSuspendExceptionEvent);
873 
874     // These tests are disabled for either the RI (b/116003018) or for jvmti-stress. For the
875     // later it is due to the additional agent causing classes to be loaded earlier as it forces
876     // deeper verification during class redefinition, causing failures.
877     // NB the agent is prevented from popping frames in either of these events in ART. See
878     // b/117615146 for more information about this restriction.
879     if (canRunClassLoadTests && CanRunClassLoadingTests()) {
880       // This test doesn't work on RI since the RI disallows use of PopFrame during a ClassLoad
881       // event. See b/116003018 for more information.
882       System.out.println("Test stopped during a ClassLoad event.");
883       runTestOn(new ClassLoadObject(),
884           (thr) -> setupSuspendClassEvent(EVENT_TYPE_CLASS_LOAD, ClassLoadObject.CLASS_NAMES, thr),
885           SuspendEvents::clearSuspendClassEvent);
886 
887       // The RI handles a PopFrame during a ClassPrepare event incorrectly. See b/116003018 for
888       // more information.
889       System.out.println("Test stopped during a ClassPrepare event.");
890       runTestOn(new ClassLoadObject(),
891           (thr) -> setupSuspendClassEvent(EVENT_TYPE_CLASS_PREPARE,
892                                           ClassLoadObject.CLASS_NAMES,
893                                           thr),
894           SuspendEvents::clearSuspendClassEvent);
895     }
896     System.out.println("Test stopped during random Suspend.");
897     final SuspendSuddenlyObject sso = new SuspendSuddenlyObject();
898     runTestOn(
899         sso,
900         new TestSuspender() {
901           public void setup(Thread thr) { }
902           public void waitForSuspend(Thread thr) {
903             while (!sso.is_spinning) {}
904             Suspension.suspend(thr);
905           }
906           public void cleanup(Thread thr) {
907             sso.stop_spinning = true;
908           }
909         });
910 
911     final Method redefineCalledFunction =
912        RedefineTestObject.class.getDeclaredMethod("calledFunction");
913     final int redefLine = Breakpoint.locationToLine(redefineCalledFunction, 0) + 2;
914     final long redefLoc = Breakpoint.lineToLocation(redefineCalledFunction, redefLine);
915     System.out.println("Test redefining frame being popped.");
916     runTestOn(new RedefineTestObject(),
917         (thr) -> setupSuspendBreakpointFor(redefineCalledFunction, redefLoc, thr),
918         (thr) -> {
919           clearSuspendBreakpointFor(thr);
920           Redefinition.doCommonClassRedefinition(RedefineTestObject.class,
921                                                  RedefineTestObject.CLASS_BYTES,
922                                                  RedefineTestObject.DEX_BYTES);
923         });
924 
925     System.out.println("Test stopped during a native method fails");
926     runTestOn(new NativeCalledObject(),
927         SuspendEvents::setupWaitForNativeCall,
928         SuspendEvents::clearWaitForNativeCall);
929 
930     System.out.println("Test stopped in a method called by native fails");
931     final Method nativeCallerMethod = NativeCallerObject.class.getDeclaredMethod("calledFunction");
932     runTestOn(new NativeCallerObject(),
933         (thr) -> setupSuspendMethodEvent(nativeCallerMethod, /*enter*/ false, thr),
934         SuspendEvents::clearSuspendMethodEvent);
935 
936 
937     final Object lock2 = new Object();
938     synchronized (lock2) {}
939     System.out.println("Test stopped with monitor in enclosing frame.");
940     runTestOn(new StandardTestObject() {
941           @Override
942           public void run() {
943             synchronized (lock2) {
944               super.run();
945             }
946           }
947         },
948         (thr) -> setupSuspendBreakpointFor(calledFunction, loc, thr),
949         SuspendEvents::clearSuspendBreakpointFor);
950     synchronized (lock2) {}
951   }
952 
953   // Volatile is to prevent any future optimizations that could invalidate this test by doing
954   // constant propagation and eliminating the failing paths before the verifier is able to load the
955   // class.
956   static volatile boolean ranClassLoadTest = false;
957   static boolean classesPreverified = false;
958   private static final class RCLT0 { public void foo() {} }
959   private static final class RCLT1 { public void foo() {} }
960   // If classes are not preverified for some reason (interp-ac, no-image, etc) the verifier will
961   // actually load classes as it runs. This means that we cannot use the class-load tests as they
962   // are written. TODO Support this.
963   public boolean CanRunClassLoadingTests() {
964     if (ranClassLoadTest) {
965       return classesPreverified;
966     }
967     if (!ranClassLoadTest) {
968       // Only this will ever be executed.
969       new RCLT0().foo();
970     } else {
971       // This will never be executed. If classes are not preverified the verifier will load RCLT1
972       // when the enclosing method is run. This behavior makes the class-load/prepare test cases
973       // impossible to successfully run (they will deadlock).
974       new RCLT1().foo();
975       System.out.println("FAILURE: UNREACHABLE Location!");
976     }
977     classesPreverified = !isClassLoaded("Lart/Test1953$RCLT1;");
978     ranClassLoadTest = true;
979     return classesPreverified;
980   }
981 
982   public static native boolean isClassLoaded(String name);
983   public static native void popFrame(Thread thr);
984 }
985