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     */
013    package org.jikesrvm.compilers.common;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.adaptive.measurements.RuntimeMeasurements;
017    import org.jikesrvm.classloader.RVMMethod;
018    import 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     */
027    public 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      public static void recompileAllDynamicallyLoadedMethods(boolean report) {
036        int numMethods = CompiledMethods.numCompiledMethods();
037        for (int cmid = 1; cmid < numMethods; cmid++) {
038          // To avoid the assertion for unused cmids
039          CompiledMethod cpMeth = CompiledMethods.getCompiledMethodUnchecked(cmid);
040          if (cpMeth == null) {
041            if (DEBUG) {
042              VM.sysWrite("Not recompiling method ID ", cmid, " because it has no compiledMethod\n");
043            }
044          } else {
045            RVMMethod meth = cpMeth.getMethod();
046            if (DEBUG) {
047              VM.sysWrite("numMethods: " +
048                          numMethods +
049                          ", Inspecting cpMethod " +
050                          cpMeth +
051                          ", method: " +
052                          cpMeth.getMethod() +
053                          "(" +
054                          cmid +
055                          ")\n");
056            }
057            if (cpMeth.getCompilerType() == CompiledMethod.TRAP) {
058              if (DEBUG) {
059                VM.sysWrite("Not recompiling compiled method " +
060                            cpMeth +
061                            "(" +
062                            cmid +
063                            ") because it a TRAP, i.e. has no source code\n");
064              }
065            } else {
066              if (meth.getDeclaringClass().isResolved()) {
067                if (meth.getDeclaringClass().isInBootImage()) {
068                  if (DEBUG) {
069                    VM.sysWrite("Not recompiling bootimage method " + meth + "(" + cmid + ")\n");
070                  }
071                } else {
072                  if (meth.isAbstract()) {
073                    if (DEBUG) VM.sysWrite("Not recompiling abstract method " + meth + "(" + cmid + ")\n");
074                  } else if (meth.isNative()) {
075                    if (DEBUG) VM.sysWrite("Not recompiling native method " + meth + "(" + cmid + ")\n");
076                  } else {
077                    if (DEBUG || report) VM.sysWrite("Recompiling " + meth + "(" + cmid + ") ");
078                    recompile((NormalMethod) meth);
079                    if (DEBUG || report) VM.sysWrite("...done\n");
080                  }
081                }
082              } else {
083                if (DEBUG) VM.sysWrite("Class not resolved" + meth + "(" + cmid + ")\n");
084              }
085            }
086          }
087        }
088    
089        if (VM.BuildForAdaptiveSystem) {
090          // clear profiling counter
091          if (DEBUG || report) { VM.sysWrite("Reseting profiling information\n"); }
092          RuntimeMeasurements.resetReportableObjects();
093        }
094      }
095    
096      /**
097       * recompile and replace the argument method by invoking the runtime compiler
098       */
099      public static void recompile(NormalMethod meth) {
100        try {
101          CompiledMethod cm = RuntimeCompiler.compile(meth);
102          meth.replaceCompiledMethod(cm);
103        } catch (Throwable e) {
104          VM.sysWrite("Failure while recompiling \"" + meth + "\" : " + e + "\n");
105        }
106      }
107    }
108