soot.toolkits.scalar.SimpleLocalUses Maven / Gradle / Ivy
Show all versions of soot Show documentation
package soot.toolkits.scalar;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 1999 Raja Vallee-Rai
* %%
* 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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Body;
import soot.Local;
import soot.Timers;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.options.Options;
import soot.toolkits.graph.UnitGraph;
/**
* Analysis that implements the LocalUses interface. Uses for a Local defined at a given Unit are returned as a list of
* UnitValueBoxPairs each containing a Unit that use the local and the Local itself wrapped in a ValueBox.
*/
public class SimpleLocalUses implements LocalUses {
private static final Logger logger = LoggerFactory.getLogger(SimpleLocalUses.class);
final Body body;
private final Map> unitToUses;
/**
* Construct the analysis from a UnitGraph representation of a method body and a LocalDefs interface. This supposes that a
* LocalDefs analysis must have been computed prior.
*
*
* Note: If you do not already have a UnitGraph, it may be cheaper to use the constructor which only requires a Body.
*/
public SimpleLocalUses(UnitGraph graph, LocalDefs localDefs) {
this(graph.getBody(), localDefs);
}
/**
* Construct the analysis from a method body and a LocalDefs interface. This supposes that a LocalDefs analysis must have
* been computed prior.
*/
public SimpleLocalUses(Body body, LocalDefs localDefs) {
this.body = body;
this.unitToUses = new HashMap>(body.getUnits().size() * 2 + 1, 0.7f);
final Options options = Options.v();
if (options.verbose()) {
logger.debug("[" + body.getMethod().getName() + "] Constructing SimpleLocalUses...");
}
if (options.time()) {
Timers.v().usesTimer.start();
}
// Traverse units and associate uses with definitions
for (Unit unit : body.getUnits()) {
for (ValueBox useBox : unit.getUseBoxes()) {
Value v = useBox.getValue();
if (v instanceof Local) {
// Add this statement to the uses of the definition of the local
Local l = (Local) v;
List defs = localDefs.getDefsOfAt(l, unit);
if (defs != null) {
UnitValueBoxPair newPair = new UnitValueBoxPair(unit, useBox);
for (Unit def : defs) {
List lst = unitToUses.get(def);
if (lst == null) {
unitToUses.put(def, lst = new ArrayList());
}
lst.add(newPair);
}
}
}
}
}
if (options.time()) {
Timers.v().usesTimer.end();
}
if (options.verbose()) {
logger.debug("[" + body.getMethod().getName() + "] finished SimpleLocalUses...");
}
}
/**
* Uses for a Local defined at a given Unit are returned as a list of UnitValueBoxPairs each containing a Unit that use the
* local and the Local itself wrapped in a ValueBox.
*
* @param s
* a unit that we want to query for the uses of the Local it (may) define.
* @return a UnitValueBoxPair of the Units that use the Local.
*/
@Override
public List getUsesOf(Unit s) {
List l = unitToUses.get(s);
return (l == null) ? Collections.emptyList() : Collections.unmodifiableList(l);
}
/**
* Gets all variables that are used in this body
*
* @return The list of variables used in this body
*/
public Set getUsedVariables() {
Set res = new HashSet();
for (List vals : unitToUses.values()) {
for (UnitValueBoxPair val : vals) {
res.add((Local) val.valueBox.getValue());
}
}
return res;
}
/**
* Gets all variables that are not used in this body
*
* @return The list of variables declared, but not used in this body
*/
public Set getUnusedVariables() {
Set res = new HashSet(body.getLocals());
res.retainAll(getUsedVariables());
return res;
}
}