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.StringTokenizer;
020    import org.jikesrvm.VM;
021    import org.jikesrvm.adaptive.controller.Controller;
022    import org.jikesrvm.adaptive.database.callgraph.PartialCallGraph;
023    import org.jikesrvm.classloader.RVMClassLoader;
024    import org.jikesrvm.classloader.MemberReference;
025    import org.jikesrvm.classloader.RVMMethod;
026    import org.jikesrvm.classloader.MethodReference;
027    
028    /**
029     * Utility to read dynamic call graph annotations from file in ascii format.
030     * Takes a single argument: the name of the file containing the ascii
031     * annotations.  Each line of the file corresponds to an annotation
032     * for one method and has the following format:
033     * <p>
034     * <pre>
035     * CallSite < classloader, classname, method, signature> method_size byte_code_index <callee_classloader, classname, method, signature> method_size weight: weight
036     * </pre>
037     * Where the types and meanings of the fields is as follows:
038     * <ul>
039     * <li><code>&lt;signature></code> <i>string</i> The method signature</li>
040     * </ul>
041     *
042     *
043     * @see CompilerAdvice
044     */
045    public class DynamicCallFileInfoReader {
046    
047      /**
048       * Read annoations from a specified file. Reads all annotations at
049       * once and returns a collection of compiler advice attributes.
050       *
051       * @param file The annoation file to be read
052       */
053      public static void readDynamicCallFile(String file, boolean boot) {
054        BufferedReader fileIn = null;
055    
056        if (file == null) return;// null;
057    
058        if ((!VM.runningVM) && (Controller.dcg == null)) {
059          Controller.dcg = new PartialCallGraph(300);
060        } else if (Controller.dcg == null) {
061          System.out.println("dcg is null ");
062          return;
063        }
064        try {
065          fileIn = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
066          try {
067            for (String s = fileIn.readLine(); s != null; s = fileIn.readLine()) {
068              StringTokenizer parser = new StringTokenizer(s, " \n,");
069              readOneCallSiteAttribute(parser, boot);
070            }
071          } catch (IOException e) {
072            e.printStackTrace();
073            VM.sysFail("Error parsing input dynamic call graph file" + file);
074          }
075          fileIn.close();
076        } catch (java.io.FileNotFoundException e) {
077          System.out.println("IO: Couldn't read compiler advice attribute file: " + file + e);
078        } catch (java.io.UnsupportedEncodingException e) {
079          System.out.println("IO: UTF-16 is not supported: " + e);
080        } catch (IOException e) {
081          VM.sysFail("Error closing input dynamic call graph file" + file);
082        }
083    
084      }
085    
086      private static void readOneCallSiteAttribute(StringTokenizer parser, boolean boot) {
087        String firstToken = parser.nextToken();
088        if (firstToken.equals("CallSite")) {
089          MemberReference callerKey = MemberReference.parse(parser, boot);
090          if (callerKey == null) return;
091          MethodReference callerRef = callerKey.asMethodReference();
092          RVMMethod caller, callee;
093          if (callerRef.getType().getClassLoader() == RVMClassLoader.getApplicationClassLoader()) {
094            caller = callerRef.resolve();
095          } else {
096            caller = callerRef.getResolvedMember();
097          }
098          //if (caller == null) continue;
099          @SuppressWarnings("unused") // serves as doco - token skipped
100              int callerSize = Integer.parseInt(parser.nextToken());
101          int bci = Integer.parseInt(parser.nextToken());
102          MemberReference calleeKey = MemberReference.parse(parser, boot);
103          if (calleeKey == null) return;
104          MethodReference calleeRef = calleeKey.asMethodReference();
105          //if (callee == null) continue;
106          if (calleeRef.getType().getClassLoader() == RVMClassLoader.getApplicationClassLoader()) {
107            callee = calleeRef.resolve();
108          } else {
109            callee = calleeRef.getResolvedMember();
110          }
111          @SuppressWarnings("unused") // serves as doco - token skipped
112              int calleeSize = Integer.parseInt(parser.nextToken());
113          parser.nextToken(); // skip "weight:"
114          float weight = Float.parseFloat(parser.nextToken());
115          if ((caller == null) || (callee == null)) {
116            Controller.dcg.incrementUnResolvedEdge(callerRef, bci, calleeRef, weight);
117          } else {
118            Controller.dcg.incrementEdge(caller, bci, callee, weight);
119          }
120        } else {
121          VM.sysFail("Format error in dynamic call graph file");
122        }
123      }
124    }
125    
126    
127    
128    
129