xref: /aosp_15_r20/art/test/2246-trace-v2/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2024 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 final int TRACE_OUTPUT_V2_FLAG = 0b010;
28*795d594fSAndroid Build Coastguard Worker     private static final int STREAMING_DUAL_CLOCK_VERSION = 1;
29*795d594fSAndroid Build Coastguard Worker     private static final int STREAMING_WALL_CLOCK_VERSION = 1;
30*795d594fSAndroid Build Coastguard Worker     private static File file;
31*795d594fSAndroid Build Coastguard Worker 
main(String[] args)32*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Exception {
33*795d594fSAndroid Build Coastguard Worker         System.loadLibrary(args[0]);
34*795d594fSAndroid Build Coastguard Worker         String name = System.getProperty("java.vm.name");
35*795d594fSAndroid Build Coastguard Worker         if (!"Dalvik".equals(name)) {
36*795d594fSAndroid Build Coastguard Worker             System.out.println("This test is not supported on " + name);
37*795d594fSAndroid Build Coastguard Worker             return;
38*795d594fSAndroid Build Coastguard Worker         }
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker         ensureJitCompiled(Main.class, "$noinline$doSomeWorkJIT");
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker         System.out.println("***** streaming test - dual clock *******");
43*795d594fSAndroid Build Coastguard Worker         testTracing(/* streaming=*/true, /* flags= */ 0);
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker         System.out.println("***** streaming test - wall clock *******");
46*795d594fSAndroid Build Coastguard Worker         testTracing(/* streaming=*/true, /* flags= */ WALL_CLOCK_FLAG);
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker         System.out.println("***** non-streaming test - dual clock *******");
49*795d594fSAndroid Build Coastguard Worker         testTracing(/* streaming=*/false, /* flags= */ 0);
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker         System.out.println("***** non-streaming test - wall clock *******");
52*795d594fSAndroid Build Coastguard Worker         testTracing(/* streaming=*/false, /* flags= */ WALL_CLOCK_FLAG);
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker 
testTracing(boolean streaming, int flags)55*795d594fSAndroid Build Coastguard Worker     public static void testTracing(boolean streaming, int flags) throws Exception {
56*795d594fSAndroid Build Coastguard Worker         Main m = new Main();
57*795d594fSAndroid Build Coastguard Worker         Thread t = new Thread(() -> {
58*795d594fSAndroid Build Coastguard Worker             try {
59*795d594fSAndroid Build Coastguard Worker                 file = createTempFile();
60*795d594fSAndroid Build Coastguard Worker                 FileOutputStream out_file = new FileOutputStream(file);
61*795d594fSAndroid Build Coastguard Worker                 VMDebug.startMethodTracingV2(
62*795d594fSAndroid Build Coastguard Worker                         file.getPath(), out_file.getFD(), 0, flags, false, 0, streaming);
63*795d594fSAndroid Build Coastguard Worker                 Main m1 = new Main();
64*795d594fSAndroid Build Coastguard Worker                 m1.$noinline$doSomeWork();
65*795d594fSAndroid Build Coastguard Worker                 // Call JITed code multiple times to flush out any issues with timestamps.
66*795d594fSAndroid Build Coastguard Worker                 for (int i = 0; i < 20; i++) {
67*795d594fSAndroid Build Coastguard Worker                     m.$noinline$doSomeWorkJIT();
68*795d594fSAndroid Build Coastguard Worker                 }
69*795d594fSAndroid Build Coastguard Worker                 VMDebug.$noinline$stopMethodTracing();
70*795d594fSAndroid Build Coastguard Worker                 out_file.close();
71*795d594fSAndroid Build Coastguard Worker                 dumpTrace(file.getAbsolutePath(), "TestThread2246");
72*795d594fSAndroid Build Coastguard Worker                 file.delete();
73*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
74*795d594fSAndroid Build Coastguard Worker                 System.out.println("Exception in thread " + e);
75*795d594fSAndroid Build Coastguard Worker                 e.printStackTrace();
76*795d594fSAndroid Build Coastguard Worker             } finally {
77*795d594fSAndroid Build Coastguard Worker                 file.delete();
78*795d594fSAndroid Build Coastguard Worker             }
79*795d594fSAndroid Build Coastguard Worker         }, "TestThread2246");
80*795d594fSAndroid Build Coastguard Worker         try {
81*795d594fSAndroid Build Coastguard Worker             if (VMDebug.getMethodTracingMode() != 0) {
82*795d594fSAndroid Build Coastguard Worker                 VMDebug.$noinline$stopMethodTracing();
83*795d594fSAndroid Build Coastguard Worker             }
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker             t.start();
86*795d594fSAndroid Build Coastguard Worker             t.join();
87*795d594fSAndroid Build Coastguard Worker 
88*795d594fSAndroid Build Coastguard Worker             file = createTempFile();
89*795d594fSAndroid Build Coastguard Worker             FileOutputStream main_out_file = new FileOutputStream(file);
90*795d594fSAndroid Build Coastguard Worker             VMDebug.startMethodTracingV2(
91*795d594fSAndroid Build Coastguard Worker                     file.getPath(), main_out_file.getFD(), 0, flags, false, 0, streaming);
92*795d594fSAndroid Build Coastguard Worker             m.$noinline$doSomeWork();
93*795d594fSAndroid Build Coastguard Worker             // Call JITed code multiple times to flush out any issues with timestamps.
94*795d594fSAndroid Build Coastguard Worker             for (int i = 0; i < 20; i++) {
95*795d594fSAndroid Build Coastguard Worker                 m.$noinline$doSomeWorkJIT();
96*795d594fSAndroid Build Coastguard Worker             }
97*795d594fSAndroid Build Coastguard Worker             m.doSomeWorkThrow();
98*795d594fSAndroid Build Coastguard Worker             VMDebug.$noinline$stopMethodTracing();
99*795d594fSAndroid Build Coastguard Worker             main_out_file.close();
100*795d594fSAndroid Build Coastguard Worker             dumpTrace(file.getAbsolutePath(), "main");
101*795d594fSAndroid Build Coastguard Worker             file.delete();
102*795d594fSAndroid Build Coastguard Worker         } finally {
103*795d594fSAndroid Build Coastguard Worker             file.delete();
104*795d594fSAndroid Build Coastguard Worker         }
105*795d594fSAndroid Build Coastguard Worker     }
106*795d594fSAndroid Build Coastguard Worker 
createTempFile()107*795d594fSAndroid Build Coastguard Worker     private static File createTempFile() throws Exception {
108*795d594fSAndroid Build Coastguard Worker         try {
109*795d594fSAndroid Build Coastguard Worker             return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
110*795d594fSAndroid Build Coastguard Worker         } catch (IOException e) {
111*795d594fSAndroid Build Coastguard Worker             System.setProperty("java.io.tmpdir", "/data/local/tmp");
112*795d594fSAndroid Build Coastguard Worker             try {
113*795d594fSAndroid Build Coastguard Worker                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
114*795d594fSAndroid Build Coastguard Worker             } catch (IOException e2) {
115*795d594fSAndroid Build Coastguard Worker                 System.setProperty("java.io.tmpdir", "/sdcard");
116*795d594fSAndroid Build Coastguard Worker                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
117*795d594fSAndroid Build Coastguard Worker             }
118*795d594fSAndroid Build Coastguard Worker         }
119*795d594fSAndroid Build Coastguard Worker     }
120*795d594fSAndroid Build Coastguard Worker 
callOuterFunction()121*795d594fSAndroid Build Coastguard Worker     public void callOuterFunction() {
122*795d594fSAndroid Build Coastguard Worker         callLeafFunction();
123*795d594fSAndroid Build Coastguard Worker     }
124*795d594fSAndroid Build Coastguard Worker 
callLeafFunction()125*795d594fSAndroid Build Coastguard Worker     public void callLeafFunction() {}
126*795d594fSAndroid Build Coastguard Worker 
$noinline$doSomeWork()127*795d594fSAndroid Build Coastguard Worker     public void $noinline$doSomeWork() {
128*795d594fSAndroid Build Coastguard Worker         callOuterFunction();
129*795d594fSAndroid Build Coastguard Worker         callLeafFunction();
130*795d594fSAndroid Build Coastguard Worker     }
131*795d594fSAndroid Build Coastguard Worker 
$noinline$doSomeWorkJIT()132*795d594fSAndroid Build Coastguard Worker     public void $noinline$doSomeWorkJIT() {
133*795d594fSAndroid Build Coastguard Worker         callOuterFunction();
134*795d594fSAndroid Build Coastguard Worker         callLeafFunction();
135*795d594fSAndroid Build Coastguard Worker     }
136*795d594fSAndroid Build Coastguard Worker 
callThrowFunction()137*795d594fSAndroid Build Coastguard Worker     public void callThrowFunction() throws Exception {
138*795d594fSAndroid Build Coastguard Worker         throw new Exception("test");
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker 
doSomeWorkThrow()141*795d594fSAndroid Build Coastguard Worker     public void doSomeWorkThrow() {
142*795d594fSAndroid Build Coastguard Worker         try {
143*795d594fSAndroid Build Coastguard Worker             callThrowFunction();
144*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
145*795d594fSAndroid Build Coastguard Worker         }
146*795d594fSAndroid Build Coastguard Worker     }
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker     private static class VMDebug {
149*795d594fSAndroid Build Coastguard Worker         private static final Method startMethodTracingMethod;
150*795d594fSAndroid Build Coastguard Worker         private static final Method stopMethodTracingMethod;
151*795d594fSAndroid Build Coastguard Worker         private static final Method getMethodTracingModeMethod;
152*795d594fSAndroid Build Coastguard Worker         static {
153*795d594fSAndroid Build Coastguard Worker             try {
154*795d594fSAndroid Build Coastguard Worker                 Class<?> c = Class.forName("dalvik.system.VMDebug");
155*795d594fSAndroid Build Coastguard Worker                 startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class,
156*795d594fSAndroid Build Coastguard Worker                         FileDescriptor.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE,
157*795d594fSAndroid Build Coastguard Worker                         Integer.TYPE, Boolean.TYPE);
158*795d594fSAndroid Build Coastguard Worker                 stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing");
159*795d594fSAndroid Build Coastguard Worker                 getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode");
160*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
161*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException(e);
162*795d594fSAndroid Build Coastguard Worker             }
163*795d594fSAndroid Build Coastguard Worker         }
164*795d594fSAndroid Build Coastguard Worker 
startMethodTracingV2(String filename, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs, boolean streaming)165*795d594fSAndroid Build Coastguard Worker         public static void startMethodTracingV2(String filename, FileDescriptor fd, int bufferSize,
166*795d594fSAndroid Build Coastguard Worker                 int flags, boolean samplingEnabled, int intervalUs, boolean streaming)
167*795d594fSAndroid Build Coastguard Worker                 throws Exception {
168*795d594fSAndroid Build Coastguard Worker             startMethodTracingMethod.invoke(null, filename, fd, bufferSize,
169*795d594fSAndroid Build Coastguard Worker                     flags | TRACE_OUTPUT_V2_FLAG, samplingEnabled, intervalUs, streaming);
170*795d594fSAndroid Build Coastguard Worker         }
$noinline$stopMethodTracing()171*795d594fSAndroid Build Coastguard Worker         public static void $noinline$stopMethodTracing() throws Exception {
172*795d594fSAndroid Build Coastguard Worker             stopMethodTracingMethod.invoke(null);
173*795d594fSAndroid Build Coastguard Worker         }
getMethodTracingMode()174*795d594fSAndroid Build Coastguard Worker         public static int getMethodTracingMode() throws Exception {
175*795d594fSAndroid Build Coastguard Worker             return (int) getMethodTracingModeMethod.invoke(null);
176*795d594fSAndroid Build Coastguard Worker         }
177*795d594fSAndroid Build Coastguard Worker     }
178*795d594fSAndroid Build Coastguard Worker 
ensureJitCompiled(Class<?> cls, String methodName)179*795d594fSAndroid Build Coastguard Worker     private static native void ensureJitCompiled(Class<?> cls, String methodName);
dumpTrace(String fileName, String threadName)180*795d594fSAndroid Build Coastguard Worker     private static native void dumpTrace(String fileName, String threadName);
181*795d594fSAndroid Build Coastguard Worker }
182