Logo Search packages:      
Sourcecode: tau version File versions

Interpreter.java

package TauIL.interpreter;

import TauIL.absyn.*;
import TauIL.util.InstList;

import java.io.PrintStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Vector;

/**
 * The TauIL interpreter is used to interpret an {@link AbstractSyntaxTree} which is the
 * intermediate representation generated by the TauIL {@link TauIL.parser.Parser}. A TauIL interpreter
 * instance has methods to change the abstract syntax on the fly and therefore can be used 
 * on multiple syntax trees without the need to instantiate a new instance.
 */
00017 public class Interpreter {
    // Abstract syntax tree currently being interpreted.
    private AbstractSyntaxTree ast;

    // Vector of selective insturmentation lists for use by TAU insturmentor.
    private Vector list;

    // Global and local inclusion and exclusion lists.
    private Vector [] global_exclude = new Vector[Entity.MAX_ENTITY_VALUE + 1], 
      global_include = new Vector[Entity.MAX_ENTITY_VALUE + 1];

    private Vector [] local_exclude = new Vector[Entity.MAX_ENTITY_VALUE + 1], 
      local_include = new Vector[Entity.MAX_ENTITY_VALUE + 1];

    // Pointers are used by the interpreter to actually refer to the
    // global and local lists.

    // *----------- Pointers -------------*

    // These pointers are set to point at the appropriate global or local 
    // list based on point in interpretation.
    private Vector [] include = new Vector[Entity.MAX_ENTITY_VALUE + 1], 
      exclude = new Vector[Entity.MAX_ENTITY_VALUE + 1];

    // These pointers are set to point at the appropriate list based on
    // the target directive.
    private Vector [] condition_list = new Vector[Entity.MAX_ENTITY_VALUE + 1], 
      anti_list = new Vector[Entity.MAX_ENTITY_VALUE + 1];

    // This pointer is set to point at the appropriate list base on whether
    // conditions or anti_conditions are being interpreted.
    private Vector [] current_list = new Vector[Entity.MAX_ENTITY_VALUE + 1];

    // *---------- End Pointers ------------*

    // Current insturmentation tree node and current data source.
    private Directive data_source;
    private Instrumentation scenario;

    // Data source object for analytical data evaluation.
    private DataSource data;

    // Insturmentation target.
    private int target = InstList.EXCLUDE;

    // Insturmentation count.
    private int count = 0;

    // Debug and verbose mode flags.
    private boolean debug = false;
    private boolean verbose = false;

    // Used to quiet paraprof output.
    private File empty_file = new File("tauIL_dev_null");
    private PrintStream dev_null;

    /**
     * Creates a new TauIL interpreter instance.
     *
     */
00077     public Interpreter() {
      debug("Interpreter : Interpreter()");

      // Initialize inclusion and exclusion lists.
      for (int i = 0; i <= Entity.MAX_ENTITY_VALUE; i++) {
          global_exclude[i] = new Vector();
          global_include[i] = new Vector();

          local_include[i] = new Vector();
          local_exclude[i] = new Vector();
      }

      list = new Vector();

      ast = null;
    }

    /**
     * Creates a new TauIL interpreter instance with the given {@link AbstractSyntaxTree}.
     *
     * @param ast TauIL {@link AbstractSyntaxTree} to be interpreted by the TauIL interpreter.
     */
00099     public Interpreter(AbstractSyntaxTree ast) {
      this();

      debug("Interpreter : Interpreter(AbstractSyntaxTree)");

      this.ast = ast;
    }

    /**
     * Sets the {@link AbstractSyntaxTree} to be interpreted by the TauIL interpreter.
     *
     * @param ast a TauIL {@link AbstractSyntaxTree} to be interpreted by the TauIL interpreter.
     */
00112     public void setAST(AbstractSyntaxTree ast) {
      debug("Interpreter : setAST(AbstractSyntaxTree)");

      this.ast = ast;
    }

    /**
     * Retrieves the current {@link AbstractSyntaxTree} that the interpreter contains.
     *
     * @return a TauIL {@link AbstractSyntaxTree}.
     */
00123     public AbstractSyntaxTree getAST() {
      debug("Interpreter : getAST()");

      return ast;
    }

    /**
     * Gets the number of selective insturmentation lists created.
     *
     * @return number of generated insturmentation lists.
     */
00134     public int numberInstLists() {
      return list.size();
    }

    /**
     * Retrieves the generated selective insturmentation lists.
     *
     * @return a Vector of {@link InstList} objects.
     */
00143     public Vector getInstLists() {
      return list;
    }

    /**
     * Toggles debuging mode on or off.
     *
     * @param debug a true value enables debugging and false disables.
     */
00152     public void setDebugMode(boolean debug) {
      this.debug = debug;
    }

    /**
     * Toggles verbose output on or off.
     *
     * @param verbose a true values enables verbose output while false
     *        quiets the interpreter.
     */
00162     public void setVerboseMode(boolean verbose) {
      this.verbose = verbose;
    }

    /**
     * Interprets the current {@link AbstractSyntaxTree}.
     */
00169     public void interpret() throws Exception {
      debug("Interpreter : interpret()");

      // Throw error if a syntax tree hasn't been specified.
      if (ast == null) 
          throw new Error("AST is null!");

      // Set up file for output redirect.
      if (empty_file.exists())
          empty_file.delete();

      empty_file.createNewFile();
      dev_null = new PrintStream(new FileOutputStream(empty_file));

      // Set the include and exclude pointers to the global lists.
      include = global_include;
      exclude = global_exclude;

      debug("Interpreting global declarations...");
      interpretList((SyntaxList) ast.declarations);

      // Set the include and exclude pointers too the local lists.
      include = local_include;
      exclude = local_exclude;

      debug("Interpreting insturmentation scenarios...");
      interpretList((SyntaxList) ast.root);

      dev_null.close();
      empty_file.delete();
    }

    private void interpretList(SyntaxList list) {
      debug("Interpreter : interpretList(SyntaxList)");

      // Create a new list manager.
      ListManager iterator = new ListManager(list);

      // Iterate through the list and interpert each element.
      while (iterator.hasNext())
          interpretAS(iterator.next());
    }

    private void interpretAS(AbstractSyntax absyn) {
      debug("Interpreter : interpretAS(AbstractSyntax)");

      if (absyn == null) return;
      else if (absyn instanceof SyntaxElement) interpretElem((SyntaxElement) absyn);
      else if (absyn instanceof SyntaxAttribute) throw new Error(absyn + " : Syntax attributes can not be interpreted!");
      else throw new Error(absyn + " : Unrecogonized abstract syntax element!");
    }

    private void interpretElem(SyntaxElement elem) {
      debug("Interpreter : interpretElem(SyntaxElement)");

      if (elem == null) return;
      else if (elem instanceof Declaration) interpret((Declaration) elem);
      else if (elem instanceof Statement) interpret((Statement) elem);
      else if (elem instanceof Directive) interpret((Directive) elem);
      else if (elem instanceof Instrumentation) interpret((Instrumentation) elem);

      /*
      else if (elem instanceof InsturmentationList) interpretList((InsturmentationList) elem);
      else throw new Error("Unrecogonized syntax element : " + elem);
      */
    }

    private void interpret(Declaration dec) {
      debug("Interpreter : interpret(Declaration)");

      if (dec == null) return;
      else if (dec instanceof IncludeDec) interpret((IncludeDec) dec);
      else throw new Error(dec + " : Unrecognized declaration class!");
    }

    private void interpret(Statement elem) {
      debug("Interpreter : interpret(Statement)");

      if (elem instanceof MultiStatement) interpret((MultiStatement) elem);
      else if (elem instanceof OperatorStatement) throw new Error(elem + " : Operator statments must be contained within a mulitistatment!");
      
    }

    private void interpret(Directive direct) {
      debug("Interpreter : interpret(Directive)");

      switch(direct.directive) {
      case Directive.TARGET :
          if (direct.flag == Directive.INCLUDE) {
            condition_list = local_include;
            anti_list = local_exclude;
            target = InstList.INCLUDE;
          }
          break;
      case Directive.TYPE :
          break;
      case Directive.USE :
          data_source = direct;
          break;
      default :
          throw new Error(direct.directive + " : Unrecognized directive type!");
      }
    }

    private void interpret(IncludeDec dec) {
      debug("Interpreter : interpret(IncludeDec)");

      // Temporary pointer.
      Vector temp;

      // Set temporary pointer to the appropriate list offset.
      switch(dec.include_flag) {
      case IncludeDec.INCLUDE :
          temp = include[dec.entity_flag];
          break;
      case IncludeDec.EXCLUDE :
          temp = exclude[dec.entity_flag];
          break;
      default :
          throw new Error(dec.include_flag + " : Unrecognized include declaration type!");
      }

      // Iterate through the entity list and add each entity to the
      // temporary pointer list.
      ListManager iterator = new ListManager(dec.list);
      while (iterator.hasNext()) {
          Entity ent = (Entity) iterator.next();
          temp.add(ent.name);
      }
    }

    private void interpret(Instrumentation instr) {
      debug("Interpreter : interpret(Instrumentation)");

      scenario = instr;

      resetLocalLists();

      // Set default condition and anti_condition lists.
      condition_list = local_exclude;
      anti_list = local_include;

      // Set default target.
      target = InstList.EXCLUDE;

      // Based on data source type set default source information.
      switch(instr.type) {
      case Instrumentation.PROFILE :
          data_source = new Directive(Directive.USE, Directive.FILE, "pprof.dat");
          break;
      case Instrumentation.STATIC :
          throw new Error(instr.type + " : Sorry, no support for static data sources at this time!");
      case Instrumentation.RUNTIME :
          throw new Error(instr.type + " : Sorry, no support for runtime data sources at this time!");
      default :
          throw new Error(instr.type + " : Unrecognized data source type!");
      }

      debug("Interpreting instrumentation directives...");
      interpretList(instr.directives);

      // Load data source.
      loadDataSource();

      debug("Interpreting instrumentation declarations...");
      interpretList(instr.declarations);

      debug("Interpreting instrumentation conditions...");
      current_list = condition_list;
      interpretList(instr.conditions);

      debug("Interpreting instrumentation anti-conditions...");
      current_list = anti_list;
      interpretList(instr.anti_conditions);

      // --------------- incomplete -------------------------------

      Vector files = new Vector(condition_list[Entity.FILE]);
      Vector events = new Vector(condition_list[Entity.EVENT]);

      files.removeAll(anti_list[Entity.FILE]);
      events.removeAll(anti_list[Entity.EVENT]);

      list.add(new InstList(instr.fname, files, events, target));

      // ----------------------------------------------------------

      // Increment scenario count.
      count++;
    }

    private void interpret(MultiStatement list) {
      debug("Interpreter : interpret(MultiStatement)");
      info("__________________________________________________________________________________");
      info(list.generateSyntax());
      info("");

      ListManager iterator = new ListManager(list);

      while (data.hasNext()) {
          boolean match = true;

          data.next();
          iterator.reset();

          while(iterator.hasNext() && match)
            match = interpret((OperatorStatement) iterator.next());

          if (match) {
            String name = data.getEventName();

            info("\t" + name);

            if (current_list[Entity.EVENT].indexOf(name) == -1)
                current_list[Entity.EVENT].add(name);
          }
      }

      data.reset();

    }

    private boolean interpret(OperatorStatement eval) {
      debug("Interpreter : interpret(OperatorStatement)");
      
      ProfileDataSource pds = (ProfileDataSource) data;

      if (pds.isTimeMetric() && (eval.field.metric == Field.COUNTER)) {
          System.out.println("Counter metrics in rule, but profile contains timer metrics!");
          return false;
      } else if (!pds.isTimeMetric() && (eval.field.metric == Field.TIMER)) {
          System.out.println("Timer metrics in rule, but profile contains counter metrics!");
          return false;
      }

      double value;

      switch(eval.field.field) {
      case Field.NUMCALLS :
          value = pds.getNumCalls();
          break;
      case Field.NUMSUBRS :
          value = pds.getNumSubRS();
          break;
      case Field.PERCENT :
          value = pds.getPercent();
          break;
      case Field.USEC :
          value = pds.getUsec();
          break;
      case Field.COUNT :
          value = pds.getCount();
          break;
      case Field.CUMUSEC :
          value = pds.getCumUsec();
          break;
      case Field.TOTCOUNT :
          value = pds.getTotCount();
          break;
      case Field.STDDEV :
          value = pds.getStdDev();
          break;
      case Field.USECS_CALL :
          value = pds.getUsecsPerCall();
          break;
      case Field.COUNTS_CALL :
          value = pds.getCountsPerCall();
          break;
      default :
          throw new Error(eval.field.field + " : Unrecognized field!");
      }

      return evaluate(value, eval.op, eval.val.value.doubleValue());
    }

    private boolean evaluate(double data_val, Operator op, double test_val) {
      debug("Interpreter : evaluate(double, Operator, double)");
      
      switch (op.op) {
      case Operator.EQ :
          return (data_val == test_val);
      case Operator.LT :
          return (data_val < test_val);
      case Operator.GT :
          return (data_val > test_val);
      case Operator.GTEQ :
          return (data_val >= test_val);
      case Operator.LTEQ :
          return (data_val <= test_val);
      case Operator.NEQ :
          return (data_val != test_val);
      default :
          return false;
      }
    }

    private void loadDataSource() {
      debug("Interpreter : loadDataSource()");

      switch(data_source.flag) {
      case Directive.FILE :
          break;
      case Directive.DB :
          throw new Error(data_source.flag + " : Database data sources are not supported at this time!");
      default :
          throw new Error(data_source.flag + " : Unrecognized data source use type!");
      }

      switch(scenario.type) {
      case Instrumentation.PROFILE :
          data = new ProfileDataSource(data_source.arg);
          break;
      case Instrumentation.STATIC :
      case Instrumentation.RUNTIME :
      }

      PrintStream temp = System.out;
      System.setOut(dev_null);

      data.load();

      System.setOut(temp);
    }

    private void resetLocalLists() {
      debug("Interpreter : resetLocalLists()");

      for (int i = 0; i <= Entity.MAX_ENTITY_VALUE; i++) {
          local_exclude[i].clear();
          local_include[i].clear();

          local_exclude[i].addAll(global_exclude[i]);
          local_include[i].addAll(global_include[i]);
      }
    }

    private void debug(String text) {
      if (debug)
          System.out.println(text);
    }

    private void info(String text) {
      if (verbose)
          System.out.println(text);
    }
}

Generated by  Doxygen 1.6.0   Back to index