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>&lt;class&gt;</code> <i>string</i> The name of the class</li>
031 * <li><code>&lt;method&gt;</code> <i>string</i> The name of the method</li>
032 * <li><code>&lt;signature&gt;</code> <i>string</i> The method signature</li>
033 * <li><code>&lt;advice&gt;</code> <i>in </i> The integer value for the
034 * compiler, as given in CompilerInfo</li>
035 * <li><code>&lt;optLevel&gt;</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}