1e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light/* 2e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * Copyright (C) 2017 The Android Open Source Project 3e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * 4e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * Licensed under the Apache License, Version 2.0 (the "License"); 5e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * you may not use this file except in compliance with the License. 6e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * You may obtain a copy of the License at 7e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * 8e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * http://www.apache.org/licenses/LICENSE-2.0 9e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * 10e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * Unless required by applicable law or agreed to in writing, software 11e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * distributed under the License is distributed on an "AS IS" BASIS, 12e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * See the License for the specific language governing permissions and 14e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light * limitations under the License. 15e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light */ 16e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 17e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightpackage art; 18e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 19e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.io.PrintWriter; 20e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.io.StringWriter; 21e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.concurrent.Semaphore; 22e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.Arrays; 23e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.lang.reflect.Executable; 24e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.lang.reflect.Method; 25e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.List; 26e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.Set; 27e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.ArrayList; 28e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.HashSet; 29e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.function.IntUnaryOperator; 30e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightimport java.util.function.Function; 31e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 32e814f9d09c0fb1b678e610780d11ce3577db3599Alex Lightpublic class Test1925 { 33e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void handleFramePop(Executable m, boolean exception, long location) { 34e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light System.out.println( 35e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light m + " pop. Line=" + Breakpoint.locationToLine(m, location) + " exception:" + exception); 36e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 37e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 38e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesA(int times, Runnable safepoint) { 39e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 40e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 41e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 42e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 43e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesB(times - 1, safepoint); 44e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 45e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 46e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesB(int times, Runnable safepoint) { 47e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 48e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 49e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 50e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 51e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesC(times - 1, safepoint); 52e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 53e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 54e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesC(int times, Runnable safepoint) { 55e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 56e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 57e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 58e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 59e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesD(times - 1, safepoint); 60e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 61e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 62e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesD(int times, Runnable safepoint) { 63e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 64e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 65e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 66e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 67e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesE(times - 1, safepoint); 68e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 69e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 70e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesE(int times, Runnable safepoint) { 71e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 72e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 73e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 74e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 75e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesF(times - 1, safepoint); 76e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 77e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 78e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesF(int times, Runnable safepoint) { 79e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 80e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 81e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 82e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 83e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesG(times - 1, safepoint); 84e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 85e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 86e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesG(int times, Runnable safepoint) { 87e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 88e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 89e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 90e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 91e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesH(times - 1, safepoint); 92e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 93e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 94e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesH(int times, Runnable safepoint) { 95e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 96e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 97e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 98e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 99e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesI(times - 1, safepoint); 100e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 101e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 102e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesI(int times, Runnable safepoint) { 103e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 104e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 105e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 106e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 107e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesJ(times - 1, safepoint); 108e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 109e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 110e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesJ(int times, Runnable safepoint) { 111e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 112e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 113e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 114e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 115e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesK(times - 1, safepoint); 116e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 117e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 118e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static class RecursionError extends Error { 119e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public RecursionError(String s) { super(s); } 120e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 121e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void recurTimesK(int times, Runnable safepoint) { 122e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times == 0) { 123e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 124e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light return; 125e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 126e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light safepoint.run(); 127e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light throw new RecursionError("Unable recur further. Still " + times + " outstanding!"); 128e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 129e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 130e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void doRecurTestWith(final int times, int watch_frame) throws Exception { 131e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light final String target_method_name_start = "recurTimes"; 132e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light final Runnable safepoint = () -> { 133e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light StackTrace.StackFrameData target_frame = null; 134e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light int cnt = 0; 135e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light for (StackTrace.StackFrameData frame : StackTrace.GetStackTrace(Thread.currentThread())) { 136e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (frame.method.getName().startsWith(target_method_name_start)) { 137e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light if (times - cnt == watch_frame) { 138e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light target_frame = frame; 139e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light break; 140e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } else { 141e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light cnt++; 142e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 143e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 144e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 145e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light try { 146e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light FramePop.notifyFramePop(null, target_frame.depth); 147e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } catch (Exception e) { 148e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light throw new Error("Unexpected error in notifyFramePop!", e); 149e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 150e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light }; 151e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light try { 152e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light recurTimesA(times, safepoint); 153e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light System.out.println("Ran recurTimes(" + times + ") without errors!"); 154e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } catch (Throwable e) { 155e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")"); 156e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 157e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 158e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light 159e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light public static void run() throws Exception { 160e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light FramePop.enableFramePopEvent( 161e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light Test1925.class, 162e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light Test1925.class.getDeclaredMethod( 163e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light "handleFramePop", Executable.class, Boolean.TYPE, Long.TYPE), 164e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light null); 165e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light doRecurTestWith(10, 5); 166e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light doRecurTestWith(100, 95); 167e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light } 168e814f9d09c0fb1b678e610780d11ce3577db3599Alex Light} 169