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