mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-07 19:15:04 +00:00
AS3 - improved switch handling
This commit is contained in:
@@ -444,7 +444,7 @@ public class AVM2Graph extends Graph {
|
||||
ret.addAll(output);
|
||||
return ret;
|
||||
}
|
||||
if (((part.nextParts.size() == 2)
|
||||
if (false && (((part.nextParts.size() == 2)
|
||||
&& (!stack.isEmpty())
|
||||
&& (stack.peek() instanceof StrictEqAVM2Item)
|
||||
&& (part.nextParts.get(0).getHeight() >= 2)
|
||||
@@ -457,7 +457,7 @@ public class AVM2Graph extends Graph {
|
||||
&& (part.nextParts.get(1).getHeight() >= 2)
|
||||
&& (this.avm2code.code.get(this.avm2code.fixIPAfterDebugLine(part.nextParts.get(1).start)).definition instanceof PushIntegerTypeIns)
|
||||
&& (!part.nextParts.get(1).nextParts.isEmpty())
|
||||
&& (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) {
|
||||
&& (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns)))) {
|
||||
|
||||
if (stack.peek() instanceof StrictEqAVM2Item) {
|
||||
ignoredSwitches2.add(part.nextParts.get(0).nextParts.get(0).end);
|
||||
@@ -815,6 +815,16 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
if (avm2code.isKilled(ri.regIndex, 0, Integer.MAX_VALUE)) {
|
||||
if (i + 1 < list.size()) {
|
||||
if (list.get(i + 1) instanceof SwitchItem) {
|
||||
SwitchItem si = (SwitchItem) list.get(i + 1);
|
||||
if (si.switchedObject instanceof LocalRegAVM2Item) {
|
||||
if (((LocalRegAVM2Item) si.switchedObject).regIndex == ri.regIndex) {
|
||||
si.switchedObject = ri.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i + 2 < list.size()) {
|
||||
if ((list.get(i + 1) instanceof IntegerValueAVM2Item) && (list.get(i + 2) instanceof ReturnValueAVM2Item)) {
|
||||
ReturnValueAVM2Item r = (ReturnValueAVM2Item) list.get(i + 2);
|
||||
|
||||
@@ -29,11 +29,12 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SimpleValue;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.IntegerValueTypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class IntegerValueAVM2Item extends NumberValueAVM2Item {
|
||||
public class IntegerValueAVM2Item extends NumberValueAVM2Item implements IntegerValueTypeItem {
|
||||
|
||||
public Long value;
|
||||
|
||||
@@ -81,4 +82,9 @@ public class IntegerValueAVM2Item extends NumberValueAVM2Item {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return (int) (long) value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,4 +125,27 @@ public class LocalRegAVM2Item extends AVM2Item {
|
||||
public boolean hasReturnValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 67 * hash + this.regIndex;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final LocalRegAVM2Item other = (LocalRegAVM2Item) obj;
|
||||
if (this.regIndex != other.regIndex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfEqIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNeIns;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.EqualsTypeItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
@@ -32,7 +33,7 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.LogicalOpItem;
|
||||
import java.util.List;
|
||||
|
||||
public class EqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondition {
|
||||
public class EqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondition, EqualsTypeItem {
|
||||
|
||||
public EqAVM2Item(GraphSourceItem instruction, GraphTargetItem leftSide, GraphTargetItem rightSide) {
|
||||
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "==");
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.EqualsTypeItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
@@ -32,7 +33,7 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.LogicalOpItem;
|
||||
import java.util.List;
|
||||
|
||||
public class StrictEqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondition {
|
||||
public class StrictEqAVM2Item extends BinaryOpItem implements LogicalOpItem, IfCondition, EqualsTypeItem {
|
||||
|
||||
public StrictEqAVM2Item(GraphSourceItem instruction, GraphTargetItem leftSide, GraphTargetItem rightSide) {
|
||||
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "===");
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.EqualsTypeItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
@@ -29,7 +30,7 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.LogicalOpItem;
|
||||
import java.util.List;
|
||||
|
||||
public class EqActionItem extends BinaryOpItem implements LogicalOpItem {
|
||||
public class EqActionItem extends BinaryOpItem implements LogicalOpItem, EqualsTypeItem {
|
||||
|
||||
boolean version2;
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
* 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.action.model.operations;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.EqualsTypeItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
@@ -27,7 +29,7 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.LogicalOpItem;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class StrictEqActionItem extends BinaryOpItem implements LogicalOpItem, Inverted, EqualsTypeItem {
|
||||
|
||||
public StrictEqActionItem(GraphSourceItem instruction, GraphTargetItem leftSide, GraphTargetItem rightSide) {
|
||||
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "===");
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.graph.model.BinaryOp;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface EqualsTypeItem extends BinaryOp {
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import com.jpexs.decompiler.graph.model.ForItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.IntegerValueItem;
|
||||
import com.jpexs.decompiler.graph.model.IntegerValueTypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LabelItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.LogicalOpItem;
|
||||
@@ -1498,7 +1499,7 @@ public class Graph {
|
||||
//********************************END PART DECOMPILING
|
||||
if (parseNext) {
|
||||
|
||||
if (part.nextParts.size() > 2) {//direct switch, seen in the wild...
|
||||
if (part.nextParts.size() > 2) {
|
||||
GraphPart next = getMostCommonPart(localData, part.nextParts, loops);
|
||||
List<GraphPart> vis = new ArrayList<>();
|
||||
GraphTargetItem switchedItem = stack.pop();
|
||||
@@ -1513,15 +1514,94 @@ public class Graph {
|
||||
loops.add(swLoop);
|
||||
boolean first = false;
|
||||
int pos = 0;
|
||||
|
||||
Map<Integer, GraphTargetItem> caseExpressions = new HashMap<>();
|
||||
Map<Integer, GraphTargetItem> caseExpressionLeftSides = new HashMap<>();
|
||||
Map<Integer, GraphTargetItem> caseExpressionRightSides = new HashMap<>();
|
||||
GraphTargetItem it = switchedItem;
|
||||
int defaultBranch = 0;
|
||||
|
||||
while (it instanceof TernarOpItem) {
|
||||
TernarOpItem to = (TernarOpItem) it;
|
||||
if (to.expression instanceof EqualsTypeItem) {
|
||||
if (to.onTrue instanceof IntegerValueTypeItem) {
|
||||
int cpos = ((IntegerValueTypeItem) to.onTrue).intValue();
|
||||
caseExpressionLeftSides.put(cpos, ((EqualsTypeItem) to.expression).getLeftSide());
|
||||
caseExpressionRightSides.put(cpos, ((EqualsTypeItem) to.expression).getRightSide());
|
||||
it = to.onFalse;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//int ignoredBranch = -1;
|
||||
if (it instanceof IntegerValueTypeItem) {
|
||||
defaultBranch = ((IntegerValueTypeItem) it).intValue();
|
||||
}
|
||||
|
||||
if (!caseExpressionRightSides.isEmpty()) {
|
||||
GraphTargetItem firstItem;
|
||||
firstItem = (GraphTargetItem) caseExpressionRightSides.values().toArray()[0];
|
||||
boolean sameRight = true;
|
||||
for (GraphTargetItem cit : caseExpressionRightSides.values()) {
|
||||
if (!cit.equals(firstItem)) {
|
||||
sameRight = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sameRight) {
|
||||
caseExpressions = caseExpressionLeftSides;
|
||||
switchedItem = firstItem;
|
||||
} else {
|
||||
firstItem = (GraphTargetItem) caseExpressionLeftSides.values().toArray()[0];
|
||||
|
||||
boolean sameLeft = true;
|
||||
for (GraphTargetItem cit : caseExpressionLeftSides.values()) {
|
||||
if (!cit.equals(firstItem)) {
|
||||
sameLeft = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sameLeft) {
|
||||
caseExpressions = caseExpressionRightSides;
|
||||
switchedItem = firstItem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
first = true;
|
||||
pos = 0;
|
||||
//This is tied to AS3 switch implementation which has nextparts switched from index 1. TODO: Make more universal
|
||||
GraphPart defaultPart = part.nextParts.get(1 + defaultBranch);
|
||||
|
||||
for (GraphPart p : part.nextParts) {
|
||||
if (p != defaultPart) {
|
||||
if (caseExpressions.containsKey(pos)) {
|
||||
caseValues.add(caseExpressions.get(pos));
|
||||
} else {
|
||||
caseValues.add(new IntegerValueItem(null, pos));
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
first = true;
|
||||
pos = 0;
|
||||
List<GraphTargetItem> nextCommands = null;
|
||||
for (GraphPart p : part.nextParts) {
|
||||
|
||||
if (!first) {
|
||||
caseValues.add(new IntegerValueItem(null, pos++));
|
||||
/*if (pos == ignoredBranch) {
|
||||
pos++;
|
||||
continue;
|
||||
}*/
|
||||
if (p != defaultPart) {
|
||||
if (vis.contains(p)) {
|
||||
valueMappings.add(caseCommands.size() - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
valueMappings.add(caseCommands.size());
|
||||
}
|
||||
List<GraphPart> stopPart2 = new ArrayList<>();
|
||||
@@ -1539,19 +1619,37 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
if (next != p) {
|
||||
//int stackLenBefore = stack.size();
|
||||
TranslateStack s2 = (TranslateStack) stack.clone();
|
||||
s2.clear();
|
||||
List<GraphTargetItem> nextCommands = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
makeAllCommands(nextCommands, s2);
|
||||
if (first) {
|
||||
|
||||
if (p == defaultPart && !defaultCommands.isEmpty()) {
|
||||
//ignore
|
||||
} else {
|
||||
TranslateStack s2 = (TranslateStack) stack.clone();
|
||||
s2.clear();
|
||||
nextCommands = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
makeAllCommands(nextCommands, s2);
|
||||
if (p == defaultPart) {
|
||||
defaultCommands = nextCommands;
|
||||
} else {
|
||||
caseCommands.add(nextCommands);
|
||||
}
|
||||
vis.add(p);
|
||||
}
|
||||
} else {
|
||||
if (p == defaultPart) {
|
||||
defaultCommands = nextCommands;
|
||||
} else {
|
||||
caseCommands.add(nextCommands);
|
||||
}
|
||||
vis.add(p);
|
||||
}
|
||||
first = false;
|
||||
pos++;
|
||||
}
|
||||
//remove last break from default clause
|
||||
if (!defaultCommands.isEmpty() && (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem)) {
|
||||
BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1);
|
||||
if (bi.loopId == swLoop.id) {
|
||||
defaultCommands.remove(defaultCommands.size() - 1);
|
||||
}
|
||||
}
|
||||
SwitchItem sw = new SwitchItem(null, swLoop, switchedItem, caseValues, caseCommands, defaultCommands, valueMappings);
|
||||
currentRet.add(sw);
|
||||
@@ -1559,6 +1657,7 @@ public class Graph {
|
||||
if (next != null) {
|
||||
currentRet.addAll(printGraph(partCodes, partCodePos, visited, localData, stack, allParts, part, next, stopPart, loops, null, staticOperation, path, recursionLevel + 1));
|
||||
}
|
||||
pos++;
|
||||
} //else
|
||||
GraphPart nextOnePart = null;
|
||||
if (part.nextParts.size() == 2) {
|
||||
|
||||
@@ -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.helpers.GraphTextWriter;
|
||||
@@ -25,7 +26,7 @@ import java.util.Set;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public class IntegerValueItem extends GraphTargetItem implements IntegerValueTypeItem {
|
||||
|
||||
private final int intValue;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class IntegerValueItem extends GraphTargetItem {
|
||||
|
||||
@Override
|
||||
public Object getResult() {
|
||||
public Object getResult() {
|
||||
return (long) intValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,4 +59,9 @@ public class IntegerValueItem extends GraphTargetItem {
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return intValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.jpexs.decompiler.graph.model;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface IntegerValueTypeItem {
|
||||
|
||||
public int intValue();
|
||||
}
|
||||
Reference in New Issue
Block a user