|
|
@ -14,12 +14,14 @@ |
|
|
|
|
|
|
|
|
|
|
|
package de.fernflower.modules.decompiler.sforms; |
|
|
|
package de.fernflower.modules.decompiler.sforms; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map.Entry; |
|
|
|
import java.util.Map.Entry; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import test.util.DotExporter; |
|
|
|
import de.fernflower.code.CodeConstants; |
|
|
|
import de.fernflower.code.CodeConstants; |
|
|
|
import de.fernflower.modules.decompiler.exps.AssignmentExprent; |
|
|
|
import de.fernflower.modules.decompiler.exps.AssignmentExprent; |
|
|
|
import de.fernflower.modules.decompiler.exps.Exprent; |
|
|
|
import de.fernflower.modules.decompiler.exps.Exprent; |
|
|
@ -34,134 +36,143 @@ import de.fernflower.modules.decompiler.vars.VarVersionPaar; |
|
|
|
import de.fernflower.struct.StructMethod; |
|
|
|
import de.fernflower.struct.StructMethod; |
|
|
|
import de.fernflower.struct.gen.MethodDescriptor; |
|
|
|
import de.fernflower.struct.gen.MethodDescriptor; |
|
|
|
import de.fernflower.util.FastSparseSetFactory; |
|
|
|
import de.fernflower.util.FastSparseSetFactory; |
|
|
|
|
|
|
|
import de.fernflower.util.FastSparseSetFactory.FastSparseSet; |
|
|
|
import de.fernflower.util.InterpreterUtil; |
|
|
|
import de.fernflower.util.InterpreterUtil; |
|
|
|
import de.fernflower.util.SFormsFastMapDirect; |
|
|
|
import de.fernflower.util.SFormsFastMapDirect; |
|
|
|
import de.fernflower.util.FastSparseSetFactory.FastSparseSet; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class SSAConstructorSparseEx { |
|
|
|
public class SSAConstructorSparseEx { |
|
|
|
|
|
|
|
|
|
|
|
// node id, var, version
|
|
|
|
// node id, var, version
|
|
|
|
private HashMap<String, SFormsFastMapDirect> inVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
private HashMap<String, SFormsFastMapDirect> inVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
|
|
|
|
|
|
|
|
// node id, var, version (direct branch)
|
|
|
|
// node id, var, version (direct branch)
|
|
|
|
private HashMap<String, SFormsFastMapDirect> outVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
private HashMap<String, SFormsFastMapDirect> outVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
|
|
|
|
|
|
|
|
// node id, var, version (negative branch)
|
|
|
|
// node id, var, version (negative branch)
|
|
|
|
private HashMap<String, SFormsFastMapDirect> outNegVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
private HashMap<String, SFormsFastMapDirect> outNegVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
|
|
|
|
|
|
|
|
// node id, var, version
|
|
|
|
// node id, var, version
|
|
|
|
private HashMap<String, SFormsFastMapDirect> extraVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
private HashMap<String, SFormsFastMapDirect> extraVarVersions = new HashMap<String, SFormsFastMapDirect>(); |
|
|
|
|
|
|
|
|
|
|
|
// (var, version), version
|
|
|
|
// (var, version), version
|
|
|
|
private HashMap<VarVersionPaar, FastSparseSet<Integer>> phi = new HashMap<VarVersionPaar, FastSparseSet<Integer>>(); |
|
|
|
private HashMap<VarVersionPaar, FastSparseSet<Integer>> phi = new HashMap<VarVersionPaar, FastSparseSet<Integer>>(); |
|
|
|
|
|
|
|
|
|
|
|
// var, version
|
|
|
|
// var, version
|
|
|
|
private HashMap<Integer, Integer> lastversion = new HashMap<Integer, Integer>(); |
|
|
|
private HashMap<Integer, Integer> lastversion = new HashMap<Integer, Integer>(); |
|
|
|
|
|
|
|
|
|
|
|
private List<VarVersionPaar> startVars = new ArrayList<VarVersionPaar>(); |
|
|
|
private List<VarVersionPaar> startVars = new ArrayList<VarVersionPaar>(); |
|
|
|
|
|
|
|
|
|
|
|
// set factory
|
|
|
|
// set factory
|
|
|
|
private FastSparseSetFactory<Integer> factory; |
|
|
|
private FastSparseSetFactory<Integer> factory; |
|
|
|
|
|
|
|
|
|
|
|
public void splitVariables(RootStatement root, StructMethod mt) { |
|
|
|
public void splitVariables(RootStatement root, StructMethod mt) { |
|
|
|
|
|
|
|
|
|
|
|
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); |
|
|
|
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); |
|
|
|
DirectGraph dgraph = flatthelper.buildDirectGraph(root); |
|
|
|
DirectGraph dgraph = flatthelper.buildDirectGraph(root); |
|
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
// try {
|
|
|
|
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
|
|
|
|
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
|
|
|
|
// } catch(Exception ex) {ex.printStackTrace();}
|
|
|
|
// } catch(Exception ex) {ex.printStackTrace();}
|
|
|
|
|
|
|
|
|
|
|
|
HashSet<Integer> setInit = new HashSet<Integer>(); |
|
|
|
HashSet<Integer> setInit = new HashSet<Integer>(); |
|
|
|
for(int i=0;i<64;i++) { |
|
|
|
for(int i = 0; i < 64; i++) { |
|
|
|
setInit.add(i); |
|
|
|
setInit.add(i); |
|
|
|
} |
|
|
|
} |
|
|
|
factory = new FastSparseSetFactory<Integer>(setInit); |
|
|
|
factory = new FastSparseSetFactory<Integer>(setInit); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect firstmap = createFirstMap(mt); |
|
|
|
SFormsFastMapDirect firstmap = createFirstMap(mt); |
|
|
|
extraVarVersions.put(dgraph.first.id, firstmap); |
|
|
|
extraVarVersions.put(dgraph.first.id, firstmap); |
|
|
|
|
|
|
|
|
|
|
|
setCatchMaps(root, dgraph, flatthelper); |
|
|
|
setCatchMaps(root, dgraph, flatthelper); |
|
|
|
|
|
|
|
|
|
|
|
HashSet<String> updated = new HashSet<String>(); |
|
|
|
HashSet<String> updated = new HashSet<String>(); |
|
|
|
do { |
|
|
|
do { |
|
|
|
// System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
|
|
|
|
// System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
|
|
|
|
ssaStatements(dgraph, updated); |
|
|
|
ssaStatements(dgraph, updated); |
|
|
|
// System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
|
|
|
|
// System.out.println("~~~~~~~~~~~~~ \r\n"+root.toJava());
|
|
|
|
} while(!updated.isEmpty()); |
|
|
|
} while (!updated.isEmpty()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void ssaStatements(DirectGraph dgraph, HashSet<String> updated) { |
|
|
|
private void ssaStatements(DirectGraph dgraph, HashSet<String> updated) { |
|
|
|
|
|
|
|
|
|
|
|
// try {
|
|
|
|
// try {
|
|
|
|
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr1_my.dot"));
|
|
|
|
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr1_my.dot"));
|
|
|
|
// } catch(Exception ex) {ex.printStackTrace();}
|
|
|
|
// } catch(Exception ex) {ex.printStackTrace();}
|
|
|
|
|
|
|
|
|
|
|
|
for(DirectNode node: dgraph.nodes) { |
|
|
|
for(DirectNode node : dgraph.nodes) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (node.id.endsWith("_inc")) {
|
|
|
|
|
|
|
|
// System.out.println();
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
|
|
// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr1_my.dot"));
|
|
|
|
|
|
|
|
// } catch (Exception ex) {
|
|
|
|
|
|
|
|
// ex.printStackTrace();
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
updated.remove(node.id); |
|
|
|
updated.remove(node.id); |
|
|
|
mergeInVarMaps(node, dgraph); |
|
|
|
mergeInVarMaps(node, dgraph); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect varmap = inVarVersions.get(node.id); |
|
|
|
SFormsFastMapDirect varmap = inVarVersions.get(node.id); |
|
|
|
varmap = new SFormsFastMapDirect(varmap); |
|
|
|
varmap = new SFormsFastMapDirect(varmap); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect[] varmaparr = new SFormsFastMapDirect[] {varmap, null}; |
|
|
|
SFormsFastMapDirect[] varmaparr = new SFormsFastMapDirect[] { varmap, null }; |
|
|
|
|
|
|
|
|
|
|
|
if(node.exprents != null) { |
|
|
|
if (node.exprents != null) { |
|
|
|
for(Exprent expr: node.exprents) { |
|
|
|
for(Exprent expr : node.exprents) { |
|
|
|
processExprent(expr, varmaparr); |
|
|
|
processExprent(expr, varmaparr); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(varmaparr[1] == null) { |
|
|
|
if (varmaparr[1] == null) { |
|
|
|
varmaparr[1] = varmaparr[0]; |
|
|
|
varmaparr[1] = varmaparr[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean this_updated = !mapsEqual(varmaparr[0], outVarVersions.get(node.id)) |
|
|
|
boolean this_updated = !mapsEqual(varmaparr[0], outVarVersions.get(node.id)) |
|
|
|
|| (outNegVarVersions.containsKey(node.id) && !mapsEqual(varmaparr[1], outNegVarVersions.get(node.id))); |
|
|
|
|| (outNegVarVersions.containsKey(node.id) && !mapsEqual(varmaparr[1], outNegVarVersions.get(node.id))); |
|
|
|
|
|
|
|
|
|
|
|
if(this_updated) { |
|
|
|
if (this_updated) { |
|
|
|
outVarVersions.put(node.id, varmaparr[0]); |
|
|
|
outVarVersions.put(node.id, varmaparr[0]); |
|
|
|
if(dgraph.mapNegIfBranch.containsKey(node.id)) { |
|
|
|
if (dgraph.mapNegIfBranch.containsKey(node.id)) { |
|
|
|
outNegVarVersions.put(node.id, varmaparr[1]); |
|
|
|
outNegVarVersions.put(node.id, varmaparr[1]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(DirectNode nd: node.succs) { |
|
|
|
for(DirectNode nd : node.succs) { |
|
|
|
updated.add(nd.id); |
|
|
|
updated.add(nd.id); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void processExprent(Exprent expr, SFormsFastMapDirect[] varmaparr) { |
|
|
|
private void processExprent(Exprent expr, SFormsFastMapDirect[] varmaparr) { |
|
|
|
|
|
|
|
|
|
|
|
if(expr == null) { |
|
|
|
if (expr == null) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VarExprent varassign = null; |
|
|
|
VarExprent varassign = null; |
|
|
|
|
|
|
|
boolean finished = false; |
|
|
|
boolean finished = false; |
|
|
|
|
|
|
|
|
|
|
|
switch(expr.type) { |
|
|
|
switch (expr.type) { |
|
|
|
case Exprent.EXPRENT_ASSIGNMENT: |
|
|
|
case Exprent.EXPRENT_ASSIGNMENT: |
|
|
|
AssignmentExprent assexpr = (AssignmentExprent)expr; |
|
|
|
AssignmentExprent assexpr = (AssignmentExprent) expr; |
|
|
|
if(assexpr.getCondtype() == AssignmentExprent.CONDITION_NONE) { |
|
|
|
if (assexpr.getCondtype() == AssignmentExprent.CONDITION_NONE) { |
|
|
|
Exprent dest = assexpr.getLeft(); |
|
|
|
Exprent dest = assexpr.getLeft(); |
|
|
|
if(dest.type == Exprent.EXPRENT_VAR) { |
|
|
|
if (dest.type == Exprent.EXPRENT_VAR) { |
|
|
|
varassign = (VarExprent)dest; |
|
|
|
varassign = (VarExprent) dest; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
case Exprent.EXPRENT_FUNCTION: |
|
|
|
case Exprent.EXPRENT_FUNCTION: |
|
|
|
FunctionExprent func = (FunctionExprent)expr; |
|
|
|
FunctionExprent func = (FunctionExprent) expr; |
|
|
|
switch(func.getFunctype()) { |
|
|
|
switch (func.getFunctype()) { |
|
|
|
case FunctionExprent.FUNCTION_IIF: |
|
|
|
case FunctionExprent.FUNCTION_IIF: |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect varmapFalse; |
|
|
|
SFormsFastMapDirect varmapFalse; |
|
|
|
if(varmaparr[1] == null) { |
|
|
|
if (varmaparr[1] == null) { |
|
|
|
varmapFalse = new SFormsFastMapDirect(varmaparr[0]); |
|
|
|
varmapFalse = new SFormsFastMapDirect(varmaparr[0]); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
varmapFalse = varmaparr[1]; |
|
|
|
varmapFalse = varmaparr[1]; |
|
|
@ -169,92 +180,90 @@ public class SSAConstructorSparseEx { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
processExprent(func.getLstOperands().get(1), varmaparr); |
|
|
|
processExprent(func.getLstOperands().get(1), varmaparr); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] {varmapFalse, null}; |
|
|
|
SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] { varmapFalse, null }; |
|
|
|
processExprent(func.getLstOperands().get(2), varmaparrNeg); |
|
|
|
processExprent(func.getLstOperands().get(2), varmaparrNeg); |
|
|
|
|
|
|
|
|
|
|
|
mergeMaps(varmaparr[0], varmaparrNeg[0]); |
|
|
|
mergeMaps(varmaparr[0], varmaparrNeg[0]); |
|
|
|
varmaparr[1] = null; |
|
|
|
varmaparr[1] = null; |
|
|
|
|
|
|
|
|
|
|
|
finished = true; |
|
|
|
finished = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FunctionExprent.FUNCTION_CADD: |
|
|
|
case FunctionExprent.FUNCTION_CADD: |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] {new SFormsFastMapDirect(varmaparr[0]), null}; |
|
|
|
SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] { new SFormsFastMapDirect(varmaparr[0]), null }; |
|
|
|
|
|
|
|
|
|
|
|
processExprent(func.getLstOperands().get(1), varmaparrAnd); |
|
|
|
processExprent(func.getLstOperands().get(1), varmaparrAnd); |
|
|
|
|
|
|
|
|
|
|
|
// false map
|
|
|
|
// false map
|
|
|
|
varmaparr[1] = mergeMaps(varmaparr[varmaparr[1]==null?0:1], varmaparrAnd[varmaparrAnd[1]==null?0:1]); |
|
|
|
varmaparr[1] = mergeMaps(varmaparr[varmaparr[1] == null ? 0 : 1], varmaparrAnd[varmaparrAnd[1] == null ? 0 : 1]); |
|
|
|
// true map
|
|
|
|
// true map
|
|
|
|
varmaparr[0] = varmaparrAnd[0]; |
|
|
|
varmaparr[0] = varmaparrAnd[0]; |
|
|
|
|
|
|
|
|
|
|
|
finished = true; |
|
|
|
finished = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FunctionExprent.FUNCTION_COR: |
|
|
|
case FunctionExprent.FUNCTION_COR: |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
processExprent(func.getLstOperands().get(0), varmaparr); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] {new SFormsFastMapDirect(varmaparr[varmaparr[1]==null?0:1]), null}; |
|
|
|
SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] { new SFormsFastMapDirect(varmaparr[varmaparr[1] == null ? 0 : 1]), null }; |
|
|
|
|
|
|
|
|
|
|
|
processExprent(func.getLstOperands().get(1), varmaparrOr); |
|
|
|
processExprent(func.getLstOperands().get(1), varmaparrOr); |
|
|
|
|
|
|
|
|
|
|
|
// false map
|
|
|
|
// false map
|
|
|
|
varmaparr[1] = varmaparrOr[varmaparrOr[1]==null?0:1]; |
|
|
|
varmaparr[1] = varmaparrOr[varmaparrOr[1] == null ? 0 : 1]; |
|
|
|
// true map
|
|
|
|
// true map
|
|
|
|
varmaparr[0] = mergeMaps(varmaparr[0], varmaparrOr[0]); |
|
|
|
varmaparr[0] = mergeMaps(varmaparr[0], varmaparrOr[0]); |
|
|
|
|
|
|
|
|
|
|
|
finished = true; |
|
|
|
finished = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(finished) { |
|
|
|
if (finished) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Exprent> lst = expr.getAllExprents(); |
|
|
|
List<Exprent> lst = expr.getAllExprents(); |
|
|
|
lst.remove(varassign); |
|
|
|
lst.remove(varassign); |
|
|
|
|
|
|
|
|
|
|
|
for(Exprent ex: lst) { |
|
|
|
for(Exprent ex : lst) { |
|
|
|
processExprent(ex, varmaparr); |
|
|
|
processExprent(ex, varmaparr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect varmap = varmaparr[0]; |
|
|
|
SFormsFastMapDirect varmap = varmaparr[0]; |
|
|
|
|
|
|
|
|
|
|
|
if(varassign != null) { |
|
|
|
if (varassign != null) { |
|
|
|
|
|
|
|
|
|
|
|
Integer varindex = varassign.getIndex(); |
|
|
|
Integer varindex = varassign.getIndex(); |
|
|
|
|
|
|
|
|
|
|
|
if(varassign.getVersion() == 0) { |
|
|
|
if (varassign.getVersion() == 0) { |
|
|
|
// get next version
|
|
|
|
// get next version
|
|
|
|
Integer nextver = getNextFreeVersion(varindex); |
|
|
|
Integer nextver = getNextFreeVersion(varindex); |
|
|
|
|
|
|
|
|
|
|
|
// set version
|
|
|
|
// set version
|
|
|
|
varassign.setVersion(nextver); |
|
|
|
varassign.setVersion(nextver); |
|
|
|
|
|
|
|
|
|
|
|
setCurrentVar(varmap, varindex, nextver); |
|
|
|
setCurrentVar(varmap, varindex, nextver); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
setCurrentVar(varmap, varindex, varassign.getVersion()); |
|
|
|
setCurrentVar(varmap, varindex, varassign.getVersion()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} else if(expr.type == Exprent.EXPRENT_VAR) { |
|
|
|
} else if (expr.type == Exprent.EXPRENT_VAR) { |
|
|
|
|
|
|
|
|
|
|
|
VarExprent vardest = (VarExprent)expr; |
|
|
|
VarExprent vardest = (VarExprent) expr; |
|
|
|
Integer varindex = vardest.getIndex(); |
|
|
|
Integer varindex = vardest.getIndex(); |
|
|
|
FastSparseSet<Integer> vers = varmap.get(varindex); |
|
|
|
FastSparseSet<Integer> vers = varmap.get(varindex); |
|
|
|
|
|
|
|
|
|
|
|
int cardinality = vers.getCardinality(); |
|
|
|
int cardinality = vers.getCardinality(); |
|
|
|
if(cardinality == 1) { // == 1
|
|
|
|
if (cardinality == 1) { // == 1
|
|
|
|
// set version
|
|
|
|
// set version
|
|
|
|
Integer it = vers.iterator().next(); |
|
|
|
Integer it = vers.iterator().next(); |
|
|
|
vardest.setVersion(it.intValue()); |
|
|
|
vardest.setVersion(it.intValue()); |
|
|
|
} else if(cardinality == 2) { // size > 1
|
|
|
|
} else if (cardinality == 2) { // size > 1
|
|
|
|
Integer current_vers = vardest.getVersion(); |
|
|
|
Integer current_vers = vardest.getVersion(); |
|
|
|
|
|
|
|
|
|
|
|
VarVersionPaar currpaar = new VarVersionPaar(varindex, current_vers); |
|
|
|
VarVersionPaar currpaar = new VarVersionPaar(varindex, current_vers); |
|
|
|
if(current_vers != 0 && phi.containsKey(currpaar)) { |
|
|
|
if (current_vers != 0 && phi.containsKey(currpaar)) { |
|
|
|
setCurrentVar(varmap, varindex, current_vers); |
|
|
|
setCurrentVar(varmap, varindex, current_vers); |
|
|
|
// update phi node
|
|
|
|
// update phi node
|
|
|
|
phi.get(currpaar).union(vers); |
|
|
|
phi.get(currpaar).union(vers); |
|
|
@ -263,111 +272,110 @@ public class SSAConstructorSparseEx { |
|
|
|
Integer nextver = getNextFreeVersion(varindex); |
|
|
|
Integer nextver = getNextFreeVersion(varindex); |
|
|
|
// set version
|
|
|
|
// set version
|
|
|
|
vardest.setVersion(nextver); |
|
|
|
vardest.setVersion(nextver); |
|
|
|
|
|
|
|
|
|
|
|
setCurrentVar(varmap, varindex, nextver); |
|
|
|
setCurrentVar(varmap, varindex, nextver); |
|
|
|
// create new phi node
|
|
|
|
// create new phi node
|
|
|
|
phi.put(new VarVersionPaar(varindex, nextver), vers); |
|
|
|
phi.put(new VarVersionPaar(varindex, nextver), vers); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} // 0 means uninitialized variable, which is impossible
|
|
|
|
} // 0 means uninitialized variable, which is impossible
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Integer getNextFreeVersion(Integer var) { |
|
|
|
private Integer getNextFreeVersion(Integer var) { |
|
|
|
Integer nextver = lastversion.get(var); |
|
|
|
Integer nextver = lastversion.get(var); |
|
|
|
if(nextver==null) { |
|
|
|
if (nextver == null) { |
|
|
|
nextver = new Integer(1); |
|
|
|
nextver = new Integer(1); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
nextver = new Integer(nextver.intValue()+1); |
|
|
|
nextver = new Integer(nextver.intValue() + 1); |
|
|
|
} |
|
|
|
} |
|
|
|
lastversion.put(var, nextver); |
|
|
|
lastversion.put(var, nextver); |
|
|
|
return nextver; |
|
|
|
return nextver; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void mergeInVarMaps(DirectNode node, DirectGraph dgraph) { |
|
|
|
private void mergeInVarMaps(DirectNode node, DirectGraph dgraph) { |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect mapNew = new SFormsFastMapDirect(); |
|
|
|
SFormsFastMapDirect mapNew = new SFormsFastMapDirect(); |
|
|
|
|
|
|
|
|
|
|
|
for(DirectNode pred: node.preds) { |
|
|
|
for(DirectNode pred : node.preds) { |
|
|
|
SFormsFastMapDirect mapOut = getFilteredOutMap(node.id, pred.id, dgraph, node.id); |
|
|
|
SFormsFastMapDirect mapOut = getFilteredOutMap(node.id, pred.id, dgraph, node.id); |
|
|
|
if(mapNew.isEmpty()) { |
|
|
|
if (mapNew.isEmpty()) { |
|
|
|
mapNew = mapOut.getCopy(); |
|
|
|
mapNew = mapOut.getCopy(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
mergeMaps(mapNew, mapOut); |
|
|
|
mergeMaps(mapNew, mapOut); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(extraVarVersions.containsKey(node.id)) { |
|
|
|
if (extraVarVersions.containsKey(node.id)) { |
|
|
|
SFormsFastMapDirect mapExtra = extraVarVersions.get(node.id); |
|
|
|
SFormsFastMapDirect mapExtra = extraVarVersions.get(node.id); |
|
|
|
if(mapNew.isEmpty()) { |
|
|
|
if (mapNew.isEmpty()) { |
|
|
|
mapNew = mapExtra.getCopy(); |
|
|
|
mapNew = mapExtra.getCopy(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
mergeMaps(mapNew, mapExtra); |
|
|
|
mergeMaps(mapNew, mapExtra); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inVarVersions.put(node.id, mapNew); |
|
|
|
inVarVersions.put(node.id, mapNew); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private SFormsFastMapDirect getFilteredOutMap(String nodeid, String predid, DirectGraph dgraph, |
|
|
|
private SFormsFastMapDirect getFilteredOutMap(String nodeid, String predid, DirectGraph dgraph, String destid) { |
|
|
|
String destid) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect mapNew = new SFormsFastMapDirect(); |
|
|
|
SFormsFastMapDirect mapNew = new SFormsFastMapDirect(); |
|
|
|
|
|
|
|
|
|
|
|
if(nodeid.equals(dgraph.mapNegIfBranch.get(predid))) { |
|
|
|
if (nodeid.equals(dgraph.mapNegIfBranch.get(predid))) { |
|
|
|
if(outNegVarVersions.containsKey(predid)) { |
|
|
|
if (outNegVarVersions.containsKey(predid)) { |
|
|
|
mapNew = outNegVarVersions.get(predid).getCopy(); |
|
|
|
mapNew = outNegVarVersions.get(predid).getCopy(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if(outVarVersions.containsKey(predid)) { |
|
|
|
} else if (outVarVersions.containsKey(predid)) { |
|
|
|
mapNew = outVarVersions.get(predid).getCopy(); |
|
|
|
mapNew = outVarVersions.get(predid).getCopy(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean isFinallyExit = dgraph.mapShortRangeFinallyPaths.containsKey(predid); |
|
|
|
boolean isFinallyExit = dgraph.mapShortRangeFinallyPaths.containsKey(predid); |
|
|
|
|
|
|
|
|
|
|
|
if(isFinallyExit && !mapNew.isEmpty()) { |
|
|
|
if (isFinallyExit && !mapNew.isEmpty()) { |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect mapNewTemp = mapNew.getCopy(); |
|
|
|
SFormsFastMapDirect mapNewTemp = mapNew.getCopy(); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect mapTrueSource = new SFormsFastMapDirect(); |
|
|
|
SFormsFastMapDirect mapTrueSource = new SFormsFastMapDirect(); |
|
|
|
|
|
|
|
|
|
|
|
String exceptionDest = dgraph.mapFinallyMonitorExceptionPathExits.get(predid); |
|
|
|
String exceptionDest = dgraph.mapFinallyMonitorExceptionPathExits.get(predid); |
|
|
|
boolean isExceptionMonitorExit = (exceptionDest != null && !nodeid.equals(exceptionDest)); |
|
|
|
boolean isExceptionMonitorExit = (exceptionDest != null && !nodeid.equals(exceptionDest)); |
|
|
|
|
|
|
|
|
|
|
|
HashSet<String> setLongPathWrapper = new HashSet<String>(); |
|
|
|
HashSet<String> setLongPathWrapper = new HashSet<String>(); |
|
|
|
for(FinallyPathWrapper finwraplong : dgraph.mapLongRangeFinallyPaths.get(predid)) { |
|
|
|
for(FinallyPathWrapper finwraplong : dgraph.mapLongRangeFinallyPaths.get(predid)) { |
|
|
|
setLongPathWrapper.add(finwraplong.destination+"##"+finwraplong.source); |
|
|
|
setLongPathWrapper.add(finwraplong.destination + "##" + finwraplong.source); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(FinallyPathWrapper finwrap : dgraph.mapShortRangeFinallyPaths.get(predid)) { |
|
|
|
for(FinallyPathWrapper finwrap : dgraph.mapShortRangeFinallyPaths.get(predid)) { |
|
|
|
SFormsFastMapDirect map; |
|
|
|
SFormsFastMapDirect map; |
|
|
|
|
|
|
|
|
|
|
|
boolean recFinally = dgraph.mapShortRangeFinallyPaths.containsKey(finwrap.source); |
|
|
|
boolean recFinally = dgraph.mapShortRangeFinallyPaths.containsKey(finwrap.source); |
|
|
|
|
|
|
|
|
|
|
|
if(recFinally) { |
|
|
|
if (recFinally) { |
|
|
|
// recursion
|
|
|
|
// recursion
|
|
|
|
map = getFilteredOutMap(finwrap.entry, finwrap.source, dgraph, destid); |
|
|
|
map = getFilteredOutMap(finwrap.entry, finwrap.source, dgraph, destid); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if(finwrap.entry.equals(dgraph.mapNegIfBranch.get(finwrap.source))) { |
|
|
|
if (finwrap.entry.equals(dgraph.mapNegIfBranch.get(finwrap.source))) { |
|
|
|
map = outNegVarVersions.get(finwrap.source); |
|
|
|
map = outNegVarVersions.get(finwrap.source); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
map = outVarVersions.get(finwrap.source); |
|
|
|
map = outVarVersions.get(finwrap.source); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// false path?
|
|
|
|
// false path?
|
|
|
|
boolean isFalsePath = true; |
|
|
|
boolean isFalsePath = true; |
|
|
|
|
|
|
|
|
|
|
|
if(recFinally) { |
|
|
|
if (recFinally) { |
|
|
|
isFalsePath = !finwrap.destination.equals(nodeid); |
|
|
|
isFalsePath = !finwrap.destination.equals(nodeid); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
isFalsePath = !setLongPathWrapper.contains(destid+"##"+finwrap.source); |
|
|
|
isFalsePath = !setLongPathWrapper.contains(destid + "##" + finwrap.source); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(isFalsePath) { |
|
|
|
if (isFalsePath) { |
|
|
|
mapNewTemp.complement(map); |
|
|
|
mapNewTemp.complement(map); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if(mapTrueSource.isEmpty()) { |
|
|
|
if (mapTrueSource.isEmpty()) { |
|
|
|
if(map != null) { |
|
|
|
if (map != null) { |
|
|
|
mapTrueSource = map.getCopy(); |
|
|
|
mapTrueSource = map.getCopy(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -376,8 +384,8 @@ public class SSAConstructorSparseEx { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(isExceptionMonitorExit) { |
|
|
|
if (isExceptionMonitorExit) { |
|
|
|
|
|
|
|
|
|
|
|
mapNew = mapTrueSource; |
|
|
|
mapNew = mapTrueSource; |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -385,119 +393,117 @@ public class SSAConstructorSparseEx { |
|
|
|
mapNewTemp.union(mapTrueSource); |
|
|
|
mapNewTemp.union(mapTrueSource); |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect oldInMap = inVarVersions.get(nodeid); |
|
|
|
SFormsFastMapDirect oldInMap = inVarVersions.get(nodeid); |
|
|
|
if(oldInMap != null) { |
|
|
|
if (oldInMap != null) { |
|
|
|
mapNewTemp.union(oldInMap); |
|
|
|
mapNewTemp.union(oldInMap); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mapNew.intersection(mapNewTemp); |
|
|
|
mapNew.intersection(mapNewTemp); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return mapNew; |
|
|
|
return mapNew; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SFormsFastMapDirect mergeMaps(SFormsFastMapDirect mapTo, SFormsFastMapDirect map2) { |
|
|
|
private SFormsFastMapDirect mergeMaps(SFormsFastMapDirect mapTo, SFormsFastMapDirect map2) { |
|
|
|
|
|
|
|
|
|
|
|
if(map2 != null && !map2.isEmpty()) { |
|
|
|
if (map2 != null && !map2.isEmpty()) { |
|
|
|
mapTo.union(map2); |
|
|
|
mapTo.union(map2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return mapTo; |
|
|
|
return mapTo; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean mapsEqual(SFormsFastMapDirect map1, SFormsFastMapDirect map2) { |
|
|
|
private boolean mapsEqual(SFormsFastMapDirect map1, SFormsFastMapDirect map2) { |
|
|
|
|
|
|
|
|
|
|
|
if(map1 == null) { |
|
|
|
if (map1 == null) { |
|
|
|
return map2 == null; |
|
|
|
return map2 == null; |
|
|
|
} else if (map2 == null) { |
|
|
|
} else if (map2 == null) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(map1.size() != map2.size()) { |
|
|
|
if (map1.size() != map2.size()) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(Entry<Integer, FastSparseSet<Integer>> ent2: map2.entryList()) { |
|
|
|
for(Entry<Integer, FastSparseSet<Integer>> ent2 : map2.entryList()) { |
|
|
|
if(!InterpreterUtil.equalObjects(map1.get(ent2.getKey()), ent2.getValue())) { |
|
|
|
if (!InterpreterUtil.equalObjects(map1.get(ent2.getKey()), ent2.getValue())) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setCurrentVar(SFormsFastMapDirect varmap, Integer var, Integer vers) { |
|
|
|
private void setCurrentVar(SFormsFastMapDirect varmap, Integer var, Integer vers) { |
|
|
|
FastSparseSet<Integer> set = factory.spawnEmptySet(); |
|
|
|
FastSparseSet<Integer> set = factory.spawnEmptySet(); |
|
|
|
set.add(vers); |
|
|
|
set.add(vers); |
|
|
|
varmap.put(var, set); |
|
|
|
varmap.put(var, set); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void setCatchMaps(Statement stat, DirectGraph dgraph, FlattenStatementsHelper flatthelper) { |
|
|
|
private void setCatchMaps(Statement stat, DirectGraph dgraph, FlattenStatementsHelper flatthelper) { |
|
|
|
|
|
|
|
|
|
|
|
SFormsFastMapDirect map; |
|
|
|
SFormsFastMapDirect map; |
|
|
|
|
|
|
|
|
|
|
|
switch(stat.type) { |
|
|
|
switch (stat.type) { |
|
|
|
case Statement.TYPE_CATCHALL: |
|
|
|
case Statement.TYPE_CATCHALL: |
|
|
|
case Statement.TYPE_TRYCATCH: |
|
|
|
case Statement.TYPE_TRYCATCH: |
|
|
|
|
|
|
|
|
|
|
|
List<VarExprent> lstVars; |
|
|
|
List<VarExprent> lstVars; |
|
|
|
if(stat.type == Statement.TYPE_CATCHALL) { |
|
|
|
if (stat.type == Statement.TYPE_CATCHALL) { |
|
|
|
lstVars = ((CatchAllStatement)stat).getVars(); |
|
|
|
lstVars = ((CatchAllStatement) stat).getVars(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
lstVars = ((CatchStatement)stat).getVars(); |
|
|
|
lstVars = ((CatchStatement) stat).getVars(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(int i=1;i<stat.getStats().size();i++) { |
|
|
|
for(int i = 1; i < stat.getStats().size(); i++) { |
|
|
|
int varindex = lstVars.get(i-1).getIndex(); |
|
|
|
int varindex = lstVars.get(i - 1).getIndex(); |
|
|
|
int version = getNextFreeVersion(varindex); // == 1
|
|
|
|
int version = getNextFreeVersion(varindex); // == 1
|
|
|
|
|
|
|
|
|
|
|
|
map = new SFormsFastMapDirect(); |
|
|
|
map = new SFormsFastMapDirect(); |
|
|
|
setCurrentVar(map, varindex, version); |
|
|
|
setCurrentVar(map, varindex, version); |
|
|
|
|
|
|
|
|
|
|
|
extraVarVersions.put(dgraph.nodes.getWithKey(flatthelper.getMapDestinationNodes().get(stat.getStats().get(i).id)[0]).id, map); |
|
|
|
extraVarVersions.put(dgraph.nodes.getWithKey(flatthelper.getMapDestinationNodes().get(stat.getStats().get(i).id)[0]).id, map); |
|
|
|
startVars.add(new VarVersionPaar(varindex, version)); |
|
|
|
startVars.add(new VarVersionPaar(varindex, version)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(Statement st: stat.getStats()) { |
|
|
|
for(Statement st : stat.getStats()) { |
|
|
|
setCatchMaps(st, dgraph, flatthelper); |
|
|
|
setCatchMaps(st, dgraph, flatthelper); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private SFormsFastMapDirect createFirstMap(StructMethod mt) { |
|
|
|
private SFormsFastMapDirect createFirstMap(StructMethod mt) { |
|
|
|
|
|
|
|
|
|
|
|
boolean thisvar = (mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0; |
|
|
|
boolean thisvar = (mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0; |
|
|
|
|
|
|
|
|
|
|
|
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); |
|
|
|
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); |
|
|
|
|
|
|
|
|
|
|
|
int paramcount = md.params.length + (thisvar?1:0); |
|
|
|
int paramcount = md.params.length + (thisvar ? 1 : 0); |
|
|
|
|
|
|
|
|
|
|
|
int varindex = 0; |
|
|
|
int varindex = 0; |
|
|
|
SFormsFastMapDirect map = new SFormsFastMapDirect(); |
|
|
|
SFormsFastMapDirect map = new SFormsFastMapDirect(); |
|
|
|
for(int i=0;i<paramcount;i++) { |
|
|
|
for(int i = 0; i < paramcount; i++) { |
|
|
|
int version = getNextFreeVersion(varindex); // == 1
|
|
|
|
int version = getNextFreeVersion(varindex); // == 1
|
|
|
|
|
|
|
|
|
|
|
|
FastSparseSet<Integer> set = factory.spawnEmptySet(); |
|
|
|
FastSparseSet<Integer> set = factory.spawnEmptySet(); |
|
|
|
set.add(version); |
|
|
|
set.add(version); |
|
|
|
map.put(varindex, set); |
|
|
|
map.put(varindex, set); |
|
|
|
startVars.add(new VarVersionPaar(varindex, version)); |
|
|
|
startVars.add(new VarVersionPaar(varindex, version)); |
|
|
|
|
|
|
|
|
|
|
|
if(thisvar) { |
|
|
|
if (thisvar) { |
|
|
|
if(i==0) { |
|
|
|
if (i == 0) { |
|
|
|
varindex++; |
|
|
|
varindex++; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
varindex+=md.params[i-1].stack_size; |
|
|
|
varindex += md.params[i - 1].stack_size; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
varindex+=md.params[i].stack_size; |
|
|
|
varindex += md.params[i].stack_size; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return map; |
|
|
|
return map; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public HashMap<VarVersionPaar, FastSparseSet<Integer>> getPhi() { |
|
|
|
public HashMap<VarVersionPaar, FastSparseSet<Integer>> getPhi() { |
|
|
|
return phi; |
|
|
|
return phi; |
|
|
|
} |
|
|
|
} |
|
|
@ -505,5 +511,5 @@ public class SSAConstructorSparseEx { |
|
|
|
public List<VarVersionPaar> getStartVars() { |
|
|
|
public List<VarVersionPaar> getStartVars() { |
|
|
|
return startVars; |
|
|
|
return startVars; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|