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.util;
014    
015    import java.util.Collection;
016    import java.util.HashMap;
017    import java.util.List;
018    import java.util.ListIterator;
019    import org.jikesrvm.classloader.Atom;
020    import org.jikesrvm.classloader.RVMMethod;
021    import 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></code> <i>string</i> The name of the class</li>
031     * <li><code>&lt;method></code> <i>string</i> The name of the method</li>
032     * <li><code>&lt;signature></code> <i>string</i> The method signature</li>
033     * <li><code>&lt;advice></code> <i>in </i> The integer value for the
034     * compiler, as given in CompilerInfo</li>
035     * <li><code>&lt;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     */
043    public 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 int compiler;   // The compiler to use for the method
054      private 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() { return className; }
076    
077      /**
078       * Getter method for method name
079       *
080       * @return the method name for this attribute
081       */
082      public Atom getMethodName() { return methodName; }
083    
084      /**
085       * Getter method for method signature
086       *
087       * @return the method signature for this attribute
088       */
089      public Atom getMethodSig() { return methodSig; }
090    
091      /**
092       * Getter method for compiler ID
093       *
094       * @return the compiler ID for this attribute
095       */
096      public int getCompiler() { return compiler; }
097    
098      /**
099       * Getter method for optimization level
100       *
101       * @return the optimization level for this attribute
102       */
103      public int getOptLevel() { return optLevel; }
104    
105      /**
106       * Constructor
107       *
108       * @param className The name of the class for the compiler site
109       * @param methodName The name of the method for the compiler site
110       * @param methodSig The signature of the method for the compiler site
111       * @param compiler   The ID of the compiler to use for this method
112       *
113       * @see CompilerAdviceInfoReader
114       */
115      public CompilerAdviceAttribute(Atom className, Atom methodName, Atom methodSig, int compiler) {
116        this.className = className;
117        this.methodName = methodName;
118        this.methodSig = methodSig;
119        this.compiler = compiler;
120        this.optLevel = -1;
121      }
122    
123      /**
124       * Constructor
125       *
126       * @param className  The name of the class for the compiler site
127       * @param methodName The name of the method for the compiler site
128       * @param methodSig  The signature of the method for the compiler site
129       * @param compiler   The ID of the compiler to use for this method
130       * @param optLevel   The optimization level if using Opt compiler
131       *
132       * @see CompilerAdviceInfoReader
133       */
134      public CompilerAdviceAttribute(Atom className, Atom methodName, Atom methodSig, int compiler,
135                                        int optLevel) {
136        this.className = className;
137        this.methodName = methodName;
138        this.methodSig = methodSig;
139        this.compiler = compiler;
140        this.optLevel = optLevel;
141      }
142    
143      /**
144       * Stringify this instance
145       *
146       * @return The state of this instance expressed as a string
147       */
148      @Override
149      public String toString() {
150        return ("Compiler advice: " +
151                className +
152                " " +
153                methodName +
154                " " +
155                methodSig +
156                " " +
157                compiler +
158                "(" +
159                optLevel +
160                ")");
161      }
162    
163      /**
164       * Use a list of compiler advice attributes to create an advice map
165       * keyed on <code>RVMMethod</code> instances.  This map is used by
166       * <code>getCompilerAdviceInfo()</code>.
167       *
168       * @param compilerAdviceList A list of compiler advice attributes
169       * @see #getCompilerAdviceInfo
170       */
171      public static void registerCompilerAdvice(List<CompilerAdviceAttribute> compilerAdviceList) {
172        // do nothing for empty list
173        if (compilerAdviceList == null) return;
174    
175        hasAdvice = true;
176    
177        // iterate over each element of the list
178        ListIterator<CompilerAdviceAttribute> it = compilerAdviceList.listIterator();
179        while (it.hasNext()) {
180          // pick up an attribute
181          CompilerAdviceAttribute attr = it.next();
182          attribMap.put(attr, attr);
183          // XXX if already there, should we warn the user?
184        }
185      }
186    
187      /**
188       * Given a method and bytecode offset, return an compiler advice
189       * attribute or null if none is found for that method and offset.
190       *
191       * @param method The method containing the site in question
192       * @return Attribute advice for that site or null if none is found.
193       */
194      public static CompilerAdviceAttribute getCompilerAdviceInfo(RVMMethod method) {
195        tempAttr.className = method.getDeclaringClass().getDescriptor();
196        tempAttr.methodName = method.getName();
197        tempAttr.methodSig = method.getDescriptor();
198        CompilerAdviceAttribute value = attribMap.get(tempAttr);
199    
200        if (value == null) {
201          return defaultAttr;
202        } else {
203          return value;
204        }
205      }
206    
207      public static Collection<CompilerAdviceAttribute> values() {
208        return attribMap.values();
209      }
210    
211      public static boolean hasAdvice() {
212        return hasAdvice;
213      }
214    
215      @Override
216      public boolean equals(Object obj) {
217        if (super.equals(obj)) {
218          return true;
219        }
220    
221        if (obj instanceof CompilerAdviceAttribute) {
222          CompilerAdviceAttribute attr = (CompilerAdviceAttribute) obj;
223          if (attr.className == className && attr.methodName == methodName && attr.methodSig == methodSig) {
224            return true;
225          }
226        }
227        return false;
228      }
229    
230      @Override
231      public int hashCode() {
232        return className.hashCode() ^ methodName.hashCode() ^ methodSig.hashCode();
233      }
234    }