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