Test1923.java revision e814f9d09c0fb1b678e610780d11ce3577db3599
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 17package art; 18 19import java.io.PrintWriter; 20import java.io.StringWriter; 21import java.util.concurrent.Semaphore; 22import java.util.Arrays; 23import java.lang.reflect.Executable; 24import java.lang.reflect.Method; 25import java.util.List; 26import java.util.Set; 27import java.util.ArrayList; 28import java.util.HashSet; 29import java.util.function.IntUnaryOperator; 30import java.util.function.Function; 31 32public class Test1923 { 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 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 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 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 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 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 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 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 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 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 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 { 119 public RecursionError(String s) { super(s); } 120 } 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 130 public static class ThreadPauser implements Runnable { 131 public final Semaphore sem_wakeup_main; 132 public final Semaphore sem_wait; 133 134 public ThreadPauser() { 135 sem_wakeup_main = new Semaphore(0); 136 sem_wait = new Semaphore(0); 137 } 138 139 public void run() { 140 try { 141 sem_wakeup_main.release(); 142 sem_wait.acquire(); 143 } catch (Exception e) { 144 throw new Error("Error with semaphores!", e); 145 } 146 } 147 148 public void waitForOtherThreadToPause() throws Exception { 149 sem_wakeup_main.acquire(); 150 } 151 152 public void wakeupOtherThread() throws Exception { 153 sem_wait.release(); 154 } 155 } 156 157 public static void doRecurTestWith(final int times, int watch_frame) throws Exception { 158 final String target_method_name_start = "recurTimes"; 159 final ThreadPauser safepoint = new ThreadPauser(); 160 Thread target = new Thread(() -> { 161 try { 162 recurTimesA(times, safepoint); 163 System.out.println("Ran recurTimes(" + times + ") without errors!"); 164 } catch (RecursionError e) { 165 System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")"); 166 } 167 }); 168 target.start(); 169 safepoint.waitForOtherThreadToPause(); 170 Suspension.suspend(target); 171 // Safe block 172 int cnt = 0; 173 StackTrace.StackFrameData target_frame = null; 174 for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(target)) { 175 if (frame.method.getName().startsWith(target_method_name_start)) { 176 if (times - cnt == watch_frame) { 177 target_frame = frame; 178 break; 179 } else { 180 cnt++; 181 } 182 } 183 } 184 if (target_frame != null) { 185 FramePop.notifyFramePop(target, target_frame.depth); 186 } else { 187 System.out.println( 188 "Unable to find stack frame for " + watch_frame + " depth of " 189 + target_method_name_start); 190 } 191 Suspension.resume(target); 192 safepoint.wakeupOtherThread(); 193 target.join(); 194 } 195 196 public static void run() throws Exception { 197 // TODO Investigate what thread argument means for FramePop event enable. 198 // Listen for events on all threads. 199 FramePop.enableFramePopEvent( 200 Test1923.class, 201 Test1923.class.getDeclaredMethod( 202 "handleFramePop", Executable.class, Boolean.TYPE, Long.TYPE), 203 null); 204 doRecurTestWith(10, 0); 205 doRecurTestWith(10, 5); 206 doRecurTestWith(10, 10); 207 doRecurTestWith(100, 95); 208 } 209} 210