1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import java.io.File; 18*795d594fSAndroid Build Coastguard Worker import java.io.FileDescriptor; 19*795d594fSAndroid Build Coastguard Worker import java.io.FileOutputStream; 20*795d594fSAndroid Build Coastguard Worker import java.io.IOException; 21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker public class Main { 24*795d594fSAndroid Build Coastguard Worker private static final String TEMP_FILE_NAME_PREFIX = "test"; 25*795d594fSAndroid Build Coastguard Worker private static final String TEMP_FILE_NAME_SUFFIX = ".trace"; 26*795d594fSAndroid Build Coastguard Worker private static final int WALL_CLOCK_FLAG = 0x010; 27*795d594fSAndroid Build Coastguard Worker private static File file; 28*795d594fSAndroid Build Coastguard Worker main(String[] args)29*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 30*795d594fSAndroid Build Coastguard Worker System.loadLibrary(args[0]); 31*795d594fSAndroid Build Coastguard Worker String name = System.getProperty("java.vm.name"); 32*795d594fSAndroid Build Coastguard Worker if (!"Dalvik".equals(name)) { 33*795d594fSAndroid Build Coastguard Worker System.out.println("This test is not supported on " + name); 34*795d594fSAndroid Build Coastguard Worker return; 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker ensureJitCompiled(Main.class, "$noinline$doSomeWorkJIT"); 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Worker System.out.println("***** streaming test - dual clock *******"); 40*795d594fSAndroid Build Coastguard Worker StreamTraceParser stream_parser = new StreamTraceParser(); 41*795d594fSAndroid Build Coastguard Worker testTracing( 42*795d594fSAndroid Build Coastguard Worker /* streaming=*/true, /* flags= */ 0, stream_parser, 43*795d594fSAndroid Build Coastguard Worker BaseTraceParser.STREAMING_DUAL_CLOCK_VERSION); 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker System.out.println("***** streaming test - wall clock *******"); 46*795d594fSAndroid Build Coastguard Worker StreamTraceParser stream_parser_wall_clock = new StreamTraceParser(); 47*795d594fSAndroid Build Coastguard Worker testTracing( 48*795d594fSAndroid Build Coastguard Worker /* streaming=*/true, /* flags= */ WALL_CLOCK_FLAG, stream_parser, 49*795d594fSAndroid Build Coastguard Worker BaseTraceParser.STREAMING_WALL_CLOCK_VERSION); 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker System.out.println("***** non streaming test - dual clock *******"); 52*795d594fSAndroid Build Coastguard Worker NonStreamTraceParser non_stream_parser = new NonStreamTraceParser(); 53*795d594fSAndroid Build Coastguard Worker testTracing(/* streaming=*/false, /* flags= */ 0, non_stream_parser, 54*795d594fSAndroid Build Coastguard Worker BaseTraceParser.DUAL_CLOCK_VERSION); 55*795d594fSAndroid Build Coastguard Worker 56*795d594fSAndroid Build Coastguard Worker System.out.println("***** non streaming test - wall clock *******"); 57*795d594fSAndroid Build Coastguard Worker NonStreamTraceParser non_stream_parser_wall_clock = new NonStreamTraceParser(); 58*795d594fSAndroid Build Coastguard Worker testTracing(/* streaming=*/false, /* flags= */ WALL_CLOCK_FLAG, 59*795d594fSAndroid Build Coastguard Worker non_stream_parser_wall_clock, BaseTraceParser.WALL_CLOCK_VERSION); 60*795d594fSAndroid Build Coastguard Worker } 61*795d594fSAndroid Build Coastguard Worker testTracing(boolean streaming, int flags, BaseTraceParser parser, int expected_version)62*795d594fSAndroid Build Coastguard Worker public static void testTracing(boolean streaming, int flags, BaseTraceParser parser, 63*795d594fSAndroid Build Coastguard Worker int expected_version) throws Exception { 64*795d594fSAndroid Build Coastguard Worker Main m = new Main(); 65*795d594fSAndroid Build Coastguard Worker Thread t = new Thread(() -> { 66*795d594fSAndroid Build Coastguard Worker try { 67*795d594fSAndroid Build Coastguard Worker file = createTempFile(); 68*795d594fSAndroid Build Coastguard Worker FileOutputStream out_file = new FileOutputStream(file); 69*795d594fSAndroid Build Coastguard Worker VMDebug.startMethodTracing( 70*795d594fSAndroid Build Coastguard Worker file.getPath(), out_file.getFD(), 0, flags, false, 0, streaming); 71*795d594fSAndroid Build Coastguard Worker Main m1 = new Main(); 72*795d594fSAndroid Build Coastguard Worker m1.$noinline$doSomeWork(); 73*795d594fSAndroid Build Coastguard Worker // Call JITed code multiple times to flush out any issues with timestamps. 74*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 20; i++) { 75*795d594fSAndroid Build Coastguard Worker m.$noinline$doSomeWorkJIT(); 76*795d594fSAndroid Build Coastguard Worker } 77*795d594fSAndroid Build Coastguard Worker VMDebug.$noinline$stopMethodTracing(); 78*795d594fSAndroid Build Coastguard Worker out_file.close(); 79*795d594fSAndroid Build Coastguard Worker parser.CheckTraceFileFormat(file, expected_version, "TestThread2246"); 80*795d594fSAndroid Build Coastguard Worker file.delete(); 81*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 82*795d594fSAndroid Build Coastguard Worker System.out.println("Exception in thread " + e); 83*795d594fSAndroid Build Coastguard Worker e.printStackTrace(); 84*795d594fSAndroid Build Coastguard Worker } finally { 85*795d594fSAndroid Build Coastguard Worker file.delete(); 86*795d594fSAndroid Build Coastguard Worker } 87*795d594fSAndroid Build Coastguard Worker }, "TestThread2246"); 88*795d594fSAndroid Build Coastguard Worker try { 89*795d594fSAndroid Build Coastguard Worker if (VMDebug.getMethodTracingMode() != 0) { 90*795d594fSAndroid Build Coastguard Worker VMDebug.$noinline$stopMethodTracing(); 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker t.start(); 94*795d594fSAndroid Build Coastguard Worker t.join(); 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker file = createTempFile(); 97*795d594fSAndroid Build Coastguard Worker FileOutputStream main_out_file = new FileOutputStream(file); 98*795d594fSAndroid Build Coastguard Worker VMDebug.startMethodTracing( 99*795d594fSAndroid Build Coastguard Worker file.getPath(), main_out_file.getFD(), 0, flags, false, 0, streaming); 100*795d594fSAndroid Build Coastguard Worker m.$noinline$doSomeWork(); 101*795d594fSAndroid Build Coastguard Worker // Call JITed code multiple times to flush out any issues with timestamps. 102*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 20; i++) { 103*795d594fSAndroid Build Coastguard Worker m.$noinline$doSomeWorkJIT(); 104*795d594fSAndroid Build Coastguard Worker } 105*795d594fSAndroid Build Coastguard Worker m.doSomeWorkThrow(); 106*795d594fSAndroid Build Coastguard Worker VMDebug.$noinline$stopMethodTracing(); 107*795d594fSAndroid Build Coastguard Worker main_out_file.close(); 108*795d594fSAndroid Build Coastguard Worker parser.CheckTraceFileFormat(file, expected_version, "main"); 109*795d594fSAndroid Build Coastguard Worker file.delete(); 110*795d594fSAndroid Build Coastguard Worker } finally { 111*795d594fSAndroid Build Coastguard Worker file.delete(); 112*795d594fSAndroid Build Coastguard Worker } 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker createTempFile()115*795d594fSAndroid Build Coastguard Worker private static File createTempFile() throws Exception { 116*795d594fSAndroid Build Coastguard Worker try { 117*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 118*795d594fSAndroid Build Coastguard Worker } catch (IOException e) { 119*795d594fSAndroid Build Coastguard Worker System.setProperty("java.io.tmpdir", "/data/local/tmp"); 120*795d594fSAndroid Build Coastguard Worker try { 121*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 122*795d594fSAndroid Build Coastguard Worker } catch (IOException e2) { 123*795d594fSAndroid Build Coastguard Worker System.setProperty("java.io.tmpdir", "/sdcard"); 124*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 125*795d594fSAndroid Build Coastguard Worker } 126*795d594fSAndroid Build Coastguard Worker } 127*795d594fSAndroid Build Coastguard Worker } 128*795d594fSAndroid Build Coastguard Worker callOuterFunction()129*795d594fSAndroid Build Coastguard Worker public void callOuterFunction() { 130*795d594fSAndroid Build Coastguard Worker callLeafFunction(); 131*795d594fSAndroid Build Coastguard Worker } 132*795d594fSAndroid Build Coastguard Worker callLeafFunction()133*795d594fSAndroid Build Coastguard Worker public void callLeafFunction() {} 134*795d594fSAndroid Build Coastguard Worker $noinline$doSomeWork()135*795d594fSAndroid Build Coastguard Worker public void $noinline$doSomeWork() { 136*795d594fSAndroid Build Coastguard Worker callOuterFunction(); 137*795d594fSAndroid Build Coastguard Worker callLeafFunction(); 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker $noinline$doSomeWorkJIT()140*795d594fSAndroid Build Coastguard Worker public void $noinline$doSomeWorkJIT() { 141*795d594fSAndroid Build Coastguard Worker callOuterFunction(); 142*795d594fSAndroid Build Coastguard Worker callLeafFunction(); 143*795d594fSAndroid Build Coastguard Worker } 144*795d594fSAndroid Build Coastguard Worker callThrowFunction()145*795d594fSAndroid Build Coastguard Worker public void callThrowFunction() throws Exception { 146*795d594fSAndroid Build Coastguard Worker throw new Exception("test"); 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker doSomeWorkThrow()149*795d594fSAndroid Build Coastguard Worker public void doSomeWorkThrow() { 150*795d594fSAndroid Build Coastguard Worker try { 151*795d594fSAndroid Build Coastguard Worker callThrowFunction(); 152*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 153*795d594fSAndroid Build Coastguard Worker } 154*795d594fSAndroid Build Coastguard Worker } 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker private static class VMDebug { 157*795d594fSAndroid Build Coastguard Worker private static final Method startMethodTracingMethod; 158*795d594fSAndroid Build Coastguard Worker private static final Method stopMethodTracingMethod; 159*795d594fSAndroid Build Coastguard Worker private static final Method getMethodTracingModeMethod; 160*795d594fSAndroid Build Coastguard Worker static { 161*795d594fSAndroid Build Coastguard Worker try { 162*795d594fSAndroid Build Coastguard Worker Class<?> c = Class.forName("dalvik.system.VMDebug"); 163*795d594fSAndroid Build Coastguard Worker startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class, 164*795d594fSAndroid Build Coastguard Worker FileDescriptor.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE, 165*795d594fSAndroid Build Coastguard Worker Integer.TYPE, Boolean.TYPE); 166*795d594fSAndroid Build Coastguard Worker stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing"); 167*795d594fSAndroid Build Coastguard Worker getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode"); 168*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 169*795d594fSAndroid Build Coastguard Worker throw new RuntimeException(e); 170*795d594fSAndroid Build Coastguard Worker } 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker startMethodTracing(String filename, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs, boolean streaming)173*795d594fSAndroid Build Coastguard Worker public static void startMethodTracing(String filename, FileDescriptor fd, int bufferSize, 174*795d594fSAndroid Build Coastguard Worker int flags, boolean samplingEnabled, int intervalUs, boolean streaming) 175*795d594fSAndroid Build Coastguard Worker throws Exception { 176*795d594fSAndroid Build Coastguard Worker startMethodTracingMethod.invoke( 177*795d594fSAndroid Build Coastguard Worker null, filename, fd, bufferSize, flags, samplingEnabled, intervalUs, streaming); 178*795d594fSAndroid Build Coastguard Worker } $noinline$stopMethodTracing()179*795d594fSAndroid Build Coastguard Worker public static void $noinline$stopMethodTracing() throws Exception { 180*795d594fSAndroid Build Coastguard Worker stopMethodTracingMethod.invoke(null); 181*795d594fSAndroid Build Coastguard Worker } getMethodTracingMode()182*795d594fSAndroid Build Coastguard Worker public static int getMethodTracingMode() throws Exception { 183*795d594fSAndroid Build Coastguard Worker return (int) getMethodTracingModeMethod.invoke(null); 184*795d594fSAndroid Build Coastguard Worker } 185*795d594fSAndroid Build Coastguard Worker } 186*795d594fSAndroid Build Coastguard Worker ensureJitCompiled(Class<?> cls, String methodName)187*795d594fSAndroid Build Coastguard Worker private static native void ensureJitCompiled(Class<?> cls, String methodName); 188*795d594fSAndroid Build Coastguard Worker } 189