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:
Jindra Petřík
2024-08-12 19:51:40 +02:00
parent 02baf4baa6
commit 16ff10a890
31 changed files with 487 additions and 58 deletions
@@ -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() {