1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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.IOException; 19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 20*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.ConcurrentSkipListMap; 21*795d594fSAndroid Build Coastguard Worker import java.util.HashMap; 22*795d594fSAndroid Build Coastguard Worker import java.util.HashSet; 23*795d594fSAndroid Build Coastguard Worker import java.util.LinkedHashMap; 24*795d594fSAndroid Build Coastguard Worker import java.util.LinkedHashSet; 25*795d594fSAndroid Build Coastguard Worker import java.util.Map; 26*795d594fSAndroid Build Coastguard Worker import java.util.Set; 27*795d594fSAndroid Build Coastguard Worker import java.util.TreeMap; 28*795d594fSAndroid Build Coastguard Worker import java.util.TreeSet; 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker public class Main { 31*795d594fSAndroid Build Coastguard Worker private static final String TEMP_FILE_NAME_PREFIX = "test"; 32*795d594fSAndroid Build Coastguard Worker private static final String TEMP_FILE_NAME_SUFFIX = ".trace"; 33*795d594fSAndroid Build Coastguard Worker private static File file; 34*795d594fSAndroid Build Coastguard Worker main(String[] args)35*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 36*795d594fSAndroid Build Coastguard Worker String name = System.getProperty("java.vm.name"); 37*795d594fSAndroid Build Coastguard Worker if (!"Dalvik".equals(name)) { 38*795d594fSAndroid Build Coastguard Worker System.out.println("This test is not supported on " + name); 39*795d594fSAndroid Build Coastguard Worker return; 40*795d594fSAndroid Build Coastguard Worker } 41*795d594fSAndroid Build Coastguard Worker file = createTempFile(); 42*795d594fSAndroid Build Coastguard Worker try { 43*795d594fSAndroid Build Coastguard Worker new Main().ensureCaller(true, 0); 44*795d594fSAndroid Build Coastguard Worker new Main().ensureCaller(false, 0); 45*795d594fSAndroid Build Coastguard Worker } finally { 46*795d594fSAndroid Build Coastguard Worker if (file != null) { 47*795d594fSAndroid Build Coastguard Worker file.delete(); 48*795d594fSAndroid Build Coastguard Worker } 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker } 51*795d594fSAndroid Build Coastguard Worker createTempFile()52*795d594fSAndroid Build Coastguard Worker private static File createTempFile() throws Exception { 53*795d594fSAndroid Build Coastguard Worker try { 54*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 55*795d594fSAndroid Build Coastguard Worker } catch (IOException e) { 56*795d594fSAndroid Build Coastguard Worker System.setProperty("java.io.tmpdir", "/data/local/tmp"); 57*795d594fSAndroid Build Coastguard Worker try { 58*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 59*795d594fSAndroid Build Coastguard Worker } catch (IOException e2) { 60*795d594fSAndroid Build Coastguard Worker System.setProperty("java.io.tmpdir", "/sdcard"); 61*795d594fSAndroid Build Coastguard Worker return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX); 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker } 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker // We make sure 'doLoadsOfStuff' has a caller, because it is this caller that will be 67*795d594fSAndroid Build Coastguard Worker // pushed in the side instrumentation frame. ensureCaller(boolean warmup, int invocationCount)68*795d594fSAndroid Build Coastguard Worker public void ensureCaller(boolean warmup, int invocationCount) throws Exception { 69*795d594fSAndroid Build Coastguard Worker doLoadsOfStuff(warmup, invocationCount); 70*795d594fSAndroid Build Coastguard Worker } 71*795d594fSAndroid Build Coastguard Worker 72*795d594fSAndroid Build Coastguard Worker // The number of recursive calls we are going to do in 'doLoadsOfStuff' to ensure 73*795d594fSAndroid Build Coastguard Worker // the JIT sees it hot. 74*795d594fSAndroid Build Coastguard Worker static final int NUMBER_OF_INVOCATIONS = 5; 75*795d594fSAndroid Build Coastguard Worker doLoadsOfStuff(boolean warmup, int invocationCount)76*795d594fSAndroid Build Coastguard Worker public void doLoadsOfStuff(boolean warmup, int invocationCount) throws Exception { 77*795d594fSAndroid Build Coastguard Worker // Warmup is to make sure the JIT gets a chance to compile 'doLoadsOfStuff'. 78*795d594fSAndroid Build Coastguard Worker if (warmup) { 79*795d594fSAndroid Build Coastguard Worker if (invocationCount < NUMBER_OF_INVOCATIONS) { 80*795d594fSAndroid Build Coastguard Worker doLoadsOfStuff(warmup, ++invocationCount); 81*795d594fSAndroid Build Coastguard Worker } else { 82*795d594fSAndroid Build Coastguard Worker // Give the JIT a chance to compiler. 83*795d594fSAndroid Build Coastguard Worker Thread.sleep(1000); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker } else { 86*795d594fSAndroid Build Coastguard Worker if (invocationCount == 0) { 87*795d594fSAndroid Build Coastguard Worker // When running the trace in trace mode, there is already a trace running. 88*795d594fSAndroid Build Coastguard Worker if (VMDebug.getMethodTracingMode() != 0) { 89*795d594fSAndroid Build Coastguard Worker VMDebug.stopMethodTracing(); 90*795d594fSAndroid Build Coastguard Worker } 91*795d594fSAndroid Build Coastguard Worker VMDebug.startMethodTracing(file.getPath(), 0, 0, false, 0); 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker fillJit(); 94*795d594fSAndroid Build Coastguard Worker if (invocationCount < NUMBER_OF_INVOCATIONS) { 95*795d594fSAndroid Build Coastguard Worker doLoadsOfStuff(warmup, ++invocationCount); 96*795d594fSAndroid Build Coastguard Worker } else { 97*795d594fSAndroid Build Coastguard Worker VMDebug.stopMethodTracing(); 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker } 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker // This method creates enough profiling data to fill the code cache and trigger 103*795d594fSAndroid Build Coastguard Worker // a collection in debug mode (at the time of the test 10KB of data space). We 104*795d594fSAndroid Build Coastguard Worker // used to crash by not looking at the instrumentation stack and deleting JIT code 105*795d594fSAndroid Build Coastguard Worker // that will be later restored by the instrumentation. fillJit()106*795d594fSAndroid Build Coastguard Worker public static void fillJit() throws Exception { 107*795d594fSAndroid Build Coastguard Worker Map map = new HashMap(); 108*795d594fSAndroid Build Coastguard Worker map.put("foo", "bar"); 109*795d594fSAndroid Build Coastguard Worker map.clear(); 110*795d594fSAndroid Build Coastguard Worker map.containsKey("foo"); 111*795d594fSAndroid Build Coastguard Worker map.containsValue("foo"); 112*795d594fSAndroid Build Coastguard Worker map.entrySet(); 113*795d594fSAndroid Build Coastguard Worker map.equals(map); 114*795d594fSAndroid Build Coastguard Worker map.hashCode(); 115*795d594fSAndroid Build Coastguard Worker map.isEmpty(); 116*795d594fSAndroid Build Coastguard Worker map.keySet(); 117*795d594fSAndroid Build Coastguard Worker map.putAll(map); 118*795d594fSAndroid Build Coastguard Worker map.remove("foo"); 119*795d594fSAndroid Build Coastguard Worker map.size(); 120*795d594fSAndroid Build Coastguard Worker map.put("bar", "foo"); 121*795d594fSAndroid Build Coastguard Worker map.values(); 122*795d594fSAndroid Build Coastguard Worker 123*795d594fSAndroid Build Coastguard Worker map = new LinkedHashMap(); 124*795d594fSAndroid Build Coastguard Worker map.put("foo", "bar"); 125*795d594fSAndroid Build Coastguard Worker map.clear(); 126*795d594fSAndroid Build Coastguard Worker map.containsKey("foo"); 127*795d594fSAndroid Build Coastguard Worker map.containsValue("foo"); 128*795d594fSAndroid Build Coastguard Worker map.entrySet(); 129*795d594fSAndroid Build Coastguard Worker map.equals(map); 130*795d594fSAndroid Build Coastguard Worker map.hashCode(); 131*795d594fSAndroid Build Coastguard Worker map.isEmpty(); 132*795d594fSAndroid Build Coastguard Worker map.keySet(); 133*795d594fSAndroid Build Coastguard Worker map.putAll(map); 134*795d594fSAndroid Build Coastguard Worker map.remove("foo"); 135*795d594fSAndroid Build Coastguard Worker map.size(); 136*795d594fSAndroid Build Coastguard Worker map.put("bar", "foo"); 137*795d594fSAndroid Build Coastguard Worker map.values(); 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker map = new TreeMap(); 140*795d594fSAndroid Build Coastguard Worker map.put("foo", "bar"); 141*795d594fSAndroid Build Coastguard Worker map.clear(); 142*795d594fSAndroid Build Coastguard Worker map.containsKey("foo"); 143*795d594fSAndroid Build Coastguard Worker map.containsValue("foo"); 144*795d594fSAndroid Build Coastguard Worker map.entrySet(); 145*795d594fSAndroid Build Coastguard Worker map.equals(map); 146*795d594fSAndroid Build Coastguard Worker map.hashCode(); 147*795d594fSAndroid Build Coastguard Worker map.isEmpty(); 148*795d594fSAndroid Build Coastguard Worker map.keySet(); 149*795d594fSAndroid Build Coastguard Worker map.putAll(map); 150*795d594fSAndroid Build Coastguard Worker map.remove("foo"); 151*795d594fSAndroid Build Coastguard Worker map.size(); 152*795d594fSAndroid Build Coastguard Worker map.put("bar", "foo"); 153*795d594fSAndroid Build Coastguard Worker map.values(); 154*795d594fSAndroid Build Coastguard Worker 155*795d594fSAndroid Build Coastguard Worker map = new ConcurrentSkipListMap(); 156*795d594fSAndroid Build Coastguard Worker map.put("foo", "bar"); 157*795d594fSAndroid Build Coastguard Worker map.clear(); 158*795d594fSAndroid Build Coastguard Worker map.containsKey("foo"); 159*795d594fSAndroid Build Coastguard Worker map.containsValue("foo"); 160*795d594fSAndroid Build Coastguard Worker map.entrySet(); 161*795d594fSAndroid Build Coastguard Worker map.equals(map); 162*795d594fSAndroid Build Coastguard Worker map.hashCode(); 163*795d594fSAndroid Build Coastguard Worker map.isEmpty(); 164*795d594fSAndroid Build Coastguard Worker map.keySet(); 165*795d594fSAndroid Build Coastguard Worker map.putAll(map); 166*795d594fSAndroid Build Coastguard Worker map.remove("foo"); 167*795d594fSAndroid Build Coastguard Worker map.size(); 168*795d594fSAndroid Build Coastguard Worker map.put("bar", "foo"); 169*795d594fSAndroid Build Coastguard Worker map.values(); 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker Set set = new HashSet(); 172*795d594fSAndroid Build Coastguard Worker set.add("foo"); 173*795d594fSAndroid Build Coastguard Worker set.addAll(set); 174*795d594fSAndroid Build Coastguard Worker set.clear(); 175*795d594fSAndroid Build Coastguard Worker set.contains("foo"); 176*795d594fSAndroid Build Coastguard Worker set.containsAll(set); 177*795d594fSAndroid Build Coastguard Worker set.equals(set); 178*795d594fSAndroid Build Coastguard Worker set.hashCode(); 179*795d594fSAndroid Build Coastguard Worker set.isEmpty(); 180*795d594fSAndroid Build Coastguard Worker set.iterator(); 181*795d594fSAndroid Build Coastguard Worker set.remove("foo"); 182*795d594fSAndroid Build Coastguard Worker set.removeAll(set); 183*795d594fSAndroid Build Coastguard Worker set.retainAll(set); 184*795d594fSAndroid Build Coastguard Worker set.size(); 185*795d594fSAndroid Build Coastguard Worker set.add("foo"); 186*795d594fSAndroid Build Coastguard Worker set.toArray(); 187*795d594fSAndroid Build Coastguard Worker 188*795d594fSAndroid Build Coastguard Worker set = new LinkedHashSet(); 189*795d594fSAndroid Build Coastguard Worker set.add("foo"); 190*795d594fSAndroid Build Coastguard Worker set.addAll(set); 191*795d594fSAndroid Build Coastguard Worker set.clear(); 192*795d594fSAndroid Build Coastguard Worker set.contains("foo"); 193*795d594fSAndroid Build Coastguard Worker set.containsAll(set); 194*795d594fSAndroid Build Coastguard Worker set.equals(set); 195*795d594fSAndroid Build Coastguard Worker set.hashCode(); 196*795d594fSAndroid Build Coastguard Worker set.isEmpty(); 197*795d594fSAndroid Build Coastguard Worker set.iterator(); 198*795d594fSAndroid Build Coastguard Worker set.remove("foo"); 199*795d594fSAndroid Build Coastguard Worker set.removeAll(set); 200*795d594fSAndroid Build Coastguard Worker set.retainAll(set); 201*795d594fSAndroid Build Coastguard Worker set.size(); 202*795d594fSAndroid Build Coastguard Worker set.add("foo"); 203*795d594fSAndroid Build Coastguard Worker set.toArray(); 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker set = new TreeSet(); 206*795d594fSAndroid Build Coastguard Worker set.add("foo"); 207*795d594fSAndroid Build Coastguard Worker set.addAll(set); 208*795d594fSAndroid Build Coastguard Worker set.clear(); 209*795d594fSAndroid Build Coastguard Worker set.contains("foo"); 210*795d594fSAndroid Build Coastguard Worker set.containsAll(set); 211*795d594fSAndroid Build Coastguard Worker set.equals(set); 212*795d594fSAndroid Build Coastguard Worker set.hashCode(); 213*795d594fSAndroid Build Coastguard Worker set.isEmpty(); 214*795d594fSAndroid Build Coastguard Worker set.iterator(); 215*795d594fSAndroid Build Coastguard Worker set.remove("foo"); 216*795d594fSAndroid Build Coastguard Worker set.removeAll(set); 217*795d594fSAndroid Build Coastguard Worker set.retainAll(set); 218*795d594fSAndroid Build Coastguard Worker set.size(); 219*795d594fSAndroid Build Coastguard Worker set.add("foo"); 220*795d594fSAndroid Build Coastguard Worker set.toArray(); 221*795d594fSAndroid Build Coastguard Worker } 222*795d594fSAndroid Build Coastguard Worker 223*795d594fSAndroid Build Coastguard Worker private static class VMDebug { 224*795d594fSAndroid Build Coastguard Worker private static final Method startMethodTracingMethod; 225*795d594fSAndroid Build Coastguard Worker private static final Method stopMethodTracingMethod; 226*795d594fSAndroid Build Coastguard Worker private static final Method getMethodTracingModeMethod; 227*795d594fSAndroid Build Coastguard Worker static { 228*795d594fSAndroid Build Coastguard Worker try { 229*795d594fSAndroid Build Coastguard Worker Class<?> c = Class.forName("dalvik.system.VMDebug"); 230*795d594fSAndroid Build Coastguard Worker startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class, 231*795d594fSAndroid Build Coastguard Worker Integer.TYPE, Integer.TYPE, Boolean.TYPE, Integer.TYPE); 232*795d594fSAndroid Build Coastguard Worker stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing"); 233*795d594fSAndroid Build Coastguard Worker getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode"); 234*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 235*795d594fSAndroid Build Coastguard Worker throw new RuntimeException(e); 236*795d594fSAndroid Build Coastguard Worker } 237*795d594fSAndroid Build Coastguard Worker } 238*795d594fSAndroid Build Coastguard Worker startMethodTracing(String filename, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)239*795d594fSAndroid Build Coastguard Worker public static void startMethodTracing(String filename, int bufferSize, int flags, 240*795d594fSAndroid Build Coastguard Worker boolean samplingEnabled, int intervalUs) throws Exception { 241*795d594fSAndroid Build Coastguard Worker startMethodTracingMethod.invoke(null, filename, bufferSize, flags, samplingEnabled, 242*795d594fSAndroid Build Coastguard Worker intervalUs); 243*795d594fSAndroid Build Coastguard Worker } stopMethodTracing()244*795d594fSAndroid Build Coastguard Worker public static void stopMethodTracing() throws Exception { 245*795d594fSAndroid Build Coastguard Worker stopMethodTracingMethod.invoke(null); 246*795d594fSAndroid Build Coastguard Worker } getMethodTracingMode()247*795d594fSAndroid Build Coastguard Worker public static int getMethodTracingMode() throws Exception { 248*795d594fSAndroid Build Coastguard Worker return (int) getMethodTracingModeMethod.invoke(null); 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker } 251*795d594fSAndroid Build Coastguard Worker } 252