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.io.BufferedReader;
016import java.io.FileInputStream;
017import java.io.IOException;
018import java.io.InputStreamReader;
019import java.util.ArrayList;
020import java.util.List;
021import java.util.NoSuchElementException;
022import java.util.StringTokenizer;
023import org.jikesrvm.VM;
024import org.jikesrvm.adaptive.controller.Controller;
025import 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 * <pre>
033 * &lt;class&gt; &lt;method&gt; &lt;signature&gt; &lt;advice&gt; &lt;optLevel&gt;
034 * </pre>
035 * Where the types and meanings of the fields is as follows:
036 * <ul>
037 * <li><code>&lt;class&gt;</code> <i>string</i> The name of the class</li>
038 * <li><code>&lt;method&gt;</code> <i>string</i> The name of the method</li>
039 * <li><code>&lt;signature&gt;</code> <i>string</i> The method signature</li>
040 * <li><code>&lt;advice&gt;</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&gt;</code> <i>int</i> (Optional) The opt level to use
044 if compiler is optimizing compiler</li>
045 * </ul>
046 *
047 * @see CompilerAdvice
048 * @see CompilerAdviceAttribute
049 */
050class CompilerAdviceInfoReader {
051
052  /**
053   * Read annotations from a specified file. Reads all annotations at
054   * once and returns a collection of compiler advice attributes.
055   *
056   * @param file The annotation file to be read
057   * @return A list of compiler advice attributes
058   */
059  public static List<CompilerAdviceAttribute> readCompilerAdviceFile(String file) {
060    List<CompilerAdviceAttribute> compilerAdviceInfo = new ArrayList<CompilerAdviceAttribute>();
061    BufferedReader fileIn = null;
062
063    if (file == null) return null;
064
065    try {
066      fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
067
068      try {
069        for (String s = fileIn.readLine(); s != null; s = fileIn.readLine()) {
070          if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1) {
071            VM.sysWrite(".");
072          }
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}