try to improve try..catch vs loops

This commit is contained in:
Jindra Petřík
2021-02-06 22:03:04 +01:00
parent 72f0c66aa7
commit 7644eddfd3
17 changed files with 559 additions and 384 deletions

View File

@@ -59,6 +59,7 @@ public class AVM2LocalData extends BaseLocalData {
public List<DottedChain> fullyQualifiedNames;
public List<ABCException> parsedExceptions = new ArrayList<>();
public List<Integer> parsedExceptionIds = new ArrayList<>();
//public Map<Integer, List<Integer>> finallyJumps;
/**
@@ -154,6 +155,7 @@ public class AVM2LocalData extends BaseLocalData {
defaultParts = localData.defaultParts;
finallyThrowParts = localData.finallyThrowParts;
inGetLoops = localData.inGetLoops;
parsedExceptionIds = localData.parsedExceptionIds;
}
public AVM2ConstantPool getConstants() {

View File

@@ -84,6 +84,7 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.ThrowState;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.model.AnyItem;
import com.jpexs.decompiler.graph.model.BreakItem;
@@ -160,7 +161,7 @@ public class AVM2Graph extends Graph {
}
@Override
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) throws InterruptedException {
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts, List<ThrowState> throwStates) throws InterruptedException {
AVM2LocalData avm2LocalData = ((AVM2LocalData) localData);
avm2LocalData.codeStats = avm2LocalData.code.getStats(avm2LocalData.abc, avm2LocalData.methodBody, avm2LocalData.methodBody.init_scope_depth, false);
getIgnoredSwitches((AVM2LocalData) localData, allParts);
@@ -171,10 +172,13 @@ public class AVM2Graph extends Graph {
for (GraphPart finallySwitchTarget : avm2LocalData.finallyJumps.values()) {
if (!avm2LocalData.defaultParts.values().contains(finallySwitchTarget)) {
finallySwitchTarget.throwParts.clear(); // having throwparts in these causes problems
for (ThrowState ts : throwStates) {
ts.throwingParts.remove(finallySwitchTarget);
}
//finallySwitchTarget.throwParts.clear(); // having throwparts in these causes problems
}
}
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = calculateLocalRegsUsage(avm2LocalData, integerSwitchesIps, path, allParts);
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = calculateLocalRegsUsage(throwStates, avm2LocalData, integerSwitchesIps, path, allParts);
avm2LocalData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos;
avm2LocalData.inGetLoops = true;
}
@@ -440,7 +444,7 @@ public class AVM2Graph extends Graph {
}
}
private void walkLocalRegsUsage(AVM2LocalData localData, Set<Integer> getLocalPos, GraphPart startPart, GraphPart part, Set<GraphPart> visited, int ip, int searchRegId) {
private void walkLocalRegsUsage(List<ThrowState> throwStates, AVM2LocalData localData, Set<Integer> getLocalPos, GraphPart startPart, GraphPart part, Set<GraphPart> visited, int ip, int searchRegId) {
if (visited.contains(part) && part != startPart) {
return;
}
@@ -510,24 +514,28 @@ public class AVM2Graph extends Graph {
//okay, proceed to finally block
} else if (targetPart.nextParts.size() == 1) {
//continue or break, definitely not a return, there won't be a register usage
walkLocalRegsUsage(localData, getLocalPos, startPart, targetPart.nextParts.get(0), visited, ip, searchRegId);
walkLocalRegsUsage(throwStates, localData, getLocalPos, startPart, targetPart.nextParts.get(0), visited, ip, searchRegId);
return;
} else {
return;
}
}
for (GraphPart p : part.nextParts) {
walkLocalRegsUsage(localData, getLocalPos, startPart, p, visited, p.start, searchRegId);
walkLocalRegsUsage(throwStates, localData, getLocalPos, startPart, p, visited, p.start, searchRegId);
}
} finally {
for (GraphPart p : part.throwParts) {
walkLocalRegsUsage(localData, getLocalPos, startPart, p, visited, p.start, searchRegId);
for (ThrowState ts : throwStates) {
if (ts.throwingParts.contains(part)) {
GraphPart p = ts.targetPart;
walkLocalRegsUsage(throwStates, localData, getLocalPos, startPart, p, visited, p.start, searchRegId);
}
}
}
}
//TODO: optimize this to make it faster!!!
public Map<Integer, Set<Integer>> calculateLocalRegsUsage(AVM2LocalData localData, Set<Integer> ignoredSwitches, String path, Set<GraphPart> allParts) {
public Map<Integer, Set<Integer>> calculateLocalRegsUsage(List<ThrowState> throwStates, AVM2LocalData localData, Set<Integer> ignoredSwitches, String path, Set<GraphPart> allParts) {
logger.log(Level.FINE, "--- {0} ---", path);
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = new TreeMap<>();
Map<GraphPart, GraphPart> reverseFinallyJumps = new HashMap<>();
@@ -557,7 +565,7 @@ public class AVM2Graph extends Graph {
if (part == null) { //might be last part of script (?)
continue;
}
walkLocalRegsUsage(localData, setLocalPosToGetLocalPos.get(ip), part, part, new HashSet<>(), ip + 1, setLocalPosToRegisterId.get(ip));
walkLocalRegsUsage(throwStates, localData, setLocalPosToGetLocalPos.get(ip), part, part, new HashSet<>(), ip + 1, setLocalPosToRegisterId.get(ip));
}
/*for (int ip : setLocalPosToGetLocalPos.keySet()) {
@@ -601,7 +609,7 @@ public class AVM2Graph extends Graph {
for (GraphPart p : allBlocks) {
if (avm2code.pos2adr(p.start) >= ex.start && avm2code.pos2adr(p.end) <= ex.end && targetPart != null) {
//Logger.getLogger(Graph.class.getName()).fine("ADDING throwpart " + target + " to " + p);
p.throwParts.add(targetPart);
//p.throwParts.add(targetPart);
//target.refs.add(p);
}
}
@@ -705,6 +713,31 @@ public class AVM2Graph extends Graph {
return ret;
}
private GraphPart firstPartOutsideWalk(GraphPart part, int startIp, int endIp, Set<GraphPart> visited) {
if (visited.contains(part)) {
return null;
}
visited.add(part);
if (part.start < startIp || part.start >= endIp) {
return part;
}
for (GraphPart n : part.nextParts) {
GraphPart r = firstPartOutsideWalk(n, startIp, endIp, visited);
if (r != null) {
return r;
}
}
return null;
}
private GraphPart searchFirstPartOutSideTryCatchSimple(ABCException ex, Collection<? extends GraphPart> allParts) {
int startIp = code.adr2pos(ex.start, true);
int endIp = code.adr2pos(ex.end, true);
GraphPart startPart = searchPart(startIp, allParts);
return firstPartOutsideWalk(startPart, startIp, endIp, new HashSet<>());
}
private GraphPart searchFirstPartOutSideTryCatch(AVM2LocalData localData, ABCException ex, List<Loop> loops, Collection<? extends GraphPart> allParts) {
LinkedHashSet<GraphPart> reachable = new LinkedHashSet<>();
int startIp = localData.code.adr2pos(ex.start, true);
@@ -722,7 +755,7 @@ public class AVM2Graph extends Graph {
subLocalData.finallyJumpsToFinallyIndex = new HashMap<>();
subLocalData.finallyThrowParts = new HashMap<>();
subLocalData.ignoredSwitches = new HashMap<>();
getReachableParts(subLocalData, startPart, reachable, loops);
getReachableParts(subLocalData, startPart, reachable, loops, new ArrayList<>() /*??*/);
for (GraphPart r : reachable) {
if (r.start < startIp || r.start >= endIp) {
@@ -739,43 +772,36 @@ public class AVM2Graph extends Graph {
return part;
}
private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, AVM2LocalData localData, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Set<GraphPart> allParts, TranslateStack stack, int staticOperation, String path) throws InterruptedException {
if (localData.parsedExceptions == null) {
localData.parsedExceptions = new ArrayList<>();
}
List<ABCException> parsedExceptions = localData.parsedExceptions;
if (localData.finallyJumps == null) {
localData.finallyJumps = new HashMap<>();
}
if (localData.ignoredSwitches == null) {
localData.ignoredSwitches = new HashMap<>();
}
long addr = avm2code.pos2adr(part.start); //avm2code.getAddrThroughJumpAndDebugLine(avm2code.pos2adr(part.start));
long maxEndAddr = -1;
List<ABCException> catchedExceptions = new ArrayList<>();
private void getCatchedExceptionIds(GraphPart part, List<Integer> previouslyCatchedExceptionIds, List<Integer> catchedExceptionIds, Reference<Integer> finallyIndex, Collection<? extends GraphPart> allParts,
List<Loop> loops, AVM2LocalData localData) {
long addr = avm2code.pos2adr(part.start);
long maxEndAddr = -1;
finallyIndex.setVal(-1);
int endIp = -1;
List<Integer> finnalysIndicesToBe = new ArrayList<>();
int realEndIp = -1;
maxEndAddr = -1;
for (int e = 0; e < body.exceptions.length; e++) {
long fixedExStart = avm2code.pos2adr(avm2code.adr2pos(body.exceptions[e].start, true));
long fixedExEnd = avm2code.pos2adr(avm2code.adr2pos(body.exceptions[e].end, true));
if (!previouslyCatchedExceptionIds.contains(e)) {
if (addr == fixedExStart) { //avm2code.getAddrThroughJumpAndDebugLine(fixedExStart)) {
ABCException ex = body.exceptions[e];
if (addr == fixedExStart) { //avm2code.getAddrThroughJumpAndDebugLine(fixedExStart)) {
ABCException ex = body.exceptions[e];
if (!parsedExceptions.contains(ex)) {
if (ex.isFinally()) {
finnalysIndicesToBe.add(e);
} else {
long endAddr = avm2code.getAddrThroughJumpAndDebugLine(fixedExEnd);
if (endAddr > maxEndAddr) {
catchedExceptions.clear();
catchedExceptionIds.clear();
maxEndAddr = avm2code.getAddrThroughJumpAndDebugLine(fixedExEnd);
endIp = avm2code.adr2pos(maxEndAddr);
realEndIp = avm2code.adr2pos(fixedExEnd);
catchedExceptions.add(body.exceptions[e]);
/*endIp = avm2code.adr2pos(maxEndAddr);
realEndIp = avm2code.adr2pos(fixedExEnd);*/
catchedExceptionIds.add(e);
} else if (endAddr == maxEndAddr) {
catchedExceptions.add(body.exceptions[e]);
catchedExceptionIds.add(e);
}
}
}
@@ -783,8 +809,7 @@ public class AVM2Graph extends Graph {
}
//GraphPart endPart = searchPart(endIp, allParts);
int finallyIndex = -1;
ABCException finallyException = null;
//finallyIndex.setVal(-1);
Collections.sort(finnalysIndicesToBe, new Comparator<Integer>() {
@Override
@@ -793,48 +818,63 @@ public class AVM2Graph extends Graph {
}
});
/*if (catchedExceptions.isEmpty() && !finnalysIndicesToBe.isEmpty()) {
for (int i = 0; i < finnalysIndicesToBe.size(); i++) {
int e = finnalysIndicesToBe.get(i);
if (!localData.ignoredSwitches.containsKey(e)) {
catchedExceptions.add(body.exceptions[e]);
finnalysIndicesToBe.remove(i);
break;
}
}
}*/
GraphPart outSideExceptionPart = null;
if (!catchedExceptions.isEmpty()) {
outSideExceptionPart = searchFirstPartOutSideTryCatch(localData, catchedExceptions.get(0), loops, allParts);
if (!catchedExceptionIds.isEmpty()) {
outSideExceptionPart = searchFirstPartOutSideTryCatch(localData, body.exceptions[catchedExceptionIds.get(0)], loops, allParts);
}
for (int e : finnalysIndicesToBe) {
ABCException finallyExceptionToBe = body.exceptions[e];
if (catchedExceptions.isEmpty() || outSideExceptionPart == null) {
if (catchedExceptionIds.isEmpty() || outSideExceptionPart == null) {
//there's no exception, finally only
finallyIndex = e;
finallyException = finallyExceptionToBe;
finallyIndex.setVal(e);
break;
}
GraphPart outSideExceptionNonEmptyPart = nearestNonEmptyPart(outSideExceptionPart);
GraphPart outSideFinallyPart = searchFirstPartOutSideTryCatch(localData, finallyExceptionToBe, loops, allParts);
if (outSideExceptionNonEmptyPart == outSideFinallyPart) {
finallyIndex = e;
finallyException = finallyExceptionToBe;
finallyIndex.setVal(e);
break;
}
if (outSideExceptionNonEmptyPart.nextParts.size() == 1 && outSideExceptionNonEmptyPart.nextParts.get(0) == outSideFinallyPart) {
if (outSideExceptionNonEmptyPart.getHeight() == 1) {
if (avm2code.code.get(outSideExceptionNonEmptyPart.start).definition instanceof PushByteIns) {
finallyIndex = e;
finallyException = finallyExceptionToBe;
finallyIndex.setVal(e);
break;
}
}
}
}
}
private boolean checkTry(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, AVM2LocalData localData, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, Set<GraphPart> allParts, TranslateStack stack, int staticOperation, String path) throws InterruptedException {
if (localData.parsedExceptions == null) {
localData.parsedExceptions = new ArrayList<>();
}
if (localData.finallyJumps == null) {
localData.finallyJumps = new HashMap<>();
}
if (localData.ignoredSwitches == null) {
localData.ignoredSwitches = new HashMap<>();
}
List<ABCException> parsedExceptions = localData.parsedExceptions;
List<Integer> parsedExceptionIds = localData.parsedExceptionIds;
List<Integer> catchedExceptionIds = new ArrayList<>();
Reference<Integer> finallyIndexRef = new Reference<>(-1);
getCatchedExceptionIds(part, parsedExceptionIds, catchedExceptionIds, finallyIndexRef, allParts, loops, localData);
List<ABCException> catchedExceptions = new ArrayList<>();
for (int e : catchedExceptionIds) {
catchedExceptions.add(body.exceptions[e]);
}
ABCException finallyException = null;
int finallyIndex = finallyIndexRef.getVal();
if (finallyIndex > -1) {
finallyException = body.exceptions[finallyIndex];
}
if (finallyException != null) {
catchedExceptions.add(finallyException);
@@ -846,10 +886,24 @@ public class AVM2Graph extends Graph {
}
if (catchedExceptions.size() > 0) {
for (ThrowState ts : throwStates) {
if (catchedExceptionIds.contains(ts.exceptionId)) {
ts.state = 1;
}
if (ts.exceptionId == finallyIndex) {
ts.state = 1;
}
}
parsedExceptions.addAll(catchedExceptions);
parsedExceptionIds.addAll(catchedExceptionIds);
if (finallyException != null) {
catchedExceptions.remove(finallyException);
}
if (finallyIndex > -1) {
parsedExceptionIds.add(finallyIndex);
}
List<GraphTargetItem> tryCommands = new ArrayList<>();
List<List<GraphTargetItem>> catchCommands = new ArrayList<>();
List<GraphTargetItem> finallyCommands = new ArrayList<>();
@@ -863,13 +917,20 @@ public class AVM2Graph extends Graph {
}
if (partsToCalCommon.size() > 1) {
afterPart = getMostCommonPart(localData, partsToCalCommon, loops);
/*System.err.println("getting common part of");
for (GraphPart p : partsToCalCommon) {
System.err.println("- " + p);
}*/
afterPart = getMostCommonPart(localData, partsToCalCommon, loops, throwStates);
//System.err.println("result: " + afterPart);
}
if (catchedExceptions.size() > 0 && afterPart == null) {
//in all catches is probably continue/return/break or something
//we need to search a part which is first outside the try..block
afterPart = searchFirstPartOutSideTryCatch(localData, catchedExceptions.get(0), loops, allParts);
//System.err.println("oursidetrycatch: " + afterPart);
}
GraphPart exAfterPart = afterPart;
@@ -877,7 +938,7 @@ public class AVM2Graph extends Graph {
if (finallyException == null) {
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(afterPart);
tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, stopPart2, loops, staticOperation, path);
tryCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, part, stopPart2, loops, throwStates, staticOperation, path);
}
boolean inlinedFinally = false;
@@ -899,12 +960,15 @@ public class AVM2Graph extends Graph {
int targetPos = avm2code.adr2pos(finallyException.target);
finallyTryTargetPart = searchPart(targetPos, allParts);
//Is it wrong to assume try target is only single part before finally?
finallyPart = finallyTryTargetPart.nextParts.isEmpty() ? null : finallyTryTargetPart.nextParts.get(0);
List<GraphPart> finallyTargetStopPart = new ArrayList<>(stopPart);
//List<GraphPart> finallyTargetStopPart = new ArrayList<>(stopPart);
if (finallyPart != null) {
//finallyTargetStopPart
}
if (afterPart != null) {
finallyTargetStopPart.add(afterPart);
//finallyTargetStopPart.add(afterPart);
}
TranslateStack st2 = (TranslateStack) stack.clone();
@@ -912,8 +976,10 @@ public class AVM2Graph extends Graph {
st2.add(new ExceptionAVM2Item(finallyException));
AVM2LocalData localData2 = new AVM2LocalData(localData);
localData2.scopeStack = new ScopeStack();
finallyTargetItems = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, null, finallyTryTargetPart, finallyTargetStopPart, loops, 0, path);
boolean targetHasThrow = false;
//We are assuming Finally target has only 1 part
finallyTargetItems = translatePart(localData, finallyTryTargetPart, st2, staticOperation, path);//printGraph(foundGotos, partCodes, partCodePos, visited, localData2, st2, allParts, null, finallyTryTargetPart, finallyTargetStopPart, loops, throwStates, 0, path);
//boolean targetHasThrow = false;
if (!finallyTargetItems.isEmpty() && (finallyTargetItems.get(finallyTargetItems.size() - 1) instanceof ThrowAVM2Item)) {
//ignore some usual commands at the beginning - these are ignored in ffdec later, but we need to check it's empty
@@ -940,7 +1006,7 @@ public class AVM2Graph extends Graph {
if (!isEmpty) { //there must be at least single command before Throw
inlinedFinally = true;
}
targetHasThrow = true;
//targetHasThrow = true;
}
List<GraphPart> tryStopPart = new ArrayList<>(stopPart);
@@ -948,23 +1014,27 @@ public class AVM2Graph extends Graph {
tryStopPart.add(finallyPart);
}
if (finallyPart == null && afterPart != null) {
tryStopPart.add(afterPart);
}
if (defaultPart != null) {
tryStopPart.add(defaultPart);
}
if (switchPart == null && inlinedFinally && afterPart == null) {
//switchPart == null && inlinedFinally &&
if (afterPart == null) {
afterPart = searchFirstPartOutSideTryCatch(localData, finallyException, loops, allParts);
if (afterPart != null) {
tryStopPart.add(afterPart);
}
if (afterPart != null) {
tryStopPart.add(afterPart);
}
if (switchPart != null) {
afterPart = defaultPart;
} else {
if (!inlinedFinally) {
afterPart = null;
}
}
tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, tryStopPart, loops, staticOperation, path);
tryCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, part, tryStopPart, loops, throwStates, staticOperation, path);
makeAllCommands(tryCommands, stack);
processIfs(tryCommands);
@@ -980,17 +1050,11 @@ public class AVM2Graph extends Graph {
finallyStopPart.add(switchPart);
}
if (finallyPart != null) {
finallyCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, finallyPart, finallyStopPart, loops, staticOperation, path);
finallyCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, finallyPart, finallyStopPart, loops, throwStates, staticOperation, path);
}
if (switchPart != null) {
finallyCommands.addAll(translatePart(localData, switchPart, stack, staticOperation, path));
stack.pop(); //value switched by lookupswitch
afterPart = defaultPart;
exAfterPart = afterPart;
} else {
if (!inlinedFinally) {
afterPart = null;
}
stack.pop(); //value switched by lookupswitch
}
}
@@ -1016,7 +1080,7 @@ public class AVM2Graph extends Graph {
stopPart2.add(defaultPart);
}
List<GraphTargetItem> currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, null, catchPart, stopPart2, loops, staticOperation, path);
List<GraphTargetItem> currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData2, st2, allParts, null, catchPart, stopPart2, loops, throwStates, staticOperation, path);
/*if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof SetLocalAVM2Item)) {
if (currentCatchCommands.get(0).value.getNotCoerced() instanceof ExceptionAVM2Item) {
currentCatchCommands.remove(0);
@@ -1031,6 +1095,15 @@ public class AVM2Graph extends Graph {
catchCommands.add(currentCatchCommands);
}
for (ThrowState ts : throwStates) {
if (catchedExceptionIds.contains(ts.exceptionId)) {
ts.state = 2;
}
if (ts.exceptionId == finallyIndex) {
ts.state = 2;
}
}
if (!inlinedFinally && catchCommands.isEmpty() && finallyCommands.isEmpty() && tryCommands.isEmpty()) {
return false;
}
@@ -1047,7 +1120,6 @@ public class AVM2Graph extends Graph {
return true;
}
TryAVM2Item tryItem = new TryAVM2Item(tryCommands, catchedExceptions, catchCommands, finallyCommands, "");
if (inlinedFinally) {
List<List<GraphTargetItem>> parentCatchCommands = new ArrayList<>();
@@ -1079,7 +1151,7 @@ public class AVM2Graph extends Graph {
if (finallyIndex > -1 && localData.finallyIndicesWithDoublePush.contains(finallyIndex)) {
stack.push(new AnyItem());
}
currentRet.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, afterPart, stopPart, loops, staticOperation, path));
currentRet.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, afterPart, stopPart, loops, throwStates, staticOperation, path));
}
return true;
}
@@ -1087,7 +1159,22 @@ public class AVM2Graph extends Graph {
}
@Override
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops) {
protected boolean canHandleVisited(BaseLocalData localData, GraphPart part) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
for (ABCException ex : body.exceptions) {
if (aLocalData.parsedExceptions.contains(ex)) {
continue;
}
int fixStart = avm2code.adr2pos(ex.start, true);
if (part.start == fixStart) {
return false;
}
}
return true;
}
@Override
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates) {
Loop toBeLoop = null;
for (Loop el : loops) {
if ((el.loopContinue == part) && (el.phase == 0)) {
@@ -1124,15 +1211,14 @@ public class AVM2Graph extends Graph {
return true;
}
@Override
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
return checkTry(currentRet, foundGotos, partCodes, partCodePos, aLocalData, part, stopPart, loops, allParts, stack, staticOperation, path);
return checkTry(currentRet, foundGotos, partCodes, partCodePos, visited, aLocalData, part, stopPart, loops, throwStates, allParts, stack, staticOperation, path);
}
@Override
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = null;
/*if (ret != null) {
@@ -1218,13 +1304,15 @@ public class AVM2Graph extends Graph {
} else {
part = part.nextParts.get(1);
GraphPart defaultPart = part;
if (code.size() > defaultPart.start && ((AVM2Instruction) code.get(defaultPart.start)).definition instanceof JumpIns) {
if (code.size() > defaultPart.start && ((AVM2Instruction) code.get(defaultPart.start)).definition instanceof JumpIns
&& defaultPart.refs.size() == 1
&& !partIsLoopContBrePre(defaultPart, loops, throwStates)) {
defaultPart = defaultPart.nextParts.get(0);
}
Reference<GraphPart> nextRef = new Reference<>(null);
Reference<GraphTargetItem> tiRef = new Reference<>(null);
SwitchItem sw = handleSwitch(switchedObject, switchStartItem, foundGotos, partCodes, partCodePos, allParts, stack, stopPart, loops, localData, staticOperation, path, caseValuesMap, defaultPart, caseBodyParts, nextRef, tiRef);
SwitchItem sw = handleSwitch(switchedObject, switchStartItem, foundGotos, partCodes, partCodePos, visited, allParts, stack, stopPart, loops, throwStates, localData, staticOperation, path, caseValuesMap, defaultPart, caseBodyParts, nextRef, tiRef);
ret = new ArrayList<>();
ret.addAll(output);
checkSwitch(localData, sw, otherSide, ret.isEmpty() ? currentRet : ret /*hack :-(*/);
@@ -1233,7 +1321,7 @@ public class AVM2Graph extends Graph {
if (tiRef.getVal() != null) {
ret.add(tiRef.getVal());
} else {
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, nextRef.getVal(), stopPart, loops, staticOperation, path));
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, nextRef.getVal(), stopPart, loops, throwStates, staticOperation, path));
}
}
}
@@ -1348,7 +1436,7 @@ public class AVM2Graph extends Graph {
}
@Override
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
if (loopItem instanceof WhileItem) {
WhileItem w = (WhileItem) loopItem;
@@ -1812,8 +1900,8 @@ public class AVM2Graph extends Graph {
}
@Override
protected FinalProcessLocalData getFinalData(BaseLocalData localData, List<Loop> loops) {
FinalProcessLocalData finalProcess = super.getFinalData(localData, loops);
protected FinalProcessLocalData getFinalData(BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
FinalProcessLocalData finalProcess = super.getFinalData(localData, loops, throwStates);
finalProcess.registerUsage = ((AVM2LocalData) localData).setLocalPosToGetLocalPos;
return finalProcess;
}
@@ -1868,4 +1956,25 @@ public class AVM2Graph extends Graph {
}
return avm2code.code.get(part.end).definition instanceof LookupSwitchIns;
}
@Override
protected List<ThrowState> getThrowStates(Set<GraphPart> allParts) {
List<ThrowState> ret = new ArrayList<>();
for (int e = 0; e < body.exceptions.length; e++) {
ThrowState ts = new ThrowState();
ts.exceptionId = e;
ts.state = 0;
ts.targetPart = searchPart(code.adr2pos(body.exceptions[e].target), allParts);
int startIp = code.adr2pos(body.exceptions[e].start, true);
int endIp = code.adr2pos(body.exceptions[e].end, true);
for (GraphPart p : allParts) {
if (p.start >= startIp && p.start < endIp) {
ts.throwingParts.add(p);
}
}
ret.add(ts);
}
return ret;
}
}

View File

@@ -48,6 +48,7 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.ThrowState;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
@@ -58,6 +59,7 @@ import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Reference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -288,7 +290,7 @@ public class ActionGraph extends Graph {
}
@Override
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
if (!output.isEmpty()) {
if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) {
StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1);
@@ -312,13 +314,11 @@ public class ActionGraph extends Graph {
}
List<GraphTargetItem> caseValuesMap = new ArrayList<>();
//int pos = 0;
StrictEqActionItem set = (StrictEqActionItem) stack.pop();
caseValuesMap.add(set.rightSide);
if (set.leftSide instanceof StoreRegisterActionItem) {
switchedObject = ((StoreRegisterActionItem) set.leftSide).value;
}
//GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0);
List<GraphPart> caseBodyParts = new ArrayList<>();
caseBodyParts.add(part.nextParts.get(0));
GraphTargetItem top = null;
@@ -339,185 +339,23 @@ public class ActionGraph extends Graph {
} else {
part = part.nextParts.get(1);
GraphPart defaultPart = part;
if (code.size() > defaultPart.start && code.get(defaultPart.start) instanceof ActionJump) {
if (code.size() > defaultPart.start && code.get(defaultPart.start) instanceof ActionJump
&& defaultPart.refs.size() == 1
&& !partIsLoopContBrePre(defaultPart, loops, throwStates)) {
defaultPart = defaultPart.nextParts.get(0);
}
boolean hasDefault = false;
/*
case 4:
case 5:
default:
trace("5 & def");
...
case 6:
*/
//must go backwards to hit case 5, not case 4
for (int i = caseBodyParts.size() - 1; i >= 0; i--) {
if (caseBodyParts.get(i) == defaultPart) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i + 1, di);
caseBodyParts.add(i + 1, defaultPart);
hasDefault = true;
break;
}
}
if (!hasDefault) {
/*
case 1:
trace("1");
case 2:
trace("2"); //no break
default:
trace("def");
...
case 3:
*/
//must go backwards to hit case 2, not case 1
for (int i = caseBodyParts.size() - 1; i >= 0; i--) {
if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops, false)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i + 1, di);
caseBodyParts.add(i + 1, defaultPart);
hasDefault = true;
break;
}
}
}
if (!hasDefault) {
/*
case 1:
trace("1");
break;
default:
trace("def"); //no break
case 2:
trace("2");
*/
for (int i = 0; i < caseBodyParts.size(); i++) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, false)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i, di);
caseBodyParts.add(i, defaultPart);
hasDefault = true;
break;
}
}
}
if (!hasDefault) {
/*
case 1:
...
case 2:
...
default:
trace("def");
*/
caseValuesMap.add(new DefaultItem());
caseBodyParts.add(defaultPart);
}
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops);
//removeEdgeToFromList(gotoTargets, breakPart);
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = breakPart;
GraphTargetItem ti = checkLoop(new ArrayList<GraphTargetItem>(), next, stopPart, loops);
//create switch as new loop break command detection to work
currentLoop = new Loop(loops.size(), null, next);
currentLoop.phase = 1;
loops.add(currentLoop);
List<Integer> valuesMapping = new ArrayList<>();
List<GraphPart> caseBodies = new ArrayList<>();
for (int i = 0; i < caseValuesMap.size(); i++) {
GraphPart cur = caseBodyParts.get(i);
if (!caseBodies.contains(cur)) {
//removeEdgeToFromList(gotoTargets, cur);
caseBodies.add(cur);
}
valuesMapping.add(caseBodies.indexOf(cur));
}
for (int i = 0; i < caseBodies.size(); i++) {
List<GraphTargetItem> currentCaseCommands = new ArrayList<>();
GraphPart nextCase = next;
if (next != null) {
if (i < caseBodies.size() - 1) {
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, false)) {
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
} else {
nextCase = caseBodies.get(i + 1);
}
}
}
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
for (GraphPart b : caseBodies) {
if (b != caseBodies.get(i)) {
stopPart2x.add(b);
}
}
if (breakPart != null) {
stopPart2x.add(breakPart);
}
currentCaseCommands.addAll(0, printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path));
if (currentCaseCommands.size() >= 2) {
if (currentCaseCommands.get(currentCaseCommands.size() - 1) instanceof BreakItem) {
if ((currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof ContinueItem) || (currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof BreakItem)) {
currentCaseCommands.remove(currentCaseCommands.size() - 1);
}
}
}
caseCommands.add(currentCaseCommands);
}
//If the lastone is default empty and alone, remove it
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
lastc.remove(lastc.size() - 1);
}
if (lastc.isEmpty()) {
int cnt2 = 0;
if (caseValuesMap.get(caseValuesMap.size() - 1) instanceof DefaultItem) {
for (int i = valuesMapping.size() - 1; i >= 0; i--) {
if (valuesMapping.get(i) == caseCommands.size() - 1) {
cnt2++;
}
}
caseValuesMap.remove(caseValuesMap.size() - 1);
valuesMapping.remove(valuesMapping.size() - 1);
if (cnt2 == 1) {
caseCommands.remove(lastc);
}
}
}
}
//remove last break from last section
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
lastc.remove(lastc.size() - 1);
}
}
Reference<GraphPart> nextRef = new Reference<>(null);
Reference<GraphTargetItem> tiRef = new Reference<>(null);
SwitchItem sw = handleSwitch(switchedObject, switchStartItem, foundGotos, partCodes, partCodePos, visited, allParts, stack, stopPart, loops, throwStates, localData, staticOperation, path, caseValuesMap, defaultPart, caseBodyParts, nextRef, tiRef);
ret = new ArrayList<>();
ret.addAll(output);
SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping);
ret.add(sti);
currentLoop.phase = 2;
if (next != null) {
if (ti != null) {
ret.add(ti);
ret.add(sw);
if (nextRef.getVal() != null) {
if (tiRef.getVal() != null) {
ret.add(tiRef.getVal());
} else {
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, next, stopPart, loops, staticOperation, path));
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, nextRef.getVal(), stopPart, loops, throwStates, staticOperation, path));
}
}
}

View File

@@ -179,12 +179,12 @@ public class Graph {
}
}
protected void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops) {
protected void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops, List<ThrowState> throwStates) {
// use LinkedHashSet to preserve order
getReachableParts(localData, part, ret, loops, true);
getReachableParts(localData, part, ret, loops, throwStates, true);
}
private void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops, boolean first) {
private void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops, List<ThrowState> throwStates, boolean first) {
// todo: honfika: why call with first = true parameter always?
Stack<GraphPartQueue> stack = new Stack<>();
GraphPartQueue queue = new GraphPartQueue();
@@ -237,8 +237,18 @@ public class Graph {
}
GraphPartQueue newParts = new GraphPartQueue();
List<GraphPart> nextParts = new ArrayList<>(getNextParts(localData, part));
/*
!!THROW
for (ThrowState ts : throwStates) {
if (ts.state != 1) {
if (ts.throwingParts.contains(part)) {
newParts.add(ts.targetPart);
}
}
}*/
loopnext:
for (GraphPart nextRaw : getNextParts(localData, part)) {
for (GraphPart nextRaw : nextParts) {
GraphPart next = checkPart(null, localData, part, nextRaw, null);
if (next == null) {
@@ -275,12 +285,12 @@ public class Graph {
}
}
public GraphPart getNextCommonPart(BaseLocalData localData, GraphPart part, List<Loop> loops) throws InterruptedException {
return getCommonPart(localData, part, getNextParts(localData, part), loops);
public GraphPart getNextCommonPart(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates) throws InterruptedException {
return getCommonPart(localData, part, getNextParts(localData, part), loops, throwStates);
}
//TODO: Make this faster!
public GraphPart getCommonPart(BaseLocalData localData, GraphPart prev, List<GraphPart> parts, List<Loop> loops) throws InterruptedException {
public GraphPart getCommonPart(BaseLocalData localData, GraphPart prev, List<GraphPart> parts, List<Loop> loops, List<ThrowState> throwStates) throws InterruptedException {
if (parts.isEmpty()) {
return null;
}
@@ -304,7 +314,7 @@ public class Graph {
if (q == p) {
continue;
}
if (!q.leadsTo(localData, this, code, p, loops, false)) {
if (!q.leadsTo(localData, this, code, p, loops, throwStates, false /*!!THROW*/)) {
common = false;
break;
}
@@ -316,7 +326,7 @@ public class Graph {
List<Set<GraphPart>> reachable = new ArrayList<>();
for (GraphPart p : parts) {
LinkedHashSet<GraphPart> r1 = new LinkedHashSet<>();
getReachableParts(localData, p, r1, loops);
getReachableParts(localData, p, r1, loops, throwStates);
r1.add(p);
reachable.add(r1);
}
@@ -339,7 +349,7 @@ public class Graph {
return null;
}
public GraphPart getMostCommonPart(BaseLocalData localData, List<GraphPart> parts, List<Loop> loops) throws InterruptedException {
public GraphPart getMostCommonPart(BaseLocalData localData, List<GraphPart> parts, List<Loop> loops, List<ThrowState> throwStates) throws InterruptedException {
if (parts.isEmpty()) {
return null;
}
@@ -364,7 +374,7 @@ public class Graph {
if (q == p) {
continue;
}
if (!q.leadsTo(localData, this, code, p, loops, false)) {
if (!q.leadsTo(localData, this, code, p, loops, throwStates, false /*!!THROW*/)) {
common = false;
break;
}
@@ -391,7 +401,7 @@ public class Graph {
Set<GraphPart> allReachable = new LinkedHashSet<>();
for (GraphPart p : parts) {
LinkedHashSet<GraphPart> r1 = new LinkedHashSet<>();
getReachableParts(localData, p, r1, loops);
getReachableParts(localData, p, r1, loops, throwStates);
Set<GraphPart> r2 = new LinkedHashSet<>();
r2.add(p);
r2.addAll(r1);
@@ -472,6 +482,10 @@ public class Graph {
}
protected List<ThrowState> getThrowStates(Set<GraphPart> allParts) {
return new ArrayList<>();
}
public List<GraphTargetItem> translate(BaseLocalData localData, int staticOperation, String path) throws InterruptedException {
Set<GraphPart> allParts = new HashSet<>();
@@ -499,10 +513,12 @@ public class Graph {
System.err.println("/parts");
}
TranslateStack stack = new TranslateStack(path);
beforeGetLoops(localData, path, allParts);
List<ThrowState> throwStates = getThrowStates(allParts);
beforeGetLoops(localData, path, allParts, throwStates);
List<Loop> loops = new ArrayList<>();
getLoops(localData, heads.get(0), loops, null);
getLoops(localData, heads.get(0), loops, throwStates, null);
afterGetLoops(localData, path, allParts);
if (debugPrintLoopList) {
@@ -514,7 +530,7 @@ public class Graph {
}
//TODO: Make getPrecontinues faster
getBackEdges(localData, loops);
getBackEdges(localData, loops, throwStates);
new GraphPrecontinueDetector().detectPrecontinues(heads, allParts, loops);
@@ -525,7 +541,7 @@ public class Graph {
System.err.println("</loopspre>");//*/
List<GotoItem> gotos = new ArrayList<>();
List<GraphTargetItem> ret = printGraph(gotos, new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path);
List<GraphTargetItem> ret = printGraph(gotos, new HashMap<>(), new HashMap<>(), new HashSet<>(), localData, stack, allParts, null, heads.get(0), null, loops, throwStates, staticOperation, path);
processIfGotos(gotos, ret);
@@ -548,15 +564,15 @@ public class Graph {
processIfs(ret);
finalProcessStack(stack, ret, path);
makeAllCommands(ret, stack);
finalProcessAll(ret, 0, getFinalData(localData, loops), path);
finalProcessAll(ret, 0, getFinalData(localData, loops, throwStates), path);
return ret;
}
protected FinalProcessLocalData getFinalData(BaseLocalData localData, List<Loop> loops) {
protected FinalProcessLocalData getFinalData(BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
return new FinalProcessLocalData(loops);
}
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) throws InterruptedException {
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts, List<ThrowState> throwStates) throws InterruptedException {
}
@@ -598,7 +614,7 @@ public class Graph {
return getUnicatePartList(result);
}
private List<GraphPart> getUsableRefs(GraphPart g, List<Loop> loops) {
private List<GraphPart> getUsableRefs(GraphPart g, List<Loop> loops, List<ThrowState> throwStates) {
List<GraphPart> ret = getUnicatePartList(g.refs);
for (Loop el : loops) {
for (GraphPart be : el.backEdges) {
@@ -613,13 +629,13 @@ public class Graph {
/**/
//if (getNextParts(localData, ref))
private void getBackEdges(BaseLocalData localData, List<Loop> loops) throws InterruptedException {
private void getBackEdges(BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) throws InterruptedException {
clearLoops(loops);
for (Loop el : loops) {
el.backEdges.clear();
Set<GraphPart> uniqueRefs = new HashSet<>(el.loopContinue.refs);
for (GraphPart r : uniqueRefs) {
if (el.loopContinue.leadsTo(localData, this, code, r, loops, true)) {
if (el.loopContinue.leadsTo(localData, this, code, r, loops, throwStates, true)) {
el.backEdges.add(r);
}
}
@@ -985,7 +1001,7 @@ public class Graph {
return ret;
}
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, GraphPart part, List<GraphPart> stopPart, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates) {
if (stopPart.contains(part)) {
return null;
}
@@ -1045,7 +1061,7 @@ public class Graph {
return false;
}
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
return null;
}
@@ -1125,11 +1141,11 @@ public class Graph {
list.remove(list.size() - 1);
}
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, int staticOperation, String path) throws InterruptedException {
return printGraph(foundGotos, partCodes, partCodePos, new HashSet<>(), localData, stack, allParts, parent, part, stopPart, loops, null, staticOperation, path, 0);
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, int staticOperation, String path) throws InterruptedException {
return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, loops, throwStates, null, staticOperation, path, 0);
}
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
return loopItem;
}
@@ -1139,9 +1155,9 @@ public class Graph {
}
}
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<GraphPart> stopPart) throws InterruptedException {
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart) throws InterruptedException {
clearLoops(loops);
getLoops(localData, part, loops, stopPart, true, 1, new ArrayList<>());
getLoops(localData, part, loops, throwStates, stopPart, true, 1, new ArrayList<>());
clearLoops(loops);
}
@@ -1149,7 +1165,11 @@ public class Graph {
return true;
}
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<GraphPart> stopPart, boolean first, int level, List<GraphPart> visited) throws InterruptedException {
protected void checkGetLoopsPart(GraphPart part) {
}
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, List<GraphPart> stopPart, boolean first, int level, List<GraphPart> visited) throws InterruptedException {
if (part == null) {
return;
@@ -1162,6 +1182,7 @@ public class Graph {
if (!visited.contains(part)) {
visited.add(part);
}
checkGetLoopsPart(part);
if (debugGetLoops) {
System.err.println("getloops: " + part);
@@ -1187,7 +1208,7 @@ public class Graph {
} else {
List<Loop> loops2 = new ArrayList<>(loops);
loops2.remove(lastP1);
if (!part.leadsTo(localData, this, code, lastP1.loopContinue, loops2, true)) {
if (!part.leadsTo(localData, this, code, lastP1.loopContinue, loops2, throwStates, true)) {
if (lastP1.breakCandidatesLocked == 0) {
if (debugGetLoops) {
System.err.println("added breakCandidate " + part + " to " + lastP1);
@@ -1212,7 +1233,7 @@ public class Graph {
}
part.level = level;
boolean isLoop = part.leadsTo(localData, this, code, part, loops, true);
boolean isLoop = part.leadsTo(localData, this, code, part, loops, throwStates, true);
Loop currentLoop = null;
if (isLoop) {
currentLoop = new Loop(loops.size(), part, null);
@@ -1232,22 +1253,22 @@ public class Graph {
}*/
nps = part.nextParts;
GraphPart next = getCommonPart(localData, part, nps, loops);
GraphPart next = getCommonPart(localData, part, nps, loops, throwStates);
List<GraphPart> stopPart2 = stopPart == null ? new ArrayList<>() : new ArrayList<>(stopPart);
if (next != null) {
stopPart2.add(next);
}
if (next != nps.get(0)) {
getLoops(localData, nps.get(0), loops, stopPart2, false, level + 1, visited);
getLoops(localData, nps.get(0), loops, throwStates, stopPart2, false, level + 1, visited);
}
if (next != nps.get(1)) {
getLoops(localData, nps.get(1), loops, stopPart2, false, level + 1, visited);
getLoops(localData, nps.get(1), loops, throwStates, stopPart2, false, level + 1, visited);
}
if (next != null) {
getLoops(localData, next, loops, stopPart, false, level, visited);
getLoops(localData, next, loops, throwStates, stopPart, false, level, visited);
}
} else if (part.nextParts.size() > 2 || partIsSwitch(part)) {
GraphPart next = getNextCommonPart(localData, part, loops);
GraphPart next = getNextCommonPart(localData, part, loops, throwStates);
for (GraphPart p : part.nextParts) {
List<GraphPart> stopPart2 = stopPart == null ? new ArrayList<>() : new ArrayList<>(stopPart);
@@ -1263,23 +1284,27 @@ public class Graph {
}
}
if (next != p) {
getLoops(localData, p, loops, stopPart2, false, level + 1, visited);
getLoops(localData, p, loops, throwStates, stopPart2, false, level + 1, visited);
}
}
if (next != null) {
getLoops(localData, next, loops, stopPart, false, level, visited);
getLoops(localData, next, loops, throwStates, stopPart, false, level, visited);
}
} else if (part.nextParts.size() == 1) {
getLoops(localData, part.nextParts.get(0), loops, stopPart, false, level, visited);
getLoops(localData, part.nextParts.get(0), loops, throwStates, stopPart, false, level, visited);
}
List<Loop> loops2 = new ArrayList<>(loops);
for (Loop l : loops2) {
l.breakCandidatesLocked++;
}
for (GraphPart t : part.throwParts) {
if (!visited.contains(t)) {
getLoops(localData, t, loops, stopPart, false, level, visited);
for (ThrowState ts : throwStates) {
//check state?
if (ts.throwingParts.contains(part)) {
GraphPart t = ts.targetPart;
if (!visited.contains(t)) {
getLoops(localData, t, loops, throwStates, stopPart, false, level, visited);
}
}
}
for (Loop l : loops2) {
@@ -1304,7 +1329,7 @@ public class Graph {
if (cand == cand2) {
continue;
}
if (cand.leadsTo(localData, this, code, cand2, loops, true)) {
if (cand.leadsTo(localData, this, code, cand2, loops, throwStates, true)) {
int lev1 = Integer.MAX_VALUE;
int lev2 = Integer.MAX_VALUE;
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
@@ -1406,7 +1431,7 @@ public class Graph {
if (removedVisited.contains(r)) {
continue;
}
getLoops(localData, r, loops, stopPart, false, removed.get(r), visited);
getLoops(localData, r, loops, throwStates, stopPart, false, removed.get(r), visited);
removedVisited.add(r);
}
start = false;
@@ -1419,7 +1444,7 @@ public class Graph {
el.phase = 2;
}
}
getLoops(localData, currentLoop.loopBreak, loops, stopPart, false, level, visited);
getLoops(localData, currentLoop.loopBreak, loops, throwStates, stopPart, false, level, visited);
}
}
@@ -1444,14 +1469,36 @@ public class Graph {
return part.nextParts;
}
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
protected boolean checkPartOutput(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
return false;
}
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops) {
protected boolean partIsLoopContBrePre(GraphPart part, List<Loop> loops, List<ThrowState> throwStates) {
for (Loop el : loops) {
if (el.phase == 1) {
if (el.loopBreak == part) {
return true;
}
if (el.loopContinue == part) {
return true;
}
if (el.loopPreContinue == part) {
return true;
}
}
}
return false;
}
protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List<Loop> loops, List<ThrowState> throwStates) {
return true;
}
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
protected boolean canHandleVisited(BaseLocalData localData, GraphPart part) {
return true;
}
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
@@ -1465,8 +1512,8 @@ public class Graph {
if (ret == null) {
ret = new ArrayList<>();
}
//try {
//try {
if (debugPrintGraph) {
System.err.println("PART " + part + " nextsize:" + getNextParts(localData, part).size());
}
@@ -1499,7 +1546,7 @@ public class Graph {
boolean isLoop = false;
Loop currentLoop = null;
boolean vCanHandleLoop = canHandleLoop(localData, part, loops);
boolean vCanHandleLoop = canHandleLoop(localData, part, loops, throwStates);
Loop ignoredLoop = null;
for (Loop el : loops) {
if ((el.loopContinue == part) && (el.phase == 0)) {
@@ -1589,24 +1636,33 @@ public class Graph {
return ret;
}
if (visited.contains(part)) {
String labelName = "addr" + part.start;
List<GraphTargetItem> firstCode = partCodes.get(part);
int firstCodePos = partCodePos.get(part);
if (firstCodePos > firstCode.size()) {
firstCodePos = firstCode.size();
}
if (firstCode.size() > firstCodePos && (firstCode.get(firstCodePos) instanceof LabelItem)) {
labelName = ((LabelItem) firstCode.get(firstCodePos)).labelName;
boolean vCanHandleVisited = canHandleVisited(localData, part);
/*if (part.start == 31) {
FIXME
new RuntimeException().printStackTrace();
}*/
if (vCanHandleVisited) {
if (visited.contains(part)) {
String labelName = "addr" + part.start;
List<GraphTargetItem> firstCode = partCodes.get(part);
int firstCodePos = partCodePos.get(part);
if (firstCodePos > firstCode.size()) {
firstCodePos = firstCode.size();
}
if (firstCode.size() > firstCodePos && (firstCode.get(firstCodePos) instanceof LabelItem)) {
labelName = ((LabelItem) firstCode.get(firstCodePos)).labelName;
} else {
firstCode.add(firstCodePos, new LabelItem(null, localData.lineStartInstruction, labelName));
}
ret.add(new GotoItem(null, localData.lineStartInstruction, labelName));
return ret;
} else {
firstCode.add(firstCodePos, new LabelItem(null, localData.lineStartInstruction, labelName));
visited.add(part);
partCodes.put(part, ret);
partCodePos.put(part, ret.size());
}
ret.add(new GotoItem(null, localData.lineStartInstruction, labelName));
return ret;
} else {
visited.add(part);
partCodes.put(part, ret);
partCodePos.put(part, ret.size());
}
List<GraphTargetItem> currentRet = ret;
UniversalLoopItem loopItem = null;
@@ -1633,7 +1689,7 @@ public class Graph {
//****************************DECOMPILING PART*************
List<GraphTargetItem> output = new ArrayList<>();
if (checkPartOutput(currentRet, foundGotos, partCodes, partCodePos, code, localData, allParts, stack, parent, part, stopPart, loops, currentLoop, staticOperation, path)) {
if (checkPartOutput(currentRet, foundGotos, partCodes, partCodePos, visited, code, localData, allParts, stack, parent, part, stopPart, loops, throwStates, currentLoop, staticOperation, path)) {
parseNext = false;
} else {
output.addAll(code.translatePart(part, localData, stack, part.start, part.end, staticOperation, path));
@@ -1643,7 +1699,7 @@ public class Graph {
}
if (parseNext) {
List<GraphTargetItem> retCheck = check(currentRet, foundGotos, partCodes, partCodePos, code, localData, allParts, stack, parent, part, stopPart, loops, output, currentLoop, staticOperation, path);
List<GraphTargetItem> retCheck = check(currentRet, foundGotos, partCodes, partCodePos, visited, code, localData, allParts, stack, parent, part, stopPart, loops, throwStates, output, currentLoop, staticOperation, path);
if (retCheck != null) {
if (!retCheck.isEmpty()) {
currentRet.addAll(retCheck);
@@ -1811,7 +1867,7 @@ public class Graph {
}
Reference<GraphPart> nextRef = new Reference<>(null);
Reference<GraphTargetItem> tiRef = new Reference<>(null);
SwitchItem sw = handleSwitch(switchedItem, originalSwitchedItem.getSrc(), foundGotos, partCodes, partCodePos, allParts, stack, stopPart, loops, localData, staticOperation, path,
SwitchItem sw = handleSwitch(switchedItem, originalSwitchedItem.getSrc(), foundGotos, partCodes, partCodePos, visited, allParts, stack, stopPart, loops, throwStates, localData, staticOperation, path,
caseValues, defaultPart, caseBodyParts, nextRef, tiRef);
GraphPart next = nextRef.getVal();
checkSwitch(localData, sw, caseExpressionOtherSides.values(), currentRet);
@@ -1820,7 +1876,7 @@ public class Graph {
if (tiRef.getVal() != null) {
ret.add(tiRef.getVal());
} else {
currentRet.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1));
currentRet.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, throwStates, null, staticOperation, path, recursionLevel + 1));
}
}
pos++;
@@ -1839,7 +1895,7 @@ public class Graph {
nps = getNextParts(localData, part);
boolean isEmpty = nps.get(0) == nps.get(1);
GraphPart next = getCommonPart(localData, part, nps, loops);
GraphPart next = getCommonPart(localData, part, nps, loops, throwStates);
//System.err.println("on part " + part + ", next: " + next);
TranslateStack trueStack = (TranslateStack) stack.clone();
TranslateStack falseStack = (TranslateStack) stack.clone();
@@ -1866,12 +1922,12 @@ public class Graph {
List<GraphTargetItem> onTrue = new ArrayList<>();
if (!isEmpty && hasOntrue) {
onTrue = printGraph(foundGotos, partCodes, partCodePos, visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
onTrue = printGraph(foundGotos, partCodes, partCodePos, visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, throwStates, null, staticOperation, path, recursionLevel + 1);
}
List<GraphTargetItem> onFalse = new ArrayList<>();
if (!isEmpty && hasOnFalse) {
onFalse = printGraph(foundGotos, partCodes, partCodePos, visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
onFalse = printGraph(foundGotos, partCodes, partCodePos, visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, throwStates, null, staticOperation, path, recursionLevel + 1);
}
//List<GraphTargetItem> out2 = new ArrayList<>();
//makeAllCommands(out2, stack);
@@ -1974,7 +2030,7 @@ public class Graph {
}
//currentRet.addAll(out2);
if (next != null) {
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1);
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, throwStates, currentRet, staticOperation, path, recursionLevel + 1);
//currentRet.addAll();
}
}
@@ -1988,7 +2044,7 @@ public class Graph {
}
if (nextOnePart != null) {
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, getNextParts(localData, part).get(0), stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1);
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, getNextParts(localData, part).get(0), stopPart, loops, throwStates, currentRet, staticOperation, path, recursionLevel + 1);
}
}
@@ -2013,7 +2069,7 @@ public class Graph {
stopContPart.add(currentLoop.loopContinue);
GraphPart precoBackup = currentLoop.loopPreContinue;
currentLoop.loopPreContinue = null;
loopItem.commands.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, precoBackup, stopContPart, loops, null, staticOperation, path, recursionLevel + 1));
loopItem.commands.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, precoBackup, stopContPart, loops, throwStates, null, staticOperation, path, recursionLevel + 1));
checkContinueAtTheEnd(loopItem.commands, currentLoop);
}
}
@@ -2078,7 +2134,7 @@ public class Graph {
currentLoop.loopPreContinue = null;
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(currentLoop.loopContinue);
List<GraphTargetItem> precoCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
List<GraphTargetItem> precoCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, throwStates, null, staticOperation, path, recursionLevel + 1);
currentLoop.loopPreContinue = backup;
checkContinueAtTheEnd(precoCommands, currentLoop);
@@ -2171,7 +2227,7 @@ public class Graph {
currentLoop.loopPreContinue = null;
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(currentLoop.loopContinue);
List<GraphTargetItem> finalComm = printGraph(foundGotos, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
List<GraphTargetItem> finalComm = printGraph(foundGotos, partCodes, partCodePos, visited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, loops, throwStates, null, staticOperation, path, recursionLevel + 1);
currentLoop.loopPreContinue = backup;
checkContinueAtTheEnd(finalComm, currentLoop);
@@ -2211,7 +2267,7 @@ public class Graph {
}
currentLoop.phase = 2;
GraphTargetItem replaced = checkLoop(ret, li, localData, loops);
GraphTargetItem replaced = checkLoop(ret, li, localData, loops, throwStates);
if (replaced != li) {
int index = ret.indexOf(li);
ret.remove(index);
@@ -2221,7 +2277,7 @@ public class Graph {
}
if (currentLoop.loopBreak != null) {
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, null, staticOperation, path, recursionLevel + 1));
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, loops, throwStates, null, staticOperation, path, recursionLevel + 1));
}
}
@@ -2505,7 +2561,7 @@ public class Graph {
}
protected SwitchItem handleSwitch(GraphTargetItem switchedObject,
GraphSourceItem switchStartItem, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> allParts, TranslateStack stack, List<GraphPart> stopPart, List<Loop> loops, BaseLocalData localData, int staticOperation, String path,
GraphSourceItem switchStartItem, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, Set<GraphPart> allParts, TranslateStack stack, List<GraphPart> stopPart, List<Loop> loops, List<ThrowState> throwStates, BaseLocalData localData, int staticOperation, String path,
List<GraphTargetItem> caseValuesMap, GraphPart defaultPart, List<GraphPart> caseBodyParts, Reference<GraphPart> nextRef, Reference<GraphTargetItem> tiRef) throws InterruptedException {
boolean hasDefault = false;
/*
@@ -2541,7 +2597,7 @@ public class Graph {
*/
//must go backwards to hit case 2, not case 1
for (int i = caseBodyParts.size() - 1; i >= 0; i--) {
if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops, false)) {
if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops, throwStates, false)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i + 1, di);
caseBodyParts.add(i + 1, defaultPart);
@@ -2562,7 +2618,7 @@ public class Graph {
trace("2");
*/
for (int i = 0; i < caseBodyParts.size(); i++) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, false)) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, throwStates, false)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i, di);
caseBodyParts.add(i, defaultPart);
@@ -2586,13 +2642,13 @@ public class Graph {
}
//gotoTargets
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops);
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops, throwStates);
//removeEdgeToFromList(gotoTargets, breakPart);
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = breakPart;
GraphTargetItem ti = checkLoop(new ArrayList<>() /*??*/, next, stopPart, loops);
GraphTargetItem ti = checkLoop(new ArrayList<>() /*??*/, next, stopPart, loops, throwStates);
//create switch as new loop break command detection to work
Loop currentLoop = new Loop(loops.size(), null, next);
@@ -2614,13 +2670,13 @@ public class Graph {
GraphPart b = caseBodies.get(i);
for (int j = i + 1; j < caseBodies.size(); j++) {
GraphPart b2 = caseBodies.get(j);
if (b2.leadsTo(localData, this, code, b, loops, false)) {
if (b2.leadsTo(localData, this, code, b, loops, throwStates, false)) {
caseBodies.remove(j);
caseBodies.add(i, b2);
i--;
continue loopi;
} else if (j > i + 1) {
if (b.leadsTo(localData, this, code, b2, loops, false)) {
if (b.leadsTo(localData, this, code, b2, loops, throwStates, false)) {
caseBodies.remove(j);
caseBodies.add(i + 1, b2);
continue loopi;
@@ -2636,9 +2692,10 @@ public class Graph {
for (int i = 0; i < caseBodies.size(); i++) {
List<GraphTargetItem> currentCaseCommands = new ArrayList<>();
boolean willHaveBreak = false;
if (i < caseBodies.size() - 1) {
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, false)) {
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, throwStates, false)) {
willHaveBreak = true;
}
}
@@ -2651,11 +2708,12 @@ public class Graph {
if (breakPart != null) {
stopPart2x.add(breakPart);
}
currentCaseCommands.addAll(0, printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path));
if (currentCaseCommands.size() >= 2) {
if (currentCaseCommands.get(currentCaseCommands.size() - 1) instanceof BreakItem) {
if ((currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof ContinueItem) || (currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof BreakItem)) {
currentCaseCommands.remove(currentCaseCommands.size() - 1);
currentCaseCommands = printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, throwStates, staticOperation, path);
if (willHaveBreak) {
if (!currentCaseCommands.isEmpty()) {
GraphTargetItem last = currentCaseCommands.get(currentCaseCommands.size() - 1);
if (!(last instanceof ContinueItem) && !(last instanceof BreakItem) && !(last instanceof GotoItem) && !(last instanceof ExitItem) && !(last instanceof ScriptEndItem)) {
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
}
}
}

View File

@@ -74,7 +74,7 @@ public class GraphPart implements Serializable {
public int order;
public List<GraphPart> throwParts = new ArrayList<>();
//public List<GraphPart> throwParts = new ArrayList<>();
public enum StopPartType {
@@ -124,7 +124,7 @@ public class GraphPart implements Serializable {
return time;
}
private boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, boolean useThrow) throws InterruptedException {
private boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
@@ -134,7 +134,7 @@ public class GraphPart implements Serializable {
return false;
}
if (tpart != this) {
return tpart.leadsTo(localData, gr, code, null, part, visited, loops, useThrow);
return tpart.leadsTo(localData, gr, code, null, part, visited, loops, throwStates, useThrow);
}
Loop currentLoop = null;
for (Loop l : loops) {
@@ -171,27 +171,40 @@ public class GraphPart implements Serializable {
for (GraphPart p : nextParts) {
if (p == part) {
return true;
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, useThrow)) {
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
return true;
}
}
if (useThrow) {
for (GraphPart p : throwParts) {
if (p == part) {
return true;
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, useThrow)) {
return true;
if (useThrow)
for (ThrowState ts : throwStates) {
if (ts.state != 1) {
if (ts.throwingParts.contains(this)) {
GraphPart p = ts.targetPart;
if (p == part) {
return true;
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
return true;
}
}
}
}
/*if (useThrow) {
for (GraphPart p : throwParts) {
if (p == part) {
return true;
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
return true;
}
}
}*/
return false;
}
public boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart part, List<Loop> loops, boolean useThrow) throws InterruptedException {
public boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
for (Loop l : loops) {
l.leadsToMark = 0;
}
return leadsTo(localData, gr, code, null /*???*/, part, new HashSet<>(), loops, useThrow);
return leadsTo(localData, gr, code, null /*???*/, part, new HashSet<>(), loops, throwStates, useThrow);
}
public GraphPart(int start, int end) {

View File

@@ -0,0 +1,16 @@
package com.jpexs.decompiler.graph;
import java.util.HashSet;
import java.util.Set;
/**
*
* @author JPEXS
*/
public class ThrowState {
public int exceptionId;
public int state;
public Set<GraphPart> throwingParts = new HashSet<>();
public GraphPart targetPart;
}