Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package soot.toolkits.scalar;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2004 Ondrej Lhotak
* %%
* This program 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 program 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Local;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.options.Options;
import soot.toolkits.graph.UnitGraph;
import soot.util.Cons;
import soot.util.HashMultiMap;
import soot.util.MultiMap;
/**
* Analysis that computes live locals, local defs, and local uses all at once.
*
* SA, 09.09.2014: Inefficient as hell (memory). Use the distinct analyses or fix this class before using it.
*/
public class CombinedDUAnalysis extends BackwardFlowAnalysis>
implements CombinedAnalysis, LocalDefs, LocalUses, LiveLocals {
private static final Logger logger = LoggerFactory.getLogger(CombinedDUAnalysis.class);
// Implementations of our interfaces...
private final Map, List> defsOfAt = new HashMap, List>();
@Override
public List getDefsOfAt(Local l, Unit s) {
Cons cons = new Cons(l, s);
List ret = defsOfAt.get(cons);
if (ret == null) {
defsOfAt.put(cons, ret = new ArrayList());
}
return ret;
}
@Override
public List getDefsOf(Local l) {
throw new RuntimeException("Not implemented");
}
private final Map> usesOf = new HashMap>();
public List getUsesOf(Unit u) {
List ret = usesOf.get(u);
if (ret == null) {
Local def = localDefed(u);
if (def == null) {
usesOf.put(u, ret = Collections.emptyList());
} else {
usesOf.put(u, ret = new ArrayList());
for (ValueBox vb : getFlowAfter(u)) {
if (vb.getValue() != def) {
continue;
}
ret.add(new UnitValueBoxPair(useBoxToUnit.get(vb), vb));
}
}
}
return ret;
}
private final Map> liveLocalsBefore = new HashMap>();
public List getLiveLocalsBefore(Unit u) {
List ret = liveLocalsBefore.get(u);
if (ret == null) {
HashSet hs = new HashSet();
for (ValueBox vb : getFlowBefore(u)) {
hs.add((Local) vb.getValue());
}
liveLocalsBefore.put(u, ret = new ArrayList(hs));
}
return ret;
}
private final Map> liveLocalsAfter = new HashMap>();
public List getLiveLocalsAfter(Unit u) {
List ret = liveLocalsAfter.get(u);
if (ret == null) {
HashSet hs = new HashSet();
for (ValueBox vb : getFlowAfter(u)) {
hs.add((Local) vb.getValue());
}
liveLocalsAfter.put(u, ret = new ArrayList(hs));
}
return ret;
}
// The actual analysis is below.
private final Map useBoxToUnit = new HashMap();
private final Map unitToLocalDefed = new HashMap();
private Local localDefed(Unit u) {
return (Local) unitToLocalDefed.get(u);
}
private final Map> unitToLocalUseBoxes = new HashMap>();
private final MultiMap localToUseBoxes = new HashMultiMap();
public CombinedDUAnalysis(UnitGraph graph) {
super(graph);
if (Options.v().verbose()) {
logger.debug("[" + graph.getBody().getMethod().getName() + "] Constructing CombinedDUAnalysis...");
}
for (Unit u : graph) {
List defs = localsInBoxes(u.getDefBoxes());
if (defs.size() == 1) {
unitToLocalDefed.put(u, defs.get(0));
} else if (defs.size() != 0) {
throw new RuntimeException("Locals defed in " + u + ": " + defs.size());
}
ArraySparseSet localUseBoxes = new ArraySparseSet();
for (ValueBox vb : u.getUseBoxes()) {
Value v = vb.getValue();
if (!(v instanceof Local)) {
continue;
}
localUseBoxes.add(vb);
if (useBoxToUnit.containsKey(vb)) {
throw new RuntimeException("Aliased ValueBox " + vb + " in Unit " + u);
}
useBoxToUnit.put(vb, u);
localToUseBoxes.put(v, vb);
}
unitToLocalUseBoxes.put(u, localUseBoxes);
}
doAnalysis();
for (Unit defUnit : graph) {
Local localDefed = localDefed(defUnit);
if (localDefed == null) {
continue;
}
for (ValueBox vb : getFlowAfter(defUnit)) {
if (vb.getValue() != localDefed) {
continue;
}
Unit useUnit = useBoxToUnit.get(vb);
getDefsOfAt(localDefed, useUnit).add(defUnit);
}
}
if (Options.v().verbose()) {
logger.debug("[" + graph.getBody().getMethod().getName() + "] Finished CombinedDUAnalysis...");
}
}
private List localsInBoxes(List boxes) {
List ret = new ArrayList();
for (ValueBox vb : boxes) {
Value v = vb.getValue();
if (!(v instanceof Local)) {
continue;
}
ret.add(v);
}
return ret;
}
// STEP 1: What are we computing?
// SETS OF USE BOXES CONTAINING LOCALS => Use HashSet.
//
// STEP 2: Precisely define what we are computing.
// A use box B is live at program point P if there exists a path from P to the
// unit using B on which the local in B is not defined.
//
// STEP 3: Decide whether it is a backwards or forwards analysis.
// BACKWARDS
//
// STEP 4: Is the merge operator union or intersection?
// UNION
protected void merge(FlowSet inout, FlowSet in) {
inout.union(in);
}
protected void merge(FlowSet in1, FlowSet in2, FlowSet out) {
in1.union(in2, out);
}
// STEP 5: Define flow equations.
// in(s) = ( out(s) minus boxes(def(s)) ) union useboxes(s)
protected void flowThrough(FlowSet out, Unit u, FlowSet in) {
Local def = localDefed(u);
out.copy(in);
if (def != null) {
Collection boxesDefed = localToUseBoxes.get(def);
for (ValueBox vb : in) {
if (boxesDefed.contains(vb)) {
in.remove(vb);
}
}
}
in.union(unitToLocalUseBoxes.get(u));
}
// STEP 6: Determine value for start/end node, and
// initial approximation.
//
// end node: empty set
// initial approximation: empty set
protected FlowSet entryInitialFlow() {
return new ArraySparseSet();
}
protected FlowSet newInitialFlow() {
return new ArraySparseSet();
}
protected void copy(FlowSet source, FlowSet dest) {
source.copy(dest);
}
}