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.io.BufferedReader;
016    import java.io.FileInputStream;
017    import java.io.IOException;
018    import java.io.InputStreamReader;
019    import java.util.ArrayList;
020    import java.util.List;
021    import java.util.NoSuchElementException;
022    import java.util.StringTokenizer;
023    import org.jikesrvm.VM;
024    import org.jikesrvm.adaptive.controller.Controller;
025    import org.jikesrvm.classloader.Atom;
026    
027    /**
028     * Utility to read compiler advice annotations from file in ascii format.
029     * Takes a single argument: the name of the file containing the ascii
030     * annotations.  Each line of the file corresponds to an annotation
031     * for one method and has the following format:
032     * <p>
033     * <pre>
034     * <class> <method> <signature> <advice> <optLevel>
035     * </pre>
036     * Where the types and meanings of the fields is as follows:
037     * <ul>
038     * <li><code>&lt;class></code> <i>string</i> The name of the class</li>
039     * <li><code>&lt;method></code> <i>string</i> The name of the method</li>
040     * <li><code>&lt;signature></code> <i>string</i> The method signature</li>
041     * <li><code>&lt;advice></code> <i>int</i> The compiler type to be used --
042     * an integer value corresponding to the compiler enumeration in
043     CompiledMethod</li>
044     * <li><code>&lt;optLevel></code> <i>int</i> (Optional) The opt level to use
045     if compiler is optimizing compiler</li>
046     * </ul>
047     *
048     *
049     * @see CompilerAdvice
050     * @see CompilerAdviceAttribute
051     */
052    class CompilerAdviceInfoReader {
053    
054      /**
055       * Read annotations from a specified file. Reads all annotations at
056       * once and returns a collection of compiler advice attributes.
057       *
058       * @param file The annotation file to be read
059       * @return A list of compiler advice attributes
060       */
061      public static List<CompilerAdviceAttribute> readCompilerAdviceFile(String file) {
062        List<CompilerAdviceAttribute> compilerAdviceInfo = new ArrayList<CompilerAdviceAttribute>();
063        BufferedReader fileIn = null;
064    
065        if (file == null) return null;
066    
067        try {
068          fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
069    
070          try {
071            for (String s = fileIn.readLine(); s != null; s = fileIn.readLine()) {
072              if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1) { VM.sysWrite("."); }
073              StringTokenizer parser = new StringTokenizer(s, " \n,");
074              compilerAdviceInfo.add(readOneAttribute(parser));
075    
076            }
077          } catch (IOException e) {
078            e.printStackTrace();
079            VM.sysFail("Error parsing input compilation advice file " + file);
080          }
081    
082          fileIn.close();
083        } catch (java.io.FileNotFoundException e) {
084          System.out.println("IO: Couldn't read compiler advice attribute file: " + file + e);
085          return null;
086        } catch (java.io.UnsupportedEncodingException e) {
087          System.out.println("IO: UTF-8 is not supported: " + e);
088          return null;
089        } catch (java.io.IOException e) {
090          System.out.println("IO: Couldn't close compiler advice attribute file: " + file + e);
091          return null;
092        }
093    
094        return compilerAdviceInfo;
095      }
096    
097      /**
098       * Actual reading is done here.  This method reads one attribute
099       * from a single line of an input stream.  There are six elements
100       * per line corresponding to each call site. First three are
101       * strings, <i>class name</i>, <i>method name</i>, <i>method
102       * signature</i>, followed by one number,
103       * <i>compiler advice</i>.
104       *
105       * @param st an input stream
106       * @return an compileration advice atribute
107       */
108      private static CompilerAdviceAttribute readOneAttribute(StringTokenizer st) {
109        int compiler, optLevel = -1;
110    
111        try {
112          Atom cls = Atom.findOrCreateUnicodeAtom(st.nextToken());
113          Atom mth = Atom.findOrCreateUnicodeAtom(st.nextToken());
114          Atom sig = Atom.findOrCreateUnicodeAtom(st.nextToken());
115          compiler = Integer.parseInt(st.nextToken());
116          optLevel = Integer.parseInt(st.nextToken());
117          // this is the attribute which will be returned
118          CompilerAdviceAttribute newAttrib;
119    
120          if (optLevel >= 0) {
121            newAttrib = new CompilerAdviceAttribute(cls, mth, sig, compiler, optLevel);
122          } else {
123            newAttrib = new CompilerAdviceAttribute(cls, mth, sig, compiler);
124          }
125    
126          return newAttrib;
127        } catch (NoSuchElementException e) {
128          return null;
129        }
130    
131      }
132    }