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.io.PrintWriter;
20 import java.io.StringWriter;
21 import java.util.concurrent.Semaphore;
22 import java.util.Arrays;
23 import java.lang.reflect.Executable;
24 import java.lang.reflect.Method;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.function.IntUnaryOperator;
30 import java.util.function.Function;
31 
32 public class Test1925 {
handleFramePop(Executable m, boolean exception, long location)33   public static void handleFramePop(Executable m, boolean exception, long location) {
34     System.out.println(
35         m + " pop. Line=" + Breakpoint.locationToLine(m, location) + " exception:" + exception);
36   }
37 
recurTimesA(int times, Runnable safepoint)38   public static void recurTimesA(int times, Runnable safepoint) {
39     if (times == 0) {
40       safepoint.run();
41       return;
42     }
43     recurTimesB(times - 1, safepoint);
44   }
45 
recurTimesB(int times, Runnable safepoint)46   public static void recurTimesB(int times, Runnable safepoint) {
47     if (times == 0) {
48       safepoint.run();
49       return;
50     }
51     recurTimesC(times - 1, safepoint);
52   }
53 
recurTimesC(int times, Runnable safepoint)54   public static void recurTimesC(int times, Runnable safepoint) {
55     if (times == 0) {
56       safepoint.run();
57       return;
58     }
59     recurTimesD(times - 1, safepoint);
60   }
61 
recurTimesD(int times, Runnable safepoint)62   public static void recurTimesD(int times, Runnable safepoint) {
63     if (times == 0) {
64       safepoint.run();
65       return;
66     }
67     recurTimesE(times - 1, safepoint);
68   }
69 
recurTimesE(int times, Runnable safepoint)70   public static void recurTimesE(int times, Runnable safepoint) {
71     if (times == 0) {
72       safepoint.run();
73       return;
74     }
75     recurTimesF(times - 1, safepoint);
76   }
77 
recurTimesF(int times, Runnable safepoint)78   public static void recurTimesF(int times, Runnable safepoint) {
79     if (times == 0) {
80       safepoint.run();
81       return;
82     }
83     recurTimesG(times - 1, safepoint);
84   }
85 
recurTimesG(int times, Runnable safepoint)86   public static void recurTimesG(int times, Runnable safepoint) {
87     if (times == 0) {
88       safepoint.run();
89       return;
90     }
91     recurTimesH(times - 1, safepoint);
92   }
93 
recurTimesH(int times, Runnable safepoint)94   public static void recurTimesH(int times, Runnable safepoint) {
95     if (times == 0) {
96       safepoint.run();
97       return;
98     }
99     recurTimesI(times - 1, safepoint);
100   }
101 
recurTimesI(int times, Runnable safepoint)102   public static void recurTimesI(int times, Runnable safepoint) {
103     if (times == 0) {
104       safepoint.run();
105       return;
106     }
107     recurTimesJ(times - 1, safepoint);
108   }
109 
recurTimesJ(int times, Runnable safepoint)110   public static void recurTimesJ(int times, Runnable safepoint) {
111     if (times == 0) {
112       safepoint.run();
113       return;
114     }
115     recurTimesK(times - 1, safepoint);
116   }
117 
118   public static class RecursionError extends Error {
RecursionError(String s)119     public RecursionError(String s) { super(s); }
120   }
recurTimesK(int times, Runnable safepoint)121   public static void recurTimesK(int times, Runnable safepoint) {
122     if (times == 0) {
123       safepoint.run();
124       return;
125     }
126     safepoint.run();
127     throw new RecursionError("Unable recur further. Still " + times + " outstanding!");
128   }
129 
doRecurTestWith(final int times, int watch_frame)130   public static void doRecurTestWith(final int times, int watch_frame) throws Exception {
131     final String target_method_name_start = "recurTimes";
132     final Runnable safepoint = () -> {
133       StackTrace.StackFrameData target_frame = null;
134       int cnt = 0;
135       for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(Thread.currentThread())) {
136         if (frame.method.getName().startsWith(target_method_name_start)) {
137           if (times - cnt == watch_frame) {
138             target_frame = frame;
139             break;
140           } else {
141             cnt++;
142           }
143         }
144       }
145       try {
146         FramePop.notifyFramePop(null, target_frame.depth);
147       } catch (Exception e) {
148         throw new Error("Unexpected error in notifyFramePop!", e);
149       }
150     };
151     try {
152       recurTimesA(times, safepoint);
153       System.out.println("Ran recurTimes(" + times + ") without errors!");
154     } catch (Throwable e) {
155       System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")");
156     }
157   }
158 
run()159   public static void run() throws Exception {
160     FramePop.enableFramePopEvent(
161         Test1925.class,
162         Test1925.class.getDeclaredMethod(
163             "handleFramePop", Executable.class, Boolean.TYPE, Long.TYPE),
164         null);
165     doRecurTestWith(10, 5);
166     doRecurTestWith(100, 95);
167   }
168 }
169