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.adaptive.recompilation; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.adaptive.controller.Controller; 017import org.jikesrvm.adaptive.util.AOSLogging; 018import org.jikesrvm.adaptive.util.CompilerAdvice; 019import org.jikesrvm.adaptive.util.CompilerAdviceAttribute; 020import org.jikesrvm.classloader.RVMClass; 021import org.jikesrvm.classloader.RVMClassLoader; 022import org.jikesrvm.classloader.RVMMethod; 023import org.jikesrvm.classloader.NormalMethod; 024import org.jikesrvm.classloader.TypeReference; 025import org.jikesrvm.compilers.baseline.EdgeCounts; 026import org.jikesrvm.compilers.common.RuntimeCompiler; 027import org.jikesrvm.compilers.opt.driver.CompilationPlan; 028import org.jikesrvm.runtime.Callbacks; 029 030/** 031 * Utilities for providing compiler advice. Advice files provided 032 * at run time allow compilers to be specified for particular methods 033 * <p> 034 * <i>Run time</i> advice is given by identifying an advice file 035 * through a command line option: 036 * <code>-X:aos:cafi=path-to-advice-file</code>. 037 * This file specifies which methods should be optimized, and at 038 * what level.<p> 039 * 040 * Optionally, a dynamic call graph and edge counts may also 041 * be provided in advice files, at the command line. 042 * <code>-X:aos:dcfi=path-to-dynamic-call-graph-file</code>. 043 * <code>-X:vm:edgeCounterFile=path-to-edge-count-file</code>. 044 * These provide synthetic profile data to the compiler that would 045 * otherwise be gathered by the AOS at run time. These are therefore 046 * strictly an optimization, so they are options. 047 * 048 * @see org.jikesrvm.adaptive.util.CompilerAdviceAttribute 049 * @see org.jikesrvm.compilers.common.RuntimeCompiler 050 */ 051public class BulkCompile implements Callbacks.StartupMonitor { 052 053 public static void init() { 054 Callbacks.addStartupMonitor(new BulkCompile()); 055 } 056 057 @Override 058 public void notifyStartup() { 059 if (Controller.options.ENABLE_PRECOMPILE) { 060 compileAllMethods(); 061 } 062 } 063 064 /** 065 * Compile all methods nominated in the compiler advice, 066 * which should have been provided in a .ca advice file.<p> 067 * 068 * This method will be called at boot time (via notifyStartup()) 069 * if ENABLE_PRECOMPILE is true. For replay compilation, this 070 * method needs to be called explicitly from within the application 071 * or benchmark harness. Typical usage in a benchmarking context 072 * would be to call this method at the end of the first iteration 073 * of the benchmark so that all/most classes were loaded, and 074 * compilation could occur prior to the second iteration. 075 */ 076 public static void compileAllMethods() { 077 if (!(Controller.options.ENABLE_BULK_COMPILE || Controller.options.ENABLE_PRECOMPILE)) { 078 /* should not be here */ 079 VM.sysFail("Attempt to perform bulk compilation without setting either -X:aos:enable_bulk_compile=true or -X:aos:enable_precompile=true"); 080 } 081 082 EdgeCounts.loadCountsFromFileIfAvailable(VM.EdgeCounterFile); 083 CompilerAdvice.readCompilerAdvice(); 084 if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1) 085 VM.sysWriteln(Controller.options.ENABLE_PRECOMPILE ? "Start precompile" : "Start bulk compile"); 086 087 for (CompilerAdviceAttribute value : CompilerAdviceAttribute.values()) { 088 if (value.getOptLevel() == -1) { 089 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 090 VM.sysWrite("Skipping base method: "); VM.sysWriteln(value.toString()); 091 } else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 092 VM.sysWrite("."); 093 } 094 continue; 095 } 096 097 ClassLoader cl = RVMClassLoader.findWorkableClassloader(value.getClassName()); 098 if (cl == null) 099 continue; 100 101 TypeReference tRef = TypeReference.findOrCreate(cl, value.getClassName()); 102 RVMClass cls = (RVMClass) tRef.peekType(); 103 104 if (cls != null) { 105 // Ensure the class is properly loaded 106 if (!cls.isInstantiated()) { 107 if (!cls.isResolved()) { 108 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 109 VM.sysWriteln("Resolving class: ", cls.toString()); 110 } else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 111 VM.sysWrite("R"); 112 } 113 cls.resolve(); 114 } 115 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 116 VM.sysWriteln("Instantiating class: ", cls.toString()); 117 } else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 118 VM.sysWrite("I"); 119 } 120 cls.instantiate(); 121 } 122 123 // Find the method 124 RVMMethod method = cls.findDeclaredMethod(value.getMethodName(), value.getMethodSig()); 125 126 127 // If found, compile it 128 if ((method != null) && 129 !method.hasNoOptCompileAnnotation() && 130 (method instanceof org.jikesrvm.classloader.NormalMethod)) { 131 // if user's requirement is higher than advice 132 if (value.getOptLevel() > Controller.options.DERIVED_MAX_OPT_LEVEL) { 133 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 134 VM.sysWrite("Replay advice overriden by default opt levels. Wanted "); VM.sysWrite(value.getOptLevel()); VM.sysWrite(", but Controller.options.DERIVED_MAX_OPT_LEVEL: "); 135 VM.sysWrite(Controller.options.DERIVED_MAX_OPT_LEVEL); VM.sysWrite(" "); VM.sysWriteln(value.toString()); 136 } else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 137 VM.sysWrite(value.getOptLevel(), "!"); 138 } 139 method.compile(); 140 } else { 141 CompilationPlan compPlan; 142 if (Controller.options.counters()) { 143 // for invocation counter, we only use one optimization level 144 compPlan = InvocationCounts.createCompilationPlan((NormalMethod) method); 145 AOSLogging.logger.recompilationStarted(compPlan); 146 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 147 VM.sysWrite("Bulk compiling for counters "); 148 VM.sysWriteln(value.toString()); 149 } 150 RuntimeCompiler.recompileWithOpt(compPlan); 151 AOSLogging.logger.recompilationCompleted(compPlan); 152 } else if (Controller.options.sampling()) { 153 // Create our set of standard optimization plans. 154 compPlan = Controller.recompilationStrategy.createCompilationPlan((NormalMethod) method, value.getOptLevel(), null); 155 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 156 VM.sysWrite("Bulk compiling for sampling "); 157 VM.sysWriteln(value.toString()); 158 } 159 if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 160 VM.sysWrite(value.getOptLevel()); 161 } 162 AOSLogging.logger.recompilationStarted(compPlan); 163 RuntimeCompiler.recompileWithOpt(compPlan); 164 AOSLogging.logger.recompilationCompleted(compPlan); 165 } else { 166 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 167 VM.sysWrite("Compiler advice file overridden "); 168 VM.sysWriteln(value.toString()); 169 } 170 method.compile(); 171 } 172 } 173 } else { 174 if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) { 175 VM.sysWrite("Replay failed for "); VM.sysWrite(value.toString()); VM.sysWrite(" "); VM.sysWriteln(cl.toString()); 176 } else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) { 177 VM.sysWrite("*"); 178 } 179 } 180 } 181 } 182 AOSLogging.logger.compileAllMethodsCompleted(); 183 if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1) VM.sysWriteln(); 184 if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1) VM.sysWriteln("Recompilation complete"); 185 } 186}