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.util; 014 015import java.util.Collection; 016import java.util.HashMap; 017import java.util.List; 018import java.util.ListIterator; 019import org.jikesrvm.classloader.Atom; 020import org.jikesrvm.classloader.RVMMethod; 021import org.jikesrvm.compilers.common.CompiledMethod; 022 023/** 024 * Defines an attribute for compiler advice, and maintains a map 025 * allowing attributes to be retrieved by method and bytecode offset. 026 * <p> 027 * Each attribute encodes an compiler site and the advice for that 028 * site: 029 * <ul> 030 * <li><code><class></code> <i>string</i> The name of the class</li> 031 * <li><code><method></code> <i>string</i> The name of the method</li> 032 * <li><code><signature></code> <i>string</i> The method signature</li> 033 * <li><code><advice></code> <i>in </i> The integer value for the 034 * compiler, as given in CompilerInfo</li> 035 * <li><code><optLevel></code> <i>in </i> The optimization level when 036 the Opt compiler is used 037 * </ul> 038 * 039 * 040 * @see CompilerAdvice 041 * @see CompilerAdviceInfoReader 042 */ 043public class CompilerAdviceAttribute { 044 045 private static HashMap<CompilerAdviceAttribute, CompilerAdviceAttribute> attribMap = null; 046 private static CompilerAdviceAttribute defaultAttr = null; 047 private static CompilerAdviceAttribute tempAttr = null; 048 private static boolean hasAdvice = false; 049 050 private Atom className; // The name of the class for the compiler site 051 private Atom methodName; // The name of the method for the compiler site 052 private Atom methodSig; // The signature of the method 053 private final int compiler; // The compiler to use for the method 054 private final int optLevel; // The optimization level 055 056 /** 057 * Initialization of key compiler advice data structure. 058 */ 059 public static void postBoot() { 060 attribMap = new HashMap<CompilerAdviceAttribute, CompilerAdviceAttribute>(); 061 062 // With defaultAttr set up this way, methods will be BASELINE compiled 063 // *unless* they appear in the advice file. If defaultAttr is set to 064 // null, then methods will be compiled in the default way for the 065 // current build configuration *unless* they appear in the advice file. 066 defaultAttr = new CompilerAdviceAttribute(null, null, null, CompiledMethod.BASELINE); 067 tempAttr = new CompilerAdviceAttribute(null, null, null, CompiledMethod.BASELINE); 068 } 069 070 /** 071 * Getter method for class name 072 * 073 * @return the class name for this attribute 074 */ 075 public Atom getClassName() { 076 return className; 077 } 078 079 /** 080 * Getter method for method name 081 * 082 * @return the method name for this attribute 083 */ 084 public Atom getMethodName() { 085 return methodName; 086 } 087 088 /** 089 * Getter method for method signature 090 * 091 * @return the method signature for this attribute 092 */ 093 public Atom getMethodSig() { 094 return methodSig; 095 } 096 097 /** 098 * Getter method for compiler ID 099 * 100 * @return the compiler ID for this attribute 101 */ 102 public int getCompiler() { 103 return compiler; 104 } 105 106 /** 107 * Getter method for optimization level 108 * 109 * @return the optimization level for this attribute 110 */ 111 public int getOptLevel() { 112 return optLevel; 113 } 114 115 /** 116 * Constructor 117 * 118 * @param className The name of the class for the compiler site 119 * @param methodName The name of the method for the compiler site 120 * @param methodSig The signature of the method for the compiler site 121 * @param compiler The ID of the compiler to use for this method 122 * 123 * @see CompilerAdviceInfoReader 124 */ 125 public CompilerAdviceAttribute(Atom className, Atom methodName, Atom methodSig, int compiler) { 126 this.className = className; 127 this.methodName = methodName; 128 this.methodSig = methodSig; 129 this.compiler = compiler; 130 this.optLevel = -1; 131 } 132 133 /** 134 * Constructor 135 * 136 * @param className The name of the class for the compiler site 137 * @param methodName The name of the method for the compiler site 138 * @param methodSig The signature of the method for the compiler site 139 * @param compiler The ID of the compiler to use for this method 140 * @param optLevel The optimization level if using Opt compiler 141 * 142 * @see CompilerAdviceInfoReader 143 */ 144 public CompilerAdviceAttribute(Atom className, Atom methodName, Atom methodSig, int compiler, 145 int optLevel) { 146 this.className = className; 147 this.methodName = methodName; 148 this.methodSig = methodSig; 149 this.compiler = compiler; 150 this.optLevel = optLevel; 151 } 152 153 /** 154 * Stringify this instance 155 * 156 * @return The state of this instance expressed as a string 157 */ 158 @Override 159 public String toString() { 160 return ("Compiler advice: " + 161 className + 162 " " + 163 methodName + 164 " " + 165 methodSig + 166 " " + 167 compiler + 168 "(" + 169 optLevel + 170 ")"); 171 } 172 173 /** 174 * Use a list of compiler advice attributes to create an advice map 175 * keyed on <code>RVMMethod</code> instances. This map is used by 176 * <code>getCompilerAdviceInfo()</code>. 177 * 178 * @param compilerAdviceList A list of compiler advice attributes 179 * @see #getCompilerAdviceInfo 180 */ 181 public static void registerCompilerAdvice(List<CompilerAdviceAttribute> compilerAdviceList) { 182 // do nothing for empty list 183 if (compilerAdviceList == null) return; 184 185 hasAdvice = true; 186 187 // iterate over each element of the list 188 ListIterator<CompilerAdviceAttribute> it = compilerAdviceList.listIterator(); 189 while (it.hasNext()) { 190 // pick up an attribute 191 CompilerAdviceAttribute attr = it.next(); 192 attribMap.put(attr, attr); 193 // XXX if already there, should we warn the user? 194 } 195 } 196 197 /** 198 * Given a method and bytecode offset, return an compiler advice 199 * attribute or null if none is found for that method and offset. 200 * 201 * @param method The method containing the site in question 202 * @return Attribute advice for that site or null if none is found. 203 */ 204 public static CompilerAdviceAttribute getCompilerAdviceInfo(RVMMethod method) { 205 tempAttr.className = method.getDeclaringClass().getDescriptor(); 206 tempAttr.methodName = method.getName(); 207 tempAttr.methodSig = method.getDescriptor(); 208 CompilerAdviceAttribute value = attribMap.get(tempAttr); 209 210 if (value == null) { 211 return defaultAttr; 212 } else { 213 return value; 214 } 215 } 216 217 public static Collection<CompilerAdviceAttribute> values() { 218 return attribMap.values(); 219 } 220 221 public static boolean hasAdvice() { 222 return hasAdvice; 223 } 224 225 @Override 226 public boolean equals(Object obj) { 227 if (super.equals(obj)) { 228 return true; 229 } 230 231 if (obj instanceof CompilerAdviceAttribute) { 232 CompilerAdviceAttribute attr = (CompilerAdviceAttribute) obj; 233 if (attr.className == className && attr.methodName == methodName && attr.methodSig == methodSig) { 234 return true; 235 } 236 } 237 return false; 238 } 239 240 @Override 241 public int hashCode() { 242 return className.hashCode() ^ methodName.hashCode() ^ methodSig.hashCode(); 243 } 244}