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) 1997 - 2018 Raja Vallée-Rai and others
* %%
* 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 static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import soot.IdentityUnit;
import soot.Local;
import soot.Timers;
import soot.Trap;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.options.Options;
import soot.toolkits.graph.DirectedGraph;
import soot.toolkits.graph.ExceptionalGraph;
import soot.toolkits.graph.ExceptionalGraph.ExceptionDest;
import soot.toolkits.graph.UnitGraph;
/**
* Analysis that provides an implementation of the LocalDefs interface.
*/
public class SimpleLocalDefs implements LocalDefs {
static private class StaticSingleAssignment implements LocalDefs {
final Map> result;
StaticSingleAssignment(Local[] locals, List[] unitList) {
assert locals.length == unitList.length;
final int N = locals.length;
result = new HashMap>((N * 3) / 2 + 7);
for (int i = 0; i < N; i++) {
if (unitList[i].isEmpty()) {
continue;
}
assert unitList[i].size() == 1;
result.put(locals[i], unitList[i]);
}
}
@Override
public List getDefsOfAt(Local l, Unit s) {
List lst = result.get(l);
if (lst == null) {
return emptyList();
}
// singleton-lists are immutable
return lst;
}
@Override
public List getDefsOf(Local l) {
return getDefsOfAt(l, null);
}
}
static private class FlowAssignment extends ForwardFlowAnalysis implements LocalDefs {
class FlowBitSet extends BitSet {
private static final long serialVersionUID = -8348696077189400377L;
FlowBitSet() {
super(universe.length);
}
List asList(int fromIndex, int toIndex) {
BitSet bits = this;
if (universe.length < toIndex || toIndex < fromIndex || fromIndex < 0) {
throw new IndexOutOfBoundsException();
}
if (fromIndex == toIndex) {
return emptyList();
}
if (fromIndex == toIndex - 1) {
if (bits.get(fromIndex)) {
return singletonList(universe[fromIndex]);
}
return emptyList();
}
int i = bits.nextSetBit(fromIndex);
if (i < 0 || i >= toIndex) {
return emptyList();
}
if (i == toIndex - 1) {
return singletonList(universe[i]);
}
List elements = new ArrayList(toIndex - i);
for (;;) {
int endOfRun = Math.min(toIndex, bits.nextClearBit(i + 1));
do {
elements.add(universe[i++]);
} while (i < endOfRun);
if (i >= toIndex) {
break;
}
i = bits.nextSetBit(i + 1);
if (i < 0 || i >= toIndex) {
break;
}
}
return elements;
}
}
final Map locals;
final List[] unitList;
final int[] localRange;
final Unit[] universe;
private Map indexOfUnit;
FlowAssignment(DirectedGraph graph, Local[] locals, List[] unitList, int units, boolean omitSSA) {
super(graph);
final int N = locals.length;
this.locals = new HashMap((N * 3) / 2 + 7);
this.unitList = unitList;
universe = new Unit[units];
indexOfUnit = new HashMap(units);
localRange = new int[N + 1];
for (int j = 0, i = 0; i < N; localRange[++i] = j) {
if (unitList[i].isEmpty()) {
continue;
}
this.locals.put(locals[i], i);
if (unitList[i].size() >= 2) {
for (Unit u : unitList[i]) {
indexOfUnit.put(u, j);
universe[j++] = u;
}
} else if (omitSSA) {
universe[j++] = unitList[i].get(0);
}
}
assert localRange[N] == units;
doAnalysis();
indexOfUnit.clear();
indexOfUnit = null;
}
@Override
public List getDefsOfAt(Local l, Unit s) {
Integer lno = locals.get(l);
if (lno == null) {
return emptyList();
}
int from = localRange[lno];
int to = localRange[lno + 1];
assert from <= to;
if (from == to) {
assert unitList[lno].size() == 1;
// both singletonList is immutable
return unitList[lno];
}
return getFlowBefore(s).asList(from, to);
}
@Override
protected boolean omissible(Unit u) {
// avoids temporary creation of iterators (more like micro-tuning)
if (u.getDefBoxes().isEmpty()) {
return true;
}
for (ValueBox vb : u.getDefBoxes()) {
Value v = vb.getValue();
if (v instanceof Local) {
Local l = (Local) v;
int lno = l.getNumber();
return (localRange[lno] == localRange[lno + 1]);
}
}
return true;
}
@Override
protected Flow getFlow(Unit from, Unit to) {
// QND
if (to instanceof IdentityUnit) {
if (graph instanceof ExceptionalGraph) {
ExceptionalGraph g = (ExceptionalGraph) graph;
if (!g.getExceptionalPredsOf(to).isEmpty()) {
// look if there is a real exception edge
for (ExceptionDest exd : g.getExceptionDests(from)) {
Trap trap = exd.getTrap();
if (null == trap) {
continue;
}
if (trap.getHandlerUnit() == to) {
return Flow.IN;
}
}
}
}
}
return Flow.OUT;
}
@Override
protected void flowThrough(FlowBitSet in, Unit unit, FlowBitSet out) {
copy(in, out);
// reassign all definitions
for (ValueBox vb : unit.getDefBoxes()) {
Value v = vb.getValue();
if (v instanceof Local) {
Local l = (Local) v;
int lno = l.getNumber();
int from = localRange[lno];
int to = localRange[1 + lno];
if (from == to) {
continue;
}
assert from <= to;
if (to - from == 1) {
// special case: this local has only one def point
out.set(from);
} else {
out.clear(from, to);
out.set(indexOfUnit.get(unit));
}
}
}
}
@Override
protected void copy(FlowBitSet source, FlowBitSet dest) {
if (dest == source) {
return;
}
dest.clear();
dest.or(source);
}
@Override
protected FlowBitSet newInitialFlow() {
return new FlowBitSet();
}
@Override
protected void mergeInto(Unit succNode, FlowBitSet inout, FlowBitSet in) {
inout.or(in);
}
@Override
protected void merge(FlowBitSet in1, FlowBitSet in2, FlowBitSet out) {
throw new UnsupportedOperationException("should never be called");
}
@Override
public List getDefsOf(Local l) {
List defs = new ArrayList();
for (Unit u : graph) {
List defsOf = getDefsOfAt(l, u);
if (defsOf != null) {
defs.addAll(defsOf);
}
}
return defs;
}
}
private LocalDefs def;
/**
*
* @param graph
*/
public SimpleLocalDefs(UnitGraph graph) {
this(graph, FlowAnalysisMode.Automatic);
}
public SimpleLocalDefs(UnitGraph graph, FlowAnalysisMode mode) {
this(graph, graph.getBody().getLocals(), mode);
}
SimpleLocalDefs(DirectedGraph graph, Collection locals, FlowAnalysisMode mode) {
this(graph, locals.toArray(new Local[locals.size()]), mode);
}
SimpleLocalDefs(DirectedGraph graph, Local[] locals, boolean omitSSA) {
this(graph, locals, omitSSA ? FlowAnalysisMode.OmitSSA : FlowAnalysisMode.Automatic);
}
/**
* The different modes in which the flow analysis can run
*/
enum FlowAnalysisMode {
/**
* Automatically detect the mode to use
*/
Automatic,
/**
* Never use the SSA form, even if the unit graph would allow for a flow-insensitive analysis without losing precision
*/
OmitSSA,
/**
* Always conduct a flow-insensitive analysis
*/
FlowInsensitive
}
SimpleLocalDefs(DirectedGraph graph, Local[] locals, FlowAnalysisMode mode) {
final Options options = Options.v();
if (options.time()) {
Timers.v().defsTimer.start();
}
final int N = locals.length;
// reassign local numbers
int[] oldNumbers = new int[N];
for (int i = 0; i < N; i++) {
oldNumbers[i] = locals[i].getNumber();
locals[i].setNumber(i);
}
init(graph, locals, mode);
// restore local numbering
for (int i = 0; i < N; i++) {
locals[i].setNumber(oldNumbers[i]);
}
if (options.time()) {
Timers.v().defsTimer.end();
}
}
private void init(DirectedGraph graph, Local[] locals, FlowAnalysisMode mode) {
@SuppressWarnings("unchecked")
List[] unitList = new List[locals.length];
Arrays.fill(unitList, emptyList());
boolean omitSSA = mode == FlowAnalysisMode.OmitSSA;
boolean doFlowAnalsis = omitSSA;
int units = 0;
// collect all def points
for (Unit unit : graph) {
for (ValueBox box : unit.getDefBoxes()) {
Value v = box.getValue();
if (v instanceof Local) {
Local l = (Local) v;
int lno = l.getNumber();
switch (unitList[lno].size()) {
case 0:
unitList[lno] = singletonList(unit);
if (omitSSA) {
units++;
}
break;
case 1:
if (!omitSSA) {
units++;
}
unitList[lno] = new ArrayList(unitList[lno]);
doFlowAnalsis = true;
// fallthrough
default:
unitList[lno].add(unit);
units++;
break;
}
}
}
}
if (doFlowAnalsis && mode != FlowAnalysisMode.FlowInsensitive) {
def = new FlowAssignment(graph, locals, unitList, units, omitSSA);
} else {
def = new StaticSingleAssignment(locals, unitList);
}
}
@Override
public List getDefsOfAt(Local l, Unit s) {
return def.getDefsOfAt(l, s);
}
@Override
public List getDefsOf(Local l) {
return def.getDefsOf(l);
}
}