mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-19 18:18:07 +00:00
AS3 switch compilation reorganized
This commit is contained in:
@@ -1292,7 +1292,7 @@ public class AVM2Graph extends Graph {
|
||||
AVM2LocalData localData2 = new AVM2LocalData(localData);
|
||||
//localData2.scopeStack = new ScopeStack();
|
||||
localData2.localScopeStack = new ScopeStack();
|
||||
|
||||
|
||||
try {
|
||||
//We are assuming Finally target has only 1 part
|
||||
translatePart(finallyTargetItems, localData2, finallyTryTargetPart, st2, staticOperation, path);
|
||||
@@ -2286,14 +2286,14 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
int firstPushPos = -1;
|
||||
|
||||
|
||||
for (int i = output.size() - 2 /*last is loop*/; i >= 0; i--) {
|
||||
if (output.get(i) instanceof PushItem) {
|
||||
firstPushPos = i;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstPushPos > -1) {
|
||||
int max = output.size() - 2;
|
||||
for (int i = firstPushPos; i <= max; i++) {
|
||||
@@ -2566,7 +2566,7 @@ public class AVM2Graph extends Graph {
|
||||
if (debugDoNotProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
loopi:
|
||||
for (int i = 1 /*not first*/; i < list.size(); i++) {
|
||||
GraphTargetItem item = list.get(i);
|
||||
@@ -2644,7 +2644,6 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> thisExpressions = new ArrayList<>();
|
||||
int defaultIndex = -1;
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
@@ -2654,6 +2653,47 @@ public class AVM2Graph extends Graph {
|
||||
if (!(thisSwitch.caseValues.get(k) instanceof IntegerValueTypeItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultIndex > -1 && !thisSwitch.additionalDefaultValues.isEmpty() && thisSwitch.additionalDefaultPosition > -1) {
|
||||
|
||||
int defaultBodyIndex = thisSwitch.valuesMapping.get(defaultIndex);
|
||||
|
||||
if (thisSwitch.additionalDefaultPosition != defaultIndex) {
|
||||
int previousBodyIndex = thisSwitch.valuesMapping.get(thisSwitch.additionalDefaultPosition);
|
||||
List<GraphTargetItem> defaultBody = thisSwitch.caseCommands.remove(defaultBodyIndex);
|
||||
thisSwitch.caseCommands.add(previousBodyIndex, defaultBody);
|
||||
for (int p = 0; p < thisSwitch.valuesMapping.size(); p++) {
|
||||
if (thisSwitch.valuesMapping.get(p) >= previousBodyIndex) {
|
||||
thisSwitch.valuesMapping.set(p, thisSwitch.valuesMapping.get(p) + 1);
|
||||
}
|
||||
}
|
||||
defaultBodyIndex = previousBodyIndex;
|
||||
GraphTargetItem lastCmd = defaultBody.isEmpty() ? null : defaultBody.get(defaultBody.size() - 1);
|
||||
if (lastCmd != null && !(lastCmd instanceof ExitItem) && !(lastCmd instanceof BreakItem) && !(lastCmd instanceof ContinueItem)) {
|
||||
defaultBody.add(new BreakItem(thisSwitch.dialect, null, null, thisSwitch.loop.id));
|
||||
}
|
||||
}
|
||||
thisSwitch.caseValues.remove(defaultIndex);
|
||||
thisSwitch.valuesMapping.remove(defaultIndex);
|
||||
|
||||
thisSwitch.caseValues.add(thisSwitch.additionalDefaultPosition, new DefaultItem(thisSwitch.dialect));
|
||||
thisSwitch.valuesMapping.add(thisSwitch.additionalDefaultPosition, defaultBodyIndex);
|
||||
for (int m = thisSwitch.additionalDefaultValues.size() - 1; m >= 0; m--) {
|
||||
thisSwitch.caseValues.add(thisSwitch.additionalDefaultPosition, thisSwitch.additionalDefaultValues.get(m));
|
||||
thisSwitch.valuesMapping.add(thisSwitch.additionalDefaultPosition, defaultBodyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> thisExpressions = new ArrayList<>();
|
||||
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
continue;
|
||||
}
|
||||
if (!(thisSwitch.caseValues.get(k) instanceof IntegerValueTypeItem)) {
|
||||
continue loopi;
|
||||
}
|
||||
int cv = ((IntegerValueTypeItem) thisSwitch.caseValues.get(k)).intValue();
|
||||
/*if (!expressionsMap.containsKey(cv)) {
|
||||
continue loopi;
|
||||
@@ -2674,32 +2714,8 @@ public class AVM2Graph extends Graph {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
|
||||
/*if (!noCaseExpressions.isEmpty() && defaultIndex == -1) {
|
||||
thisSwitch.caseValues.add(new DefaultItem(dialect));
|
||||
thisSwitch.valuesMapping.add(thisSwitch.caseCommands.size());
|
||||
if (!thisSwitch.caseCommands.isEmpty()) {
|
||||
List<GraphTargetItem> lastCommands = thisSwitch.caseCommands.get(thisSwitch.caseCommands.size() - 1);
|
||||
if (
|
||||
lastCommands.isEmpty()
|
||||
|| !(
|
||||
(lastCommands.get(lastCommands.size() - 1) instanceof ExitItem)
|
||||
|| (lastCommands.get(lastCommands.size() - 1) instanceof ContinueItem)
|
||||
|| (lastCommands.get(lastCommands.size() - 1) instanceof BreakItem)
|
||||
)
|
||||
) {
|
||||
lastCommands.add(new BreakItem(dialect, null, null, thisSwitch.loop.id));
|
||||
}
|
||||
}
|
||||
thisSwitch.caseCommands.add(new ArrayList<>());
|
||||
}*/
|
||||
|
||||
for (int k = 0; k < thisSwitch.caseValues.size(); k++) {
|
||||
/*if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
thisSwitch.removeValue(k);
|
||||
k--;
|
||||
continue;
|
||||
}*/
|
||||
if (thisSwitch.caseValues.get(k) instanceof DefaultItem) {
|
||||
int m = thisSwitch.valuesMapping.get(k);
|
||||
thisSwitch.caseValues.remove(k);
|
||||
@@ -2730,12 +2746,12 @@ public class AVM2Graph extends Graph {
|
||||
continue;
|
||||
}
|
||||
int cv = ((IntegerValueTypeItem) thisSwitch.caseValues.get(k)).intValue();
|
||||
|
||||
|
||||
if (!expressionsMap.containsKey(cv)) {
|
||||
thisSwitch.removeValue(k);
|
||||
k--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
thisSwitch.caseValues.set(k, expressionsMap.get(cv));
|
||||
}
|
||||
|
||||
|
||||
@@ -2909,34 +2909,33 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
ret.add(forwardJump);
|
||||
|
||||
int defIndex = item.caseValues.size();
|
||||
boolean hasDefault = false;
|
||||
|
||||
for (int i = item.caseValues.size() - 1; i >= 0; i--) {
|
||||
if (item.caseValues.get(i) instanceof DefaultItem) {
|
||||
hasDefault = true;
|
||||
defIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int realCasesCount = item.caseValues.size() + (hasDefault ? -1 : 0);
|
||||
|
||||
List<AVM2Instruction> cases = new ArrayList<>();
|
||||
cases.addAll(toInsList(new IntegerValueAVM2Item(null, null, defIndex).toSource(localData, this)));
|
||||
int cLen = insToBytes(cases).length;
|
||||
List<AVM2Instruction> caseLast = new ArrayList<>();
|
||||
caseLast.add(0, ins(AVM2Instructions.Jump, cLen));
|
||||
caseLast.addAll(0, toInsList(new IntegerValueAVM2Item(null, null, defIndex).toSource(localData, this)));
|
||||
int cLastLen = insToBytes(caseLast).length;
|
||||
caseLast.add(0, ins(AVM2Instructions.Jump, cLastLen));
|
||||
cases.addAll(0, caseLast);
|
||||
cases.addAll(0, toInsList(new IntegerValueAVM2Item(null, null, -1).toSource(localData, this)));
|
||||
|
||||
List<AVM2Instruction> preCases = new ArrayList<>();
|
||||
preCases.addAll(toInsList(item.switchedObject.toSource(localData, this)));
|
||||
preCases.addAll(toInsList(AssignableAVM2Item.setTemp(localData, this, switchedReg)));
|
||||
|
||||
|
||||
int pos = realCasesCount - 1;
|
||||
for (int i = item.caseValues.size() - 1; i >= 0; i--) {
|
||||
if (item.caseValues.get(i) instanceof DefaultItem) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
List<AVM2Instruction> sub = new ArrayList<>();
|
||||
sub.addAll(toInsList(new IntegerValueAVM2Item(null, null, i).toSource(localData, this)));
|
||||
sub.addAll(toInsList(new IntegerValueAVM2Item(null, null, pos--).toSource(localData, this)));
|
||||
sub.add(ins(AVM2Instructions.Jump, insToBytes(cases).length));
|
||||
int subLen = insToBytes(sub).length;
|
||||
|
||||
@@ -2946,8 +2945,10 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
cases.addAll(0, toInsList(item.caseValues.get(i).toSource(localData, this)));
|
||||
}
|
||||
cases.addAll(0, preCases);
|
||||
|
||||
|
||||
|
||||
AVM2Instruction lookupOp = new AVM2Instruction(0, AVM2Instructions.LookupSwitch, new int[1 + 1 + item.caseValues.size() + 1]);
|
||||
AVM2Instruction lookupOp = new AVM2Instruction(0, AVM2Instructions.LookupSwitch, new int[1 + 1 + realCasesCount]);
|
||||
cases.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(switchedReg))));
|
||||
List<AVM2Instruction> bodies = new ArrayList<>();
|
||||
List<Integer> bodiesOffsets = new ArrayList<>();
|
||||
@@ -2956,18 +2957,25 @@ public class AVM2SourceGenerator implements SourceGenerator {
|
||||
bodies.add(0, ins(AVM2Instructions.Label));
|
||||
bodies.add(ins(new BreakJumpIns(item.loop.id), 0)); //There could be two breaks when default clause ends with break, but official compiler does this too, so who cares...
|
||||
defOffset = -(insToBytes(bodies).length + casesLen);
|
||||
for (int i = item.caseCommands.size() - 1; i >= 0; i--) {
|
||||
for (int i = item.caseCommands.size() - 1; i >= 0; i--) {
|
||||
bodies.addAll(0, generateToInsList(localData, item.caseCommands.get(i)));
|
||||
bodies.add(0, ins(AVM2Instructions.Label));
|
||||
bodiesOffsets.add(0, -(insToBytes(bodies).length + casesLen));
|
||||
}
|
||||
lookupOp.operands[0] = defOffset;
|
||||
lookupOp.operands[1] = item.valuesMapping.size();
|
||||
// as per avm2 spec: "There are case_count+1 case offsets"
|
||||
for (int i = 0; i < item.valuesMapping.size(); i++) {
|
||||
lookupOp.operands[2 + i] = bodiesOffsets.get(item.valuesMapping.get(i));
|
||||
if (hasDefault) {
|
||||
defOffset = bodiesOffsets.get(item.valuesMapping.get(defIndex));
|
||||
}
|
||||
lookupOp.operands[2 + item.valuesMapping.size()] = defOffset;
|
||||
lookupOp.operands[0] = defOffset;
|
||||
lookupOp.operands[1] = realCasesCount - 1;
|
||||
// as per avm2 spec: "There are case_count+1 case offsets"
|
||||
pos = 0;
|
||||
for (int i = 0; i < item.valuesMapping.size(); i++) {
|
||||
if (item.caseValues.get(i) instanceof DefaultItem) {
|
||||
continue;
|
||||
}
|
||||
lookupOp.operands[2 + pos++] = bodiesOffsets.get(item.valuesMapping.get(i));
|
||||
}
|
||||
//lookupOp.operands[2 + item.valuesMapping.size()] = defOffset;
|
||||
|
||||
forwardJump.operands[0] = insToBytes(bodies).length;
|
||||
ret.addAll(bodies);
|
||||
|
||||
@@ -3753,10 +3753,13 @@ public class Graph {
|
||||
|
||||
GraphPart defaultPart = hasExpr ? getNextParts(localData, part).get(1 + defaultBranch) : getNextParts(localData, part).get(0);
|
||||
List<GraphPart> caseBodyParts = new ArrayList<>();
|
||||
List<GraphTargetItem> additionalDefaultValues = new ArrayList<>();
|
||||
int additionalDefaultPosition = -1;
|
||||
for (int i = 1; i < getNextParts(localData, part).size(); i++) {
|
||||
if (!hasExpr) {
|
||||
//This if probably should be removed, but it fails some tests...
|
||||
if (getNextParts(localData, part).get(i) == defaultPart) {
|
||||
additionalDefaultPosition = caseValues.size();
|
||||
additionalDefaultValues.add(new IntegerValueItem(dialect, null, localData.lineStartInstruction, pos));
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
@@ -3781,6 +3784,8 @@ public class Graph {
|
||||
makeAllCommands(currentRet, stack);
|
||||
SwitchItem sw = handleSwitch(switchedItem, originalSwitchedItem.getSrc(), foundGotos, partCodes, partCodePos, visited, allParts, stack, stopPart, stopPartKind, loops, throwStates, localData, staticOperation, path,
|
||||
caseValues, defaultPart, caseBodyParts, nextRef, tiRef);
|
||||
sw.additionalDefaultPosition = additionalDefaultPosition;
|
||||
sw.additionalDefaultValues = additionalDefaultValues;
|
||||
GraphPart next = nextRef.getVal();
|
||||
checkSwitch(localData, sw, caseExpressionOtherSides.values(), currentRet);
|
||||
currentRet.add(sw);
|
||||
|
||||
@@ -58,7 +58,17 @@ public class SwitchItem extends LoopItem implements Block {
|
||||
* Values mapping
|
||||
*/
|
||||
public List<Integer> valuesMapping;
|
||||
|
||||
/**
|
||||
* Additional default position. Mark for additional processing...
|
||||
*/
|
||||
public int additionalDefaultPosition = -1;
|
||||
|
||||
/**
|
||||
* Additional default values - they are not printed. This is just mark for additional processing...
|
||||
*/
|
||||
public List<GraphTargetItem> additionalDefaultValues = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Label used
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user