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