Package org.jakstab.analysis

Source Code of org.jakstab.analysis.ReachedSet

/*
* ReachedSet.java - This file is part of the Jakstab project.
* Copyright 2007-2012 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/
package org.jakstab.analysis;

import java.util.*;

import org.jakstab.analysis.composite.CompositeState;
import org.jakstab.analysis.location.LocationState;
import org.jakstab.cfa.Location;
import org.jakstab.util.Logger;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;

/**
* A set of reached states for use in the CPA algorithm. It can generate lightweight views on
* parts of its contents much like an SQL database using select(row) and where(row, hasValue).
*
* @author Johannes Kinder
*/
public class ReachedSet extends AbstractSet<AbstractState> implements Collection<AbstractState> {

  @SuppressWarnings("unused")
  private static final Logger logger = Logger.getLogger(ReachedSet.class);
 
  private final SetMultimap<AbstractState, CompositeState> compositeMap;
  private static final int indexComponent = 0;
  private final int selectedRow;
  private final int whereRow;
  private final AbstractState whereState;
 
  public ReachedSet() {
    this(-1, -1, null, HashMultimap.<AbstractState, CompositeState>create(1000, 5));
  }
 
  private ReachedSet(int selectedRow, int whereRow, AbstractState whereState,
      SetMultimap<AbstractState, CompositeState> compositeMap) {
    this.compositeMap = compositeMap;
    this.selectedRow = selectedRow;
    this.whereRow = whereRow;
    this.whereState = whereState;
  }
 
  public ReachedSet select(int component) {
    assert this.selectedRow == -1;
    return new ReachedSet(component, this.whereRow, this.whereState, this.compositeMap);
  }
 
  public ReachedSet where(int row, AbstractState state) {
    assert this.whereRow == -1 && this.whereState == null;
    return new ReachedSet(this.selectedRow, row, state, this.compositeMap);
  }
 
  public ReachedSet where(Location l) {
    assert this.whereRow == -1 && this.whereState == null;
    return where(0, new LocationState(l));
  }

  public boolean add(AbstractState s) {
    if (s instanceof CompositeState) return add((CompositeState)s);
    else throw new UnsupportedOperationException();
  }

  public boolean remove(AbstractState s) {
    if (s instanceof CompositeState) return remove((CompositeState)s);
    else throw new UnsupportedOperationException();
  }

  public boolean add(CompositeState s) {
    assert selectedRow == -1;
    return compositeMap.put(s.getComponent(indexComponent), s);
  }
 
  public boolean remove(CompositeState s) {
    assert selectedRow == -1;
    return compositeMap.remove(s.getComponent(indexComponent), s);
  }
 
  public int size() {
    if (whereRow < 0)
      return compositeMap.size();
    if (whereRow == indexComponent)
      return compositeMap.get(whereState).size();
    throw new UnsupportedOperationException("Cannot determine reached set size for non-index component restrictions!");
  }

  @Override
  public boolean contains(Object o) {
    if (selectedRow < 0) {
      if (o instanceof CompositeState)
        return compositeMap.containsEntry(((CompositeState)o).getComponent(indexComponent), o);
      else throw new UnsupportedOperationException();
    } else {
      for (AbstractState as : this) {
        if (as.equals(o)) return true;
      }
      return false;
    }
  }
 
  public void logHighestStateCounts(int count) {
    AbstractState[] stateArray = compositeMap.keySet().toArray(new AbstractState[compositeMap.keySet().size()]);
    Arrays.sort(stateArray, new Comparator<AbstractState>() {
      @Override
      public int compare(AbstractState o1, AbstractState o2) {
        Integer size1 = compositeMap.get(o1).size();
        Integer size2 = compositeMap.get(o2).size();
        return size2.compareTo(size1);
      }
    });
   
    logger.fatal("==========================================");
    logger.fatal("The " + count + " locations with highest state count:");
    logger.fatal("==========================================");
    for (int i=0; i < Math.min(count, stateArray.length); i++) {
      logger.fatal(stateArray[i] + ":\t" + compositeMap.get(stateArray[i]).size());
    }
    logger.fatal("-------------");
    logger.fatal("Top Location:");
    logger.fatal("-------------");
    for (AbstractState s : compositeMap.get(stateArray[0])) {
      logger.fatal(s);
    }
  }
 
  public void logStates(Location loc) {
    for (CompositeState c : compositeMap.get(new LocationState(loc))) {
      logger.fatal(c);
    }
  }

  @Override
  public Iterator<AbstractState> iterator() {
    return new Iterator<AbstractState>() {
      CompositeState next;
      private Iterator<CompositeState> compIter;
      // Select either generic iterator or refine by indexed map
      {
        if (whereRow == indexComponent) {
          compIter = compositeMap.get(whereState).iterator();
        } else {
          compIter = compositeMap.values().iterator();
        }
      }
     
      @Override
      public boolean hasNext() {
        while (next == null) {
          if (!compIter.hasNext()) return false;
          CompositeState c = compIter.next();
         
          // If we're filtering by indexed component (or not at all), no need for an extra comparison
          if (whereRow < 0 || whereRow == indexComponent) {
            next = c;
          } else {
            if (c.getComponent(whereRow).equals(whereState)) {
              next = c;
            }
          }
        }
        return true;
      }

      @Override
      public AbstractState next() {
        AbstractState retVal;
        if (hasNext()) {
          if (selectedRow < 0) {
            retVal = next;
          } else {
            retVal = next.getComponent(selectedRow);
          }
          next = null;
          return retVal;
        }
        else throw new NoSuchElementException();
      }

      @Override
      public void remove() {
        compIter.remove();
      }
    };
  }


}
TOP

Related Classes of org.jakstab.analysis.ReachedSet

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.