From 23227caacda6cdefe6314eb47ce583f2edc53051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 7 Mar 2021 22:08:59 +0100 Subject: [PATCH] AS3 - Compound assignments detection --- .../localregs/SetLocalTypeIns.java | 4 +-- .../instructions/other/InitPropertyIns.java | 7 +++-- .../instructions/other/SetPropertyIns.java | 27 +++++++++++++++---- .../avm2/instructions/other/SetSlotIns.java | 18 ++++++++++++- .../avm2/instructions/other/SetSuperIns.java | 19 ++++++++++++- .../decompiler/graph/GraphTargetItem.java | 13 ++++++++- .../decompiler/graph/model/DuplicateItem.java | 9 ++++++- 7 files changed, 84 insertions(+), 13 deletions(-) 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 9b0f296d1..88e9b35eb 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 @@ -125,7 +125,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S } SetLocalAVM2Item result = new SetLocalAVM2Item(ins, localData.lineStartInstruction, regId, value); - /*if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) { + if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) { CompoundableBinaryOp binaryOp = (CompoundableBinaryOp) value.getNotCoercedNoDup(); if (binaryOp.getLeftSide() instanceof LocalRegAVM2Item) { LocalRegAVM2Item loc = (LocalRegAVM2Item) binaryOp.getLeftSide(); @@ -134,7 +134,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S result.setCompoundOperator(binaryOp.getOperator()); } } - }*/ + } SetTypeIns.handleResult(value, stack, output, localData, result, regId); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java index 09f168717..7aff137f4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.instructions.other; import com.jpexs.decompiler.flash.abc.ABC; @@ -43,7 +44,9 @@ public class InitPropertyIns extends InstructionDefinition { GraphTargetItem val = stack.pop(); FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); GraphTargetItem obj = stack.pop(); - output.add(new InitPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, val)); + InitPropertyAVM2Item result = new InitPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, val); + SetPropertyIns.handleCompound(obj, multiname, val, output, result); + output.add(result); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java index 8b22152f6..83bcd5e3a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java @@ -37,6 +37,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; @@ -337,8 +338,12 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns } SetPropertyAVM2Item result = new SetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, value); + handleCompound(obj, multiname, value, output, result); - /* + SetTypeIns.handleResult(value, stack, output, localData, result, -1); + } + + public static void handleCompound(GraphTargetItem obj, FullMultinameAVM2Item multiname, GraphTargetItem value, List output, SetTypeAVM2Item result) { if (value instanceof LocalRegAVM2Item) { LocalRegAVM2Item locVal = (LocalRegAVM2Item) value; if (multiname.name instanceof LocalRegAVM2Item) { @@ -356,8 +361,8 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) binaryOp.getLeftSide(); if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname) && Objects.equals(getProp.object, obj)) { multiname.name = setLocName.value; - result.compoundValue = binaryOp.getRightSide(); - result.compoundOperator = binaryOp.getOperator(); + result.setCompoundValue(binaryOp.getRightSide()); + result.setCompoundOperator(binaryOp.getOperator()); output.remove(output.size() - 2); output.remove(output.size() - 1); } @@ -369,8 +374,20 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns } } } - }*/ - SetTypeIns.handleResult(value, stack, output, localData, result, -1); + } + + if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) { + if (!obj.hasSideEffect() && !multiname.hasSideEffect()) { + CompoundableBinaryOp binaryOp = (CompoundableBinaryOp) value.getNotCoercedNoDup(); + if (binaryOp.getLeftSide() instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item propItem = (GetPropertyAVM2Item) binaryOp.getLeftSide(); + if (Objects.equals(obj, propItem.object.getThroughDuplicate()) && Objects.equals(multiname, propItem.propertyName)) { + result.setCompoundValue(binaryOp.getRightSide()); + result.setCompoundOperator(binaryOp.getOperator()); + } + } + } + } } @Override 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 adab26d4a..1d05285fc 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 @@ -39,9 +39,11 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.CompoundableBinaryOp; import com.jpexs.helpers.Reference; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.Stack; /** @@ -140,7 +142,21 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { } } - GraphTargetItem result = new SetSlotAVM2Item(ins, localData.lineStartInstruction, obj, objnoreg, slotIndex, slotname, value); + SetSlotAVM2Item result = new SetSlotAVM2Item(ins, localData.lineStartInstruction, obj, objnoreg, slotIndex, slotname, value); + + if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) { + if (!obj.hasSideEffect()) { + CompoundableBinaryOp binaryOp = (CompoundableBinaryOp) value.getNotCoercedNoDup(); + if (binaryOp.getLeftSide() instanceof GetSlotAVM2Item) { + GetSlotAVM2Item getSlot = (GetSlotAVM2Item) binaryOp.getLeftSide(); + if (Objects.equals(obj, getSlot.scope.getThroughDuplicate()) && slotIndex == getSlot.slotIndex) { + result.compoundValue = binaryOp.getRightSide(); + result.compoundOperator = binaryOp.getOperator(); + } + } + } + } + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } 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 80afe1ba2..afe459d9f 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 @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.GetSuperAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetSuperAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -31,9 +32,11 @@ import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.graph.DottedChain; 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.LocalData; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.Stack; /** @@ -54,7 +57,21 @@ public class SetSuperIns extends InstructionDefinition implements SetTypeIns { FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); GraphTargetItem obj = stack.pop(); - GraphTargetItem result = new SetSuperAVM2Item(ins, localData.lineStartInstruction, value, obj, multiname); + SetSuperAVM2Item result = new SetSuperAVM2Item(ins, localData.lineStartInstruction, value, obj, multiname); + + if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) { + if (!obj.hasSideEffect() && !multiname.hasSideEffect()) { + CompoundableBinaryOp binaryOp = (CompoundableBinaryOp) value.getNotCoercedNoDup(); + if (binaryOp.getLeftSide() instanceof GetSuperAVM2Item) { + GetSuperAVM2Item getSuper = (GetSuperAVM2Item) binaryOp.getLeftSide(); + if (Objects.equals(obj, getSuper.object.getThroughDuplicate()) && Objects.equals(multiname, getSuper.propertyName)) { + result.setCompoundValue(binaryOp.getRightSide()); + result.setCompoundOperator(binaryOp.getOperator()); + } + } + } + } + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 26e95c5df..a2790264f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -41,8 +41,10 @@ import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.TrueItem; +import com.jpexs.helpers.Reference; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -372,7 +374,16 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { } public boolean hasSideEffect() { - return false; + Reference ref = new Reference<>(false); + visitRecursively(new AbstractGraphTargetVisitor() { + @Override + public void visit(GraphTargetItem item) { + if (item.hasSideEffect()) { + ref.setVal(Boolean.TRUE); + } + } + }); + return ref.getVal(); } public boolean isVariableComputed() { 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 6c8903c58..614f904c8 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 @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -118,4 +119,10 @@ public class DuplicateItem extends GraphTargetItem implements SimpleValue { public boolean isSimpleValue() { return ((value instanceof SimpleValue) && ((SimpleValue) value).isSimpleValue()); } + + @Override + public boolean hasSideEffect() { + return value.hasSideEffect(); + } + }