diff --git a/docs/index.html b/docs/index.html
index f2ddcff..87b0719 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -118,7 +118,6 @@
Dongjie He, Jingbo Lu, and Jingling Xue Qilin: A New Framework for Supporting Fine-Grained Context-Sensitivity in Java Pointer Analysis, 36th European Conference on Object-Oriented Programming (ECOOP'22)
Dongjie He, Jingbo Lu, Yaoqing Gao, and Jingling Xue Selecting Context-Sensitivity Modularly for Accelerating Object-Sensitive Pointer Analysis, IEEE Transactions on Software Engineering (TSE'22)
Dongjie He, Jingbo Lu, and Jingling Xue Context Debloating for Object-Sensitive Pointer Analysis, 36th IEEE/ACM International Conference on Automated Software Engineering (ASE'21)
- Jingbo Lu, Dongjie He, and Jingling Xue Selective Context-Sensitivity for k-CFA with CFL-Reachability, 28th International Static Analysis Symposium (SAS'21)
Dongjie He, Jingbo Lu, Yaoqing Gao, and Jingling Xue Accelerating Object-Sensitive Pointer Analysis by Exploiting Object Containment and Reachability, 35th European Conference on Object-Oriented Programming (ECOOP'21)
Jingbo Lu, Dongjie He, and Jingling Xue Eagle: CFL-Reachability-based Precision-Preserving Acceleration of Object-Sensitive Pointer Analysis, ACM Transactions on Software Engineering and Methodology (TOSEM 2021)
Jingbo Lu and Jingling Xue Precision-Preserving Yet Fast Object-Sensitive Pointer Analysis with Partial Context Sensitivity. ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA'19)
diff --git a/qilin.core/src/qilin/core/solver/Solver.java b/qilin.core/src/qilin/core/solver/Solver.java
index d4b587b..c49a1e9 100644
--- a/qilin.core/src/qilin/core/solver/Solver.java
+++ b/qilin.core/src/qilin/core/solver/Solver.java
@@ -284,7 +284,7 @@ protected void propagatePTS(final ValNode pointer, PointsToSetInternal other) {
P2SetVisitor p2SetVisitor = new P2SetVisitor() {
@Override
public void visit(Node n) {
- if(addTo.add(n)) {
+ if (addTo.add(n)) {
returnValue = true;
}
}
diff --git a/qilin.core/src/qilin/stat/SimplifiedEvaluator.java b/qilin.core/src/qilin/stat/SimplifiedEvaluator.java
new file mode 100644
index 0000000..4085143
--- /dev/null
+++ b/qilin.core/src/qilin/stat/SimplifiedEvaluator.java
@@ -0,0 +1,192 @@
+package qilin.stat;
+
+import qilin.core.PTA;
+import qilin.core.builder.FakeMainFactory;
+import qilin.core.builder.MethodNodeFactory;
+import qilin.core.pag.*;
+import qilin.core.sets.P2SetVisitor;
+import qilin.core.sets.PointsToSetInternal;
+import qilin.util.PTAUtils;
+import qilin.util.Stopwatch;
+import soot.*;
+import soot.jimple.*;
+import soot.jimple.toolkits.callgraph.CallGraph;
+import soot.jimple.toolkits.callgraph.Edge;
+
+import java.util.*;
+
+public class SimplifiedEvaluator implements IEvaluator {
+ protected final PTA pta;
+ protected final Exporter exporter;
+ protected Stopwatch stopwatch;
+
+ public SimplifiedEvaluator(PTA pta) {
+ this.pta = pta;
+ exporter = new Exporter();
+ }
+
+ @Override
+ public void begin() {
+ stopwatch = Stopwatch.newAndStart("PTA evaluator");
+ }
+
+ @Override
+ public void end() {
+ stopwatch.stop();
+ exporter.collectMetric("Time (sec):", String.valueOf(((double) stopwatch.elapsed())));
+ exporter.collectMetric("#Reachable Method (CI):", String.valueOf(pta.getNakedReachableMethods().size() - 1));
+ CallGraph ciCallGraph = pta.getCallGraph();
+ exporter.collectMetric("#Call Edge(CI):", String.valueOf(ciCallGraph.size() - FakeMainFactory.implicitCallEdges));
+
+ CallGraph callGraph = pta.getCallGraph();
+
+ // loop over all reachable method's statement to find casts, local
+ // references, virtual call sites
+ Set reachableMethods = new HashSet<>();
+ for (MethodOrMethodContext momc : pta.getCgb().getReachableMethods()) {
+ final SootMethod sm = momc.method();
+ reachableMethods.add(sm);
+ }
+ int totalPolyCalls = 0;
+ int totalCastsMayFail = 0;
+ for (SootMethod sm : reachableMethods) {
+ // All the statements in the method
+ for (Unit unit : PTAUtils.getMethodBody(sm).getUnits()) {
+ Stmt st = (Stmt) unit;
+ // virtual calls
+ if (st.containsInvokeExpr()) {
+ InvokeExpr ie = st.getInvokeExpr();
+ if (!(ie instanceof StaticInvokeExpr)) {
+ // Virtual, Special or Instance
+ // have to check target soot method, cannot just
+ // count edges
+ Set targets = new HashSet<>();
+ for (Iterator it = callGraph.edgesOutOf(st); it.hasNext(); )
+ targets.add(it.next().tgt());
+ if (targets.size() > 1) {
+ totalPolyCalls++;
+ }
+ }
+ } else if (st instanceof AssignStmt) {
+ Value rhs = ((AssignStmt) st).getRightOp();
+ Value lhs = ((AssignStmt) st).getLeftOp();
+ if (rhs instanceof CastExpr && lhs.getType() instanceof RefLikeType) {
+ final Type targetType = ((CastExpr) rhs).getCastType();
+ Value v = ((CastExpr) rhs).getOp();
+ if (!(v instanceof Local)) {
+ continue;
+ }
+ boolean fails = false;
+ Set pts = new HashSet<>();
+ ((PointsToSetInternal) pta.reachingObjects((Local) v)).mapToCIPointsToSet().forall(new P2SetVisitor() {
+ @Override
+ public void visit(Node n) {
+ pts.add(n);
+ }
+ });
+ for (Node n : pts) {
+ if (fails) {
+ break;
+ }
+ fails = !PTAUtils.castNeverFails(n.getType(), targetType);
+ }
+ if (fails) {
+ totalCastsMayFail++;
+ }
+ }
+ }
+ }
+ }
+ exporter.collectMetric("#May Fail Cast (Total):", String.valueOf(totalCastsMayFail));
+ exporter.collectMetric("#Virtual Call Site(Polymorphic):", String.valueOf(totalPolyCalls));
+
+ ptsStat();
+ }
+
+ private void ptsStat() {
+ int ptsCntNoNative = 0;
+ int varCntNoNative = 0;
+ // locals exclude Exceptions
+ for (Local local : pta.getPag().getLocalPointers()) {
+ try {
+ LocalVarNode lvn = pta.getPag().findLocalVarNode(local);
+ if (local.toString().contains("intermediate/")) {
+ continue;
+ }
+ mLocalVarNodes.add(lvn);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // stat avg pts.
+ for (SootMethod sm : pta.getNakedReachableMethods()) {
+ MethodPAG mpag = pta.getPag().getMethodPAG(sm);
+ MethodNodeFactory mnf = mpag.nodeFactory();
+ if (!sm.isStatic()) {
+ mLocalVarNodes.add((LocalVarNode) mnf.caseThis());
+ }
+ for (int i = 0; i < sm.getParameterCount(); ++i) {
+ Type mType = sm.getParameterType(i);
+ if (mType instanceof RefLikeType) {
+ mLocalVarNodes.add((LocalVarNode) mnf.caseParm(i));
+ }
+ }
+ }
+ Set tmp = new HashSet<>();
+ for (LocalVarNode lvn : mLocalVarNodes) {
+ SootMethod sm = lvn.getMethod();
+ if (PTAUtils.isFakeMainMethod(sm)) {
+ tmp.add(lvn);
+ continue;
+ }
+ PointsToSetInternal cpts = (PointsToSetInternal) pta.reachingObjects(lvn);
+ final Set