Package ai.interpreter

Source Code of ai.interpreter.Interpreter$MyQueue

package ai.interpreter;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import org.apache.log4j.Logger;

import ai.cfg.CFGVertice;
import ai.cfg.MethodControlFlowGraph;
import ai.cfg.Utils;
import ai.cfg.edges.CFGMultiTargetEdge;
import ai.cfg.edges.CFGMultiTargetEdge.CFGSingleEdge;
import ai.common.MutableInt;
import ai.common.Pair;
import ai.domain.AbstractSemanticsIntf;
import ai.domain.DomainIntf;
import ai.domain.widening.WideningOperator;

public class Interpreter<DI extends DomainIntf<DI>> {
 
  private class MyQueue {
    private Queue<CFGVertice> queue = new LinkedList<CFGVertice>();
    private Set<CFGVertice> vertices = new HashSet<CFGVertice>();
    public void add(CFGVertice vertice) {
      if (vertices.contains(vertice)) return;
      queue.add(vertice);
      vertices.add(vertice);
    }
   
    public CFGVertice poll() {
      CFGVertice result = queue.poll();
      vertices.remove(result);
      return result;
    }
   
    public boolean isEmpty() {
      return queue.isEmpty();
    }
  }

  private final static Logger log = Logger.getLogger(Interpreter.class.getName())
  private final MethodControlFlowGraph graph;
  private final DI initialValue;
  private final StopCondition sc;
 
  private Interpreter(MethodControlFlowGraph graph, DI initialValue, StopCondition sc){
    this.graph = graph;
    this.initialValue = initialValue;
    this.sc = sc;
  }

  private static <DI extends DomainIntf<DI>, T> DI calcualteCumulativeInput(List<T> inputs, Map<T, DI> edgeValues) {
    DI result = null;
    for (T inEdge : inputs) {
      if (!edgeValues.containsKey(inEdge))
        continue;
      DI value = edgeValues.get(inEdge);
      if (result == null) {
        result = value;
      } else {
        result = result.join(value);
      }
    }
    return result;
  }
 
  private static <T, DI> void putNonNullValue(Map<T, DI> map, T key, DI value) {
    if (value == null)
      throw new InterpreterException("Invalid domain null value");
    map.put(key, value);
  }
 
  private static final String MESSAGE_TEMPLATE = "Widening required(method:'%s',semantics:'%s'), iteration: %s";
 
  private static <DI extends DomainIntf<DI>> void logWidening(MethodControlFlowGraph cfg, AbstractSemanticsIntf<DI> semantics, int iteration) {
    log.debug("Widening required, iteration " + iteration);
    if (iteration > 1)
      log.warn(String.format(MESSAGE_TEMPLATE, cfg.getCodeFragment().getUniqueName(), semantics, iteration));
  }
 
  private Pair<CFGSingleEdge, DI> computeInputEdgeValue(AbstractSemanticsIntf<DI> semantics) {
    List<Pair<CFGSingleEdge, DI>> x = graph.getInput().acceptVerified(semantics, initialValue!=null ? initialValue : semantics.getInitialValue());
    if (x.size()!=1)
      throw new InterpreterException("This shouldn't happen");
    return x.get(0);
  }
 
  private static final Set<CFGSingleEdge> EMPTY_EDGES_SET = new HashSet<CFGSingleEdge>();
 
  private boolean allInputsCalculated(List<CFGSingleEdge> inputs, Map<CFGSingleEdge, DI> values,
      Collection<CFGSingleEdge> loopEdges){
    if (loopEdges == null)
      loopEdges = EMPTY_EDGES_SET;
    for(CFGSingleEdge input: inputs)
      if (values.get(input) == null && !loopEdges.contains(input))
        return false;
    return true;
  }
 
  private Map<CFGVertice, DI> performAnalysis(AbstractSemanticsIntf<DI> semantics){
//    Utils.printCFG(graph);
    Map<CFGVertice, DI> values = new HashMap<CFGVertice, DI>();
    Map<CFGSingleEdge, DI> edgeValues = new HashMap<CFGSingleEdge, DI>();

    Map<CFGVertice, List<CFGSingleEdge>> inputs = Utils.computeInputEdges(graph);
    //find loops and prepare counting widening iterations
    Map<CFGVertice, MutableInt> wideningCounts = new HashMap<CFGVertice, MutableInt>();
    Map<CFGVertice, Collection<CFGSingleEdge>> loopVertices = Utils.findLoopVertices(graph);
    Map<CFGVertice, WideningOperator<DI>> widenings = new HashMap<CFGVertice, WideningOperator<DI>>();
    for(CFGVertice loopVertice: loopVertices.keySet()) {
      wideningCounts.put(loopVertice, new MutableInt(0));
      widenings.put(loopVertice, semantics.getWideningOperator());
    }
   
    Pair<CFGSingleEdge, DI> start = computeInputEdgeValue(semantics);
    MyQueue queue = new MyQueue();
    putNonNullValue(edgeValues, start.left, start.right);
    queue.add(start.left.target);
    while(!queue.isEmpty()) {
      if (sc.shouldStop()) {
        System.out.println("---------------interrupted!");
        return null;
      }
      CFGVertice vertice = queue.poll();
      //compute inputs
      log.debug("Processing vertice:" + vertice);
      DI oldValue = values.get(vertice);
      log.debug("Cumulative input before: " + oldValue);
      DI newValue = calcualteCumulativeInput(inputs.get(vertice), edgeValues);
      log.debug("Cumulative input after: " + newValue);

      //perform widening if required
      if (oldValue != null && wideningCounts.containsKey(vertice)) {
        int iteration = wideningCounts.get(vertice).inc();
        WideningOperator<DI> wid = widenings.get(vertice);
        newValue = wid.widen(oldValue, newValue);
        logWidening(graph, semantics, iteration);
      }

//      //verify if semantics is "correct"
//      if (newValue == null || (oldValue != null && !oldValue.leq(newValue)))
//        throw new InterpreterException("Invalid semantics!!, old value: '%s', new value: '%s'", oldValue, newValue);
      //no changes, no propagation required
      if (oldValue !=null && oldValue.equals(newValue))
        continue;
      values.put(vertice, newValue);
      //we have to propagate!!
      for(CFGMultiTargetEdge multiEdge: vertice.getOutgoingMultiEdges())
        for(Pair<CFGSingleEdge, DI> res: multiEdge.acceptVerified(semantics, newValue)){
          log.debug(" Edge: "+res.left);
          CFGSingleEdge edge = res.left;
          DI newEdgeValue = res.right;
//          DI oldEdgeValue = edgeValues.get(res.left);
//          //verify if the semantics is "correct"
//          if (newEdgeValue == null || (oldEdgeValue != null && !oldEdgeValue.leq(newEdgeValue)))
//            throw new InterpreterException("Invalid semantics of '%s'!!", edge.toString());
          edgeValues.put(edge, newEdgeValue);
          //add target to queue
          if (allInputsCalculated(inputs.get(edge.target), edgeValues, loopVertices.get(edge.target)))
            queue.add(edge.target);
        }
    }
    return values;
  }

  public static <DI extends DomainIntf<DI>> Map<CFGVertice, DI> analyse(MethodControlFlowGraph graph, AbstractSemanticsIntf<DI> semantics,
      StopCondition sc) {
    return analyse(graph, semantics, null, sc);
  }

  /**
   * FOR TESTS ONLY!!
   * @param graph
   * @param semantics
   * @param initialValue
   * @return
   */
  public static <DI extends DomainIntf<DI>> Map<CFGVertice, DI> analyse(MethodControlFlowGraph graph, AbstractSemanticsIntf<DI> semantics,
      DI initialValue, StopCondition sc) {
    Interpreter<DI> interpreter = new Interpreter<DI>(graph, initialValue, sc);
    Map<CFGVertice, DI> values = interpreter.performAnalysis(semantics);
    sc.stop();
    return values == null ? null : Collections.unmodifiableMap(values);
  }
}
TOP

Related Classes of ai.interpreter.Interpreter$MyQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.