use of soot.jimple.InstanceFieldRef in project soot by Sable.
the class LockAllocationBodyTransformer method getLockFor.
public static Value getLockFor(EquivalentValue lockEqVal) {
Value lock = lockEqVal.getValue();
if (lock instanceof InstanceFieldRef)
return lock;
if (// it would be better to lock the array
lock instanceof ArrayRef)
// ref for each value of the index!
return ((ArrayRef) lock).getBase();
if (lock instanceof Local)
return lock;
if (lock instanceof StaticFieldRef || lock instanceof NewStaticLock) {
if (lockEqValToLock.containsKey(lockEqVal))
return lockEqValToLock.get(lockEqVal);
SootClass lockClass = null;
if (lock instanceof StaticFieldRef) {
StaticFieldRef sfrLock = (StaticFieldRef) lock;
lockClass = sfrLock.getField().getDeclaringClass();
} else if (lock instanceof NewStaticLock) {
DeadlockAvoidanceEdge dae = (DeadlockAvoidanceEdge) lock;
lockClass = dae.getLockClass();
}
SootMethod clinitMethod = null;
JimpleBody clinitBody = null;
Stmt firstStmt = null;
boolean addingNewClinit = !lockClass.declaresMethod("void <clinit>()");
if (addingNewClinit) {
clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
clinitBody = Jimple.v().newBody(clinitMethod);
clinitMethod.setActiveBody(clinitBody);
lockClass.addMethod(clinitMethod);
} else {
clinitMethod = lockClass.getMethod("void <clinit>()");
clinitBody = (JimpleBody) clinitMethod.getActiveBody();
firstStmt = clinitBody.getFirstNonIdentityStmt();
}
PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
Local lockLocal = Jimple.v().newLocal("objectLockLocal" + lockNumber, RefType.v("java.lang.Object"));
// lockNumber is increased below
// TODO: add name conflict
clinitBody.getLocals().add(lockLocal);
// avoidance code
// assign new object to lock obj
Stmt newStmt = Jimple.v().newAssignStmt(lockLocal, Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
if (addingNewClinit)
clinitUnits.add(newStmt);
else
clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
// initialize new object
SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
RefType type = RefType.v(objectClass);
SootMethod initMethod = objectClass.getMethod("void <init>()");
Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockLocal, initMethod.makeRef(), Collections.EMPTY_LIST));
if (addingNewClinit)
clinitUnits.add(initStmt);
else
clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
// copy new object to global static lock object (for use by other
// fns)
SootField actualLockObject = Scene.v().makeSootField("objectLockGlobal" + lockNumber, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
lockNumber++;
lockClass.addField(actualLockObject);
StaticFieldRef actualLockSfr = Jimple.v().newStaticFieldRef(actualLockObject.makeRef());
Stmt assignStmt = Jimple.v().newAssignStmt(actualLockSfr, lockLocal);
if (addingNewClinit)
clinitUnits.add(assignStmt);
else
clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
if (addingNewClinit)
clinitUnits.add(Jimple.v().newReturnVoidStmt());
lockEqValToLock.put(lockEqVal, actualLockSfr);
return actualLockSfr;
}
throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef, ArrayRef, or Local");
}
use of soot.jimple.InstanceFieldRef in project soot by Sable.
the class ConstraintCollector method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
TypeVariable left = null;
TypeVariable right = null;
if (l instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) l;
Type baset = ((Local) ref.getBase()).getType();
if (baset instanceof ArrayType) {
ArrayType base = (ArrayType) baset;
Value index = ref.getIndex();
if (uses) {
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
left = resolver.typeVariable(base.baseType);
}
if (index instanceof Local) {
resolver.typeVariable((Local) index).addParent(resolver.INT);
}
}
}
} else if (l instanceof Local) {
if (((Local) l).getType() instanceof IntegerType) {
left = resolver.typeVariable((Local) l);
}
} else if (l instanceof InstanceFieldRef) {
if (uses) {
InstanceFieldRef ref = (InstanceFieldRef) l;
Type fieldType = ref.getFieldRef().type();
if (fieldType instanceof IntegerType) {
left = resolver.typeVariable(ref.getFieldRef().type());
}
}
} else if (l instanceof StaticFieldRef) {
if (uses) {
StaticFieldRef ref = (StaticFieldRef) l;
Type fieldType = ref.getFieldRef().type();
if (fieldType instanceof IntegerType) {
left = resolver.typeVariable(ref.getFieldRef().type());
}
}
} else {
throw new RuntimeException("Unhandled assignment left hand side type: " + l.getClass());
}
if (r instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) r;
Type baset = ((Local) ref.getBase()).getType();
if (!(baset instanceof NullType)) {
Value index = ref.getIndex();
// Be careful, dex can do some weird object/array casting
if (baset instanceof ArrayType) {
ArrayType base = (ArrayType) baset;
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
right = resolver.typeVariable(base.baseType);
}
} else if (baset instanceof IntegerType)
right = resolver.typeVariable(baset);
if (uses)
if (index instanceof Local)
resolver.typeVariable((Local) index).addParent(resolver.INT);
}
} else if (r instanceof DoubleConstant) {
} else if (r instanceof FloatConstant) {
} else if (r instanceof IntConstant) {
int value = ((IntConstant) r).value;
if (value < -32768) {
right = resolver.INT;
} else if (value < -128) {
right = resolver.SHORT;
} else if (value < 0) {
right = resolver.BYTE;
} else if (value < 2) {
right = resolver.R0_1;
} else if (value < 128) {
right = resolver.R0_127;
} else if (value < 32768) {
right = resolver.R0_32767;
} else if (value < 65536) {
right = resolver.CHAR;
} else {
right = resolver.INT;
}
} else if (r instanceof LongConstant) {
} else if (r instanceof NullConstant) {
} else if (r instanceof StringConstant) {
} else if (r instanceof ClassConstant) {
} else if (r instanceof BinopExpr) {
// ******** BINOP EXPR ********
BinopExpr be = (BinopExpr) r;
Value lv = be.getOp1();
Value rv = be.getOp2();
TypeVariable lop = null;
TypeVariable rop = null;
// ******** LEFT ********
if (lv instanceof Local) {
if (((Local) lv).getType() instanceof IntegerType) {
lop = resolver.typeVariable((Local) lv);
}
} else if (lv instanceof DoubleConstant) {
} else if (lv instanceof FloatConstant) {
} else if (lv instanceof IntConstant) {
int value = ((IntConstant) lv).value;
if (value < -32768) {
lop = resolver.INT;
} else if (value < -128) {
lop = resolver.SHORT;
} else if (value < 0) {
lop = resolver.BYTE;
} else if (value < 2) {
lop = resolver.R0_1;
} else if (value < 128) {
lop = resolver.R0_127;
} else if (value < 32768) {
lop = resolver.R0_32767;
} else if (value < 65536) {
lop = resolver.CHAR;
} else {
lop = resolver.INT;
}
} else if (lv instanceof LongConstant) {
} else if (lv instanceof NullConstant) {
} else if (lv instanceof StringConstant) {
} else if (lv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
// ******** RIGHT ********
if (rv instanceof Local) {
if (((Local) rv).getType() instanceof IntegerType) {
rop = resolver.typeVariable((Local) rv);
}
} else if (rv instanceof DoubleConstant) {
} else if (rv instanceof FloatConstant) {
} else if (rv instanceof IntConstant) {
int value = ((IntConstant) rv).value;
if (value < -32768) {
rop = resolver.INT;
} else if (value < -128) {
rop = resolver.SHORT;
} else if (value < 0) {
rop = resolver.BYTE;
} else if (value < 2) {
rop = resolver.R0_1;
} else if (value < 128) {
rop = resolver.R0_127;
} else if (value < 32768) {
rop = resolver.R0_32767;
} else if (value < 65536) {
rop = resolver.CHAR;
} else {
rop = resolver.INT;
}
} else if (rv instanceof LongConstant) {
} else if (rv instanceof NullConstant) {
} else if (rv instanceof StringConstant) {
} else if (rv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
if ((be instanceof AddExpr) || (be instanceof SubExpr) || (be instanceof DivExpr) || (be instanceof RemExpr) || (be instanceof MulExpr)) {
if (lop != null && rop != null) {
if (uses) {
if (lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = resolver.INT;
}
} else if ((be instanceof AndExpr) || (be instanceof OrExpr) || (be instanceof XorExpr)) {
if (lop != null && rop != null) {
TypeVariable common = resolver.typeVariable();
if (rop != null)
rop.addParent(common);
if (lop != null)
lop.addParent(common);
right = common;
}
} else if (be instanceof ShlExpr) {
if (uses) {
if (lop != null && lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = (lop == null) ? null : resolver.INT;
} else if ((be instanceof ShrExpr) || (be instanceof UshrExpr)) {
if (uses) {
if (lop != null && lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = lop;
} else if ((be instanceof CmpExpr) || (be instanceof CmpgExpr) || (be instanceof CmplExpr)) {
right = resolver.BYTE;
} else if ((be instanceof EqExpr) || (be instanceof GeExpr) || (be instanceof GtExpr) || (be instanceof LeExpr) || (be instanceof LtExpr) || (be instanceof NeExpr)) {
if (uses) {
TypeVariable common = resolver.typeVariable();
if (rop != null)
rop.addParent(common);
if (lop != null)
lop.addParent(common);
}
right = resolver.BOOLEAN;
} else {
throw new RuntimeException("Unhandled binary expression type: " + be.getClass());
}
} else if (r instanceof CastExpr) {
CastExpr ce = (CastExpr) r;
if (ce.getCastType() instanceof IntegerType) {
right = resolver.typeVariable(ce.getCastType());
}
} else if (r instanceof InstanceOfExpr) {
right = resolver.BOOLEAN;
} else if (r instanceof InvokeExpr) {
InvokeExpr ie = (InvokeExpr) r;
handleInvokeExpr(ie);
if (ie.getMethodRef().returnType() instanceof IntegerType) {
right = resolver.typeVariable(ie.getMethodRef().returnType());
}
} else if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
if (uses) {
Value size = nae.getSize();
if (size instanceof Local) {
TypeVariable var = resolver.typeVariable((Local) size);
var.addParent(resolver.INT);
}
}
} else if (r instanceof NewExpr) {
} else if (r instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;
if (uses) {
for (int i = 0; i < nmae.getSizeCount(); i++) {
Value size = nmae.getSize(i);
if (size instanceof Local) {
TypeVariable var = resolver.typeVariable((Local) size);
var.addParent(resolver.INT);
}
}
}
} else if (r instanceof LengthExpr) {
right = resolver.INT;
} else if (r instanceof NegExpr) {
NegExpr ne = (NegExpr) r;
if (ne.getOp() instanceof Local) {
Local local = (Local) ne.getOp();
if (local.getType() instanceof IntegerType) {
if (uses) {
resolver.typeVariable(local).addParent(resolver.INT);
}
TypeVariable v = resolver.typeVariable();
v.addChild(resolver.BYTE);
v.addChild(resolver.typeVariable(local));
right = v;
}
} else if (ne.getOp() instanceof DoubleConstant) {
} else if (ne.getOp() instanceof FloatConstant) {
} else if (ne.getOp() instanceof IntConstant) {
int value = ((IntConstant) ne.getOp()).value;
if (value < -32768) {
right = resolver.INT;
} else if (value < -128) {
right = resolver.SHORT;
} else if (value < 0) {
right = resolver.BYTE;
} else if (value < 2) {
right = resolver.BYTE;
} else if (value < 128) {
right = resolver.BYTE;
} else if (value < 32768) {
right = resolver.SHORT;
} else if (value < 65536) {
right = resolver.INT;
} else {
right = resolver.INT;
}
} else if (ne.getOp() instanceof LongConstant) {
} else {
throw new RuntimeException("Unhandled neg expression operand type: " + ne.getOp().getClass());
}
} else if (r instanceof Local) {
Local local = (Local) r;
if (local.getType() instanceof IntegerType) {
right = resolver.typeVariable(local);
}
} else if (r instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = resolver.typeVariable(ref.getFieldRef().type());
}
} else if (r instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = resolver.typeVariable(ref.getFieldRef().type());
}
} else {
throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
}
if (left != null && right != null && (left.type() == null || right.type() == null)) {
right.addParent(left);
}
}
use of soot.jimple.InstanceFieldRef in project soot by Sable.
the class ArrayIndexLivenessAnalysis method getGenAndKillSetForDefnStmt.
private void getGenAndKillSetForDefnStmt(DefinitionStmt asstmt, HashMap<Stmt, HashSet<Value>> absgen, HashSet<Object> genset, HashSet<Value> absgenset, HashSet<Value> killset, HashSet<Value> condset) {
/* kill left hand side */
Value lhs = asstmt.getLeftOp();
Value rhs = asstmt.getRightOp();
boolean killarrayrelated = false;
boolean killallarrayref = false;
if (fieldin) {
if (lhs instanceof Local) {
HashSet<Value> related = localToFieldRef.get(lhs);
if (related != null)
killset.addAll(related);
} else if (lhs instanceof StaticFieldRef) {
killset.add(lhs);
condset.add(lhs);
} else if (lhs instanceof InstanceFieldRef) {
SootField field = ((InstanceFieldRef) lhs).getField();
HashSet<Value> related = fieldToFieldRef.get(field);
if (related != null)
killset.addAll(related);
condset.add(lhs);
}
if (asstmt.containsInvokeExpr()) {
/*
Value expr = asstmt.getInvokeExpr();
List parameters = ((InvokeExpr)expr).getArgs();
// add the method invocation
boolean killall = false;
if (expr instanceof InstanceInvokeExpr)
killall = true;
else
{
for (int i=0; i<parameters.size(); i++)
{
Value para = (Value)parameters.get(i);
if (para.getType() instanceof RefType)
{
killall = true;
break;
}
}
}
if (killall)
{
killset.addAll(allInstFieldRefs);
}
*/
killset.addAll(allFieldRefs);
}
}
if (arrayin) {
// a = ... or i = ...
if (lhs instanceof Local) {
killarrayrelated = true;
} else // a[i] = ...
if (lhs instanceof ArrayRef) {
killallarrayref = true;
condset.add(lhs);
}
// invokeexpr kills all array references.
if (asstmt.containsInvokeExpr()) {
killallarrayref = true;
}
}
if (csin) {
HashSet<Value> exprs = localToExpr.get(lhs);
if (exprs != null)
killset.addAll(exprs);
if (rhs instanceof BinopExpr) {
Value op1 = ((BinopExpr) rhs).getOp1();
Value op2 = ((BinopExpr) rhs).getOp2();
if (rhs instanceof AddExpr) {
if ((op1 instanceof Local) && (op2 instanceof Local))
genset.add(rhs);
} else if (rhs instanceof MulExpr) {
if ((op1 instanceof Local) || (op2 instanceof Local))
genset.add(rhs);
} else if (rhs instanceof SubExpr) {
if (op2 instanceof Local)
genset.add(rhs);
}
}
}
if ((lhs instanceof Local) && (fullSet.contains(lhs))) {
killset.add(lhs);
/* speculatively add lhs as live condition. */
condset.add(lhs);
} else if (lhs instanceof ArrayRef) {
/* a[i] generate a and i. */
Value base = ((ArrayRef) lhs).getBase();
Value index = ((ArrayRef) lhs).getIndex();
absgenset.add(base);
if (index instanceof Local) {
absgenset.add(index);
}
}
if (rhs instanceof Local) {
/*
if (lhs instanceof Local && fullSet.contains(rhs))
genset.add(rhs);
*/
if (fullSet.contains(rhs))
genset.add(rhs);
/*
if (fieldin && (lhs instanceof FieldRef))
genset.add(rhs);
*/
} else if (rhs instanceof FieldRef) {
if (fieldin)
genset.add(rhs);
} else if (rhs instanceof ArrayRef) {
/* lhs=a[i]. */
Value base = ((ArrayRef) rhs).getBase();
Value index = ((ArrayRef) rhs).getIndex();
absgenset.add(base);
if (index instanceof Local) {
absgenset.add(index);
}
if (arrayin) {
genset.add(rhs);
if (rectarray)
genset.add(Array2ndDimensionSymbol.v(base));
}
} else if (rhs instanceof NewArrayExpr) {
/* a = new A[i]; */
Value size = ((NewArrayExpr) rhs).getSize();
if (size instanceof Local)
genset.add(size);
} else if (rhs instanceof NewMultiArrayExpr) {
/* a = new A[i][]...;*/
/* More precisely, we should track other dimensions. */
List sizes = ((NewMultiArrayExpr) rhs).getSizes();
Iterator sizeIt = sizes.iterator();
while (sizeIt.hasNext()) {
Value size = (Value) sizeIt.next();
if (size instanceof Local)
genset.add(size);
}
} else if (rhs instanceof LengthExpr) {
/* lhs = lengthof rhs */
Value op = ((LengthExpr) rhs).getOp();
genset.add(op);
} else if (rhs instanceof JAddExpr) {
/* lhs = rhs+c, lhs=c+rhs */
Value op1 = ((JAddExpr) rhs).getOp1();
Value op2 = ((JAddExpr) rhs).getOp2();
if ((op1 instanceof IntConstant) && (op2 instanceof Local)) {
genset.add(op2);
} else if ((op2 instanceof IntConstant) && (op1 instanceof Local)) {
genset.add(op1);
}
} else if (rhs instanceof JSubExpr) {
Value op1 = ((JSubExpr) rhs).getOp1();
Value op2 = ((JSubExpr) rhs).getOp2();
if ((op1 instanceof Local) && (op2 instanceof IntConstant)) {
genset.add(op1);
}
}
if (arrayin) {
if (killarrayrelated)
killArrayRelated.put(asstmt, lhs);
if (killallarrayref)
killAllArrayRef.put(asstmt, new Boolean(true));
}
}
use of soot.jimple.InstanceFieldRef in project soot by Sable.
the class ArrayIndexLivenessAnalysis method getAllRelatedMaps.
private void getAllRelatedMaps(Body body) {
Iterator unitIt = body.getUnits().iterator();
while (unitIt.hasNext()) {
Stmt stmt = (Stmt) unitIt.next();
if (csin) {
if (stmt instanceof DefinitionStmt) {
Value rhs = ((DefinitionStmt) stmt).getRightOp();
if (rhs instanceof BinopExpr) {
Value op1 = ((BinopExpr) rhs).getOp1();
Value op2 = ((BinopExpr) rhs).getOp2();
if (rhs instanceof AddExpr) {
// op1 + op2 --> a + b
if ((op1 instanceof Local) && (op2 instanceof Local)) {
HashSet<Value> refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
}
} else // a * b, a * c, c * a
if (rhs instanceof MulExpr) {
HashSet<Value> refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
} else if (rhs instanceof SubExpr) {
if (op2 instanceof Local) {
HashSet<Value> refs = localToExpr.get(op2);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op2, refs);
}
refs.add(rhs);
if (op1 instanceof Local) {
refs = localToExpr.get(op1);
if (refs == null) {
refs = new HashSet<Value>();
localToExpr.put(op1, refs);
}
refs.add(rhs);
}
}
}
}
}
}
for (ValueBox vbox : stmt.getUseAndDefBoxes()) {
Value v = vbox.getValue();
if (fieldin) {
if (v instanceof InstanceFieldRef) {
Value base = ((InstanceFieldRef) v).getBase();
SootField field = ((InstanceFieldRef) v).getField();
HashSet<Value> baseset = localToFieldRef.get(base);
if (baseset == null) {
baseset = new HashSet<Value>();
localToFieldRef.put(base, baseset);
}
baseset.add(v);
HashSet<Value> fieldset = fieldToFieldRef.get(field);
if (fieldset == null) {
fieldset = new HashSet<Value>();
fieldToFieldRef.put(field, fieldset);
}
fieldset.add(v);
}
if (v instanceof FieldRef)
allFieldRefs.add(v);
}
if (arrayin) {
// a = ... --> kill all a[x] nodes.
// a[i] = .. --> kill all array references.
// m(a) --> kill all array references
// i = ... --> kill all array reference with index as i
/*
if (v instanceof ArrayRef)
{
Value base = ((ArrayRef)v).getBase();
Value index = ((ArrayRef)v).getIndex();
HashSet refset = (HashSet)localToArrayRef.get(base);
if (refset == null)
{
refset = new HashSet();
localToArrayRef.put(base, refset);
}
refset.add(v);
if (index instanceof Local)
{
refset = (HashSet)localToArrayRef.get(index);
if (refset == null)
{
refset = new HashSet();
localToArrayRef.put(index, refset);
}
refset.add(v);
}
allArrayRefs.add(v);
}
*/
}
}
}
}
use of soot.jimple.InstanceFieldRef in project soot by Sable.
the class DeadAssignmentEliminator method internalTransform.
/**
* Eliminates dead code in a linear fashion. Complexity is linear
* with respect to the statements.
*
* Does not work on grimp code because of the check on the right hand
* side for side effects.
*/
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
boolean eliminateOnlyStackLocals = PhaseOptions.getBoolean(options, "only-stack-locals");
final Options soptions = Options.v();
if (soptions.verbose()) {
logger.debug("[" + b.getMethod().getName() + "] Eliminating dead code...");
}
if (soptions.time()) {
Timers.v().deadCodeTimer.start();
}
Chain<Unit> units = b.getUnits();
Deque<Unit> q = new ArrayDeque<Unit>(units.size());
// Make a first pass through the statements, noting
// the statements we must absolutely keep.
boolean isStatic = b.getMethod().isStatic();
boolean allEssential = true;
boolean checkInvoke = false;
Local thisLocal = null;
for (Iterator<Unit> it = units.iterator(); it.hasNext(); ) {
Unit s = it.next();
boolean isEssential = true;
if (s instanceof NopStmt) {
// Hack: do not remove nop if is is used for a Trap
// which is at the very end of the code.
boolean removeNop = it.hasNext();
if (!removeNop) {
removeNop = true;
for (Trap t : b.getTraps()) {
if (t.getEndUnit() == s) {
removeNop = false;
break;
}
}
}
if (removeNop) {
it.remove();
continue;
}
} else if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
Value lhs = as.getLeftOp();
Value rhs = as.getRightOp();
// Stmt is of the form a = a which is useless
if (lhs == rhs && lhs instanceof Local) {
it.remove();
continue;
}
if (lhs instanceof Local && (!eliminateOnlyStackLocals || ((Local) lhs).getName().startsWith("$") || lhs.getType() instanceof NullType)) {
isEssential = false;
if (!checkInvoke) {
checkInvoke = as.containsInvokeExpr();
}
if (rhs instanceof CastExpr) {
// CastExpr : can trigger ClassCastException, but null-casts never fail
CastExpr ce = (CastExpr) rhs;
Type t = ce.getCastType();
Value v = ce.getOp();
isEssential = !(v instanceof NullConstant && t instanceof RefType);
} else if (rhs instanceof InvokeExpr || rhs instanceof ArrayRef || rhs instanceof NewExpr || rhs instanceof NewArrayExpr || rhs instanceof NewMultiArrayExpr) {
// ArrayRef : can have side effects (like throwing a null pointer exception)
// InvokeExpr : can have side effects (like throwing a null pointer exception)
// NewArrayExpr : can throw exception
// NewMultiArrayExpr : can throw exception
// NewExpr : can trigger class initialization
isEssential = true;
} else if (rhs instanceof FieldRef) {
// Can trigger class initialization
isEssential = true;
if (rhs instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) rhs;
if (!isStatic && thisLocal == null) {
thisLocal = b.getThisLocal();
}
// Any InstanceFieldRef may have side effects,
// unless the base is reading from 'this'
// in a non-static method
isEssential = (isStatic || thisLocal != ifr.getBase());
}
} else if (rhs instanceof DivExpr || rhs instanceof RemExpr) {
BinopExpr expr = (BinopExpr) rhs;
Type t1 = expr.getOp1().getType();
Type t2 = expr.getOp2().getType();
// Can trigger a division by zero
boolean t2Int = t2 instanceof IntType;
isEssential = t2Int || t1 instanceof IntType || t1 instanceof LongType || t2 instanceof LongType || t1 instanceof UnknownType || t2 instanceof UnknownType;
if (isEssential && t2Int) {
Value v = expr.getOp2();
if (v instanceof IntConstant) {
IntConstant i = (IntConstant) v;
isEssential = (i.value == 0);
} else
// could be 0, we don't know
isEssential = true;
}
if (isEssential && t2 instanceof LongType) {
Value v = expr.getOp2();
if (v instanceof LongConstant) {
LongConstant l = (LongConstant) v;
isEssential = (l.value == 0);
} else
// could be 0, we don't know
isEssential = true;
}
}
}
}
if (isEssential) {
q.addFirst(s);
}
allEssential &= isEssential;
}
if (checkInvoke || !allEssential) {
// Add all the statements which are used to compute values
// for the essential statements, recursively
final LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(b);
if (!allEssential) {
Set<Unit> essential = new HashSet<Unit>(b.getUnits().size());
while (!q.isEmpty()) {
Unit s = q.removeFirst();
if (essential.add(s)) {
for (ValueBox box : s.getUseBoxes()) {
Value v = box.getValue();
if (v instanceof Local) {
Local l = (Local) v;
List<Unit> defs = localDefs.getDefsOfAt(l, s);
if (defs != null)
q.addAll(defs);
}
}
}
}
// Remove the dead statements
units.retainAll(essential);
}
if (checkInvoke) {
final LocalUses localUses = LocalUses.Factory.newLocalUses(b, localDefs);
// Eliminate dead assignments from invokes such as x = f(), where
// x is no longer used
List<AssignStmt> postProcess = new ArrayList<AssignStmt>();
for (Unit u : units) {
if (u instanceof AssignStmt) {
AssignStmt s = (AssignStmt) u;
if (s.containsInvokeExpr()) {
// Just find one use of l which is essential
boolean deadAssignment = true;
for (UnitValueBoxPair pair : localUses.getUsesOf(s)) {
if (units.contains(pair.unit)) {
deadAssignment = false;
break;
}
}
if (deadAssignment) {
postProcess.add(s);
}
}
}
}
final Jimple jimple = Jimple.v();
for (AssignStmt s : postProcess) {
// Transform it into a simple invoke.
Stmt newInvoke = jimple.newInvokeStmt(s.getInvokeExpr());
newInvoke.addAllTagsOf(s);
units.swapWith(s, newInvoke);
// If we have a callgraph, we need to fix it
if (Scene.v().hasCallGraph())
Scene.v().getCallGraph().swapEdgesOutOf(s, newInvoke);
}
}
}
if (soptions.time()) {
Timers.v().deadCodeTimer.end();
}
}
Aggregations