From b3a693e4e39a1832c0c3c83f8e6041c38280a2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 31 Jul 2025 19:34:24 +0200 Subject: [PATCH] 2497 Swap instruction handling. WIP --- .../flash/abc/avm2/graph/AVM2Graph.java | 1 + .../instructions/InstructionDefinition.java | 43 +++++++++- .../abc/avm2/instructions/SetTypeIns.java | 4 + .../avm2/instructions/alchemy/Sf32Ins.java | 1 + .../avm2/instructions/alchemy/Sf64Ins.java | 1 + .../avm2/instructions/alchemy/Si16Ins.java | 1 + .../avm2/instructions/alchemy/Si32Ins.java | 1 + .../abc/avm2/instructions/alchemy/Si8Ins.java | 1 + .../construction/ConstructPropIns.java | 2 +- .../construction/ConstructSuperIns.java | 1 + .../avm2/instructions/executing/CallIns.java | 1 + .../executing/CallPropLexIns.java | 2 +- .../executing/CallPropVoidIns.java | 3 +- .../executing/CallPropertyIns.java | 2 +- .../instructions/executing/CallSuperIns.java | 2 +- .../executing/CallSuperVoidIns.java | 3 +- .../instructions/localregs/DecLocalIIns.java | 1 + .../instructions/localregs/DecLocalIns.java | 1 + .../localregs/GetLocalTypeIns.java | 4 +- .../instructions/localregs/IncLocalIIns.java | 1 + .../instructions/localregs/IncLocalIns.java | 1 + .../localregs/SetLocalTypeIns.java | 5 ++ .../instructions/other/DeletePropertyIns.java | 2 +- .../instructions/other/FindPropertyIns.java | 2 +- .../other/FindPropertyStrictIns.java | 2 +- .../instructions/other/GetDescendantsIns.java | 2 +- .../instructions/other/GetPropertyIns.java | 4 +- .../avm2/instructions/other/GetSuperIns.java | 2 +- .../instructions/other/ReturnValueIns.java | 1 + .../instructions/other/ReturnVoidIns.java | 1 + .../instructions/other/SetGlobalSlotIns.java | 1 + .../avm2/instructions/other/SetSlotIns.java | 11 ++- .../avm2/instructions/other/SetSuperIns.java | 4 +- .../abc/avm2/instructions/other/ThrowIns.java | 4 +- .../other/decimalsupport/DecLocalPIns.java | 1 + .../other/decimalsupport/IncLocalPIns.java | 1 + .../abc/avm2/instructions/stack/PopIns.java | 1 + .../avm2/instructions/stack/PopScopeIns.java | 1 + .../avm2/instructions/stack/PushWithIns.java | 1 + .../abc/avm2/instructions/stack/SwapIns.java | 40 ++++++++- .../abc/avm2/instructions/xml/DXNSIns.java | 1 + .../avm2/instructions/xml/DXNSLateIns.java | 1 + .../parser/script/AVM2SourceGenerator.java | 8 ++ .../parser/script/ActionScript3Parser.java | 4 + .../script/ActionScript3SimpleParser.java | 3 + .../parser/script/ActionScript2Parser.java | 4 + .../script/ActionScript2SimpleParser.java | 3 + .../parser/script/ActionSourceGenerator.java | 9 +- .../src/com/jpexs/decompiler/graph/Graph.java | 2 + .../decompiler/graph/SourceGenerator.java | 11 +++ .../decompiler/graph/TranslateStack.java | 82 +++++++++++++++++++ .../decompiler/graph/model/DuplicateItem.java | 4 +- .../decompiler/graph/model/SwapItem.java | 78 ++++++++++++++++++ .../ActionScript3AssembledDecompileTest.java | 17 +++- ...ipt3CrossCompileSwfToolsDecompileTest.java | 12 ++- 55 files changed, 366 insertions(+), 36 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwapItem.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 9918ce423..c4020480b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -1390,6 +1390,7 @@ public class AVM2Graph extends Graph { //should not happen finallyCommands.clear(); } + stack.pop(); //duplicated switched value stack.pop(); //value switched by lookupswitch } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index d34437939..a4010259d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -62,6 +62,8 @@ 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.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.PushItem; import com.jpexs.helpers.LinkedIdentityHashSet; import com.jpexs.helpers.Reference; import java.io.Serializable; @@ -377,7 +379,8 @@ public abstract class InstructionDefinition implements Serializable { * @param ins Instruction * @return Resolved multiname */ - protected FullMultinameAVM2Item resolveMultiname(AVM2LocalData localData, boolean property, TranslateStack stack, AVM2ConstantPool constants, int multinameIndex, AVM2Instruction ins) { + protected FullMultinameAVM2Item resolveMultiname(AVM2LocalData localData, boolean property, TranslateStack stack, AVM2ConstantPool constants, int multinameIndex, AVM2Instruction ins, List output) { + stack.allowSwap(output); GraphTargetItem ns = null; GraphTargetItem name = null; if (multinameIndex > 0 && multinameIndex < constants.getMultinameCount()) { @@ -543,15 +546,17 @@ public abstract class InstructionDefinition implements Serializable { * @param path Path */ public void handleSetProperty(boolean init, AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + stack.allowSwap(output); int multinameIndex = ins.operands[0]; GraphTargetItem value = stack.pop(); - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); //assembled/TestIncrement if ((value instanceof IncrementAVM2Item) || (value instanceof DecrementAVM2Item)) { boolean isIncrement = (value instanceof IncrementAVM2Item); if (value.value instanceof DuplicateItem) { GraphTargetItem duplicated = value.value.value; + stack.moveToStack(output); if (!stack.isEmpty()) { if (stack.peek() == duplicated) { GraphTargetItem notCoerced = duplicated.getNotCoerced(); @@ -602,6 +607,7 @@ public abstract class InstructionDefinition implements Serializable { GetLexAVM2Item getLex = (GetLexAVM2Item) value.value.getNotCoercedNoDup(); if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) && (obj instanceof FindPropertyAVM2Item)) { + stack.moveToOutput(output, false); if (hasConvert) { if (isIncrement) { output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); @@ -629,6 +635,7 @@ public abstract class InstructionDefinition implements Serializable { } } if (Objects.equals(getProp.object, obj)) { + stack.moveToOutput(output, false); if (hasConvert) { if (isIncrement) { output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); @@ -652,6 +659,7 @@ public abstract class InstructionDefinition implements Serializable { GraphTargetItem duplicated = value.value; if ((duplicated instanceof IncrementAVM2Item) || (duplicated instanceof DecrementAVM2Item)) { boolean isIncrement = (duplicated instanceof IncrementAVM2Item); + stack.moveToStack(output); if (!stack.isEmpty()) { if (stack.peek() == duplicated) { GraphTargetItem incrementedProp = duplicated.value; @@ -702,7 +710,8 @@ public abstract class InstructionDefinition implements Serializable { boolean isIncrement = (valueSetLocalReg.value instanceof IncrementAVM2Item); if (valueSetLocalReg.value.value instanceof DuplicateItem) { GraphTargetItem duplicated = valueSetLocalReg.value.value.value; - if (!stack.isEmpty() && stack.peek() == duplicated) { + if (output.size() >= 2 && output.get(output.size() - 2) instanceof PushItem && ((PushItem) output.get(output.size() - 2)).value == duplicated) { + //if (!stack.isEmpty() && stack.peek() == duplicated) { GraphTargetItem notCoerced = duplicated.getNotCoerced(); if (notCoerced instanceof GetPropertyAVM2Item) { GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) notCoerced; @@ -723,7 +732,9 @@ public abstract class InstructionDefinition implements Serializable { } getProperty.object = objSetLocalReg.value; output.remove(output.size() - 1); - stack.pop(); + output.remove(output.size() - 1); + stack.moveToStack(output); + //stack.pop(); if (isIncrement) { stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty)); } else { @@ -739,6 +750,7 @@ public abstract class InstructionDefinition implements Serializable { } } + stack.moveToStack(output); if (!stack.isEmpty()) { GraphTargetItem checked = checkIncDec(false, multinameIndex, ins, localData, stack.peek(), valueLocalReg, nameLocalReg, objLocalReg); if (checked != null) { @@ -758,6 +770,29 @@ public abstract class InstructionDefinition implements Serializable { } } + if (obj instanceof PopItem) { + if (output.size() >= 2 + && output.get(output.size() - 1) instanceof SetLocalAVM2Item + && output.get(output.size() - 2) instanceof PushItem + && multiname.name instanceof LocalRegAVM2Item) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(output.size() - 1); + LocalRegAVM2Item localReg = (LocalRegAVM2Item) multiname.name; + PushItem pi = (PushItem) output.get(output.size() - 2); + if (setLocal.regIndex == localReg.regIndex) { + GraphSourceItem src = setLocal.getSrc(); + if (src != null) { + if (localData.getSetLocalUsages(localData.code.adr2pos(src.getAddress())).size() == 1) { + output.remove(output.size() - 1); + output.remove(output.size() - 1); + stack.moveToStack(output); + obj = pi.value; + multiname.name = setLocal.value; + } + } + } + } + } + if (obj.getThroughDuplicate() instanceof ConstructAVM2Item) { ConstructAVM2Item c = (ConstructAVM2Item) obj.getThroughDuplicate(); if (c.object instanceof ApplyTypeAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java index 5ddc818a7..c853be5b4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java @@ -73,6 +73,7 @@ public interface SetTypeIns { if (notCoercedValue instanceof DuplicateItem) { GraphTargetItem insideDup = notCoercedValue.value; if (!AVM2Item.mustStayIntact1(insideDup.getNotCoercedNoDup())) { + stack.moveToStack(output); if (!stack.isEmpty() && stack.peek() == insideDup) { stack.pop(); @@ -89,6 +90,7 @@ public interface SetTypeIns { value = insideDup; } result.value = value; + stack.moveToOutput(output, false); output.add(result); for (int i = 0; i < numDups; i++) { stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : value.returnType())); @@ -109,6 +111,7 @@ public interface SetTypeIns { } if (regId > -1 && AVM2Item.mustStayIntact2(insideDup.getNotCoerced())) { //hack + stack.moveToOutput(output, false); output.add(result); stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : TypeItem.UNBOUNDED)); return; @@ -120,6 +123,7 @@ public interface SetTypeIns { } } } + stack.moveToOutput(output, false); output.add(result); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java index 1af3c7019..953d79369 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf32Ins.java @@ -62,6 +62,7 @@ public class Sf32Ins extends InstructionDefinition implements AlchemyTypeIns { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem ofs = stack.pop(); GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, false); output.add(new AlchemyStoreAVM2Item(ins, localData.lineStartInstruction, value, ofs, "f", 32)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java index e11b39188..303bdc461 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Sf64Ins.java @@ -62,6 +62,7 @@ public class Sf64Ins extends InstructionDefinition implements AlchemyTypeIns { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem ofs = stack.pop(); GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, false); output.add(new AlchemyStoreAVM2Item(ins, localData.lineStartInstruction, value, ofs, "f", 64)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java index 3a3b58dff..4b10965f5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si16Ins.java @@ -62,6 +62,7 @@ public class Si16Ins extends InstructionDefinition implements AlchemyTypeIns { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem ofs = stack.pop(); GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, false); output.add(new AlchemyStoreAVM2Item(ins, localData.lineStartInstruction, value, ofs, "i", 16)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java index 88871339d..38cd8150c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si32Ins.java @@ -62,6 +62,7 @@ public class Si32Ins extends InstructionDefinition implements AlchemyTypeIns { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem ofs = stack.pop(); GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, false); output.add(new AlchemyStoreAVM2Item(ins, localData.lineStartInstruction, value, ofs, "i", 32)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java index 5e822e246..fd31d2f9d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/Si8Ins.java @@ -62,6 +62,7 @@ public class Si8Ins extends InstructionDefinition implements AlchemyTypeIns { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem ofs = stack.pop(); GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, false); output.add(new AlchemyStoreAVM2Item(ins, localData.lineStartInstruction, value, ofs, "i", 8)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java index 64139609e..4ae496351 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructPropIns.java @@ -74,7 +74,7 @@ public class ConstructPropIns extends InstructionDefinition { for (int a = 0; a < argCount; a++) { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); if (multiname.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructSuperIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructSuperIns.java index 3fd97786c..d4d5c2aa8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructSuperIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/ConstructSuperIns.java @@ -72,6 +72,7 @@ public class ConstructSuperIns extends InstructionDefinition { args.add(0, stack.pop()); } GraphTargetItem obj = stack.pop(); + stack.moveToOutput(output, false); output.add(new ConstructSuperAVM2Item(ins, localData.lineStartInstruction, obj, args)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallIns.java index c97e26d89..0ca15144b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallIns.java @@ -80,6 +80,7 @@ public class CallIns extends InstructionDefinition { for (int a = 0; a < argCount; a++) { args.add(0, stack.pop()); } + stack.allowSwap(output); GraphTargetItem receiver = stack.pop(); GraphTargetItem function = stack.pop(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropLexIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropLexIns.java index 0c5128cbc..8b495d1d4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropLexIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropLexIns.java @@ -82,7 +82,7 @@ public class CallPropLexIns extends CallPropertyIns { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java index 4ea5eb175..a22558e78 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java @@ -82,13 +82,14 @@ public class CallPropVoidIns extends InstructionDefinition { for (int a = 0; a < argCount; a++) { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); Reference callType = new Reference<>(null); GetPropertyIns.resolvePropertyType(localData, obj, multiname, isStatic, type, callType); + stack.moveToOutput(output, false); output.add(new CallPropertyAVM2Item(ins, localData.lineStartInstruction, true, obj, multiname, args, callType.getVal(), isStatic.getVal())); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java index 7245190e8..d522a31bc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java @@ -83,7 +83,7 @@ public class CallPropertyIns extends InstructionDefinition { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperIns.java index e0a21f6c7..2251887f9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperIns.java @@ -80,7 +80,7 @@ public class CallSuperIns extends InstructionDefinition { for (int a = 0; a < argCount; a++) { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem receiver = stack.pop(); stack.push(new CallSuperAVM2Item(ins, localData.lineStartInstruction, false, receiver, multiname, args)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperVoidIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperVoidIns.java index 41d08e0a2..1edb34dc0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperVoidIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallSuperVoidIns.java @@ -79,9 +79,10 @@ public class CallSuperVoidIns extends InstructionDefinition { for (int a = 0; a < argCount; a++) { args.add(0, stack.pop()); } - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem receiver = stack.pop(); + stack.moveToOutput(output, false); output.add(new CallSuperAVM2Item(ins, localData.lineStartInstruction, true, receiver, multiname, args)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java index 82168ecc3..dd57f988c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java @@ -73,6 +73,7 @@ public class DecLocalIIns extends InstructionDefinition { } } if (!isPostDec) { + stack.moveToOutput(output, false); output.add(new DecLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java index a9cd42f6b..23fb515fd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java @@ -74,6 +74,7 @@ public class DecLocalIns extends InstructionDefinition { } } if (!isPostDec) { + stack.moveToOutput(output, false); output.add(new DecLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java index 5fd2d615a..737f7e762 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java @@ -134,6 +134,7 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { result = new PostDecrementAVM2Item(setProp.getSrc(), localData.lineStartInstruction, getProp); } output.remove(output.size() - 1); + stack.moveToStack(output); stack.add(result); return; } @@ -153,6 +154,7 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { } output.remove(output.size() - 1); + stack.moveToStack(output); if (setItem instanceof SetPropertyAVM2Item) { if ((setItem.value instanceof IncrementAVM2Item) || (setItem.value instanceof DecrementAVM2Item)) { @@ -176,7 +178,7 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { } } - stack.add(setItem); + stack.push(setItem); return; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java index 93b17308f..4a37a4e9f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java @@ -73,6 +73,7 @@ public class IncLocalIIns extends InstructionDefinition { } } if (!isPostInc) { + stack.moveToOutput(output, false); output.add(new IncLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java index 3240ec757..9bd29176f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java @@ -74,6 +74,7 @@ public class IncLocalIns extends InstructionDefinition { } } if (!isPostInc) { + stack.moveToOutput(output, false); output.add(new IncLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index e7e6f2162..9b6736d37 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -83,6 +83,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S localData.localRegAssignmentIps.put(regId, localData.localRegAssignmentIps.get(regId) + 1); //localRegsAssignmentIps.put(regId, ip); if (value.getThroughDuplicate() instanceof NewActivationAVM2Item) { + stack.moveToOutput(output, false); output.add(new StoreNewActivationAVM2Item(ins, localData.lineStartInstruction, regId)); return; } @@ -102,9 +103,11 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S stack.pop(); stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } else { + stack.moveToOutput(output, false); output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } } else { + stack.moveToOutput(output, false); output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } return; @@ -125,9 +128,11 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S stack.pop(); stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } else { + stack.moveToOutput(output, false); output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } } else { + stack.moveToOutput(output, false); output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } return; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/DeletePropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/DeletePropertyIns.java index 93ac26829..fb8099d63 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/DeletePropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/DeletePropertyIns.java @@ -58,7 +58,7 @@ public class DeletePropertyIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyIns.java index 915cface4..b9f9d090c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyIns.java @@ -63,7 +63,7 @@ public class FindPropertyIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); stack.push(new FindPropertyAVM2Item(ins, localData.lineStartInstruction, multiname)); //resolve right object } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyStrictIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyStrictIns.java index 339abea83..3c204a94a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyStrictIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/FindPropertyStrictIns.java @@ -63,7 +63,7 @@ public class FindPropertyStrictIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); stack.push(new FindPropertyAVM2Item(ins, localData.lineStartInstruction, multiname)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetDescendantsIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetDescendantsIns.java index f5d14edcd..526908693 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetDescendantsIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetDescendantsIns.java @@ -55,7 +55,7 @@ public class GetDescendantsIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); stack.push(new GetDescendantsAVM2Item(ins, localData.lineStartInstruction, obj, multiname)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java index da29cb667..800fc3c71 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java @@ -91,8 +91,8 @@ public class GetPropertyIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { - int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + int multinameIndex = ins.operands[0]; + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); //remove dups if (obj instanceof FindPropertyAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSuperIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSuperIns.java index d0d0deeb6..8fbd85093 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSuperIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetSuperIns.java @@ -45,7 +45,7 @@ public class GetSuperIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnValueIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnValueIns.java index 8bddf28bd..90c36acee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnValueIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnValueIns.java @@ -55,6 +55,7 @@ public class ReturnValueIns extends InstructionDefinition { if (value instanceof SetLocalAVM2Item) { value = value.value; } + stack.moveToOutput(output, true); output.add(new ReturnValueAVM2Item(ins, localData.lineStartInstruction, value)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnVoidIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnVoidIns.java index f7521a550..e51478b2c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnVoidIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ReturnVoidIns.java @@ -49,6 +49,7 @@ public class ReturnVoidIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + stack.moveToOutput(output, true); output.add(new ReturnVoidAVM2Item(ins, localData.lineStartInstruction)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java index 419ae6a58..1741a6c19 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java @@ -44,6 +44,7 @@ public class SetGlobalSlotIns extends InstructionDefinition implements SetTypeIn @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int slotIndex = ins.operands[0]; + stack.allowSwap(output); GraphTargetItem value = stack.pop(); GraphTargetItem obj = new GlobalAVM2Item(ins, localData.lineStartInstruction); SetSlotIns.handleSetSlot(localData, stack, ins, output, slotIndex, obj, value); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index afd4cf7e7..70ba8b38b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -61,6 +61,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int slotIndex = ins.operands[0]; + stack.allowSwap(output); GraphTargetItem value = stack.pop(); GraphTargetItem obj = stack.pop(); //scopeId if (obj.getThroughRegister() instanceof NewActivationAVM2Item) { @@ -100,7 +101,8 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { GetSlotAVM2Item slotItem = (GetSlotAVM2Item) inside; if ((slotItem.scope.getThroughRegister() == obj.getThroughRegister()) && (slotItem.slotName == slotname)) { - if (stack.size() > 0) { + stack.moveToStack(output); + if (!stack.isEmpty()) { GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); if (top == inside) { stack.pop(); @@ -109,9 +111,11 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { stack.pop(); stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } else { + stack.moveToOutput(output, false); output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } } else { + stack.moveToOutput(output, false); output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, inside)); } return; @@ -125,7 +129,8 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { GetSlotAVM2Item slotItem = (GetSlotAVM2Item) inside; if ((slotItem.scope.getThroughRegister() == obj.getThroughRegister()) && (slotItem.slotName == slotname)) { - if (stack.size() > 0) { + stack.moveToStack(output); + if (!stack.isEmpty()) { GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); if (top == inside) { stack.pop(); @@ -134,9 +139,11 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { stack.pop(); stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } else { + stack.moveToOutput(output, false); output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } } else { + stack.moveToOutput(output, false); output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, inside)); } return; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java index 58129500b..3a51ca6f1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java @@ -48,11 +48,13 @@ public class SetSuperIns extends InstructionDefinition implements SetTypeIns { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + stack.allowSwap(output); + int multinameIndex = ins.operands[0]; GraphTargetItem value = stack.pop(); - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); Reference isStatic = new Reference<>(false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ThrowIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ThrowIns.java index 92d474758..65433c007 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ThrowIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/ThrowIns.java @@ -51,7 +51,9 @@ public class ThrowIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { - output.add(new ThrowAVM2Item(ins, localData.lineStartInstruction, stack.pop())); + GraphTargetItem value = stack.pop(); + stack.moveToOutput(output, true); + output.add(new ThrowAVM2Item(ins, localData.lineStartInstruction, value)); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/DecLocalPIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/DecLocalPIns.java index 3a3346666..c367520c9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/DecLocalPIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/DecLocalPIns.java @@ -84,6 +84,7 @@ public class DecLocalPIns extends InstructionDefinition { } } if (!isPostDec) { + stack.moveToOutput(output, false); output.add(new DecLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/IncLocalPIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/IncLocalPIns.java index 80d82b890..3bdceaaf3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/IncLocalPIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/IncLocalPIns.java @@ -84,6 +84,7 @@ public class IncLocalPIns extends InstructionDefinition { } } if (!isPostInc) { + stack.moveToOutput(output, false); output.add(new IncLocalAVM2Item(ins, localData.lineStartInstruction, regId)); } if (localData.localRegs.containsKey(regId)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java index 7f75e97b0..24ba52a3a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopIns.java @@ -63,6 +63,7 @@ public class PopIns extends InstructionDefinition { return; } + stack.moveToOutput(output, false); output.add(top); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopScopeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopScopeIns.java index 441ce3cc3..2aed7ba54 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopScopeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PopScopeIns.java @@ -53,6 +53,7 @@ public class PopScopeIns extends InstructionDefinition { GraphTargetItem scope = localData.localScopeStack.pop(); if (scope instanceof WithObjectAVM2Item) { scope = ((WithObjectAVM2Item) scope).scope; + stack.moveToOutput(output, false); output.add(new WithEndAVM2Item(ins, localData.lineStartInstruction, scope)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushWithIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushWithIns.java index 713848eaf..b69843180 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushWithIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushWithIns.java @@ -45,6 +45,7 @@ public class PushWithIns extends InstructionDefinition { GraphTargetItem w = stack.pop(); WithObjectAVM2Item wot = new WithObjectAVM2Item(ins, localData.lineStartInstruction, w); localData.localScopeStack.push(wot); + stack.moveToOutput(output, false); output.add(new WithAVM2Item(ins, localData.lineStartInstruction, w)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java index d0f89e036..ef858a3f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java @@ -20,11 +20,18 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphTargetDialect; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.EscapeXAttrAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.graph.GraphSourceItemPos; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.DuplicateItem; +import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import java.util.List; /** @@ -55,10 +62,35 @@ public class SwapIns extends InstructionDefinition { GraphTargetItem o1 = stack.pop(); GraphTargetItem o2 = stack.pop(); - stack.push(o1); - stack.push(o2); - o1.getMoreSrc().add(new GraphSourceItemPos(ins, 0)); - o2.getMoreSrc().add(new GraphSourceItemPos(ins, 0)); + + if (((o1 instanceof ExceptionAVM2Item) && (o2 instanceof ExceptionAVM2Item)) + || + ( + ( + ((o1 instanceof SimpleValue) && ((SimpleValue) o1).isSimpleValue() && !(o1 instanceof DuplicateItem)) + || + (o1 instanceof EscapeXAttrAVM2Item) + ) + && + ( + ((o2 instanceof SimpleValue) && ((SimpleValue) o2).isSimpleValue() && !(o2 instanceof DuplicateItem)) + || + (o2 instanceof EscapeXAttrAVM2Item) + ) + + ) + ) { + stack.push(o1); + stack.push(o2); + o1.getMoreSrc().add(new GraphSourceItemPos(ins, 0)); + o2.getMoreSrc().add(new GraphSourceItemPos(ins, 0)); + return; + } + + stack.moveToOutput(output, false); + output.add(new PushItem(o2)); + output.add(new PushItem(o1)); + output.add(new SwapItem(AVM2GraphTargetDialect.INSTANCE, ins, localData.lineStartInstruction)); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java index a76ffe710..0395e5af7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java @@ -52,6 +52,7 @@ public class DXNSIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + stack.moveToOutput(output, false); //FIXME!!! - search namespace output.add(new DefaultXMLNamespace(ins, localData.lineStartInstruction, new StringAVM2Item(ins, localData.lineStartInstruction, localData.getConstants().getString(ins.operands[0])))); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java index 490dc3d03..81c7bf7de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java @@ -52,6 +52,7 @@ public class DXNSLateIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem xmlns = stack.pop(); + stack.moveToOutput(output, false); output.add(new DefaultXMLNamespace(ins, localData.lineStartInstruction, xmlns)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 6f0c68fde..d0d755f7a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -104,6 +104,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; @@ -3580,6 +3581,13 @@ public class AVM2SourceGenerator implements SourceGenerator { return ret; } + @Override + public List generate(SourceGeneratorLocalData localData, SwapItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.add(ins(AVM2Instructions.Swap)); + return ret; + } + /** * For some strange reasons, && and || operators must have coerced * both sides when there is specific type expected. diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index 22e2a00f5..f47cddef4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -118,6 +118,7 @@ import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.ParenthesisItem; import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; @@ -2460,6 +2461,9 @@ public class ActionScript3Parser { ret = new PopItem(DIALECT, null, null); allowMemberOrCall = true; break; + case "swap": + ret = new SwapItem(DIALECT, null, null); + break; case "goto": //TODO case "multiname": throw new AVM2ParseException("Compiling §§" + s.value + " is not available, sorry", lexer.yyline()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java index 916fb76b7..f6b55370e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java @@ -1886,6 +1886,9 @@ public class ActionScript3SimpleParser implements SimpleParser { ret = true; allowMemberOrCall = true; break; + case "swap": + ret = true; + break; case "goto": expectedType(errors, SymbolGroup.IDENTIFIER); //errors.add(new SimpleParseException("Compiling §§" + s.value + " is not available, sorry", lexer.yyline(), s.position)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index a6e89c41f..bb66b0fd7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -164,6 +164,7 @@ import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.ParenthesisItem; import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; @@ -1878,6 +1879,9 @@ public class ActionScript2Parser { ret = new PopItem(DIALECT, null, null); allowMemberOrCall = true; break; + case "swap": + ret = new SwapItem(DIALECT, null, null); + break; case "strict": s = lex(); expected(s, lexer.yyline(), SymbolType.INTEGER); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java index f8aba031b..8ced5125f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java @@ -1342,6 +1342,9 @@ public class ActionScript2SimpleParser implements SimpleParser { ret = true; allowMemberOrCall = true; break; + case "swap": + ret = true; + break; case "strict": s = lexer.lex(); expected(errors, s, lexer.yyline(), SymbolType.INTEGER); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java index fa55a8fe5..68af24437 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java @@ -40,6 +40,7 @@ import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; import com.jpexs.decompiler.flash.action.swf7.ActionExtends; @@ -65,6 +66,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; @@ -1191,7 +1193,6 @@ public class ActionSourceGenerator implements SourceGenerator { return ret; } - private int checkOffsetBounds(int offset, String errorItem, int errorLine) throws CompilationException { if (offset < -32768) { throw new CompilationException("Generated offset for " + errorItem + " is lower than mininum allowed for SI16.", errorLine); @@ -1201,4 +1202,10 @@ public class ActionSourceGenerator implements SourceGenerator { } return offset; } + @Override + public List generate(SourceGeneratorLocalData localData, SwapItem item) throws CompilationException { + List ret = new ArrayList<>(); + ret.add(new ActionStackSwap()); + return ret; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index f7a5111b9..4df34de95 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -3369,6 +3369,7 @@ public class Graph { if (code.size() <= part.start) { if (!(!ret.isEmpty() && ret.get(ret.size() - 1) instanceof ExitItem)) { + stack.moveToOutput(ret, true); ret.add(new ScriptEndItem(dialect)); } return ret; @@ -3533,6 +3534,7 @@ public class Graph { } while (exHappened); if ((part.end >= code.size() - 1) && getNextParts(localData, part).isEmpty()) { if (!(!output.isEmpty() && output.get(output.size() - 1) instanceof ExitItem)) { + stack.moveToOutput(output, true); output.add(new ScriptEndItem(dialect)); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java index a5e0172be..97d560a6a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java @@ -30,6 +30,7 @@ import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.OrItem; import com.jpexs.decompiler.graph.model.PopItem; import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.TernarOpItem; import com.jpexs.decompiler.graph.model.TrueItem; @@ -243,4 +244,14 @@ public interface SourceGenerator { * @throws CompilationException On compilation error */ public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException; + + /** + * Generates source code for SwapItem. + * + * @param localData Local data + * @param item SwapItem + * @return List of GraphSourceItem + * @throws CompilationException On compilation error + */ + public List generate(SourceGeneratorLocalData localData, SwapItem item) throws CompilationException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index 0976e92bf..cf60499d0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -16,7 +16,12 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; +import com.jpexs.decompiler.graph.model.BranchStackResistant; import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.PushItem; +import com.jpexs.decompiler.graph.model.SwapItem; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -144,6 +149,10 @@ public class TranslateStack extends Stack { public synchronized GraphTargetItem peek() { if (path != null) { if (this.isEmpty()) { + /*if (connectedOutput != null && !connectedOutput.isEmpty() && connectedOutput.get(connectedOutput.size() - 1) instanceof PushItem) { + PushItem pi = (PushItem) connectedOutput.get(connectedOutput.size() - 1); + return pi.value; + }*/ Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attempt to Peek empty stack", path); return getPop(); } @@ -160,6 +169,10 @@ public class TranslateStack extends Stack { public synchronized GraphTargetItem peek(int index) { if (path != null) { if (index > this.size()) { + /*if (connectedOutput != null && connectedOutput.size() >= index - this.size() && connectedOutput.get(connectedOutput.size() - (index - this.size())) instanceof PushItem) { + PushItem pi = (PushItem) connectedOutput.get(connectedOutput.size() - (index - this.size())); + return pi.value; + }*/ Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attempt to Peek item from stack", path); return getPop(); } @@ -176,6 +189,11 @@ public class TranslateStack extends Stack { public synchronized GraphTargetItem pop() { if (path != null) { if (this.isEmpty()) { + /*if (connectedOutput != null && !connectedOutput.isEmpty() && connectedOutput.get(connectedOutput.size() - 1) instanceof PushItem) { + PushItem pi = (PushItem) connectedOutput.remove(connectedOutput.size() - 1); + return pi.value; + }*/ + PopItem oldpop = getPop(); pop = null; Logger.getLogger(TranslateStack.class.getName()).log(Level.FINE, "{0}: Attempt to Pop empty stack", path); @@ -184,4 +202,68 @@ public class TranslateStack extends Stack { } return super.pop(); } + + public void moveToStack(List output) { + if (!isEmpty()) { + return; + } + int i = output.size() - 1; + for (; i >= 0; i--) { + if (!(output.get(i) instanceof PushItem)) { + break; + } + } + i++; + while(i < output.size()) { + PushItem pi = (PushItem) output.remove(i); + push(pi.value); + } + } + + public void moveToOutput(List output, boolean beforeExit) { + if (true) { + //return; + } + int pos = output.size(); + + for (int i = size() - 1; i >= 0; i--) { + GraphTargetItem item = get(i); + if (item instanceof BranchStackResistant) { + continue; + } + if (item instanceof NewActivationAVM2Item) { + break; + } + if (item instanceof ExceptionAVM2Item) { + break; + } + remove(i); + output.add(pos, beforeExit ? item : new PushItem(item)); + } + } + + public void allowSwap(List output) { + if (!isEmpty()) { + return; + } + if (output.size() < 3) { + return; + } + if (!(output.get(output.size() - 1) instanceof SwapItem)) { + return; + } + + if (!(output.get(output.size() - 2) instanceof PushItem)) { + return; + } + + if (!(output.get(output.size() - 3) instanceof PushItem)) { + return; + } + + output.remove(output.size() - 1); + push(((PushItem)output.remove(output.size() - 1)).value); + push(((PushItem)output.remove(output.size() - 1)).value); + //moveToStack(output); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java index 5119a8da5..c2bf1fb1c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DuplicateItem.java @@ -59,9 +59,9 @@ public class DuplicateItem extends GraphTargetItem implements SimpleValue { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - if (!value.hasSideEffect() || !Configuration.displayDupInstructions.get()) { + /*if (!value.hasSideEffect() || !Configuration.displayDupInstructions.get()) { return value.appendTry(writer, localData); - } + }*/ writer.append("§§dup("); value.appendTry(writer, localData); return writer.append(")"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwapItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwapItem.java new file mode 100644 index 000000000..2c35764c5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwapItem.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010-2025 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.model; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetDialect; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import java.util.List; + +/** + * Pop item from the stack. + * + * @author JPEXS + */ +public class SwapItem extends GraphTargetItem { + + /** + * Constructor. + * + * @param dialect Dialect + * @param src Source + * @param lineStartIns Line start instruction + */ + public SwapItem(GraphTargetDialect dialect, GraphSourceItem src, GraphSourceItem lineStartIns) { + super(dialect, src, lineStartIns, PRECEDENCE_PRIMARY); + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.append("§§swap()"); + return writer; + } + + @Override + public boolean hasReturnValue() { + return false; + } + + @Override + public GraphTargetItem returnType() { + return TypeItem.UNBOUNDED; + } + + @Override + public Object getResult() { + return Null.INSTANCE; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return generator.generate(localData, this); + } + + @Override + public boolean hasSideEffect() { + return true; //? + } +} diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index a0d3eef70..cf75b0913 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -341,13 +341,24 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testPushWhile() { decompileMethod("assembled", "testPushWhile", "var _loc3_:int = 5;\r\n" - + "§§push(obfuscated[\"xxx\"] = new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))());\r\n" + + "§§push(new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))());\r\n" + + "§§push(§§dup(new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))()));\r\n" + + "§§push(obfuscated);\r\n" + + "§§swap();\r\n" + + "§§pop()[\"xxx\"] = §§pop();\r\n" + "§§push(50);\r\n" + "while(§§dup(§§pop()))\r\n" + "{\r\n" - + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 0x29 ^ 0x6F;\r\n" - + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 0x54;\r\n" + + "§§push(§§pop());\r\n" + "§§push(§§pop() - 1);\r\n" + + "§§swap();\r\n" + + "§§push(§§pop());\r\n" + + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 0x29 ^ 0x6F;\r\n" + + "§§push(§§pop());\r\n" + + "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 0x54;\r\n" + + "§§push(§§pop());\r\n" + + "§§push(§§pop());\r\n" + + "§§swap();\r\n" + "}\r\n" + "§§pop();\r\n" + "§§pop();\r\n", diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java index 9a9e8ce1c..118995957 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java @@ -713,14 +713,16 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript + "var _loc1_:int = 5;\r\n" + "if(_loc1_ > 4)\r\n" + "{\r\n" + + "§§push(\"RET\");\r\n" + "trace(\"in finally\");\r\n" - + "return \"RET\";\r\n" + + "return §§pop();\r\n" + "}\r\n" + "trace(\"between\");\r\n" + "if(_loc1_ < 3)\r\n" + "{\r\n" + + "§§push(\"RE2\");\r\n" + "trace(\"in finally\");\r\n" - + "return \"RE2\";\r\n" + + "return §§pop();\r\n" + "}\r\n" + "trace(\"in try2\");\r\n" + "}\r\n" @@ -788,9 +790,10 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript + "trace(\"in try2\");\r\n" + "if(_loc1_ > 4)\r\n" + "{\r\n" + + "§§push(\"RET\");\r\n" + "trace(\"in finally2\");\r\n" + "trace(\"in finally1\");\r\n" - + "return \"RET\";\r\n" + + "return §§pop();\r\n" + "}\r\n" + "}\r\n" + "catch(e:Error)\r\n" @@ -832,10 +835,11 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript + "trace(\"in try2\");\r\n" + "if(_loc1_ > 4)\r\n" + "{\r\n" + + "§§push(\"RET\");\r\n" + "trace(\"in finally2\");\r\n" + "trace(\"in finally1\");\r\n" + "trace(\"in finally0\");\r\n" - + "return \"RET\";\r\n" + + "return §§pop();\r\n" + "}\r\n" + "}\r\n" + "catch(e2:Error)\r\n"