mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-10 17:25:21 +00:00
Fixed: #2270 AS3 decompilation - unnnecessary local registers assignments as part of expressions when using optimization like dup, setlocal N instead of setlocal N, getlocal N
This commit is contained in:
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
|
||||
@@ -30,6 +31,7 @@ import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.helpers.LinkedIdentityHashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -221,6 +223,12 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
*/
|
||||
public Set<Integer> seenMethods = new HashSet<>();
|
||||
|
||||
|
||||
/**
|
||||
* Bottom set locals
|
||||
*/
|
||||
public LinkedIdentityHashSet<SetLocalAVM2Item> bottomSetLocals = new LinkedIdentityHashSet<>();
|
||||
|
||||
/**
|
||||
* Constructs a new AVM2LocalData
|
||||
*/
|
||||
@@ -287,6 +295,7 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
pushDefaultPart = localData.pushDefaultPart;
|
||||
finallyKinds = localData.finallyKinds;
|
||||
seenMethods = localData.seenMethods;
|
||||
bottomSetLocals = localData.bottomSetLocals;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -289,6 +289,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetRecursiveVisitor;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.Block;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
@@ -302,6 +303,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.LinkedIdentityHashSet;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import com.jpexs.helpers.ReflectionTools;
|
||||
import com.jpexs.helpers.stat.Statistics;
|
||||
@@ -320,6 +322,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -1842,11 +1845,12 @@ public class AVM2Code implements Cloneable {
|
||||
* @param fullyQualifiedNames Fully qualified names
|
||||
* @param visited Visited
|
||||
* @param localRegAssigmentIps Local register assignment IPs
|
||||
* @param bottomStackSetLocals Set locals on bottom of the stack
|
||||
* @return Convert output
|
||||
* @throws ConvertException On convert error
|
||||
* @throws InterruptedException On interrupt
|
||||
*/
|
||||
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, ScopeStack localScopeStack, 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) 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, ScopeStack localScopeStack, 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, LinkedIdentityHashSet<SetLocalAVM2Item> bottomStackSetLocals) throws ConvertException, InterruptedException {
|
||||
boolean debugMode = DEBUG_MODE;
|
||||
if (debugMode) {
|
||||
System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString());
|
||||
@@ -1901,26 +1905,13 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if ((ins.definition instanceof SetLocalTypeIns) && (ip + 1 <= end)) { // set_local_x,get_local_x.. no other local_x get
|
||||
|
||||
AVM2Instruction insAfter = code.get(ip + 1);
|
||||
Set<Integer> usages = setLocalPosToGetLocalPos.containsKey(ip) ? setLocalPosToGetLocalPos.get(ip) : new HashSet<>();
|
||||
|
||||
if (!(stack.peek().getNotCoercedNoDup() instanceof DuplicateItem) && !AVM2Item.mustStayIntact2(stack.peek()) && usages.size() == 1 && (usages.iterator().next().equals(ip + 1)) && (insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) {
|
||||
ip += 2;
|
||||
continue iploop;
|
||||
} else {
|
||||
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
|
||||
ip++;
|
||||
continue iploop;
|
||||
}
|
||||
} else*/
|
||||
/*
|
||||
if (ins.definition instanceof DupIns) {
|
||||
int nextPos;
|
||||
do {
|
||||
AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null;
|
||||
if (insAfter == null) {
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals);
|
||||
ip++;
|
||||
break;
|
||||
}
|
||||
@@ -1942,14 +1933,16 @@ public class AVM2Code implements Cloneable {
|
||||
//stack.add("(" + stack.pop() + ")||");
|
||||
isAnd = false;
|
||||
} else {
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals);
|
||||
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(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
|
||||
} else
|
||||
*/
|
||||
if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) {
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals);
|
||||
//ip = end + 1;
|
||||
break;
|
||||
} else if (ins.definition instanceof NewFunctionIns) {
|
||||
@@ -1985,13 +1978,18 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
// What to do when hasDup is false?
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals);
|
||||
NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek();
|
||||
nft.functionName = functionName;
|
||||
ip++;
|
||||
} else {
|
||||
try {
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive);
|
||||
try {
|
||||
ins.definition.translate(switchParts, callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, localScopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, this, thisHasDefaultToPrimitive, bottomStackSetLocals);
|
||||
|
||||
|
||||
if (stack.size() == 1 && (stack.peek() instanceof SetLocalAVM2Item)) {
|
||||
bottomStackSetLocals.add((SetLocalAVM2Item) stack.peek());
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
/*String last="";
|
||||
int len=5;
|
||||
@@ -2281,9 +2279,9 @@ public class AVM2Code implements Cloneable {
|
||||
break;
|
||||
}*/
|
||||
Reference<Boolean> hasPrevReference = new Reference<>(false);
|
||||
value.visitRecursivelyNoBlock(new AbstractGraphTargetVisitor() {
|
||||
value.visitRecursivelyNoBlock(new AbstractGraphTargetRecursiveVisitor() {
|
||||
@Override
|
||||
public void visit(GraphTargetItem subItem) {
|
||||
public void visit(GraphTargetItem subItem, Stack<GraphTargetItem> parentStack) {
|
||||
Multiname propertyMultiName;
|
||||
String propertyName;
|
||||
if (subItem instanceof GetPropertyAVM2Item) {
|
||||
@@ -2343,9 +2341,9 @@ public class AVM2Code implements Cloneable {
|
||||
GraphTargetItem currentItem = items.get(i);
|
||||
List<GraphTargetItem> itemsOnLine = new ArrayList<>();
|
||||
itemsOnLine.add(currentItem);
|
||||
currentItem.visitRecursivelyNoBlock(new AbstractGraphTargetVisitor() {
|
||||
currentItem.visitRecursivelyNoBlock(new AbstractGraphTargetRecursiveVisitor() {
|
||||
@Override
|
||||
public void visit(GraphTargetItem item) {
|
||||
public void visit(GraphTargetItem item, Stack<GraphTargetItem> parentStack) {
|
||||
itemsOnLine.add(item);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.jpexs.decompiler.flash.abc.avm2;
|
||||
|
||||
import com.jpexs.decompiler.flash.FinalProcessLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import com.jpexs.helpers.LinkedIdentityHashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -40,6 +42,11 @@ public class AVM2FinalProcessLocalData extends FinalProcessLocalData {
|
||||
* Set local position to get local position mapping.
|
||||
*/
|
||||
public Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Bottom set locals
|
||||
*/
|
||||
public LinkedIdentityHashSet<SetLocalAVM2Item> bottomSetLocals = new LinkedIdentityHashSet<>();
|
||||
|
||||
/**
|
||||
* Constructs AVM2 final process local data.
|
||||
@@ -49,11 +56,13 @@ public class AVM2FinalProcessLocalData extends FinalProcessLocalData {
|
||||
* mapping
|
||||
* @param setLocalPosToGetLocalPos Set local position to get local position
|
||||
* mapping
|
||||
* @param bottomSetLocals Bottom set locals
|
||||
*/
|
||||
public AVM2FinalProcessLocalData(List<Loop> loops, HashMap<Integer, String> localRegNames, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos) {
|
||||
public AVM2FinalProcessLocalData(List<Loop> loops, HashMap<Integer, String> localRegNames, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, LinkedIdentityHashSet<SetLocalAVM2Item> bottomSetLocals) {
|
||||
super(loops);
|
||||
this.localRegNames = localRegNames;
|
||||
this.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos;
|
||||
this.bottomSetLocals = bottomSetLocals;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,9 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ConstructAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
@@ -81,6 +83,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictEqAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetRecursiveVisitor;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
@@ -122,6 +125,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
@@ -2641,6 +2645,51 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AVM2FinalProcessLocalData adata = (AVM2FinalProcessLocalData) localData;
|
||||
//if(false)
|
||||
if (!adata.bottomSetLocals.isEmpty()) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
if (list.get(i) instanceof LoopItem) {
|
||||
continue;
|
||||
}
|
||||
if (list.get(i) instanceof WithEndAVM2Item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference<SetLocalAVM2Item> foundSetLoc = new Reference<>(null);
|
||||
list.get(i).visitRecursivelyNoBlock(new AbstractGraphTargetRecursiveVisitor() {
|
||||
@Override
|
||||
public void visit(GraphTargetItem item, Stack<GraphTargetItem> parentStack) {
|
||||
|
||||
if (item instanceof SetLocalAVM2Item) {
|
||||
if (adata.bottomSetLocals.contains((SetLocalAVM2Item) item)) {
|
||||
int s = parentStack.size() - 1;
|
||||
if (parentStack.get(s) instanceof CoerceAVM2Item) {
|
||||
s--;
|
||||
} else if (parentStack.get(s) instanceof ConvertAVM2Item) {
|
||||
s--;
|
||||
}
|
||||
if (s >= 0) {
|
||||
GraphTargetItem parent = parentStack.get(s);
|
||||
if (!(parent instanceof SetTypeAVM2Item)) { //not a chained assignment
|
||||
foundSetLoc.setVal((SetLocalAVM2Item) item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (foundSetLoc.getVal() != null) {
|
||||
SetLocalAVM2Item setLoc = foundSetLoc.getVal();
|
||||
list.add(i, setLoc.clone());
|
||||
setLoc.hideValue = true;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
convert this situation:
|
||||
|
||||
@@ -2656,13 +2705,13 @@ public class AVM2Graph extends Graph {
|
||||
It's TestSwapAssignment assembled test case.
|
||||
|
||||
*/
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
/*for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
GraphTargetItem item = list.get(i);
|
||||
Map<Integer, List<SetLocalAVM2Item>> setRegisters = new HashMap<>();
|
||||
item.visitRecursivelyNoBlock(new AbstractGraphTargetVisitor() {
|
||||
item.visitRecursivelyNoBlock(new AbstractGraphTargetRecursiveVisitor() {
|
||||
@Override
|
||||
public void visit(GraphTargetItem item) {
|
||||
public void visit(GraphTargetItem item, GraphTargetItem parent) {
|
||||
if (item instanceof SetLocalAVM2Item) {
|
||||
SetLocalAVM2Item setLoc = (SetLocalAVM2Item) item;
|
||||
if (setLoc.causedByDup) {
|
||||
@@ -2770,15 +2819,15 @@ public class AVM2Graph extends Graph {
|
||||
});
|
||||
i = newI.getVal();
|
||||
}
|
||||
|
||||
*/
|
||||
//Handle for loops at the end:
|
||||
super.finalProcess(list, level, localData, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FinalProcessLocalData getFinalData(BaseLocalData localData, List<Loop> loops, List<ThrowState> throwStates) {
|
||||
FinalProcessLocalData finalProcess = new AVM2FinalProcessLocalData(loops, ((AVM2LocalData) localData).localRegNames, ((AVM2LocalData) localData).setLocalPosToGetLocalPos);
|
||||
finalProcess.registerUsage = ((AVM2LocalData) localData).setLocalPosToGetLocalPos;
|
||||
FinalProcessLocalData finalProcess = new AVM2FinalProcessLocalData(loops, ((AVM2LocalData) localData).localRegNames, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).bottomSetLocals);
|
||||
finalProcess.registerUsage = ((AVM2LocalData) localData).setLocalPosToGetLocalPos;
|
||||
return finalProcess;
|
||||
}
|
||||
|
||||
@@ -3081,4 +3130,37 @@ public class AVM2Graph extends Graph {
|
||||
protected SecondPassData prepareSecondPass(List<GraphTargetItem> list) {
|
||||
return new SecondPassData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphTargetItem getIfExpression(BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output) {
|
||||
GraphTargetItem result = stack.pop();
|
||||
|
||||
/*
|
||||
Fixes this case:
|
||||
|
||||
var i:int;
|
||||
if ((i = 5) > 2 && i < 10) {
|
||||
...
|
||||
}
|
||||
|
||||
when instead
|
||||
setlocal x
|
||||
getlocal x
|
||||
|
||||
there is:
|
||||
dup
|
||||
setlocal x
|
||||
|
||||
*/
|
||||
|
||||
if (stack.getMark("firstSetLocal") != null) {
|
||||
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) stack.getMark("firstSetLocal");
|
||||
if (setLocal.directlyCausedByDup) {
|
||||
output.add(setLocal.clone());
|
||||
setLocal.hideValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
@@ -30,6 +31,7 @@ import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.helpers.LinkedIdentityHashSet;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -203,7 +205,7 @@ public class AVM2GraphSource extends GraphSource {
|
||||
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
|
||||
List<GraphTargetItem> ret = new ArrayList<>();
|
||||
Reference<GraphSourceItem> lineStartItem = new Reference<>(localData.lineStartInstruction);
|
||||
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, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps);
|
||||
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, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, ((AVM2LocalData) localData).bottomSetLocals);
|
||||
localData.lineStartInstruction = lineStartItem.getVal();
|
||||
ret.addAll(co.output);
|
||||
return ret;
|
||||
|
||||
@@ -62,6 +62,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.DuplicateItem;
|
||||
import com.jpexs.helpers.LinkedIdentityHashSet;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -290,9 +291,10 @@ public abstract class InstructionDefinition implements Serializable {
|
||||
* @param ip IP
|
||||
* @param code AVM2 code
|
||||
* @param thisHasDefaultToPrimitive This has default to primitive
|
||||
* @param bottomSetLocals Bottom set locals
|
||||
* @throws InterruptedException On interrupt
|
||||
*/
|
||||
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, ScopeStack localScopeStack, 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, 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, ScopeStack localScopeStack, 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, AVM2Code code, boolean thisHasDefaultToPrimitive, LinkedIdentityHashSet<SetLocalAVM2Item> bottomSetLocals) throws InterruptedException {
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.allSwitchParts = switchParts;
|
||||
localData.isStatic = isStatic;
|
||||
@@ -314,6 +316,7 @@ public abstract class InstructionDefinition implements Serializable {
|
||||
localData.code = code;
|
||||
localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive;
|
||||
localData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos;
|
||||
localData.bottomSetLocals = bottomSetLocals;
|
||||
translate(localData, stack, ins, output, path);
|
||||
lineStartItem.setVal(localData.lineStartInstruction);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
|
||||
import com.jpexs.decompiler.graph.model.DuplicateItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import java.util.List;
|
||||
|
||||
@@ -145,6 +146,10 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value instanceof DuplicateItem) {
|
||||
result.directlyCausedByDup = true;
|
||||
}
|
||||
|
||||
SetTypeIns.handleResult(value, stack, output, localData, result, regId, value.returnType());
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ public class SetLocalAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assig
|
||||
* Caused by duplicate
|
||||
*/
|
||||
public boolean causedByDup = false;
|
||||
|
||||
/**
|
||||
* Directly caused by duplicate
|
||||
*/
|
||||
public boolean directlyCausedByDup = false;
|
||||
|
||||
@Override
|
||||
public DeclarationAVM2Item getDeclaration() {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Abstract graph target recursive visitor.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class AbstractGraphTargetRecursiveVisitor implements GraphTargetRecursiveVisitorInterface {
|
||||
|
||||
/**
|
||||
* Constructs new AbstractGraphTargetVisitor
|
||||
*/
|
||||
public AbstractGraphTargetRecursiveVisitor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void visit(GraphTargetItem item, Stack<GraphTargetItem> parentStack);
|
||||
|
||||
@Override
|
||||
public final void visitAll(Collection<GraphTargetItem> items, Stack<GraphTargetItem> parentStack) {
|
||||
for (GraphTargetItem item : items) {
|
||||
visit(item, parentStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2715,6 +2715,18 @@ public class Graph {
|
||||
return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, stopPartKind, loops, throwStates, null, staticOperation, path, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if expression from stack.
|
||||
* Can be overriden for custom handling
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @param output Output
|
||||
* @return Expression
|
||||
*/
|
||||
protected GraphTargetItem getIfExpression(BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output) {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks graph parts and converts them to target items.
|
||||
*
|
||||
@@ -3254,7 +3266,7 @@ public class Graph {
|
||||
} //else
|
||||
GraphPart nextOnePart = null;
|
||||
if (getNextParts(localData, part).size() == 2 && !partIsSwitch(part)) {
|
||||
GraphTargetItem expr = stack.pop();
|
||||
GraphTargetItem expr = getIfExpression(localData, stack, currentRet);
|
||||
|
||||
if (nextOnePart == null) {
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Graph target item - an item in high level representation of the code.
|
||||
@@ -963,15 +964,19 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
*
|
||||
* @param visitor Visitor
|
||||
*/
|
||||
public final void visitRecursivelyNoBlock(GraphTargetVisitorInterface visitor) {
|
||||
public final void visitRecursivelyNoBlock(GraphTargetRecursiveVisitorInterface visitor) {
|
||||
Set<GraphTargetItem> visitedItems = new HashSet<>();
|
||||
Stack<GraphTargetItem> parentStack = new Stack<>();
|
||||
parentStack.add(this);
|
||||
visitNoBlock(new AbstractGraphTargetVisitor() {
|
||||
@Override
|
||||
public void visit(GraphTargetItem item) {
|
||||
if (item != null && !visitedItems.contains(item)) {
|
||||
visitedItems.add(item);
|
||||
visitor.visit(item);
|
||||
visitor.visit(item, parentStack);
|
||||
parentStack.push(item);
|
||||
item.visitNoBlock(this);
|
||||
parentStack.pop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Recursive graph target visitor interface.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface GraphTargetRecursiveVisitorInterface {
|
||||
|
||||
/**
|
||||
* Visits a graph target item.
|
||||
*
|
||||
* @param item Graph target item
|
||||
* @param parentStack Stack of parents
|
||||
*/
|
||||
public void visit(GraphTargetItem item, Stack<GraphTargetItem> parentStack);
|
||||
|
||||
/**
|
||||
* Visits all graph target items.
|
||||
*
|
||||
* @param items Collection of graph target items
|
||||
* @param parentStack Stack of parents
|
||||
*/
|
||||
public void visitAll(Collection<GraphTargetItem> items, Stack<GraphTargetItem> parentStack);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.graph;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Graph source visitor interface.
|
||||
* Graph target visitor interface.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -38,6 +42,27 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
*/
|
||||
private final String path;
|
||||
|
||||
private Map<String, GraphTargetItem> marks = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Sets mark.
|
||||
* @param name Name
|
||||
* @param value Value
|
||||
*/
|
||||
public void setMark(String name, GraphTargetItem value) {
|
||||
marks.put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets mark.
|
||||
* @param name Name
|
||||
* @return Value
|
||||
*/
|
||||
public GraphTargetItem getMark(String name) {
|
||||
return marks.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies all items in the stack.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user