summaryrefslogtreecommitdiff
path: root/test/554-jit-profile-file/src/Main.java
blob: 98297ed8ed5f34e26e9caf6002af5bc2a9babba4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;

public class Main {

  public void coldMethod() {
    hotMethod();
  }

  public String hotMethod() {
    HashMap<String, String> map = new HashMap<String, String>();
    for (int i = 0; i < 10; i++) {
      map.put("" + i, "" + i + 1);
    }
    return map.get("1");
  }

  private static final String PKG_NAME = "test.package";
  private static final String APP_DIR_PREFIX = "app_dir_";
  private static final String CODE_CACHE = "code_cache";
  private static final String PROFILE_FILE = PKG_NAME + ".prof";
  private static final String TEMP_FILE_NAME_PREFIX = "dummy";
  private static final String TEMP_FILE_NAME_SUFFIX = "-file";
  private static final int JIT_INVOCATION_COUNT = 200;

  /* needs to match Runtime:: kProfileBackground */
  private static final int PROFILE_BACKGROUND = 1;

  public static void main(String[] args) throws Exception {
    System.loadLibrary(args[0]);

    File file = null;
    File appDir = null;
    File profileDir = null;
    File profileFile = null;
    try {
      // We don't know where we have rights to create the code_cache. So create
      // a dummy temporary file and get its parent directory. That will serve as
      // the app directory.
      file = createTempFile();
      appDir = new File(file.getParent(), APP_DIR_PREFIX + file.getName());
      appDir.mkdir();
      profileDir = new File(appDir, CODE_CACHE);
      profileDir.mkdir();

      // Registering the app info will set the profile file name.
      VMRuntime.registerAppInfo(PKG_NAME, appDir.getPath());

      // Make sure the hot methods are jitted.
      Main m = new Main();
      OtherDex o = new OtherDex();
      for (int i = 0; i < JIT_INVOCATION_COUNT; i++) {
        m.hotMethod();
        o.hotMethod();
      }

      // Sleep for 2 second to make sure that the methods had a chance to get compiled.
      Thread.sleep(2000);
      // Updating the process state to BACKGROUND will trigger profile saving.
      VMRuntime.updateProcessState(PROFILE_BACKGROUND);

      // Check that the profile file exists.
      profileFile = new File(profileDir, PROFILE_FILE);
      if (!profileFile.exists()) {
        throw new RuntimeException("No profile file found");
      }
      // Dump the profile file.
      // We know what methods are hot and we compare with the golden `expected` output.
      System.out.println(getProfileInfoDump(profileFile.getPath()));
    } finally {
      if (file != null) {
        file.delete();
      }
      if (profileFile != null) {
        profileFile.delete();
      }
      if (profileDir != null) {
        profileDir.delete();
      }
      if (appDir != null) {
        appDir.delete();
      }
    }
  }

  private static class VMRuntime {
    private static final Method registerAppInfoMethod;
    private static final Method updateProcessStateMethod;
    private static final Method getRuntimeMethod;
    static {
      try {
        Class c = Class.forName("dalvik.system.VMRuntime");
        registerAppInfoMethod = c.getDeclaredMethod("registerAppInfo",
            String.class, String.class, String.class);
        updateProcessStateMethod = c.getDeclaredMethod("updateProcessState", Integer.TYPE);
        getRuntimeMethod = c.getDeclaredMethod("getRuntime");
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    public static void registerAppInfo(String pkgName, String appDir) throws Exception {
      registerAppInfoMethod.invoke(null, pkgName, appDir, null);
    }
    public static void updateProcessState(int state) throws Exception {
      Object runtime = getRuntimeMethod.invoke(null);
      updateProcessStateMethod.invoke(runtime, state);
    }
  }

  static native String getProfileInfoDump(
      String filename);

  private static File createTempFile() throws Exception {
    try {
      return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
    } catch (IOException e) {
      System.setProperty("java.io.tmpdir", "/data/local/tmp");
      try {
        return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
      } catch (IOException e2) {
        System.setProperty("java.io.tmpdir", "/sdcard");
        return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
      }
    }
  }
}