Fixed: Try..catch.finally vs loops

This commit is contained in:
Jindra Petřík
2021-02-02 09:42:38 +01:00
parent 28650d40fb
commit e649d08a08
20 changed files with 866 additions and 171 deletions

View File

@@ -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() {

View File

@@ -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--;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;
}
}
}
}
}
}

View File

@@ -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));
}
}

View File

@@ -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) {