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