public class ICTime {
  private static final int NUM_HITS = 10000;
  private static final int NUM_MISS = 10000;

  public static class Fruit {
    public String name() { return "Fruit"; }
  }
  public static class Apple extends Fruit {
    public String name() { return "Apple"; }
  }
  public static class Orange extends Fruit {
    public String name() { return "Orange"; }
  }

  private static long start, stop;

  private static void warmup() {
    // Make sure all classes are loaded and all methods are compiled
    Fruit f = new Fruit();
    f.name();
    f = new Apple();
    f.name();
    f = new Orange();
    f.name();
  }
  private static void profileICSetup() {
    Fruit f = new Apple();

    // Test fresh call-sites
    // Using a large no. of callsites ensures we are immune from
    // precision issues of System.nanoTime()
    start = System.nanoTime();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    f.name();
    stop = System.nanoTime();
    System.out.println("ICSetup = " + (stop - start)/1024 + "ns");
  }

  private static String wrapper(Fruit f) {
    return f.name();
  }

  private static void profileICHit() {
    Apple a = new Apple();
    wrapper(a);

    start = System.nanoTime();
    for(int i = 0; i < NUM_HITS; ++i) {
      wrapper(a);
    }
    stop = System.nanoTime();
    System.out.println("ICHit = " + (stop - start)/NUM_HITS + "ns");
  }

  private static void profileICMiss() {
    Orange o = new Orange();
    wrapper(o);

    start = System.nanoTime();
    for(int i = 0; i < NUM_MISS; ++i) {
      wrapper(o);
    }
    stop = System.nanoTime();
    System.out.println("ICMiss = " + (stop - start)/NUM_MISS + "ns");
  }

  public static void main(String[] args) {
    warmup();
    profileICSetup();
    profileICHit();
    profileICMiss();
  }
}
