1545412b4b250d6024ff071c094c226187860a086Igor Murashkin// Copyright (C) 2017 The Android Open Source Project
2545412b4b250d6024ff071c094c226187860a086Igor Murashkin//
3545412b4b250d6024ff071c094c226187860a086Igor Murashkin// Licensed under the Apache License, Version 2.0 (the "License");
4545412b4b250d6024ff071c094c226187860a086Igor Murashkin// you may not use this file except in compliance with the License.
5545412b4b250d6024ff071c094c226187860a086Igor Murashkin// You may obtain a copy of the License at
6545412b4b250d6024ff071c094c226187860a086Igor Murashkin//
7545412b4b250d6024ff071c094c226187860a086Igor Murashkin//     http://www.apache.org/licenses/LICENSE-2.0
8545412b4b250d6024ff071c094c226187860a086Igor Murashkin//
9545412b4b250d6024ff071c094c226187860a086Igor Murashkin// Unless required by applicable law or agreed to in writing, software
10545412b4b250d6024ff071c094c226187860a086Igor Murashkin// distributed under the License is distributed on an "AS IS" BASIS,
11545412b4b250d6024ff071c094c226187860a086Igor Murashkin// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12545412b4b250d6024ff071c094c226187860a086Igor Murashkin// See the License for the specific language governing permissions and
13545412b4b250d6024ff071c094c226187860a086Igor Murashkin// limitations under the License.
14545412b4b250d6024ff071c094c226187860a086Igor Murashkinimport java.lang.reflect.Method;
15545412b4b250d6024ff071c094c226187860a086Igor Murashkinimport java.util.ArrayList;
16545412b4b250d6024ff071c094c226187860a086Igor Murashkinimport java.util.Collections;
17545412b4b250d6024ff071c094c226187860a086Igor Murashkin
18545412b4b250d6024ff071c094c226187860a086Igor Murashkinpublic class Main {
19545412b4b250d6024ff071c094c226187860a086Igor Murashkin
20545412b4b250d6024ff071c094c226187860a086Igor Murashkin  static class OatMethodAndOffset implements Comparable<OatMethodAndOffset> {
21545412b4b250d6024ff071c094c226187860a086Igor Murashkin    Method method;
22545412b4b250d6024ff071c094c226187860a086Igor Murashkin    long codeOffset;
23545412b4b250d6024ff071c094c226187860a086Igor Murashkin
24545412b4b250d6024ff071c094c226187860a086Igor Murashkin    public OatMethodAndOffset(Method method, long codeOffset) {
25545412b4b250d6024ff071c094c226187860a086Igor Murashkin      this.method = method;
26545412b4b250d6024ff071c094c226187860a086Igor Murashkin      this.codeOffset = codeOffset;
27545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
28545412b4b250d6024ff071c094c226187860a086Igor Murashkin
29545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // e.g. "Foo::Bar()"
30545412b4b250d6024ff071c094c226187860a086Igor Murashkin    public String methodReferenceString() {
31545412b4b250d6024ff071c094c226187860a086Igor Murashkin      return method.getDeclaringClass().getName() + "::" + method.getName();
32545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
33545412b4b250d6024ff071c094c226187860a086Igor Murashkin
34545412b4b250d6024ff071c094c226187860a086Igor Murashkin    @Override
35545412b4b250d6024ff071c094c226187860a086Igor Murashkin    public int compareTo(OatMethodAndOffset other) {
36545412b4b250d6024ff071c094c226187860a086Igor Murashkin      return Long.compareUnsigned(codeOffset, other.codeOffset);
37545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
38545412b4b250d6024ff071c094c226187860a086Igor Murashkin  }
39545412b4b250d6024ff071c094c226187860a086Igor Murashkin
40545412b4b250d6024ff071c094c226187860a086Igor Murashkin  // Print the list of methods in Generated.class, sorted by their OAT code address.
41545412b4b250d6024ff071c094c226187860a086Igor Murashkin  public static void main(String[] args) {
42545412b4b250d6024ff071c094c226187860a086Igor Murashkin    System.loadLibrary(args[0]);
43545412b4b250d6024ff071c094c226187860a086Igor Murashkin
44545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // Make sure to check "Test.class" because Main.class still has JNI which could be compiled
45545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // even if the rest of the classes are not.
46545412b4b250d6024ff071c094c226187860a086Igor Murashkin    if (!hasOatCompiledCode(Test.class)) {
47545412b4b250d6024ff071c094c226187860a086Igor Murashkin      System.out.println("No OAT class");
48545412b4b250d6024ff071c094c226187860a086Igor Murashkin      return;
49545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
50545412b4b250d6024ff071c094c226187860a086Igor Murashkin
51545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // We only care about explicitly defined methods from Generated.java.
52545412b4b250d6024ff071c094c226187860a086Igor Murashkin    Method[] interesting_methods;
53545412b4b250d6024ff071c094c226187860a086Igor Murashkin    try {
54545412b4b250d6024ff071c094c226187860a086Igor Murashkin      interesting_methods = Test.getTestMethods();
55545412b4b250d6024ff071c094c226187860a086Igor Murashkin    } catch (NoSuchMethodException e) {
56545412b4b250d6024ff071c094c226187860a086Igor Murashkin      e.printStackTrace();
57545412b4b250d6024ff071c094c226187860a086Igor Murashkin      return;
58545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
59545412b4b250d6024ff071c094c226187860a086Igor Murashkin
60545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // Get the list of oat code methods for each Java method.
61545412b4b250d6024ff071c094c226187860a086Igor Murashkin    ArrayList<OatMethodAndOffset> offsets_list = new ArrayList<OatMethodAndOffset>();
62545412b4b250d6024ff071c094c226187860a086Igor Murashkin    for (Method m : interesting_methods) {
63545412b4b250d6024ff071c094c226187860a086Igor Murashkin      offsets_list.add(new OatMethodAndOffset(m, getOatMethodQuickCode(m)));
64545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
65545412b4b250d6024ff071c094c226187860a086Igor Murashkin
66545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // Sort by the offset address.
67545412b4b250d6024ff071c094c226187860a086Igor Murashkin    Collections.sort(offsets_list);
68545412b4b250d6024ff071c094c226187860a086Igor Murashkin
69545412b4b250d6024ff071c094c226187860a086Igor Murashkin    // Print each method as a method reference string.
70545412b4b250d6024ff071c094c226187860a086Igor Murashkin    for (OatMethodAndOffset m : offsets_list) {
71545412b4b250d6024ff071c094c226187860a086Igor Murashkin      System.out.println(m.methodReferenceString());
72545412b4b250d6024ff071c094c226187860a086Igor Murashkin    }
73545412b4b250d6024ff071c094c226187860a086Igor Murashkin  }
74545412b4b250d6024ff071c094c226187860a086Igor Murashkin
75545412b4b250d6024ff071c094c226187860a086Igor Murashkin  // Does Main.class have an OatClass with actually compiled code?
76545412b4b250d6024ff071c094c226187860a086Igor Murashkin  private static native boolean hasOatCompiledCode(Class kls);
77545412b4b250d6024ff071c094c226187860a086Igor Murashkin  // Get the OatMethod's pointer to code. We get 'real' memory address, not relative offset,
78545412b4b250d6024ff071c094c226187860a086Igor Murashkin  // but it's still good since we never compare multiple OAT files here.
79545412b4b250d6024ff071c094c226187860a086Igor Murashkin  private static native long getOatMethodQuickCode(Method method);
80545412b4b250d6024ff071c094c226187860a086Igor Murashkin}
81