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.jimple.toolkits.pointer;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 - 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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import soot.Local;
import soot.RefType;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.ConditionExpr;
import soot.jimple.EqExpr;
import soot.jimple.IfStmt;
import soot.jimple.InstanceOfExpr;
import soot.jimple.IntConstant;
import soot.jimple.NeExpr;
import soot.jimple.NewExpr;
import soot.jimple.NullConstant;
import soot.jimple.Stmt;
import soot.toolkits.graph.BriefUnitGraph;
import soot.toolkits.graph.UnitGraph;
import soot.toolkits.scalar.ForwardBranchedFlowAnalysis;
/** A flow analysis that detects redundant cast checks. */
public class CastCheckEliminator extends ForwardBranchedFlowAnalysis {
Map unitToKill = new HashMap();
Map unitToGenFallThrough = new HashMap();
Map unitToGenBranch = new HashMap();
LocalTypeSet emptySet;
public CastCheckEliminator(BriefUnitGraph cfg) {
super(cfg);
makeInitialSet();
doAnalysis();
tagCasts();
}
/** Put the results of the analysis into tags in cast statements. */
protected void tagCasts() {
for (Iterator sIt = ((UnitGraph) graph).getBody().getUnits().iterator(); sIt.hasNext();) {
final Stmt s = (Stmt) sIt.next();
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Value rhs = as.getRightOp();
if (rhs instanceof CastExpr) {
CastExpr cast = (CastExpr) rhs;
Type t = cast.getCastType();
if (t instanceof RefType) {
if (cast.getOp() instanceof Local) {
Local l = (Local) cast.getOp();
LocalTypeSet set = (LocalTypeSet) getFlowBefore(s);
s.addTag(new CastCheckTag(set.get(set.indexOf(l, (RefType) t))));
} else {
NullConstant nc = (NullConstant) cast.getOp();
s.addTag(new CastCheckTag(true));
}
}
}
}
}
}
/**
* Find all the locals of reference type and all the types used in casts to initialize the mapping from locals and types to
* bits in the bit vector in LocalTypeSet.
*/
protected void makeInitialSet() {
// Find all locals of reference type
Collection locals = ((UnitGraph) graph).getBody().getLocals();
List refLocals = new ArrayList();
for (Iterator lIt = locals.iterator(); lIt.hasNext();) {
final Local l = (Local) lIt.next();
if (l.getType() instanceof RefType) {
refLocals.add(l);
}
}
// Find types of all casts
List types = new ArrayList();
for (Iterator sIt = ((UnitGraph) graph).getBody().getUnits().iterator(); sIt.hasNext();) {
final Stmt s = (Stmt) sIt.next();
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Value rhs = as.getRightOp();
if (rhs instanceof CastExpr) {
Type t = ((CastExpr) rhs).getCastType();
if (t instanceof RefType && !types.contains(t)) {
types.add(t);
}
}
}
}
emptySet = new LocalTypeSet(refLocals, types);
}
/** Returns a new, aggressive (local,type) set. */
@Override
protected LocalTypeSet newInitialFlow() {
LocalTypeSet ret = (LocalTypeSet) emptySet.clone();
ret.setAllBits();
return ret;
}
/** This is the flow function as described in the assignment write-up. */
@Override
protected void flowThrough(LocalTypeSet in, Unit unit, List outFallValues,
List outBranchValues) {
final LocalTypeSet out = (LocalTypeSet) in.clone();
LocalTypeSet outBranch = out; // aliased to out unless unit is IfStmt
final Stmt stmt = (Stmt) unit;
// First kill all locals defined in this statement
for (Iterator bIt = stmt.getDefBoxes().iterator(); bIt.hasNext();) {
final ValueBox b = (ValueBox) bIt.next();
Value v = b.getValue();
if (v instanceof Local && v.getType() instanceof RefType) {
out.killLocal((Local) v);
}
}
// An AssignStmt may be a new, a simple copy, or a cast
if (stmt instanceof AssignStmt) {
AssignStmt astmt = (AssignStmt) stmt;
Value rhs = astmt.getRightOp();
Value lhs = astmt.getLeftOp();
if (lhs instanceof Local && rhs.getType() instanceof RefType) {
Local l = (Local) lhs;
if (rhs instanceof NewExpr) {
out.localMustBeSubtypeOf(l, (RefType) rhs.getType());
} else if (rhs instanceof CastExpr) {
CastExpr cast = (CastExpr) rhs;
Type castType = cast.getCastType();
if (castType instanceof RefType && cast.getOp() instanceof Local) {
RefType refType = (RefType) castType;
Local opLocal = (Local) cast.getOp();
out.localCopy(l, opLocal);
out.localMustBeSubtypeOf(l, refType);
out.localMustBeSubtypeOf(opLocal, refType);
}
} else if (rhs instanceof Local) {
out.localCopy(l, (Local) rhs);
}
}
// Handle if statements
} else if (stmt instanceof IfStmt) {
IfStmt ifstmt = (IfStmt) stmt;
// This do ... while(false) is here so I can break out of it rather
// than having to have seven nested if statements. Silly people who
// took goto's out of the language...
do {
if (graph.getPredsOf(stmt).size() != 1) {
break;
}
Object predecessor = graph.getPredsOf(stmt).get(0);
if (!(predecessor instanceof AssignStmt)) {
break;
}
AssignStmt pred = (AssignStmt) predecessor;
if (!(pred.getRightOp() instanceof InstanceOfExpr)) {
break;
}
InstanceOfExpr iofexpr = (InstanceOfExpr) pred.getRightOp();
if (!(iofexpr.getCheckType() instanceof RefType)) {
break;
}
if (!(iofexpr.getOp() instanceof Local)) {
break;
}
ConditionExpr c = (ConditionExpr) ifstmt.getCondition();
if (!c.getOp1().equals(pred.getLeftOp())) {
break;
}
if (!(c.getOp2() instanceof IntConstant)) {
break;
}
if (((IntConstant) c.getOp2()).value != 0) {
break;
}
if (c instanceof NeExpr) {
// The IfStmt is like this:
// if x instanceof t goto somewhere_else
// So x is of type t on the taken branch
outBranch = (LocalTypeSet) out.clone();
outBranch.localMustBeSubtypeOf((Local) iofexpr.getOp(), (RefType) iofexpr.getCheckType());
} else if (c instanceof EqExpr) {
// The IfStmt is like this:
// if !(x instanceof t) goto somewhere_else
// So x is of type t on the fallthrough branch
outBranch = (LocalTypeSet) out.clone();
out.localMustBeSubtypeOf((Local) iofexpr.getOp(), (RefType) iofexpr.getCheckType());
}
} while (false);
}
// Now copy the computed (local,type) set to all successors
for (Iterator it = outFallValues.iterator(); it.hasNext();) {
copy(out, it.next());
}
for (Iterator it = outBranchValues.iterator(); it.hasNext();) {
copy(outBranch, it.next());
}
}
@Override
protected void copy(LocalTypeSet s, LocalTypeSet d) {
d.and(s);
d.or(s);
}
// The merge operator is set intersection.
@Override
protected void merge(LocalTypeSet in1, LocalTypeSet in2, LocalTypeSet o) {
o.setAllBits();
o.and(in1);
o.and(in2);
}
/** Returns a new, aggressive (local,type) set. */
@Override
protected LocalTypeSet entryInitialFlow() {
LocalTypeSet ret = (LocalTypeSet) emptySet.clone();
return ret;
}
}