Skip to content

Commit

Permalink
Merge pull request #2138 from MarcMil/mdev
Browse files Browse the repository at this point in the history
Fix the ConstantValueToInitializerTransformer & Performance optimizations for type resolver
  • Loading branch information
StevenArzt authored Jan 15, 2025
2 parents 8bf0272 + abed019 commit 8d201bb
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 50 deletions.
56 changes: 49 additions & 7 deletions src/main/java/soot/jimple/toolkits/typing/fast/TypeResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import soot.ArrayType;
import soot.BooleanType;
Expand Down Expand Up @@ -69,6 +72,7 @@
import soot.jimple.SpecialInvokeExpr;
import soot.jimple.Stmt;
import soot.jimple.toolkits.typing.Util;
import soot.jimple.toolkits.typing.fast.UseChecker.UseCheckerCache;
import soot.toolkits.scalar.LocalDefs;

/**
Expand All @@ -83,17 +87,22 @@
* @author Ben Bellamy
*/
public class TypeResolver {
private static final int SINGLE_THREAD_LIMIT = 100000;
private static int NUM_CORES = Math.max(1, Runtime.getRuntime().availableProcessors() - 2);

protected final JimpleBody jb;

private List<DefinitionStmt> assignments;
private HashMap<Local, BitSet> depends;
private Set<Local> singleAssignments;
private BitSet simple;
private final LocalGenerator localGenerator;
private final UseCheckerCache useCheckerCache;

public TypeResolver(JimpleBody jb) {
this.jb = jb;
this.localGenerator = Scene.v().createLocalGenerator(jb);
this.useCheckerCache = new UseCheckerCache(jb);

}

Expand Down Expand Up @@ -402,7 +411,7 @@ private ITyping typePromotion(ITyping tg) {
}

protected UseChecker createUseChecker(JimpleBody jb) {
return new UseChecker(jb);
return new UseChecker(jb, useCheckerCache);
}

protected TypePromotionUseVisitor createTypePromotionUseVisitor(JimpleBody jb, ITyping tg) {
Expand Down Expand Up @@ -453,14 +462,47 @@ protected CastInsertionUseVisitor createCastInsertionUseVisitor(ITyping tg, IHie
private ITyping minCasts(Collection<ITyping> sigma, IHierarchy h, int[] count) {
count[0] = -1;
ITyping r = null;
for (ITyping tg : sigma) {
int n = this.insertCasts(tg, h, true);
if (count[0] == -1 || n < count[0]) {
count[0] = n;
r = tg;
if (sigma.size() <= SINGLE_THREAD_LIMIT) {
for (ITyping tg : sigma) {
int n = this.insertCasts(tg, h, true);
if (count[0] == -1 || n < count[0]) {
count[0] = n;
r = tg;
}
}
return r;
} else {
ExecutorService executionService = Executors.newFixedThreadPool(NUM_CORES);
ITyping[] minTyping = new ITyping[1];
try {
for (ITyping tg : sigma) {
executionService.submit(new Runnable() {

@Override
public void run() {
int n = insertCasts(tg, h, true);
if (count[0] == -1 || n < count[0]) {
synchronized (count) {
if (count[0] == -1 || n < count[0]) {
count[0] = n;
minTyping[0] = tg;
}
}
}
}

});
}
} finally {
executionService.shutdown();
try {
executionService.awaitTermination(100, TimeUnit.DAYS);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted during type resolving", e);
}
}
return minTyping[0];
}
return r;
}

static class WorklistElement {
Expand Down
97 changes: 70 additions & 27 deletions src/main/java/soot/jimple/toolkits/typing/fast/UseChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,53 @@ public class UseChecker extends AbstractStmtSwitch {
private ITyping tg;
private IUseVisitor uv;

private LocalDefs defs = null;
private LocalUses uses = null;

private static final Logger logger = LoggerFactory.getLogger(UseChecker.class);

public static class UseCheckerCache {
private LocalDefs defs = null;
private LocalUses uses = null;

private final Type objectType = Scene.v().getObjectType();
private final JimpleBody body;

public UseCheckerCache(JimpleBody body) {
this.body = body;
}

public Type getObjectType() {
return objectType;
}

public LocalDefs getDefs() {
LocalDefs d = defs;
if (d == null) {
d = G.v().soot_toolkits_scalar_LocalDefsFactory().newLocalDefs(body);
defs = d;
}
return d;
}

public LocalUses getUses() {
LocalUses u = uses;
if (u != null) {
return u;
}
u = LocalUses.Factory.newLocalUses(body, getDefs());
uses = u;
return u;
}
}

private UseCheckerCache cache;

public UseChecker(JimpleBody jb) {
this.jb = jb;
cache = new UseCheckerCache(jb);
}

public UseChecker(JimpleBody jb, UseCheckerCache cache) {
this.jb = jb;
this.cache = cache;
}

public void check(ITyping tg, IUseVisitor uv) {
Expand Down Expand Up @@ -203,6 +243,9 @@ public void caseAssignStmt(AssignStmt stmt) {
Value lhs = stmt.getLeftOp();
Value rhs = stmt.getRightOp();
Type tlhs = null;
LocalDefs defs = cache.defs;
LocalUses uses = cache.uses;
final IUseVisitor uv = this.uv;

if (lhs instanceof Local) {
tlhs = this.tg.get((Local) lhs);
Expand All @@ -221,10 +264,10 @@ public void caseAssignStmt(AssignStmt stmt) {
// is java.lang.Object
if (rhs instanceof Local) {
Type rhsType = this.tg.get((Local) rhs);
if ((tgType == Scene.v().getObjectType() && rhsType instanceof PrimType) || tgType instanceof WeakObjectType) {
if ((tgType == cache.getObjectType() && rhsType instanceof PrimType) || tgType instanceof WeakObjectType) {
if (defs == null) {
defs = G.v().soot_toolkits_scalar_LocalDefsFactory().newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
defs = cache.getDefs();
uses = cache.getUses();
}

// Check the original type of the array from the alloc site
Expand Down Expand Up @@ -254,9 +297,9 @@ public void caseAssignStmt(AssignStmt stmt) {

this.handleArrayRef(aref, stmt);

aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setLeftOp(this.uv.visit(lhs, tlhs, stmt));
aref.setBase((Local) uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
stmt.setLeftOp(uv.visit(lhs, tlhs, stmt));
} else if (lhs instanceof FieldRef) {
tlhs = ((FieldRef) lhs).getFieldRef().type();
if (lhs instanceof InstanceFieldRef) {
Expand All @@ -269,7 +312,7 @@ public void caseAssignStmt(AssignStmt stmt) {
rhs = stmt.getRightOp();

if (rhs instanceof Local) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) rhs;
Local base = (Local) aref.getBase();
Expand All @@ -287,11 +330,11 @@ public void caseAssignStmt(AssignStmt stmt) {
// For some fixed type T, we assume that we can fix the array to T[].
if (bt instanceof RefType || bt instanceof NullType) {
String btName = bt instanceof NullType ? null : ((RefType) bt).getSootClass().getName();
if (btName == null || Scene.v().getObjectType().toString().equals(btName) || "java.io.Serializable".equals(btName)
if (btName == null || cache.getObjectType().toString().equals(btName) || "java.io.Serializable".equals(btName)
|| "java.lang.Cloneable".equals(btName)) {
if (defs == null) {
defs = G.v().soot_toolkits_scalar_LocalDefsFactory().newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
defs = cache.getDefs();
uses = cache.getUses();
}
// First, we check the definitions. If we can see the definitions and know the array type
// that way, we are safe.
Expand Down Expand Up @@ -409,39 +452,39 @@ public void caseAssignStmt(AssignStmt stmt) {

this.handleArrayRef(aref, stmt);

aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, trhs, stmt));
aref.setBase((Local) uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(uv.visit(rhs, trhs, stmt));
} else if (rhs instanceof InstanceFieldRef) {
this.handleInstanceFieldRef((InstanceFieldRef) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof BinopExpr) {
this.handleBinopExpr((BinopExpr) rhs, stmt, tlhs);
} else if (rhs instanceof InvokeExpr) {
this.handleInvokeExpr((InvokeExpr) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof CastExpr) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof InstanceOfExpr) {
InstanceOfExpr ioe = (InstanceOfExpr) rhs;
ioe.setOp(this.uv.visit(ioe.getOp(), Scene.v().getObjectType(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
ioe.setOp(uv.visit(ioe.getOp(), Scene.v().getObjectType(), stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) rhs;
nae.setSize(this.uv.visit(nae.getSize(), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
nae.setSize(uv.visit(nae.getSize(), IntType.v(), stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) rhs;
for (int i = 0, e = nmae.getSizeCount(); i < e; i++) {
nmae.setSize(i, this.uv.visit(nmae.getSize(i), IntType.v(), stmt));
nmae.setSize(i, uv.visit(nmae.getSize(i), IntType.v(), stmt));
}
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof LengthExpr) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NegExpr) {
((NegExpr) rhs).setOp(this.uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
((NegExpr) rhs).setOp(uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
} else if (rhs instanceof Constant) {
if (!(rhs instanceof NullConstant)) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setRightOp(uv.visit(rhs, tlhs, stmt));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,10 @@
import soot.Type;
import soot.Unit;
import soot.UnitPatchingChain;
import soot.Value;
import soot.ValueBox;
import soot.VoidType;
import soot.jimple.AssignStmt;
import soot.jimple.Constant;
import soot.jimple.DoubleConstant;
import soot.jimple.FieldRef;
import soot.jimple.FloatConstant;
import soot.jimple.InstanceFieldRef;
import soot.jimple.IntConstant;
Expand Down Expand Up @@ -123,7 +120,7 @@ public void transformClass(SootClass sc) {
if (sf.isStatic()) {
Stmt initStmt = jimp.newAssignStmt(jimp.newStaticFieldRef(sf.makeRef()), constant);
if (smInit == null) {
smInit = getOrCreateInitializer(sc, alreadyInitialized);
smInit = getOrCreateInitializer(sc);
}
if (smInit != null) {
smInit.getActiveBody().getUnits().addFirst(initStmt);
Expand Down Expand Up @@ -196,7 +193,7 @@ private boolean isInstanceFieldAssignedConstantInBody(SootField sf, Constant con
return false;
}

private SootMethod getOrCreateInitializer(SootClass sc, Set<SootField> alreadyInitialized) {
private SootMethod getOrCreateInitializer(SootClass sc) {
// Create a static initializer if we don't already have one
SootMethod smInit = sc.getMethodByNameUnsafe(SootMethod.staticInitializerName);
if (smInit == null) {
Expand All @@ -206,17 +203,6 @@ private SootMethod getOrCreateInitializer(SootClass sc, Set<SootField> alreadyIn
smInit.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
} else if (smInit.isPhantom()) {
return null;
} else {
// We need to collect those variables that are already initialized somewhere
for (Unit u : smInit.retrieveActiveBody().getUnits()) {
Stmt s = (Stmt) u;
for (ValueBox vb : s.getDefBoxes()) {
Value value = vb.getValue();
if (value instanceof FieldRef) {
alreadyInitialized.add(((FieldRef) value).getField());
}
}
}
}
return smInit;
}
Expand Down

0 comments on commit 8d201bb

Please sign in to comment.