/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.common;
import org.jikesrvm.VM;
import org.jikesrvm.adaptive.measurements.RuntimeMeasurements;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.classloader.NormalMethod;
/**
* This class enables an external driver to block recompile all
* methods that have been dynamically compiled since the VM began
* execution. This support can be used to eliminate the effects
* of early vs. late compilation by removing all dynamic linking
* and "bad" class hierarchy based optimizations.
*/
public final class RecompilationManager {
private static final boolean DEBUG = false;
/**
* Use the runtime compiler to forcibly recompile all dynamically
* loaded methods.
*
* @param report whether to print a report
*/
public static void recompileAllDynamicallyLoadedMethods(boolean report) {
int numMethods = CompiledMethods.numCompiledMethods();
for (int cmid = 1; cmid < numMethods; cmid++) {
// To avoid the assertion for unused cmids
CompiledMethod cpMeth = CompiledMethods.getCompiledMethodUnchecked(cmid);
if (cpMeth == null) {
if (DEBUG) {
VM.sysWriteln("Not recompiling method ID ", cmid, " because it has no compiledMethod");
}
} else {
RVMMethod meth = cpMeth.getMethod();
if (DEBUG) {
VM.sysWriteln("numMethods: " +
numMethods +
", Inspecting cpMethod " +
cpMeth +
", method: " +
cpMeth.getMethod() +
"(" +
cmid +
")");
}
if (cpMeth.getCompilerType() == CompiledMethod.TRAP) {
if (DEBUG) {
VM.sysWriteln("Not recompiling compiled method " +
cpMeth +
"(" +
cmid +
") because it a TRAP, i.e. has no source code");
}
} else {
if (meth.getDeclaringClass().isResolved()) {
if (meth.getDeclaringClass().isInBootImage()) {
if (DEBUG) {
VM.sysWriteln("Not recompiling bootimage method " + meth + "(" + cmid + ")");
}
} else {
if (meth.isAbstract()) {
if (DEBUG) VM.sysWriteln("Not recompiling abstract method " + meth + "(" + cmid + ")");
} else if (meth.isNative()) {
if (DEBUG) VM.sysWriteln("Not recompiling native method " + meth + "(" + cmid + ")");
} else {
if (DEBUG || report) VM.sysWrite("Recompiling " + meth + "(" + cmid + ") ");
recompile((NormalMethod) meth);
if (DEBUG || report) VM.sysWriteln("...done");
}
}
} else {
if (DEBUG) VM.sysWriteln("Class not resolved" + meth + "(" + cmid + ")");
}
}
}
}
if (VM.BuildForAdaptiveSystem) {
// clear profiling counter
if (DEBUG || report) {
VM.sysWriteln("Reseting profiling information");
}
RuntimeMeasurements.resetReportableObjects();
}
}
/**
* recompile and replace the argument method by invoking the runtime compiler.
*
* @param meth the method to recompile
*/
public static void recompile(NormalMethod meth) {
try {
CompiledMethod cm = RuntimeCompiler.compile(meth);
meth.replaceCompiledMethod(cm);
} catch (Throwable e) {
VM.sysWriteln("Failure while recompiling \"" + meth + "\" : " + e);
}
}
}