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