Better Pre/Post increments/decrements.

Temporary registers hidden.
This commit is contained in:
Jindra Pet��k
2012-12-25 20:47:34 +01:00
parent 6ee4949ca7
commit ede22092f9
14 changed files with 297 additions and 301 deletions
+10 -145
View File
@@ -527,6 +527,8 @@ public class AVM2Code {
};
//endoflist
public static InstructionDefinition instructionSetByCode[] = buildInstructionSetByCode();
public boolean hideTemporaryRegisters=true;
private static InstructionDefinition[] buildInstructionSetByCode() {
InstructionDefinition result[] = new InstructionDefinition[256];
@@ -948,7 +950,7 @@ public class AVM2Code {
return localRegNames;
}
private void clearKilledAssigments(List<TreeItem> output) {
private void clearTemporaryRegisters(List<TreeItem> output) {
for (int i = 0; i < output.size(); i++) {
if (output.get(i) instanceof SetLocalTreeItem) {
if (isKilled(((SetLocalTreeItem) output.get(i)).regIndex, 0, code.size() - 1)) {
@@ -1471,148 +1473,6 @@ public class AVM2Code {
} else if (insAfter.definition instanceof IfTrueIns) {
//stack.add("(" + stack.pop() + ")||");
isAnd = false;
} else if ((insAfter.definition instanceof IncrementIIns) || ((insAfter.definition instanceof IncrementIns))) {
int np = -1;
if (((np = ipOfType(ip + 2, false, SetLocalTypeIns.class, CoerceOrConvertTypeIns.class, start, end)) > -1)
&& (ipOfType(ip - 1, true, GetLocalTypeIns.class, CoerceOrConvertTypeIns.class, start, end) > -1)) {
stack.add(new PostIncrementTreeItem(insAfter, stack.pop()));
ip = np + 1;
addr = pos2adr(ip);
break;
}
if (((ip - 1 >= start) && (ip + 2 <= end))
&& (code.get(ip + 2).definition instanceof SetLocalTypeIns)
&& (isKilled(((SetLocalTypeIns) code.get(ip + 2).definition).getRegisterId(code.get(ip + 2)), ip + 3, end))) {
int pos = -1;
for (int d = ip + 3; d <= end; d++) {
if (!((code.get(d).definition instanceof GetLocalTypeIns)
&& (isKilled(((GetLocalTypeIns) code.get(d).definition).getRegisterId(code.get(d)), d + 1, end)))) {
pos = d;
break;
}
}
if (pos > -1) {
if (code.get(pos).definition instanceof SetTypeIns) {
stack.push(new PostIncrementTreeItem(insAfter, stack.pop()));
ip = pos + 1;
addr = pos2adr(ip);
break;
}
}
}
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames);
ip++;
addr = pos2adr(ip);
break;
} else if ((insAfter.definition instanceof DecrementIIns) || ((insAfter.definition instanceof DecrementIns))) {
int np = -1;
if (((np = ipOfType(ip + 2, false, SetLocalTypeIns.class, CoerceOrConvertTypeIns.class, start, end)) > -1)
&& (ipOfType(ip - 1, true, GetLocalTypeIns.class, CoerceOrConvertTypeIns.class, start, end) > -1)) {
stack.add(new PostDecrementTreeItem(insAfter, stack.pop()));
ip = np + 1;
addr = pos2adr(ip);
break;
}
if (((ip - 1 >= start) && (ip + 2 <= end))
&& (code.get(ip + 2).definition instanceof SetLocalTypeIns)
&& (isKilled(((SetLocalTypeIns) code.get(ip + 2).definition).getRegisterId(code.get(ip + 2)), ip + 3, end))) {
int pos = -1;
for (int d = ip + 3; d <= end; d++) {
if (!((code.get(d).definition instanceof GetLocalTypeIns)
&& (isKilled(((GetLocalTypeIns) code.get(d).definition).getRegisterId(code.get(d)), d + 1, end)))) {
pos = d;
break;
}
}
if (pos > -1) {
if (code.get(pos).definition instanceof SetTypeIns) {
stack.push(new PostDecrementTreeItem(insAfter, stack.pop()));
ip = pos + 1;
addr = pos2adr(ip);
break;
}
}
}
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames);
ip++;
addr = pos2adr(ip);
break;
} else if ((insBefore.definition instanceof IncrementIIns) || ((insBefore.definition instanceof IncrementIns))) {
if (((ip - 2 >= start) && (ip + 2 <= end)) && (code.get(ip + 1).definition instanceof CoerceOrConvertTypeIns) && (code.get(ip + 2).definition instanceof SetLocalTypeIns) && (code.get(ip - 2).definition instanceof GetLocalTypeIns)) {
stack.pop();
int regId = ((SetLocalTypeIns) code.get(ip + 2).definition).getRegisterId(code.get(ip + 2));
stack.add(new PreIncrementTreeItem(insBefore, new LocalRegTreeItem(code.get(ip + 2), regId, localRegs.get(regId))));
ip += 3;
addr = pos2adr(ip);
break;
}
if (((ip - 1 >= start) && (ip + 2 <= end))
&& (code.get(ip + 1).definition instanceof SetLocalTypeIns)
&& (isKilled(((SetLocalTypeIns) code.get(ip + 1).definition).getRegisterId(code.get(ip + 1)), ip + 2, end))) {
int pos = -1;
for (int d = ip + 2; d <= end; d++) {
if (!((code.get(d).definition instanceof GetLocalTypeIns)
&& (isKilled(((GetLocalTypeIns) code.get(d).definition).getRegisterId(code.get(d)), d + 1, end)))) {
pos = d;
break;
}
}
if (pos > -1) {
if (code.get(pos).definition instanceof SetTypeIns) {
TreeItem s = stack.pop();
if (s instanceof IncrementTreeItem) {
stack.push(new PreIncrementTreeItem(insBefore, ((IncrementTreeItem) s).object));
}
ip = pos + 1;
addr = pos2adr(ip);
break;
}
}
}
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames);
ip++;
addr = pos2adr(ip);
break;
} else if ((insBefore.definition instanceof DecrementIIns) || ((insBefore.definition instanceof DecrementIns))) {
if (((ip - 2 >= start) && (ip + 2 <= end)) && (code.get(ip + 1).definition instanceof CoerceOrConvertTypeIns) && (code.get(ip + 2).definition instanceof SetLocalTypeIns) && (code.get(ip - 2).definition instanceof GetLocalTypeIns)) {
stack.pop();
int regId = ((SetLocalTypeIns) code.get(ip + 2).definition).getRegisterId(code.get(ip + 2));
stack.add(new PreDecrementTreeItem(insBefore, new LocalRegTreeItem(code.get(ip + 2), regId, localRegs.get(regId))));
ip += 3;
addr = pos2adr(ip);
break;
}
if (((ip - 1 >= start) && (ip + 2 <= end))
&& (code.get(ip + 1).definition instanceof SetLocalTypeIns)
&& (isKilled(((SetLocalTypeIns) code.get(ip + 1).definition).getRegisterId(code.get(ip + 1)), ip + 2, end))) {
int pos = -1;
for (int d = ip + 2; d <= end; d++) {
if (!((code.get(d).definition instanceof GetLocalTypeIns)
&& (isKilled(((GetLocalTypeIns) code.get(d).definition).getRegisterId(code.get(d)), d + 1, end)))) {
pos = d;
break;
}
}
if (pos > -1) {
if (code.get(pos).definition instanceof SetTypeIns) {
TreeItem s = stack.pop();
if (s instanceof DecrementTreeItem) {
stack.push(new PreDecrementTreeItem(insBefore, ((DecrementTreeItem) s).object));
}
ip = pos + 1;
addr = pos2adr(ip);
break;
}
}
}
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames);
ip++;
addr = pos2adr(ip);
break;
} else if (insAfter.definition instanceof SetLocalTypeIns) {
//chained assignments
int reg = (((SetLocalTypeIns) insAfter.definition).getRegisterId(insAfter));
@@ -1728,7 +1588,10 @@ public class AVM2Code {
if (debugMode) {
System.out.println("CLOSE SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString());
}
//clearKilledAssigments(output);
if(hideTemporaryRegisters)
{
clearTemporaryRegisters(output);
}
return new ConvertOutput(stack, output);
} catch (ConvertException cex) {
throw cex;
@@ -1736,6 +1599,7 @@ public class AVM2Code {
if (ex instanceof UnknownJumpException) {
throw (UnknownJumpException) ex;
}
ex.printStackTrace();
throw new ConvertException(ex.getClass().getSimpleName(), ip);
}
}
@@ -1813,6 +1677,7 @@ public class AVM2Code {
list = toSource(isStatic, classIndex, localRegs, new Stack<TreeItem>(), new Stack<TreeItem>(), abc, constants, method_info, body, 0, code.size() - 1, localRegNames).output;
s = listToString(list, constants, localRegNames);
} catch (Exception ex) {
ex.printStackTrace();
s = "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex.getMessage() + "\r\n */";
return s;
}
@@ -1842,7 +1707,7 @@ public class AVM2Code {
}
HashMap<Integer, String> localRegTypes = getLocalRegTypes(constants);
for (int i = paramCount + 1; i < regCount; i++) {
if ((!(localRegs.get(i) instanceof NewActivationTreeItem))/*&&(!isKilled(i, 0, code.size()-1))*/) {
if ((!(localRegs.get(i) instanceof NewActivationTreeItem)&&((!hideTemporaryRegisters)||(!isKilled(i, 0, code.size()-1))))) {
sub += "var " + TreeItem.localRegName(localRegNames, i);
if (localRegTypes.containsKey(i)) {
sub += ":" + localRegTypes.get(i);
@@ -31,42 +31,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SetLocal0Ins extends InstructionDefinition implements SetTypeIns, SetLocalTypeIns {
public class SetLocal0Ins extends SetLocalTypeIns {
public SetLocal0Ins() {
super(0xd4, "setlocal_0", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.localRegisters.put(0, lda.operandStack.pop());
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem val = (TreeItem) stack.pop();
localRegs.put(0, val);
if (val instanceof NewActivationTreeItem) {
return;
}
if (val instanceof FindPropertyTreeItem) {
return;
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, 0, val));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, 0);
}
public int getRegisterId(AVM2Instruction ins) {
return 0;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -31,42 +31,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SetLocal1Ins extends InstructionDefinition implements SetTypeIns, SetLocalTypeIns {
public class SetLocal1Ins extends SetLocalTypeIns {
public SetLocal1Ins() {
super(0xd5, "setlocal_1", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.localRegisters.put(1, lda.operandStack.pop());
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem val = (TreeItem) stack.pop();
localRegs.put(1, val);
if (val instanceof NewActivationTreeItem) {
return;
}
if (val instanceof FindPropertyTreeItem) {
return;
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, 1, val));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, 1);
}
public int getRegisterId(AVM2Instruction ins) {
return 1;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -31,42 +31,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SetLocal2Ins extends InstructionDefinition implements SetTypeIns, SetLocalTypeIns {
public class SetLocal2Ins extends SetLocalTypeIns {
public SetLocal2Ins() {
super(0xd6, "setlocal_2", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.localRegisters.put(2, lda.operandStack.pop());
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem val = (TreeItem) stack.pop();
localRegs.put(2, val);
if (val instanceof NewActivationTreeItem) {
return;
}
if (val instanceof FindPropertyTreeItem) {
return;
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, 2, val));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, 2);
}
public int getRegisterId(AVM2Instruction ins) {
return 2;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -31,42 +31,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SetLocal3Ins extends InstructionDefinition implements SetTypeIns, SetLocalTypeIns {
public class SetLocal3Ins extends SetLocalTypeIns {
public SetLocal3Ins() {
super(0xd7, "setlocal_3", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.localRegisters.put(3, lda.operandStack.pop());
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem val = (TreeItem) stack.pop();
localRegs.put(3, val);
if (val instanceof NewActivationTreeItem) {
return;
}
if (val instanceof FindPropertyTreeItem) {
return;
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, 3, val));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, 3);
}
public int getRegisterId(AVM2Instruction ins) {
return 3;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -32,42 +32,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SetLocalIns extends InstructionDefinition implements SetTypeIns, SetLocalTypeIns {
public class SetLocalIns extends SetLocalTypeIns {
public SetLocalIns() {
super(0x63, "setlocal", new int[]{AVM2Code.DAT_LOCAL_REG_INDEX});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.localRegisters.put((int) (long) (Long) arguments.get(0), lda.operandStack.pop());
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem val = (TreeItem) stack.pop();
localRegs.put(ins.operands[0], val);
if (val instanceof NewActivationTreeItem) {
return;
}
if (val instanceof FindPropertyTreeItem) {
return;
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, ins.operands[0], val));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, ins.operands[0]);
}
public int getRegisterId(AVM2Instruction ins) {
return ins.operands[0];
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -16,9 +16,104 @@
*/
package com.jpexs.asdec.abc.avm2.instructions.localregs;
import com.jpexs.asdec.abc.ABC;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.asdec.abc.avm2.instructions.SetTypeIns;
import com.jpexs.asdec.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.FindPropertyTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.GetPropertyTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.NewActivationTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostIncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.SetLocalTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreIncrementTreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public interface SetLocalTypeIns {
public abstract class SetLocalTypeIns extends InstructionDefinition implements SetTypeIns {
public SetLocalTypeIns(int instructionCode, String instructionName, int[] operands) {
super(instructionCode, instructionName, operands);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
int regId = getRegisterId(ins);
TreeItem value = (TreeItem) stack.pop();
localRegs.put(regId, value);
if (value instanceof NewActivationTreeItem) {
return;
}
if (value instanceof FindPropertyTreeItem) {
return;
}
if (value.getNotCoerced() instanceof IncrementTreeItem) {
TreeItem inside = ((IncrementTreeItem) value.getNotCoerced()).object.getNotCoerced();
if (inside instanceof LocalRegTreeItem) {
if (((LocalRegTreeItem) inside).regIndex == regId) {
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == inside) {
stack.pop();
stack.push(new PostIncrementTreeItem(ins, inside));
} else if ((top instanceof IncrementTreeItem) && (((IncrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreIncrementTreeItem(ins, inside));
} else {
output.add(new PostIncrementTreeItem(ins, inside));
}
} else {
output.add(new PostIncrementTreeItem(ins, inside));
}
return;
}
}
}
if (value.getNotCoerced() instanceof DecrementTreeItem) {
TreeItem inside = ((DecrementTreeItem) value.getNotCoerced()).object.getNotCoerced();
if (inside instanceof LocalRegTreeItem) {
if (((LocalRegTreeItem) inside).regIndex == regId) {
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == inside) {
stack.pop();
stack.push(new PostDecrementTreeItem(ins, inside));
} else if ((top instanceof DecrementTreeItem) && (((DecrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreDecrementTreeItem(ins, inside));
} else {
output.add(new PostDecrementTreeItem(ins, inside));
}
} else {
output.add(new PostDecrementTreeItem(ins, inside));
}
return;
}
}
}
//if(val.startsWith("catchscope ")) return;
//if(val.startsWith("newactivation()")) return;
output.add(new SetLocalTreeItem(ins, regId, value));
}
public String getObject(Stack<TreeItem> stack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, HashMap<Integer, String> localRegNames) {
return TreeItem.localRegName(localRegNames, getRegisterId(ins));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
public abstract int getRegisterId(AVM2Instruction ins);
}
@@ -22,9 +22,17 @@ import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.asdec.abc.avm2.instructions.SetTypeIns;
import com.jpexs.asdec.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.GetPropertyTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostIncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.SetPropertyTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreIncrementTreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
@@ -42,6 +50,65 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
TreeItem value = (TreeItem) stack.pop();
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem obj = (TreeItem) stack.pop();
if (value.getThroughRegister() instanceof IncrementTreeItem) {
TreeItem inside = ((IncrementTreeItem) value.getThroughRegister()).object.getThroughRegister().getNotCoerced();
if (inside instanceof GetPropertyTreeItem) {
GetPropertyTreeItem insideProp = ((GetPropertyTreeItem) inside);
if (insideProp.propertyName.compareSame(multiname)) {
TreeItem insideObj = obj;
if (insideObj instanceof LocalRegTreeItem) {
insideObj = ((LocalRegTreeItem) insideObj).computedValue;
}
if (insideProp.object == insideObj) {
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == insideProp) {
stack.pop();
stack.push(new PostIncrementTreeItem(ins, insideProp));
} else if ((top instanceof IncrementTreeItem) && (((IncrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreIncrementTreeItem(ins, insideProp));
} else {
output.add(new PostIncrementTreeItem(ins, insideProp));
}
} else {
output.add(new PostIncrementTreeItem(ins, insideProp));
}
return;
}
}
}
}
if (value.getThroughRegister() instanceof DecrementTreeItem) {
TreeItem inside = ((DecrementTreeItem) value.getThroughRegister()).object.getThroughRegister().getNotCoerced();
if (inside instanceof GetPropertyTreeItem) {
GetPropertyTreeItem insideProp = ((GetPropertyTreeItem) inside);
if (insideProp.propertyName.compareSame(multiname)) {
TreeItem insideObj = obj;
if (insideObj instanceof LocalRegTreeItem) {
insideObj = ((LocalRegTreeItem) insideObj).computedValue;
}
if (insideProp.object == insideObj) {
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == insideProp) {
stack.pop();
stack.push(new PostDecrementTreeItem(ins, insideProp));
} else if ((top instanceof DecrementTreeItem) && (((DecrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreDecrementTreeItem(ins, insideProp));
} else {
output.add(new PostDecrementTreeItem(ins, insideProp));
}
} else {
output.add(new PostDecrementTreeItem(ins, insideProp));
}
return;
}
}
}
}
output.add(new SetPropertyTreeItem(ins, obj, multiname, value));
}
@@ -22,10 +22,18 @@ import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.asdec.abc.avm2.instructions.SetTypeIns;
import com.jpexs.asdec.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.GetSlotTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.NewActivationTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostIncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.SetSlotTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.clauses.ExceptionTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreIncrementTreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import com.jpexs.asdec.abc.types.Multiname;
import com.jpexs.asdec.abc.types.traits.TraitSlotConst;
@@ -65,7 +73,59 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
return;
}
}
if (value.getNotCoerced() instanceof IncrementTreeItem) {
TreeItem inside = ((IncrementTreeItem) value.getNotCoerced()).object.getThroughRegister().getNotCoerced();
if (inside instanceof GetSlotTreeItem) {
GetSlotTreeItem slotItem=(GetSlotTreeItem)inside;
if ((slotItem.scope.getThroughRegister()==obj.getThroughRegister())
&&(slotItem.slotName==slotname))
{
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == inside) {
stack.pop();
stack.push(new PostIncrementTreeItem(ins, inside));
} else if ((top instanceof IncrementTreeItem) && (((IncrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreIncrementTreeItem(ins, inside));
} else {
output.add(new PostIncrementTreeItem(ins, inside));
}
} else {
output.add(new PostIncrementTreeItem(ins, inside));
}
return;
}
}
}
if (value.getNotCoerced() instanceof DecrementTreeItem) {
TreeItem inside = ((DecrementTreeItem) value.getNotCoerced()).object.getThroughRegister().getNotCoerced();
if (inside instanceof GetSlotTreeItem) {
GetSlotTreeItem slotItem=(GetSlotTreeItem)inside;
if ((slotItem.scope.getThroughRegister()==obj.getThroughRegister())
&&(slotItem.slotName==slotname))
{
if (stack.size() > 0) {
TreeItem top = stack.peek().getNotCoerced();
if (top == inside) {
stack.pop();
stack.push(new PostDecrementTreeItem(ins, inside));
} else if ((top instanceof DecrementTreeItem) && (((DecrementTreeItem) top).object == inside)) {
stack.pop();
stack.push(new PreDecrementTreeItem(ins, inside));
} else {
output.add(new PostDecrementTreeItem(ins, inside));
}
} else {
output.add(new PostDecrementTreeItem(ins, inside));
}
return;
}
}
}
output.add(new SetSlotTreeItem(ins, obj, slotname, value));
}
@@ -43,7 +43,7 @@ public class DupIns extends InstructionDefinition {
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames) {
TreeItem v = (TreeItem) stack.pop();
stack.push(v);
stack.push(v);
stack.push(v);
}
@@ -36,4 +36,9 @@ public class ConvertTreeItem extends TreeItem {
//return hilight("("+type+")")+
return value.toString(constants, localRegNames);
}
@Override
public TreeItem getNotCoerced() {
return value;
}
}
@@ -24,8 +24,8 @@ public class FullMultinameTreeItem extends TreeItem {
public int multinameIndex;
public TreeItem name;
public TreeItem namespace;
public TreeItem namespace;
public FullMultinameTreeItem(AVM2Instruction instruction, int multinameIndex, TreeItem name) {
super(instruction, PRECEDENCE_PRIMARY);
this.multinameIndex = multinameIndex;
@@ -69,4 +69,37 @@ public class FullMultinameTreeItem extends TreeItem {
}
return ret;
}
public boolean compareSame(FullMultinameTreeItem other)
{
if(multinameIndex!=other.multinameIndex){
return false;
}
TreeItem tiName=name;
while(tiName instanceof LocalRegTreeItem){
tiName=((LocalRegTreeItem)tiName).computedValue;
}
TreeItem tiName2=other.name;
while(tiName2 instanceof LocalRegTreeItem){
tiName2=((LocalRegTreeItem)tiName2).computedValue;
}
if(tiName!=tiName2){
return false;
}
TreeItem tiNameSpace=namespace;
while(tiNameSpace instanceof LocalRegTreeItem){
tiNameSpace=((LocalRegTreeItem)tiNameSpace).computedValue;
}
TreeItem tiNameSpace2=other.namespace;
while(tiNameSpace2 instanceof LocalRegTreeItem){
tiNameSpace2=((LocalRegTreeItem)tiNameSpace2).computedValue;
}
if(tiNameSpace!=tiNameSpace2){
return false;
}
return true;
}
}
@@ -48,4 +48,11 @@ public class LocalRegTreeItem extends TreeItem {
public boolean isTrue() {
return computedValue.isTrue();
}
@Override
public TreeItem getThroughRegister() {
return computedValue.getThroughRegister();
}
}
@@ -42,13 +42,17 @@ public abstract class TreeItem {
public static final int NOPRECEDENCE = 16;
public int precedence = NOPRECEDENCE;
public AVM2Instruction instruction;
public TreeItem(AVM2Instruction instruction, int precedence) {
this.instruction = instruction;
this.precedence = precedence;
}
public abstract String toString(ConstantPool constants, HashMap<Integer, String> localRegNames);
public String toStringNoH(ConstantPool constants, HashMap<Integer, String> localRegNames){
return Highlighting.stripHilights(toString(constants,localRegNames));
}
public String toStringSemicoloned(ConstantPool constants, HashMap<Integer, String> localRegNames) {
return toString(constants, localRegNames) + (needsSemicolon() ? ";" : "");
@@ -104,6 +108,10 @@ public abstract class TreeItem {
public TreeItem getNotCoerced() {
return this;
}
public TreeItem getThroughRegister() {
return this;
}
public static String localRegName(HashMap<Integer, String> localRegNames, int reg) {
if (localRegNames.containsKey(reg)) {