diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 53a6f1b26..1b28e3363 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; @@ -831,6 +832,24 @@ public class AVM2Graph extends Graph { return next; } + @Override + protected boolean isPartEmpty(GraphPart part) { + if (part.nextParts.size() > 1) { + return false; + } + if (part.start < 0) { + return false; + } + for (int ip = part.start; ip <= part.end; ip++) { + if (!(avm2code.code.get(ip).definition instanceof DebugLineIns) + && !(avm2code.code.get(ip).definition instanceof JumpIns)) { + return false; + } + } + return true; + } + + @Override protected GraphTargetItem checkLoop(LoopItem loopItem, BaseLocalData localData, List loops) { AVM2LocalData aLocalData = (AVM2LocalData) localData; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 182f5c334..068537d15 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -812,7 +812,7 @@ public class Graph { } } - private void findGotoTargetsWalk(Map> partToNext, Map> partToPrev, Reference currentVirtualNum, List openedExceptions, GraphPartEdge e, + private void findGotoTargetsWalk(Map partReplacements, Map> partToNext, Map> partToPrev, Reference currentVirtualNum, List openedExceptions, GraphPartEdge e, Set opened, Set closed, Set closedBranches, @@ -972,11 +972,13 @@ public class Graph { if (!branches.isEmpty()) { logger.fine("removedCount before: " + removedCount); removedCount += comparedPaths.size(); - if (partToNext.get(decision).size() > 2 && removedCount < partToNext.get(decision).size() - 1) { + /*if (partToNext.get(decision).size() > 2 && removedCount < partToNext.get(decision).size() - 1) { //ignore - } else { - branches.remove(branches.size() - 1); - } + } else {*/ + /*branches.remove(branches.size() - 1); + logger.fine("closing branch 2: " + decision); + closedBranches.add(decision);*/ + //} } } else { branches = comparedPaths.get(0); @@ -995,8 +997,6 @@ public class Graph { } - List nexts = new ArrayList<>(); - boolean isExceptionStart = false; GraphExceptionParts nearestEx = null; List currentExceptions = new ArrayList<>(); @@ -1021,16 +1021,20 @@ public class Graph { //openedExceptions = new ArrayList<>(); openedExceptions.addAll(currentExceptions); List virtualNexts = new ArrayList<>(); - virtualNexts.add(p); + //virtualNexts.add(p); virtualNexts.addAll(currentExceptionTargets); - virtualNexts.add(nearestEx.end); + GraphPart end = nearestEx.end; + if (partReplacements.containsKey(end)) { + end = partReplacements.get(end); + } + virtualNexts.add(end); currentVirtualNum.setVal(currentVirtualNum.getVal() - 1); GraphPart virtualPart = new GraphPart(currentVirtualNum.getVal(), currentVirtualNum.getVal()); partToNext.put(virtualPart, virtualNexts); partToPrev.put(virtualPart, new ArrayList<>()); // connection from prevs of p to virtualPart - for (int k = 0; k < partToPrev.get(p).size(); k++) { + /*for (int k = 0; k < partToPrev.get(p).size(); k++) { GraphPart pr = partToPrev.get(p).get(k); List prevNexts = partToNext.get(pr); for (int j = 0; j < prevNexts.size(); j++) { @@ -1039,18 +1043,41 @@ public class Graph { } } partToPrev.get(virtualPart).add(pr); - } + }*/ for (GraphPart t : virtualNexts) { - if (t == nearestEx.end) { + if (t == end) { partToPrev.get(t).add(virtualPart); } else { partToPrev.get(t).clear(); partToPrev.get(t).add(virtualPart); } } - p = virtualPart; + findGotoWalkNexts(partReplacements, partToNext, partToPrev, currentVirtualNum, openedExceptions, opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets, virtualPart, branches); } + findGotoWalkNexts(partReplacements, partToNext, partToPrev, currentVirtualNum, openedExceptions, opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets, p, branches); + } + + protected boolean isPartEmpty(GraphPart part) { + return false; + } + + private void findGotoWalkNexts(Map partReplacements, Map> partToNext, Map> partToPrev, Reference currentVirtualNum, List openedExceptions, + Set opened, + Set closed, + Set closedBranches, + Set exitEdges, + Set backEdges, + Set throwEdges, + Set allowedThrowEdges, + List exceptionParts, + Map> edgeToBranches, + GraphPart start, + List gotoTargets, + GraphPart p, + List branches) { + List nexts = new ArrayList<>(); + //filter out backedges for (GraphPart n : partToNext.get(p)) { GraphPartEdge ne = new GraphPartEdge(p, n); @@ -1061,9 +1088,6 @@ public class Graph { } } - - int sizeNextsNoThrow = nexts.size(); - closed.add(p); Stack walkStack = new Stack<>(); @@ -1079,30 +1103,8 @@ public class Graph { walkStack.push(ne); } - /*if (isTryBegin(p)) { - for (GraphPart t : p.throwParts) { - GraphPartEdge te = new GraphPartEdge(p, t); - if (backEdges.contains(te)) { - continue; - } - edgeToBranches.put(te, branches); - walkStack.push(te); - } - }*/ - - /*logger.fine("processing throwparts of " + p); - for (GraphPart n : p.throwParts) { - GraphPartEdge ne = new GraphPartEdge(p, n); - List subBranches = new ArrayList<>(branches); - if (p.throwParts.size() > 1) { - subBranches = new ArrayList<>(branches); - subBranches.add(p); - } - edgeToBranches.put(ne, subBranches); - walkStack.push(ne); - }*/ while (!walkStack.isEmpty()) { - findGotoTargetsWalk(partToNext, partToPrev, currentVirtualNum, openedExceptions, walkStack.pop(), opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets); + findGotoTargetsWalk(partReplacements, partToNext, partToPrev, currentVirtualNum, openedExceptions, walkStack.pop(), opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets); } } @@ -1110,7 +1112,7 @@ public class Graph { if (!path.endsWith(".run")) { //return; } - logger.info("------ " + path); + logger.fine("------ " + path); //logger.info("GETTING precontinues of " + path + " ================="); Set opened = new HashSet<>(); Set closed = new HashSet<>(); @@ -1123,13 +1125,12 @@ public class Graph { Map partByIp = new HashMap<>(); Map> partToNext = new HashMap<>(); Map> partToPrev = new HashMap<>(); + Map partReplacements = new HashMap<>(); for (GraphPart p : allParts) { if (p.start == -1) { continue; } - //if (p.start >= 0) { - partByIp.put(p.start, p); - //} + partByIp.put(p.start, p); partToNext.put(p, new ArrayList<>()); partToNext.get(p).addAll(p.nextParts); partToPrev.put(p, new ArrayList<>()); @@ -1141,6 +1142,29 @@ public class Graph { } } + for (GraphPart p : allParts) { + if (p.start == -1) { + continue; + } + GraphPart pr = partReplacements.containsKey(p) ? partReplacements.get(p) : p; + if (isPartEmpty(pr) && partToNext.get(pr).size() == 1) { + + GraphPart afterP = partToNext.get(pr).get(0); + while (partToPrev.get(afterP).contains(pr)) { + partToPrev.get(afterP).remove(pr); + } + + for (int i = 0; i < partToPrev.get(pr).size(); i++) { + GraphPart pp = partToPrev.get(pr).get(i); + partToNext.get(pp).remove(pr); + partToNext.get(pp).add(afterP); + partToPrev.get(afterP).add(pp); + } + partReplacements.put(pr, afterP); + + } + } + for (GraphException ex : exceptions) { exceptionParts.add(new GraphExceptionParts( partByIp.containsKey(ex.start) ? partByIp.get(ex.start) : null, @@ -1170,7 +1194,7 @@ public class Graph { Map> edgeToBranches = new HashMap<>(); opened.add(startPart); GraphPart start = startPart; - findGotoTargetsWalk(partToNext, partToPrev, new Reference<>(-2), new ArrayList<>(), new GraphPartEdge(startPart, startPart), opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets); + findGotoTargetsWalk(partReplacements, partToNext, partToPrev, new Reference<>(-2), new ArrayList<>(), new GraphPartEdge(startPart, startPart), opened, closed, closedBranches, exitEdges, backEdges, throwEdges, allowedThrowEdges, exceptionParts, edgeToBranches, start, gotoTargets); } private boolean isTryBegin(GraphPart part) { diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf b/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf index 8d9cf5ebe..dac9336b8 100644 Binary files a/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf and b/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf differ diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml index aa763d3a3..f0f38ee1c 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml +++ b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml @@ -16,7 +16,7 @@ CONFIG::timeStamp - '19.01.2021' + '20.01.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestGotos.as b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestGotos.as index 32db399b3..d82cb07a3 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestGotos.as +++ b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestGotos.as @@ -33,6 +33,7 @@ package tests { trace("z"); } + trace("after"); } return 89;