in src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java [531:665]
private SFormsFastMapDirect getFilteredOutMap(String nodeid, String predid, DirectGraph dgraph, String destid) {
SFormsFastMapDirect mapNew = new SFormsFastMapDirect();
boolean isFinallyExit = dgraph.mapShortRangeFinallyPaths.containsKey(predid);
if (nodeid.equals(dgraph.mapNegIfBranch.get(predid))) {
if (outNegVarVersions.containsKey(predid)) {
mapNew = outNegVarVersions.get(predid).getCopy();
}
}
else if (outVarVersions.containsKey(predid)) {
mapNew = outVarVersions.get(predid).getCopy();
}
if (isFinallyExit) {
SFormsFastMapDirect mapNewTemp = mapNew.getCopy();
SFormsFastMapDirect mapTrueSource = new SFormsFastMapDirect();
String exceptionDest = dgraph.mapFinallyMonitorExceptionPathExits.get(predid);
boolean isExceptionMonitorExit = (exceptionDest != null && !nodeid.equals(exceptionDest));
HashSet<String> setLongPathWrapper = new HashSet<>();
for (List<FinallyPathWrapper> lstwrapper : dgraph.mapLongRangeFinallyPaths.values()) {
for (FinallyPathWrapper finwraplong : lstwrapper) {
setLongPathWrapper.add(finwraplong.destination + "##" + finwraplong.source);
}
}
for (FinallyPathWrapper finwrap : dgraph.mapShortRangeFinallyPaths.get(predid)) {
SFormsFastMapDirect map;
boolean recFinally = dgraph.mapShortRangeFinallyPaths.containsKey(finwrap.source);
if (recFinally) {
// recursion
map = getFilteredOutMap(finwrap.entry, finwrap.source, dgraph, destid);
}
else {
if (finwrap.entry.equals(dgraph.mapNegIfBranch.get(finwrap.source))) {
map = outNegVarVersions.get(finwrap.source);
}
else {
map = outVarVersions.get(finwrap.source);
}
}
// false path?
boolean isFalsePath;
if (recFinally) {
isFalsePath = !finwrap.destination.equals(nodeid);
}
else {
isFalsePath = !setLongPathWrapper.contains(destid + "##" + finwrap.source);
}
if (isFalsePath) {
mapNewTemp.complement(map);
}
else {
if (mapTrueSource.isEmpty()) {
if (map != null) {
mapTrueSource = map.getCopy();
}
}
else {
mergeMaps(mapTrueSource, map);
}
}
}
if (isExceptionMonitorExit) {
mapNew = mapTrueSource;
}
else {
mapNewTemp.union(mapTrueSource);
mapNew.intersection(mapNewTemp);
if (!mapTrueSource.isEmpty() && !mapNew.isEmpty()) { // FIXME: what for??
// replace phi versions with corresponding phantom ones
HashMap<VarVersion, VarVersion> mapPhantom = phantomexitnodes.get(predid);
if (mapPhantom == null) {
mapPhantom = new HashMap<>();
}
SFormsFastMapDirect mapExitVar = mapNew.getCopy();
mapExitVar.complement(mapTrueSource);
for (Entry<Integer, FastSparseSet<Integer>> ent : mapExitVar.entryList()) {
for (Integer version : ent.getValue()) {
Integer varindex = ent.getKey();
VarVersion exitvar = new VarVersion(varindex, version);
FastSparseSet<Integer> newSet = mapNew.get(varindex);
// remove the actual exit version
newSet.remove(version);
// get or create phantom version
VarVersion phantomvar = mapPhantom.get(exitvar);
if (phantomvar == null) {
Integer newversion = getNextFreeVersion(exitvar.var, null);
phantomvar = new VarVersion(exitvar.var, newversion.intValue());
VarVersionNode exitnode = ssuversions.nodes.getWithKey(exitvar);
VarVersionNode phantomnode = ssuversions.createNode(phantomvar);
phantomnode.flags |= VarVersionNode.FLAG_PHANTOM_FIN_EXIT;
VarVersionEdge edge = new VarVersionEdge(VarVersionEdge.EDGE_PHANTOM, exitnode, phantomnode);
exitnode.addSuccessor(edge);
phantomnode.addPredecessor(edge);
mapPhantom.put(exitvar, phantomvar);
}
// add phantom version
newSet.add(phantomvar.version);
}
}
if (!mapPhantom.isEmpty()) {
phantomexitnodes.put(predid, mapPhantom);
}
}
}
}
return mapNew;
}