/*
* This is a prototype implementation of the concept of Feature-Sen
* sitive Dataflow Analysis. More details in the AOSD'12 paper:
* Dataflow Analysis for Software Product Lines
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package br.ufal.cideei.soot.analyses;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import soot.Body;
import soot.PatchingChain;
import soot.Unit;
import soot.toolkits.scalar.FlowSet;
import soot.toolkits.scalar.ForwardFlowAnalysis;
import br.ufal.cideei.soot.instrument.ConfigTag;
import br.ufal.cideei.soot.instrument.IConfigRep;
import br.ufal.cideei.soot.instrument.ILazyConfigRep;
/**
* Utility class for collecting data/metrics about FlowSets.
*
* @author T�rsis
*
*/
public class FlowSetUtils {
/**
* Count the number of units necessary to store the results of analysing body with a simultaneous analysis.
*
* @param body
* the analyzed body
* @param analysis
* the analysis used on body
* @param countKeys
* if keys in the Map of the MapLiftedFlowSet should be taken into consideration
* @param countEmptyAs
* how much should empty FlowSets should count? e.g. 0 or 1?
* @return
*/
public static int liftedMemoryUnits(Body body, ForwardFlowAnalysis<Unit, MapLiftedFlowSet> analysis, boolean countKeys, int countEmptyAs) {
int memUnits = 0;
PatchingChain<Unit> units = body.getUnits();
for (Unit unit : units) {
MapLiftedFlowSet flowAfter = analysis.getFlowAfter(unit);
MapLiftedFlowSet flowBefore = analysis.getFlowBefore(unit);
Set<Entry<IConfigRep, FlowSet>> entrySet;
entrySet = flowBefore.getMapping().entrySet();
for (Entry<IConfigRep, FlowSet> entry : entrySet) {
FlowSet value = entry.getValue();
if (value.isEmpty()) {
memUnits += countEmptyAs;
} else {
memUnits += value.size();
}
if (countKeys) {
memUnits++;
}
}
entrySet = flowAfter.getMapping().entrySet();
for (Entry<IConfigRep, FlowSet> entry : entrySet) {
FlowSet value = entry.getValue();
if (value.isEmpty()) {
memUnits += countEmptyAs;
} else {
memUnits += value.size();
}
if (countKeys) {
memUnits++;
}
}
}
return memUnits;
}
/**
* Count the number of units necessary to store the results of analysing body with a consecutive analysis.
*
* @param body the analyzed body
* @param analysis the analysis that ran on body
* @param countEmptyAs how much should empty FlowSet count? 0? 1?...
* @return
*/
public static long unliftedMemoryUnits(Body body, ForwardFlowAnalysis<Unit, FlowSet> analysis, int countEmptyAs) {
long memUnits = 0;
PatchingChain<Unit> units = body.getUnits();
for (Unit unit : units) {
int flowBeforeSize = analysis.getFlowBefore(unit).size();
if (flowBeforeSize == 0) {
memUnits += countEmptyAs;
} else {
memUnits += flowBeforeSize;
}
int flowAfterSize = analysis.getFlowAfter(unit).size();
if (flowAfterSize == 0) {
memUnits += countEmptyAs;
} else {
memUnits += flowAfterSize;
}
}
return memUnits;
}
//#ifdef LAZY
//@ /**
//@ * Calculates the average sharing degree of lazy flow sets.
//@ * @param body
//@ * @param analysis
//@ * @return
//@ */
//@ public static double averageSharingDegree(Body body, ForwardFlowAnalysis<Unit, MapLiftedFlowSet> analysis) {
//@ ConfigTag tag = (ConfigTag) body.getTag(ConfigTag.CONFIG_TAG_NAME);
//@ ILazyConfigRep lazyConfig = (ILazyConfigRep) tag.getConfigReps().iterator().next();
//@
//@ double noOfConfigs = lazyConfig.size();
//@
//@ List<Double> sharingDegrees = new ArrayList<Double>();
//@ PatchingChain<Unit> units = body.getUnits();
//@ for (Unit unit : units) {
//@ MapLiftedFlowSet flowBefore = analysis.getFlowBefore(unit);
//@ MapLiftedFlowSet flowAfter = analysis.getFlowAfter(unit);
//@
//@ sharingDegrees.add(noOfConfigs / flowBefore.size());
//@ sharingDegrees.add(noOfConfigs / flowAfter.size());
//@ }
//@
//@ double accumulator = 0.0;
//@ for (Double degree : sharingDegrees) {
//@ accumulator += degree;
//@ }
//@
//@ return accumulator / sharingDegrees.size();
//@ }
//@
//@ /**
//@ * Creates a PBM pixel matrix of an lazy analysis.
//@ *
//@ * @param body
//@ * @param analysis
//@ * @param fileName
//@ * @return
//@ */
//@ public static File pbm(Body body, ForwardFlowAnalysis<Unit, MapLiftedFlowSet> analysis, String fileName) {
//@ ConfigTag tag = (ConfigTag) body.getTag(ConfigTag.CONFIG_TAG_NAME);
//@ final int MAX_WIDTH = tag.getConfigReps().iterator().next().size();
//@ List<LinkedList<Integer>> matrix = createPixMatrix(body, analysis, MAX_WIDTH);
//@
//@ createPixMatrix(body, analysis, MAX_WIDTH);
//@
//@ OutputStream streamOut;
//@ try {
//@ streamOut = new FileOutputStream(fileName);
//@ } catch (FileNotFoundException e) {
//@ e.printStackTrace();
//@ return null;
//@ }
//@ PrintWriter writerOut = new PrintWriter(new OutputStreamWriter(streamOut));
//@ writerOut.println("P2");
//@ writerOut.println(matrix.get(0).size() + " " + matrix.size());
//@ writerOut.println("10");
//@ for (LinkedList<Integer> row : matrix) {
//@ for (Integer pix : row) {
//@ writerOut.print(pix);
//@ writerOut.print(' ');
//@ }
//@ writerOut.println("");
//@ }
//@ writerOut.flush();
//@ try {
//@ streamOut.close();
//@ } catch (IOException e) {
//@ // TODO Auto-generated catch block
//@ e.printStackTrace();
//@ return null;
//@ }
//@ return new File(fileName);
//@ }
//@
//@ private static List<LinkedList<Integer>> createPixMatrix(Body body, ForwardFlowAnalysis<Unit, MapLiftedFlowSet> analysis, final int MAX_WIDTH) {
//@ List<LinkedList<Integer>> matrix = new ArrayList<LinkedList<Integer>>();
//@ int index = 0, size = 0;
//@ PatchingChain<Unit> units = body.getUnits();
//@ for (Unit unit : units) {
//@ size = analysis.getFlowAfter(unit).size();
//@
//@ LinkedList<Integer> row = new LinkedList<Integer>();
//@ for (index = 0; index < size; index++) {
//@ row.add(0);
//@ }
//@ boolean headTailFlip = true;
//@ while (row.size() != MAX_WIDTH) {
//@ if (headTailFlip)
//@ row.addFirst(9);
//@ else
//@ row.addLast(9);
//@
//@ headTailFlip = !headTailFlip;
//@ }
//@ matrix.add(row);
//@ }
//@ return matrix;
//@ }
//@
//#endif
}