mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-13 04:28:09 +00:00
Fixed #1894 Switches vs loops decompilation (now with two passes)
This commit is contained in:
@@ -16,8 +16,11 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -26,6 +29,8 @@ import com.jpexs.decompiler.graph.SecondPassData;
|
||||
public abstract class BaseLocalData {
|
||||
|
||||
public GraphSourceItem lineStartInstruction;
|
||||
|
||||
|
||||
public Set<GraphPart> allSwitchParts = new HashSet<>();
|
||||
|
||||
public SecondPassData secondPassData = null;
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
}
|
||||
|
||||
public AVM2LocalData(AVM2LocalData localData) {
|
||||
allSwitchParts = localData.allSwitchParts;
|
||||
isStatic = localData.isStatic;
|
||||
classIndex = localData.classIndex;
|
||||
localRegs = localData.localRegs;
|
||||
|
||||
@@ -298,6 +298,7 @@ import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.decompiler.graph.SecondPassException;
|
||||
import com.jpexs.decompiler.graph.SimpleValue;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
@@ -1589,7 +1590,7 @@ public class AVM2Code implements Cloneable {
|
||||
return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true)));
|
||||
}
|
||||
|
||||
public ConvertOutput toSourceOutput(List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
|
||||
public ConvertOutput toSourceOutput(Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
|
||||
calcKilledStats(body);
|
||||
boolean debugMode = DEBUG_MODE;
|
||||
if (debugMode) {
|
||||
@@ -1664,7 +1665,7 @@ public class AVM2Code implements Cloneable {
|
||||
do {
|
||||
AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null;
|
||||
if (insAfter == null) {
|
||||
ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ip++;
|
||||
break;
|
||||
}
|
||||
@@ -1686,14 +1687,14 @@ public class AVM2Code implements Cloneable {
|
||||
//stack.add("(" + stack.pop() + ")||");
|
||||
isAnd = false;
|
||||
} else {
|
||||
ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ip++;
|
||||
break;
|
||||
//throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString());
|
||||
}
|
||||
} while (ins.definition instanceof DupIns);
|
||||
} else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) {
|
||||
ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
//ip = end + 1;
|
||||
break;
|
||||
} else if (ins.definition instanceof NewFunctionIns) {
|
||||
@@ -1729,13 +1730,13 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
// What to do when hasDup is false?
|
||||
ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek();
|
||||
nft.functionName = functionName;
|
||||
ip++;
|
||||
} else {
|
||||
try {
|
||||
ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
} catch (RuntimeException re) {
|
||||
/*String last="";
|
||||
int len=5;
|
||||
@@ -2150,8 +2151,11 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
|
||||
//try {
|
||||
list = AVM2Graph.translateViaGraph(callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
|
||||
|
||||
try{
|
||||
list = AVM2Graph.translateViaGraph(null, callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
|
||||
} catch(SecondPassException spe) {
|
||||
list = AVM2Graph.translateViaGraph(spe.getData(), callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
|
||||
}
|
||||
if (initTraits != null) {
|
||||
loopi:
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
@@ -101,6 +101,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
import com.jpexs.decompiler.graph.StopPartKind;
|
||||
import com.jpexs.decompiler.graph.ThrowState;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
@@ -633,10 +634,11 @@ public class AVM2Graph extends Graph {
|
||||
return setLocalPosToGetLocalPos;
|
||||
}
|
||||
|
||||
public static List<GraphTargetItem> translateViaGraph(List<MethodBody> callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException {
|
||||
public static List<GraphTargetItem> translateViaGraph(SecondPassData secondPassData, List<MethodBody> callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException {
|
||||
AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs);
|
||||
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.secondPassData = secondPassData;
|
||||
localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive;
|
||||
localData.isStatic = isStatic;
|
||||
localData.classIndex = classIndex;
|
||||
@@ -657,7 +659,7 @@ public class AVM2Graph extends Graph {
|
||||
Set<GraphPart> allParts = new HashSet<>();
|
||||
for (GraphPart head : g.heads) {
|
||||
populateParts(head, allParts);
|
||||
}
|
||||
}
|
||||
return g.translate(localData, staticOperation, path);
|
||||
}
|
||||
|
||||
@@ -2424,4 +2426,8 @@ public class AVM2Graph extends Graph {
|
||||
Graph.makeAllCommands(commands, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecondPassData prepareSecondPass(List<GraphTargetItem> list) {
|
||||
return new SecondPassData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class AVM2GraphSource extends GraphSource {
|
||||
List<GraphTargetItem> ret = new ArrayList<>();
|
||||
ScopeStack newstack = ((AVM2LocalData) localData).scopeStack;
|
||||
Reference<GraphSourceItem> lineStartItem = new Reference<>(localData.lineStartInstruction);
|
||||
ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
|
||||
ConvertOutput co = code.toSourceOutput(localData.allSwitchParts, ((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
|
||||
localData.lineStartInstruction = lineStartItem.getVal();
|
||||
ret.addAll(co.output);
|
||||
return ret;
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitWithSlot;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
@@ -171,8 +172,9 @@ public abstract class InstructionDefinition implements Serializable {
|
||||
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) throws InterruptedException {
|
||||
}
|
||||
|
||||
public void translate(List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException {
|
||||
public void translate(Set<GraphPart> switchParts, List<MethodBody> callStack, AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException {
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.allSwitchParts = switchParts;
|
||||
localData.isStatic = isStatic;
|
||||
localData.scriptIndex = scriptIndex;
|
||||
localData.classIndex = classIndex;
|
||||
|
||||
@@ -63,6 +63,7 @@ import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphPartChangeException;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -1009,11 +1010,11 @@ public abstract class Action implements GraphSourceItem {
|
||||
return variables2;
|
||||
}
|
||||
|
||||
public static List<GraphTargetItem> actionsPartToTree(SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
|
||||
public static List<GraphTargetItem> actionsPartToTree(Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
|
||||
if (start < actions.size() && (end > 0) && (start > 0)) {
|
||||
logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""});
|
||||
}
|
||||
ActionLocalData localData = new ActionLocalData(secondPassData, insideDoInitAction, registerNames, variables, functions);
|
||||
ActionLocalData localData = new ActionLocalData(switchParts, secondPassData, insideDoInitAction, registerNames, variables, functions);
|
||||
localData.lineStartAction = fi.getVal();
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
int ip = start;
|
||||
|
||||
@@ -112,7 +112,7 @@ public class ActionGraphSource extends GraphSource {
|
||||
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException {
|
||||
Reference<GraphSourceItem> fi = new Reference<>(localData.lineStartInstruction);
|
||||
|
||||
List<GraphTargetItem> r = Action.actionsPartToTree(localData.secondPassData, this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path, charset);
|
||||
List<GraphTargetItem> r = Action.actionsPartToTree(localData.allSwitchParts, localData.secondPassData, this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path, charset);
|
||||
localData.lineStartInstruction = fi.getVal();
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -51,10 +53,11 @@ public class ActionLocalData extends BaseLocalData {
|
||||
this.secondPassData = secondPassData;
|
||||
variables = new HashMap<>();
|
||||
functions = new HashMap<>();
|
||||
this.insideDoInitAction = insideDoInitAction;
|
||||
this.insideDoInitAction = insideDoInitAction;
|
||||
}
|
||||
|
||||
public ActionLocalData(SecondPassData secondPassData, boolean insideDoInitAction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
|
||||
public ActionLocalData(Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
|
||||
this.allSwitchParts = switchParts;
|
||||
this.regNames = regNames;
|
||||
this.variables = variables;
|
||||
this.functions = functions;
|
||||
|
||||
@@ -29,5 +29,5 @@ import java.util.List;
|
||||
public class ActionSecondPassData extends SecondPassData {
|
||||
List<List<GraphPart>> switchParts = new ArrayList<>();
|
||||
List<List<GraphPart>> switchOnFalseParts = new ArrayList<>();
|
||||
List<List<GraphTargetItem>> switchCaseExpressions = new ArrayList<>();
|
||||
List<List<GraphTargetItem>> switchCaseExpressions = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeSet;
|
||||
@@ -116,6 +117,7 @@ public class Graph {
|
||||
List<GraphPart> visited = new ArrayList<>();
|
||||
for (GraphPart head : heads) {
|
||||
time = head.setTime(time, ordered, visited);
|
||||
head.setNumblocks(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,23 +448,57 @@ public class Graph {
|
||||
if (stopPart != null) {
|
||||
for (GraphPart p : parts) {
|
||||
for (GraphPart sp : stopPart) {
|
||||
if (sp == p || p.leadsTo(localData, this, code, sp, loops, throwStates, false)) {
|
||||
if (sp == p || p.leadsTo(localData, this, code, sp, new ArrayList<Loop>() /*IGNORE LOOPS*/, throwStates, false)) {
|
||||
partsLeadingToStopPart.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("commonset:");
|
||||
for (PartCommon pc : commonSet) {
|
||||
System.err.println("- " + pc);
|
||||
}
|
||||
|
||||
System.err.println("parts:");
|
||||
for(GraphPart p :parts) {
|
||||
System.err.println("- "+p);
|
||||
}
|
||||
|
||||
if (stopPart != null) {
|
||||
System.err.println("stopparts:");
|
||||
for(GraphPart p :stopPart) {
|
||||
System.err.println("- "+p);
|
||||
}
|
||||
}
|
||||
|
||||
System.err.println("partsLeadingToStopPart:");
|
||||
for (GraphPart p : partsLeadingToStopPart) {
|
||||
System.err.println("- " + p);
|
||||
}
|
||||
|
||||
if (partsLeadingToStopPart.isEmpty()) {
|
||||
return null; //?
|
||||
}
|
||||
}
|
||||
|
||||
loopc:
|
||||
for (PartCommon pc : commonSet) {
|
||||
for (GraphPart p : partsLeadingToStopPart) {
|
||||
if (p != pc.part && !p.leadsTo(localData, this, code, pc.part, loops, throwStates, false)) {
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("ignoring " + pc.part + ", " + p + " does not lead to it");
|
||||
}
|
||||
continue loopc;
|
||||
}
|
||||
}
|
||||
if (pc.level <= 1) {
|
||||
return null;
|
||||
}
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("selected " + pc.part);
|
||||
}
|
||||
return pc.part;
|
||||
}
|
||||
|
||||
@@ -489,6 +525,32 @@ public class Graph {
|
||||
return "" + part.toString() + " (level=" + level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 71 * hash + Objects.hashCode(this.part);
|
||||
hash = 71 * hash + this.level;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final PartCommon other = (PartCommon) obj;
|
||||
if (this.level != other.level) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.part, other.part);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GraphPart getNextNoJump(GraphPart part, BaseLocalData localData) {
|
||||
@@ -569,6 +631,11 @@ public class Graph {
|
||||
getLoops(localData, heads.get(0), loops, throwStates, null);
|
||||
|
||||
afterGetLoops(localData, path, allParts);
|
||||
|
||||
//TODO: Make getPrecontinues faster
|
||||
getBackEdges(localData, loops, throwStates);
|
||||
|
||||
new GraphPrecontinueDetector().detectPrecontinues(heads, allParts, loops, throwStates);
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("<loops>");
|
||||
for (Loop el : loops) {
|
||||
@@ -576,12 +643,6 @@ public class Graph {
|
||||
}
|
||||
System.err.println("</loops>");
|
||||
}
|
||||
|
||||
//TODO: Make getPrecontinues faster
|
||||
getBackEdges(localData, loops, throwStates);
|
||||
|
||||
new GraphPrecontinueDetector().detectPrecontinues(heads, allParts, loops, throwStates);
|
||||
|
||||
/*System.err.println("<loopspre>");
|
||||
for (Loop el : loops) {
|
||||
System.err.println(el);
|
||||
@@ -593,8 +654,19 @@ public class Graph {
|
||||
|
||||
if (localData.secondPassData == null) {
|
||||
SecondPassData secondPassData = prepareSecondPass(ret);
|
||||
if (secondPassData != null) {
|
||||
throw new SecondPassException(secondPassData);
|
||||
if (secondPassData == null) {
|
||||
if (!localData.allSwitchParts.isEmpty()) {
|
||||
secondPassData = new SecondPassData();
|
||||
secondPassData.allSwitchParts = localData.allSwitchParts;
|
||||
throw new SecondPassException(secondPassData);
|
||||
}
|
||||
} else {
|
||||
if (secondPassData.getClass() == SecondPassData.class && localData.allSwitchParts.isEmpty()) {
|
||||
//nothing
|
||||
} else {
|
||||
secondPassData.allSwitchParts = localData.allSwitchParts;
|
||||
throw new SecondPassException(secondPassData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1805,8 +1877,28 @@ public class Graph {
|
||||
Map<GraphPart, Integer> count = new HashMap<>();
|
||||
GraphPart winner = null;
|
||||
int winnerCount = 0;
|
||||
int winnerNumBlock = Integer.MAX_VALUE;
|
||||
|
||||
Set<GraphPart> bannedCandidates = new HashSet<>();
|
||||
if(localData.secondPassData != null) {
|
||||
bannedCandidates = localData.secondPassData.allSwitchParts;
|
||||
}
|
||||
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("bannedCandidates:");
|
||||
for(GraphPart p:bannedCandidates) {
|
||||
System.err.println("- "+p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (GraphPart cand : currentLoop.breakCandidates) {
|
||||
|
||||
if (bannedCandidates.contains(cand)) {
|
||||
if (debugPrintLoopList) {
|
||||
System.err.println("cand "+cand+" is banned");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!count.containsKey(cand)) {
|
||||
count.put(cand, 0);
|
||||
}
|
||||
@@ -2690,7 +2782,18 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
finalComm.addAll(precoCommands);
|
||||
boolean isAllNotBlock = true;
|
||||
for (GraphTargetItem ti: precoCommands) {
|
||||
if (ti instanceof Block) {
|
||||
isAllNotBlock = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isAllNotBlock) {
|
||||
finalComm.addAll(precoCommands);
|
||||
} else {
|
||||
commands.addAll(precoCommands);
|
||||
}
|
||||
}
|
||||
if (currentLoop.precontinueCommands != null) {
|
||||
finalComm.addAll(currentLoop.precontinueCommands);
|
||||
@@ -3098,7 +3201,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> visited, Set<GraphPart> allParts, TranslateStack stack, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, 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 {
|
||||
@@ -3236,6 +3339,8 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
localData.allSwitchParts.add(caseBodies.get(i));
|
||||
|
||||
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
|
||||
List<StopPartKind> stopPartKind2x = new ArrayList<>(stopPartKind);
|
||||
for (GraphPart b : caseBodies) {
|
||||
|
||||
@@ -73,6 +73,8 @@ public class GraphPart implements Serializable {
|
||||
public int finishedTime;
|
||||
|
||||
public int order;
|
||||
|
||||
public int numBlocks = Integer.MAX_VALUE;
|
||||
|
||||
//public List<GraphPart> throwParts = new ArrayList<>();
|
||||
|
||||
@@ -123,6 +125,16 @@ public class GraphPart implements Serializable {
|
||||
ordered.add(this);
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setNumblocks(int numBlocks) {
|
||||
this.numBlocks = numBlocks;
|
||||
numBlocks++;
|
||||
for (GraphPart next : nextParts) {
|
||||
if (next.numBlocks > numBlocks) {
|
||||
next.setNumblocks(numBlocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.graph;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -64,7 +65,12 @@ public class Loop implements Serializable {
|
||||
for (GraphPart p : backEdges) {
|
||||
edgesAsStr.add(p.toString());
|
||||
}
|
||||
return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:" + phase + ", backedges: " + String.join(",", edgesAsStr) + ")";
|
||||
Set<String> bcAsStr = new LinkedHashSet<>();
|
||||
for (int i = 0; i < breakCandidates.size(); i++) {
|
||||
bcAsStr.add(breakCandidates.get(i) + " - level " + breakCandidatesLevels.get(i) +" - numblocks " + breakCandidates.get(i).numBlocks);
|
||||
}
|
||||
|
||||
return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:" + phase + ", backedges: " + String.join(",", edgesAsStr) + ", breakCandidates: " + String.join(",", bcAsStr) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class SecondPassData {
|
||||
|
||||
public class SecondPassData {
|
||||
public Set<GraphPart> allSwitchParts = new HashSet<>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user