001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.adaptive.recompilation;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.adaptive.controller.Controller;
017import org.jikesrvm.adaptive.controller.ControllerPlan;
018import org.jikesrvm.adaptive.controller.RecompilationStrategy;
019import org.jikesrvm.adaptive.recompilation.instrumentation.AOSInstrumentationPlan;
020import org.jikesrvm.classloader.NormalMethod;
021import org.jikesrvm.compilers.baseline.BaselineCompiler;
022import org.jikesrvm.compilers.common.CompiledMethod;
023import org.jikesrvm.compilers.common.CompiledMethods;
024import org.jikesrvm.compilers.opt.OptOptions;
025import org.jikesrvm.compilers.opt.driver.CompilationPlan;
026import org.jikesrvm.compilers.opt.driver.OptimizationPlanElement;
027import org.jikesrvm.compilers.opt.driver.OptimizationPlanner;
028import org.jikesrvm.runtime.Magic;
029
030/**
031 * Runtime system support for using invocation counters in baseline
032 * compiled code to select methods for optimizing recompilation
033 * by the adaptive system.  Bypasses the normal controller logic:
034 * If an invocation counter trips, then the method is enqueued for
035 * recompilation at a default optimization level.
036 */
037public final class InvocationCounts {
038
039  private static int[] counts;
040  private static boolean[] processed;
041
042  public static synchronized void allocateCounter(int id) {
043    if (counts == null) {
044      counts = new int[id + 500];
045      processed = new boolean[counts.length];
046    }
047    if (id >= counts.length) {
048      int newSize = counts.length * 2;
049      if (newSize <= id) newSize = id + 500;
050      int[] tmp = new int[newSize];
051      System.arraycopy(counts, 0, tmp, 0, counts.length);
052      boolean[] tmp2 = new boolean[newSize];
053      System.arraycopy(processed, 0, tmp2, 0, processed.length);
054      Magic.sync();
055      counts = tmp;
056      processed = tmp2;
057    }
058    counts[id] = Controller.options.INVOCATION_COUNT_THRESHOLD;
059  }
060
061  /**
062   * Called from baseline compiled code when a method's invocation counter
063   * becomes negative and thus must be handled
064   *
065   * @param id the compiled method id
066   */
067  static synchronized void counterTripped(int id) {
068    counts[id] = 0x7fffffff; // set counter to max int to avoid lots of redundant calls.
069    if (processed[id]) return;
070    processed[id] = true;
071    CompiledMethod cm = CompiledMethods.getCompiledMethod(id);
072    if (cm == null) return;
073    if (VM.VerifyAssertions) VM._assert(cm.getCompilerType() == CompiledMethod.BASELINE);
074    NormalMethod m = (NormalMethod) cm.getMethod();
075    CompilationPlan compPlan = new CompilationPlan(m, _optPlan, null, _options);
076    ControllerPlan cp =
077        new ControllerPlan(compPlan, Controller.controllerClock, id, 2.0, 2.0, 2.0); // 2.0 is a bogus number....
078    cp.execute();
079  }
080
081  public static CompilationPlan createCompilationPlan(NormalMethod method) {
082    return new CompilationPlan(method, _optPlan, null, _options);
083  }
084
085  public static CompilationPlan createCompilationPlan(NormalMethod method, AOSInstrumentationPlan instPlan) {
086    return new CompilationPlan(method, _optPlan, instPlan, _options);
087  }
088
089  /**
090   *  Initialize the recompilation strategy.<p>
091   *
092   *  Note: This uses the command line options to set up the
093   *  optimization plans, so this must be run after the command line
094   *  options are available.
095   */
096  public static void init() {
097    createOptimizationPlan();
098    BaselineCompiler.options.INVOCATION_COUNTERS = true;
099  }
100
101  private static OptimizationPlanElement[] _optPlan;
102  private static OptOptions _options;
103
104  /**
105   * Create the default set of &lt;optimization plan, options&gt; pairs
106   * Process optimizing compiler command line options.
107   */
108  static void createOptimizationPlan() {
109    _options = new OptOptions();
110
111    int optLevel = Controller.options.INVOCATION_COUNT_OPT_LEVEL;
112    String[] optCompilerOptions = Controller.getOptCompilerOptions();
113    _options.setOptLevel(optLevel);
114    RecompilationStrategy.processCommandLineOptions(_options, optLevel, optLevel, optCompilerOptions);
115    _optPlan = OptimizationPlanner.createOptimizationPlan(_options);
116  }
117
118}