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.compilers.common;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.adaptive.measurements.RuntimeMeasurements;
017import org.jikesrvm.classloader.RVMMethod;
018import org.jikesrvm.classloader.NormalMethod;
019
020/**
021 * This class enables an external driver to block recompile all
022 * methods that have been dynamically compiled since the VM began
023 * execution.  This support can be used to eliminate the effects
024 * of early vs. late compilation by removing all dynamic linking
025 * and "bad" class hierarchy based optimizations.
026 */
027public final class RecompilationManager {
028
029  private static final boolean DEBUG = false;
030
031  /**
032   * Use the runtime compiler to forcibly recompile all dynamically
033   * loaded methods.
034   *
035   * @param report whether to print a report
036   */
037  public static void recompileAllDynamicallyLoadedMethods(boolean report) {
038    int numMethods = CompiledMethods.numCompiledMethods();
039    for (int cmid = 1; cmid < numMethods; cmid++) {
040      // To avoid the assertion for unused cmids
041      CompiledMethod cpMeth = CompiledMethods.getCompiledMethodUnchecked(cmid);
042      if (cpMeth == null) {
043        if (DEBUG) {
044          VM.sysWrite("Not recompiling method ID ", cmid, " because it has no compiledMethod\n");
045        }
046      } else {
047        RVMMethod meth = cpMeth.getMethod();
048        if (DEBUG) {
049          VM.sysWrite("numMethods: " +
050                      numMethods +
051                      ", Inspecting cpMethod " +
052                      cpMeth +
053                      ", method: " +
054                      cpMeth.getMethod() +
055                      "(" +
056                      cmid +
057                      ")\n");
058        }
059        if (cpMeth.getCompilerType() == CompiledMethod.TRAP) {
060          if (DEBUG) {
061            VM.sysWrite("Not recompiling compiled method " +
062                        cpMeth +
063                        "(" +
064                        cmid +
065                        ") because it a TRAP, i.e. has no source code\n");
066          }
067        } else {
068          if (meth.getDeclaringClass().isResolved()) {
069            if (meth.getDeclaringClass().isInBootImage()) {
070              if (DEBUG) {
071                VM.sysWrite("Not recompiling bootimage method " + meth + "(" + cmid + ")\n");
072              }
073            } else {
074              if (meth.isAbstract()) {
075                if (DEBUG) VM.sysWrite("Not recompiling abstract method " + meth + "(" + cmid + ")\n");
076              } else if (meth.isNative()) {
077                if (DEBUG) VM.sysWrite("Not recompiling native method " + meth + "(" + cmid + ")\n");
078              } else {
079                if (DEBUG || report) VM.sysWrite("Recompiling " + meth + "(" + cmid + ") ");
080                recompile((NormalMethod) meth);
081                if (DEBUG || report) VM.sysWrite("...done\n");
082              }
083            }
084          } else {
085            if (DEBUG) VM.sysWrite("Class not resolved" + meth + "(" + cmid + ")\n");
086          }
087        }
088      }
089    }
090
091    if (VM.BuildForAdaptiveSystem) {
092      // clear profiling counter
093      if (DEBUG || report) {
094        VM.sysWrite("Reseting profiling information\n");
095      }
096      RuntimeMeasurements.resetReportableObjects();
097    }
098  }
099
100  /**
101   * recompile and replace the argument method by invoking the runtime compiler.
102   *
103   * @param meth the method to recompile
104   */
105  public static void recompile(NormalMethod meth) {
106    try {
107      CompiledMethod cm = RuntimeCompiler.compile(meth);
108      meth.replaceCompiledMethod(cm);
109    } catch (Throwable e) {
110      VM.sysWrite("Failure while recompiling \"" + meth + "\" : " + e + "\n");
111    }
112  }
113}
114