mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-12 06:04:52 +00:00
Fixed: Try..catch.finally vs loops
This commit is contained in:
@@ -74,10 +74,20 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
public Map<Integer, GraphPart> finallyIndexToDefaultGraphPart = new HashMap<>();
|
||||
|
||||
//exception index => switchPart
|
||||
public Map<Integer, GraphPart> ignoredSwitches;
|
||||
public Map<Integer, GraphPart> ignoredSwitches = new HashMap<>();
|
||||
|
||||
/**
|
||||
* exception index -> switch defaultPart
|
||||
*/
|
||||
public Map<Integer, GraphPart> defaultParts = new HashMap<>();
|
||||
|
||||
public Map<Integer, Integer> switchedRegs = new HashMap<>();
|
||||
|
||||
/**
|
||||
* exception index -> switch throw part
|
||||
*/
|
||||
public Map<Integer, GraphPart> finallyThrowParts = new HashMap<>();
|
||||
|
||||
//switchedPart -> index of nextpart
|
||||
public Map<GraphPart, Integer> defaultWays = new HashMap<>();
|
||||
|
||||
@@ -99,6 +109,8 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
|
||||
public Set<Integer> finallyIndicesWithDoublePush = new HashSet<>();
|
||||
|
||||
public boolean inGetLoops = false;
|
||||
|
||||
public AVM2LocalData() {
|
||||
|
||||
}
|
||||
@@ -139,6 +151,9 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
finallyIndicesWithDoublePush = localData.finallyIndicesWithDoublePush;
|
||||
finallyJumpsToFinallyIndex = localData.finallyJumpsToFinallyIndex;
|
||||
finallyIndexToDefaultGraphPart = localData.finallyIndexToDefaultGraphPart;
|
||||
defaultParts = localData.defaultParts;
|
||||
finallyThrowParts = localData.finallyThrowParts;
|
||||
inGetLoops = localData.inGetLoops;
|
||||
}
|
||||
|
||||
public AVM2ConstantPool getConstants() {
|
||||
|
||||
@@ -154,16 +154,28 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) throws InterruptedException {
|
||||
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) 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);
|
||||
Set<Integer> integerSwitchesIps = new HashSet<>();
|
||||
for (GraphPart p : ((AVM2LocalData) localData).ignoredSwitches.values()) {
|
||||
for (GraphPart p : avm2LocalData.ignoredSwitches.values()) {
|
||||
integerSwitchesIps.add(p.end);
|
||||
}
|
||||
|
||||
for (GraphPart finallySwitchTarget : avm2LocalData.finallyJumps.values()) {
|
||||
if (!avm2LocalData.defaultParts.values().contains(finallySwitchTarget)) {
|
||||
finallySwitchTarget.throwParts.clear(); // having throwparts in these causes problems
|
||||
}
|
||||
}
|
||||
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = calculateLocalRegsUsage(avm2LocalData, integerSwitchesIps, path, allParts);
|
||||
avm2LocalData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos;
|
||||
avm2LocalData.inGetLoops = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) throws InterruptedException {
|
||||
((AVM2LocalData) localData).inGetLoops = false;
|
||||
}
|
||||
|
||||
private void getIgnoredSwitches(AVM2LocalData localData, Set<GraphPart> allParts) throws InterruptedException {
|
||||
@@ -199,12 +211,20 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
int switchedReg = -1;
|
||||
int finallyKind = FINALLY_KIND_UNKNOWN;
|
||||
Integer finallyThrowPushByte = null;
|
||||
if (finallyTryTargetStack.size() == 1) {
|
||||
finallyKind = FINALLY_KIND_STACK_BASED;
|
||||
if (finallyTryTargetStack.peek() instanceof IntegerValueAVM2Item) {
|
||||
finallyThrowPushByte = ((IntegerValueAVM2Item) finallyTryTargetStack.peek()).intValue();
|
||||
}
|
||||
} else if (targetOutput.size() >= 2
|
||||
&& (targetOutput.get(targetOutput.size() - 1) instanceof SetLocalAVM2Item)
|
||||
&& (targetOutput.get(targetOutput.size() - 2) instanceof SetLocalAVM2Item)) {
|
||||
switchedReg = ((SetLocalAVM2Item) targetOutput.get(targetOutput.size() - 1)).regIndex;
|
||||
SetLocalAVM2Item setLocal = ((SetLocalAVM2Item) targetOutput.get(targetOutput.size() - 1));
|
||||
switchedReg = setLocal.regIndex;
|
||||
if (setLocal.value instanceof IntegerValueAVM2Item) {
|
||||
finallyThrowPushByte = ((IntegerValueAVM2Item) setLocal.value).intValue();
|
||||
}
|
||||
finallyKind = FINALLY_KIND_REGISTER_BASED;
|
||||
} else if (!targetOutput.isEmpty() && (targetOutput.get(targetOutput.size() - 1) instanceof ThrowAVM2Item)) {
|
||||
//inlined to single part
|
||||
@@ -213,7 +233,7 @@ public class AVM2Graph extends Graph {
|
||||
} else {
|
||||
//probably inlined code in more parts, cannot do :-(
|
||||
}
|
||||
|
||||
Integer defaultPushByte = null;
|
||||
GraphPart switchPart = null;
|
||||
if (finallyKind == FINALLY_KIND_STACK_BASED) {
|
||||
/*
|
||||
@@ -259,6 +279,40 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int finEndIp = avm2code.adr2pos(ex.end);
|
||||
GraphPart finallyEndPart = searchPart(finEndIp, allParts);
|
||||
List<GraphPart> refs = getRealRefs(finallyEndPart);
|
||||
|
||||
if (refs.size() == 1) {
|
||||
GraphPart prev = refs.get(0);
|
||||
if (prev.getHeight() == 1) {
|
||||
if (avm2code.code.get(prev.start).definition instanceof PushByteIns) {
|
||||
defaultPushByte = avm2code.code.get(prev.start).operands[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defaultPushByte == null) {
|
||||
if (getRealRefs(finallyEndPart).size() == 0) {
|
||||
if (avm2code.code.get(finallyEndPart.start - 1).definition instanceof JumpIns) {
|
||||
GraphPart prevPart = searchPart(finallyEndPart.start - 1, allParts);
|
||||
finallyEndPart = prevPart.nextParts.get(0);
|
||||
if (finallyEndPart.nextParts.size() == 1 && finallyEndPart.nextParts.get(0).refs.size() > 1) {
|
||||
for (int j = finallyEndPart.start; j <= finallyEndPart.end; j++) {
|
||||
AVM2Instruction ins = avm2code.code.get(j);
|
||||
if (ins.definition instanceof NopIns) {
|
||||
|
||||
} else if (ins.definition instanceof PushByteIns) {
|
||||
defaultPushByte = ins.operands[0];
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (finallyKind == FINALLY_KIND_REGISTER_BASED) {
|
||||
switchPart = findLookupSwitchWithGetLocal(switchedReg, finallyPart);
|
||||
int startIp = code.adr2pos(ex.start);
|
||||
@@ -270,12 +324,7 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
if (tryPart != null) {
|
||||
List<GraphPart> tryPartRefs = new ArrayList<>(tryPart.refs);
|
||||
for (int i = tryPartRefs.size() - 1; i >= 0; i--) {
|
||||
if (tryPartRefs.get(i).start < 0) {
|
||||
tryPartRefs.remove(i);
|
||||
}
|
||||
}
|
||||
List<GraphPart> tryPartRefs = getRealRefs(tryPart);
|
||||
if (tryPartRefs.size() == 1) {
|
||||
GraphPart beforeTryPart = tryPartRefs.get(0);
|
||||
if (beforeTryPart.getHeight() > 2) {
|
||||
@@ -284,8 +333,7 @@ public class AVM2Graph extends Graph {
|
||||
if (setLocalRegister == switchedReg) {
|
||||
if (avm2code.code.get(beforeTryPart.end - 1).definition instanceof PushByteIns) {
|
||||
if (switchPart != null) {
|
||||
int defaultWay = avm2code.code.get(beforeTryPart.end - 1).operands[0];
|
||||
localData.defaultWays.put(switchPart, defaultWay);
|
||||
defaultPushByte = avm2code.code.get(beforeTryPart.end - 1).operands[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,6 +344,29 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
localData.switchedRegs.put(e, switchedReg);
|
||||
if (switchPart != null) {
|
||||
|
||||
localData.defaultWays.put(switchPart, defaultPushByte);
|
||||
|
||||
if (defaultPushByte != null) {
|
||||
GraphPart defaultPart;
|
||||
if (defaultPushByte == null || defaultPushByte < 0 || defaultPushByte > switchPart.nextParts.size() - 2) {
|
||||
defaultPart = switchPart.nextParts.get(0);
|
||||
} else {
|
||||
defaultPart = switchPart.nextParts.get(1 + defaultPushByte);
|
||||
}
|
||||
localData.defaultParts.put(e, defaultPart);
|
||||
}
|
||||
|
||||
if (finallyThrowPushByte != null) {
|
||||
GraphPart finnalyThrowPart;
|
||||
if (finallyThrowPushByte == null || finallyThrowPushByte < 0 || finallyThrowPushByte > switchPart.nextParts.size() - 2) {
|
||||
finnalyThrowPart = switchPart.nextParts.get(0);
|
||||
} else {
|
||||
finnalyThrowPart = switchPart.nextParts.get(1 + finallyThrowPushByte);
|
||||
}
|
||||
localData.finallyThrowParts.put(e, finnalyThrowPart);
|
||||
}
|
||||
|
||||
for (GraphPart r : finallyPart.refs) {
|
||||
GraphPart rr = r;
|
||||
boolean needsPrev = true;
|
||||
@@ -517,23 +588,17 @@ public class AVM2Graph extends Graph {
|
||||
@Override
|
||||
protected void checkGraph(List<GraphPart> allBlocks) {
|
||||
for (ABCException ex : body.exceptions) {
|
||||
/*int startAddr = avm2code.adr2pos(ex.start);
|
||||
int endAddr = avm2code.adr2pos(ex.end);
|
||||
int targetIp = avm2code.adr2pos(ex.target);*/
|
||||
GraphPart target = null;
|
||||
GraphPart targetPart = searchPart(avm2code.adr2pos(ex.target), allBlocks);
|
||||
for (GraphPart p : allBlocks) {
|
||||
if (avm2code.pos2adr(p.start) == ex.target) {
|
||||
target = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (GraphPart p : allBlocks) {
|
||||
if (avm2code.pos2adr(p.start) >= ex.start && avm2code.pos2adr(p.end) <= ex.end && target != null) {
|
||||
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(target);
|
||||
p.throwParts.add(targetPart);
|
||||
//target.refs.add(p);
|
||||
}
|
||||
}
|
||||
/*GraphPart startPart = searchPart(avm2code.adr2pos(ex.start), allBlocks);
|
||||
|
||||
startPart.throwParts.add(targetPart);*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,6 +713,7 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
int endIp = -1;
|
||||
List<Integer> finnalysIndicesToBe = new ArrayList<>();
|
||||
int realIp = -1;
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (addr == avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].start)) {
|
||||
ABCException ex = body.exceptions[e];
|
||||
@@ -660,6 +726,7 @@ public class AVM2Graph extends Graph {
|
||||
catchedExceptions.clear();
|
||||
maxEndAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end);
|
||||
endIp = avm2code.adr2pos(maxEndAddr);
|
||||
realIp = avm2code.adr2pos(body.exceptions[e].end);
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
} else if (endAddr == maxEndAddr) {
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
@@ -672,7 +739,6 @@ public class AVM2Graph extends Graph {
|
||||
//GraphPart endPart = searchPart(endIp, allParts);
|
||||
int finallyIndex = -1;
|
||||
ABCException finallyException = null;
|
||||
Integer defaultPushByte = null;
|
||||
|
||||
for (int e : finnalysIndicesToBe) {
|
||||
ABCException finallyExceptionToBe = body.exceptions[e];
|
||||
@@ -693,7 +759,6 @@ public class AVM2Graph extends Graph {
|
||||
|
||||
if (endPart.getHeight() == 1) {
|
||||
if (avm2code.code.get(endPart.start).definition instanceof PushByteIns) {
|
||||
/*defaultPushByte = avm2code.code.get(endPart.start).operands[0];*/
|
||||
int afterEndIp = avm2code.getIpThroughJumpAndDebugLine(endPart.nextParts.get(0).start);
|
||||
int afterFinEndIp = avm2code.getIpThroughJumpAndDebugLine(finEndPart.start);
|
||||
if (afterEndIp == afterFinEndIp) {
|
||||
@@ -706,39 +771,6 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
if (finallyException != null) {
|
||||
int finEndIp = avm2code.adr2pos(finallyException.end);
|
||||
GraphPart finallyEndPart = searchPart(finEndIp, allParts);
|
||||
List<GraphPart> refs = getRealRefs(finallyEndPart);
|
||||
if (refs.size() == 1) {
|
||||
GraphPart prev = refs.get(0);
|
||||
if (prev.getHeight() == 1) {
|
||||
if (avm2code.code.get(prev.start).definition instanceof PushByteIns) {
|
||||
defaultPushByte = avm2code.code.get(prev.start).operands[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defaultPushByte == null) {
|
||||
if (getRealRefs(finallyEndPart).size() == 0) {
|
||||
if (avm2code.code.get(finallyEndPart.start - 1).definition instanceof JumpIns) {
|
||||
GraphPart prevPart = searchPart(finallyEndPart.start - 1, allParts);
|
||||
finallyEndPart = prevPart.nextParts.get(0);
|
||||
if (finallyEndPart.nextParts.size() == 1 && finallyEndPart.nextParts.get(0).refs.size() > 1) {
|
||||
for (int j = finallyEndPart.start; j <= finallyEndPart.end; j++) {
|
||||
AVM2Instruction ins = avm2code.code.get(j);
|
||||
if (ins.definition instanceof NopIns) {
|
||||
|
||||
} else if (ins.definition instanceof PushByteIns) {
|
||||
defaultPushByte = ins.operands[0];
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catchedExceptions.add(finallyException);
|
||||
}
|
||||
|
||||
@@ -766,22 +798,19 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
afterPart = endIpPart;
|
||||
GraphPart realEndIpPart = searchPart(realIp, allParts);
|
||||
if (realEndIpPart != null && getRealRefs(realEndIpPart).isEmpty()) { //swftools - there is jump on previous ip
|
||||
if (avm2code.code.get(realEndIpPart.start - 1).definition instanceof JumpIns) {
|
||||
GraphPart prevPart = searchPart(realEndIpPart.start - 1, allParts);
|
||||
realEndIpPart = prevPart.nextParts.get(0);
|
||||
}
|
||||
}
|
||||
afterPart = realEndIpPart;
|
||||
|
||||
GraphPart exAfterPart = endIpPart;
|
||||
|
||||
stack.clear(); //If the original code (before check()) had "if" in it, there would be something on stack
|
||||
|
||||
if (switchedReg > -1) {
|
||||
//There is assignment to switched reg before entering try
|
||||
if (!currentRet.isEmpty() && (currentRet.get(currentRet.size() - 1) instanceof SetLocalAVM2Item)) {
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) currentRet.get(currentRet.size() - 1);
|
||||
if (setLocal.regIndex == switchedReg) {
|
||||
if (setLocal.value.getNotCoerced() instanceof IntegerValueAVM2Item) {
|
||||
defaultPushByte = (int) (long) ((IntegerValueAVM2Item) setLocal.value.getNotCoerced()).value;
|
||||
}
|
||||
currentRet.remove(currentRet.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finallyException == null) {
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
@@ -792,20 +821,14 @@ public class AVM2Graph extends Graph {
|
||||
boolean inlinedFinally = false;
|
||||
|
||||
List<GraphTargetItem> finallyTargetItems = new ArrayList<>();
|
||||
GraphPart exAfterPart = afterPart;
|
||||
|
||||
GraphPart defaultPart = null;
|
||||
GraphPart finallyPart = null;
|
||||
if (finallyException != null) {
|
||||
|
||||
if (defaultPushByte != null) {
|
||||
GraphPart switchPart = localData.ignoredSwitches.get(finallyIndex);
|
||||
if (switchPart != null) {
|
||||
if (defaultPushByte < 0 || defaultPushByte > switchPart.nextParts.size() - 2) {
|
||||
defaultPart = switchPart.nextParts.get(0);
|
||||
} else {
|
||||
defaultPart = switchPart.nextParts.get(1 + defaultPushByte);
|
||||
}
|
||||
localData.defaultWays.put(switchPart, defaultPushByte);
|
||||
}
|
||||
GraphPart switchPart = localData.ignoredSwitches.get(finallyIndex);
|
||||
if (switchPart != null) {
|
||||
defaultPart = localData.defaultParts.containsKey(finallyIndex) ? localData.defaultParts.get(finallyIndex) : null;
|
||||
}
|
||||
|
||||
localData.finallyIndexToDefaultGraphPart.put(finallyIndex, defaultPart);
|
||||
@@ -820,7 +843,7 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart finallyPart = finallyTryTargetPart.nextParts.isEmpty() ? null : finallyTryTargetPart.nextParts.get(0);
|
||||
finallyPart = finallyTryTargetPart.nextParts.isEmpty() ? null : finallyTryTargetPart.nextParts.get(0);
|
||||
|
||||
List<GraphPart> finallyTargetStopPart = new ArrayList<>(stopPart);
|
||||
if (endIpPart != null) {
|
||||
@@ -886,7 +909,6 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
List<GraphPart> finallyStopPart = new ArrayList<>(stopPart);
|
||||
GraphPart switchPart = localData.ignoredSwitches.containsKey(finallyIndex) ? localData.ignoredSwitches.get(finallyIndex) : null;
|
||||
if (switchPart != null) {
|
||||
finallyStopPart.add(switchPart);
|
||||
}
|
||||
@@ -896,16 +918,7 @@ public class AVM2Graph extends Graph {
|
||||
if (switchPart != null) {
|
||||
finallyCommands.addAll(translatePart(localData, switchPart, stack, staticOperation, path));
|
||||
stack.pop(); //value switched by lookupswitch
|
||||
if (localData.defaultWays.containsKey(switchPart)) {
|
||||
int defaultWay = localData.defaultWays.get(switchPart);
|
||||
if (defaultWay < 0 || defaultWay > switchPart.nextParts.size() - 2) {
|
||||
afterPart = switchPart.nextParts.get(0);
|
||||
} else {
|
||||
afterPart = switchPart.nextParts.get(1 + defaultWay);
|
||||
}
|
||||
} else {
|
||||
afterPart = switchPart.nextParts.get(0); //take the default branch. TODO: detect actual value
|
||||
}
|
||||
afterPart = defaultPart;
|
||||
exAfterPart = afterPart;
|
||||
}
|
||||
//stack.pop();
|
||||
@@ -952,6 +965,13 @@ public class AVM2Graph extends Graph {
|
||||
return null;
|
||||
}
|
||||
|
||||
//remove default assignment to switched register
|
||||
if (switchedReg != -1 && !currentRet.isEmpty()
|
||||
&& (currentRet.get(currentRet.size() - 1) instanceof SetLocalAVM2Item)
|
||||
&& (((SetLocalAVM2Item) currentRet.get(currentRet.size() - 1)).regIndex == switchedReg)) {
|
||||
currentRet.remove(currentRet.size() - 1);
|
||||
}
|
||||
|
||||
List<GraphTargetItem> ret = new ArrayList<>();
|
||||
if (!inlinedFinally && catchedExceptions.isEmpty() && finallyCommands.isEmpty()) {
|
||||
ret.addAll(tryCommands);
|
||||
@@ -981,7 +1001,6 @@ public class AVM2Graph extends Graph {
|
||||
if (finallyIndex > -1 && localData.finallyIndicesWithDoublePush.contains(finallyIndex)) {
|
||||
stack.push(new AnyItem());
|
||||
}
|
||||
|
||||
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, afterPart, stopPart, loops, staticOperation, path));
|
||||
}
|
||||
return ret;
|
||||
@@ -1123,10 +1142,15 @@ public class AVM2Graph extends Graph {
|
||||
aLocalData.ignoredSwitches = new HashMap<>();
|
||||
}
|
||||
|
||||
if (aLocalData.finallyThrowParts.containsValue(part)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
if (aLocalData.ignoredSwitches.containsValue(prev)) {
|
||||
if (!aLocalData.inGetLoops && aLocalData.ignoredSwitches.containsValue(prev)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (aLocalData.finallyJumps.containsKey(prev)) {
|
||||
GraphPart switchPart = null;
|
||||
int switchedReg = -1;
|
||||
@@ -1510,7 +1534,7 @@ public class AVM2Graph extends Graph {
|
||||
if ((list.get(i + 1) instanceof ThrowAVM2Item)
|
||||
&& (list.get(i + 1).value instanceof LocalRegAVM2Item)
|
||||
&& (((LocalRegAVM2Item) list.get(i + 1).value).regIndex == ri.regIndex)) {
|
||||
ThrowAVM2Item t = (ThrowAVM2Item) list.get(i + 2);
|
||||
ThrowAVM2Item t = (ThrowAVM2Item) list.get(i + 1);
|
||||
t.value = ri.value;
|
||||
list.remove(i);
|
||||
i--;
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppResources;
|
||||
@@ -867,6 +868,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
throw ex;
|
||||
} catch (Exception | OutOfMemoryError | StackOverflowError ex) {
|
||||
|
||||
ex.printStackTrace();
|
||||
convertException = ex;
|
||||
Throwable cause = ex.getCause();
|
||||
if (ex instanceof ExecutionException && cause instanceof Exception) {
|
||||
|
||||
@@ -377,7 +377,7 @@ public class ActionGraph extends 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)) {
|
||||
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);
|
||||
@@ -398,7 +398,7 @@ public class ActionGraph extends Graph {
|
||||
trace("2");
|
||||
*/
|
||||
for (int i = 0; i < caseBodyParts.size(); i++) {
|
||||
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops)) {
|
||||
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, false)) {
|
||||
DefaultItem di = new DefaultItem();
|
||||
caseValuesMap.add(i, di);
|
||||
caseBodyParts.add(i, defaultPart);
|
||||
@@ -448,7 +448,7 @@ public class ActionGraph extends Graph {
|
||||
GraphPart nextCase = next;
|
||||
if (next != null) {
|
||||
if (i < caseBodies.size() - 1) {
|
||||
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) {
|
||||
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);
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf7;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -35,6 +36,9 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.ExitItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
@@ -300,43 +304,51 @@ public class ActionTry extends Action implements GraphSourceItemContainer {
|
||||
catchExceptionTypes.add(co.constructor);
|
||||
if (body.get(pos + 1) instanceof IfItem) {
|
||||
IfItem ifi = (IfItem) body.get(pos + 1);
|
||||
IfItem ifi = (IfItem) body.get(pos + 1);
|
||||
if (!ifi.onTrue.isEmpty()) {
|
||||
if (ifi.onTrue.get(0) instanceof DefineLocalActionItem) {
|
||||
DefineLocalActionItem dl = (DefineLocalActionItem) ifi.onTrue.get(0);
|
||||
catchExceptionNames.add(dl.name);
|
||||
List<GraphTargetItem> catchBody = new ArrayList<>(ifi.onTrue);
|
||||
catchBody.remove(0);
|
||||
catchCommands.add(catchBody);
|
||||
if (!ifi.onFalse.isEmpty()) {
|
||||
if (ifi.onFalse.get(0) instanceof PopItem) {
|
||||
pos = 1;
|
||||
body = ifi.onFalse;
|
||||
continue loopex;
|
||||
} else {
|
||||
break;
|
||||
List<GraphTargetItem> onFalse = ifi.onFalse;
|
||||
int onFalsePos = 0;
|
||||
if (ifi.onFalse.isEmpty() && !ifi.onTrue.isEmpty() && ((ifi.onTrue.get(ifi.onTrue.size() - 1) instanceof ExitItem)
|
||||
|| (ifi.onTrue.get(ifi.onTrue.size() - 1) instanceof BreakItem)
|
||||
|| (ifi.onTrue.get(ifi.onTrue.size() - 1) instanceof ContinueItem))) {
|
||||
onFalse = body;
|
||||
onFalsePos = pos + 2;
|
||||
}
|
||||
|
||||
if (!ifi.onTrue.isEmpty() && (ifi.onTrue.get(0) instanceof DefineLocalActionItem)) {
|
||||
DefineLocalActionItem dl = (DefineLocalActionItem) ifi.onTrue.get(0);
|
||||
catchExceptionNames.add(dl.name);
|
||||
List<GraphTargetItem> catchBody = new ArrayList<>(ifi.onTrue);
|
||||
catchBody.remove(0);
|
||||
catchCommands.add(catchBody);
|
||||
if (onFalse.size() > onFalsePos) {
|
||||
if (onFalse.get(onFalsePos) instanceof PopItem) {
|
||||
pos = onFalsePos + 1;
|
||||
body = onFalse;
|
||||
continue loopex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*if (body.size() == pos + 4) {
|
||||
if (body.get(pos + 2) instanceof PopItem) {
|
||||
if (body.get(pos + 3) instanceof ThrowActionItem) {
|
||||
ThrowActionItem ta = (ThrowActionItem) body.get(pos + 3);
|
||||
if (ta.value instanceof DirectValueActionItem) {
|
||||
if (((DirectValueActionItem) ta.value).value instanceof RegisterNumber) {
|
||||
RegisterNumber rn2 = (RegisterNumber) ((DirectValueActionItem) ta.value).value;
|
||||
if (rn2.number == catchRegister) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (onFalse.size() > onFalsePos && (onFalse.get(onFalsePos) instanceof DefineLocalActionItem)) {
|
||||
DefineLocalActionItem dl = (DefineLocalActionItem) onFalse.get(onFalsePos);
|
||||
catchExceptionNames.add(dl.name);
|
||||
|
||||
List<GraphTargetItem> catchBody = new ArrayList<>();
|
||||
for (int i = onFalsePos; i < onFalse.size(); i++) {
|
||||
catchBody.add(onFalse.get(i));
|
||||
}
|
||||
catchBody.remove(0);
|
||||
catchCommands.add(catchBody);
|
||||
if (!ifi.onTrue.isEmpty()) {
|
||||
if (ifi.onTrue.get(0) instanceof PopItem) {
|
||||
pos = 1;
|
||||
body = ifi.onTrue;
|
||||
continue loopex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ public class Graph {
|
||||
if (q == p) {
|
||||
continue;
|
||||
}
|
||||
if (!q.leadsTo(localData, this, code, p, loops)) {
|
||||
if (!q.leadsTo(localData, this, code, p, loops, false)) {
|
||||
common = false;
|
||||
break;
|
||||
}
|
||||
@@ -364,7 +364,7 @@ public class Graph {
|
||||
if (q == p) {
|
||||
continue;
|
||||
}
|
||||
if (!q.leadsTo(localData, this, code, p, loops)) {
|
||||
if (!q.leadsTo(localData, this, code, p, loops, false)) {
|
||||
common = false;
|
||||
break;
|
||||
}
|
||||
@@ -499,10 +499,12 @@ public class Graph {
|
||||
System.err.println("/parts");
|
||||
}
|
||||
TranslateStack stack = new TranslateStack(path);
|
||||
beforeGetLoops(localData, path, allParts);
|
||||
List<Loop> loops = new ArrayList<>();
|
||||
|
||||
getLoops(localData, heads.get(0), loops, null);
|
||||
|
||||
afterGetLoops(localData, path, allParts);
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("<loops>");
|
||||
for (Loop el : loops) {
|
||||
@@ -523,7 +525,6 @@ public class Graph {
|
||||
System.err.println("</loopspre>");//*/
|
||||
List<GotoItem> gotos = new ArrayList<>();
|
||||
|
||||
beforePrintGraph(localData, path, allParts, loops);
|
||||
List<GraphTargetItem> ret = printGraph(gotos, new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path);
|
||||
|
||||
processIfGotos(gotos, ret);
|
||||
@@ -555,7 +556,11 @@ public class Graph {
|
||||
return new FinalProcessLocalData(loops);
|
||||
}
|
||||
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) throws InterruptedException {
|
||||
protected void beforeGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) throws InterruptedException {
|
||||
|
||||
}
|
||||
|
||||
protected void afterGetLoops(BaseLocalData localData, String path, Set<GraphPart> allParts) throws InterruptedException {
|
||||
|
||||
}
|
||||
|
||||
@@ -614,7 +619,7 @@ public class Graph {
|
||||
el.backEdges.clear();
|
||||
Set<GraphPart> uniqueRefs = new HashSet<>(el.loopContinue.refs);
|
||||
for (GraphPart r : uniqueRefs) {
|
||||
if (el.loopContinue.leadsTo(localData, this, code, r, loops)) {
|
||||
if (el.loopContinue.leadsTo(localData, this, code, r, loops, true)) {
|
||||
el.backEdges.add(r);
|
||||
}
|
||||
}
|
||||
@@ -905,6 +910,23 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
//Prefer continue/return/throw/break in onTrue rather than onFalse
|
||||
if (!onFalse.isEmpty()
|
||||
&& ((onFalse.get(onFalse.size() - 1) instanceof BreakItem)
|
||||
|| (onFalse.get(onFalse.size() - 1) instanceof ExitItem)
|
||||
|| (onFalse.get(onFalse.size() - 1) instanceof ContinueItem) )
|
||||
&& !(onFalse.get(onFalse.size() - 1) instanceof ScriptEndItem)
|
||||
&& (onTrue.isEmpty() || !((onTrue.get(onTrue.size() - 1) instanceof BreakItem)
|
||||
|| (onTrue.get(onTrue.size() - 1) instanceof ExitItem)
|
||||
|| (onTrue.get(onTrue.size() - 1) instanceof ContinueItem)))) {
|
||||
ifi.expression = ifi.expression.invert(null);
|
||||
ifi.onTrue = onFalse;
|
||||
ifi.onFalse = new ArrayList<>();
|
||||
list.addAll(i + 1, onTrue);
|
||||
onFalse = ifi.onFalse;
|
||||
onTrue = ifi.onTrue;
|
||||
}
|
||||
|
||||
if (i < list.size() - 1) {
|
||||
if ((list.get(i + 1) instanceof BreakItem) && onFalse.isEmpty()) {
|
||||
if (!onTrue.isEmpty() && (onTrue.get(onTrue.size() - 1) instanceof ContinueItem)) {
|
||||
@@ -1165,7 +1187,7 @@ public class Graph {
|
||||
} else {
|
||||
List<Loop> loops2 = new ArrayList<>(loops);
|
||||
loops2.remove(lastP1);
|
||||
if (!part.leadsTo(localData, this, code, lastP1.loopContinue, loops2)) {
|
||||
if (!part.leadsTo(localData, this, code, lastP1.loopContinue, loops2, true)) {
|
||||
if (lastP1.breakCandidatesLocked == 0) {
|
||||
if (debugGetLoops) {
|
||||
System.err.println("added breakCandidate " + part + " to " + lastP1);
|
||||
@@ -1190,7 +1212,7 @@ public class Graph {
|
||||
}
|
||||
part.level = level;
|
||||
|
||||
boolean isLoop = part.leadsTo(localData, this, code, part, loops);
|
||||
boolean isLoop = part.leadsTo(localData, this, code, part, loops, true);
|
||||
Loop currentLoop = null;
|
||||
if (isLoop) {
|
||||
currentLoop = new Loop(loops.size(), part, null);
|
||||
@@ -1282,7 +1304,7 @@ public class Graph {
|
||||
if (cand == cand2) {
|
||||
continue;
|
||||
}
|
||||
if (cand.leadsTo(localData, this, code, cand2, loops)) {
|
||||
if (cand.leadsTo(localData, this, code, cand2, loops, true)) {
|
||||
int lev1 = Integer.MAX_VALUE;
|
||||
int lev2 = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
|
||||
@@ -2507,7 +2529,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)) {
|
||||
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);
|
||||
@@ -2528,7 +2550,7 @@ public class Graph {
|
||||
trace("2");
|
||||
*/
|
||||
for (int i = 0; i < caseBodyParts.size(); i++) {
|
||||
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops)) {
|
||||
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops, false)) {
|
||||
DefaultItem di = new DefaultItem();
|
||||
caseValuesMap.add(i, di);
|
||||
caseBodyParts.add(i, defaultPart);
|
||||
@@ -2580,13 +2602,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)) {
|
||||
if (b2.leadsTo(localData, this, code, b, loops, false)) {
|
||||
caseBodies.remove(j);
|
||||
caseBodies.add(i, b2);
|
||||
i--;
|
||||
continue loopi;
|
||||
} else if (j > i + 1) {
|
||||
if (b.leadsTo(localData, this, code, b2, loops)) {
|
||||
if (b.leadsTo(localData, this, code, b2, loops, false)) {
|
||||
caseBodies.remove(j);
|
||||
caseBodies.add(i + 1, b2);
|
||||
continue loopi;
|
||||
@@ -2603,7 +2625,7 @@ public class Graph {
|
||||
for (int i = 0; i < caseBodies.size(); i++) {
|
||||
List<GraphTargetItem> currentCaseCommands = new ArrayList<>();
|
||||
if (i < caseBodies.size() - 1) {
|
||||
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) {
|
||||
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops, false)) {
|
||||
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
@@ -123,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 {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
@@ -133,7 +134,7 @@ public class GraphPart implements Serializable {
|
||||
return false;
|
||||
}
|
||||
if (tpart != this) {
|
||||
if (tpart != this) {
|
||||
return tpart.leadsTo(localData, gr, code, null, part, visited, loops, useThrow);
|
||||
}
|
||||
Loop currentLoop = null;
|
||||
for (Loop l : loops) {
|
||||
@@ -170,25 +171,27 @@ public class GraphPart implements Serializable {
|
||||
for (GraphPart p : nextParts) {
|
||||
if (p == part) {
|
||||
return true;
|
||||
return true;
|
||||
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, useThrow)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (GraphPart p : throwParts) {
|
||||
if (p == part) {
|
||||
return true;
|
||||
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart part, List<Loop> loops, boolean useThrow) throws InterruptedException {
|
||||
for (Loop l : loops) {
|
||||
l.leadsToMark = 0;
|
||||
}
|
||||
}
|
||||
return leadsTo(localData, gr, code, null /*???*/, part, new HashSet<>(), loops, useThrow);
|
||||
}
|
||||
|
||||
public GraphPart(int start, int end) {
|
||||
|
||||
Reference in New Issue
Block a user