for (each) in

This commit is contained in:
Jindra Petřík
2021-01-24 16:51:45 +01:00
parent 894d89343d
commit c379555e87
7 changed files with 133 additions and 18 deletions

View File

@@ -1651,9 +1651,6 @@ public class AVM2Code implements Cloneable {
Set<Integer> usages = setLocalPosToGetLocalPos.get(ip);
if (usages.size() == 1 && (usages.iterator().next().equals(ip + 1)) && (insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) {
/*GraphTargetItem before = stack.peek();
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
stack.push(before);*/
ip += 2;
continue iploop;
} else {

View File

@@ -27,10 +27,17 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecLocalPIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncLocalPIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item;
@@ -161,8 +168,28 @@ public class AVM2Graph extends Graph {
registerToLastSetLocalPos.put(regId, ip);
setLocalPosToGetLocalPos.put(ip, new TreeSet<>());
}
List<Integer> usedRegs = new ArrayList<>();
if (ins.definition instanceof GetLocalTypeIns) {
int regId = ((GetLocalTypeIns) ins.definition).getRegisterId(ins);
usedRegs.add(regId);
}
if ((ins.definition instanceof IncLocalIns)
|| (ins.definition instanceof IncLocalIIns)
|| (ins.definition instanceof IncLocalPIns)
|| (ins.definition instanceof DecLocalIns)
|| (ins.definition instanceof DecLocalIIns)
|| (ins.definition instanceof DecLocalPIns)) {
usedRegs.add(ins.operands[0]);
}
if ((ins.definition instanceof IncLocalPIns)
|| (ins.definition instanceof DecLocalPIns)) {
usedRegs.add(ins.operands[1]);
}
if (ins.definition instanceof HasNext2Ins) {
usedRegs.add(ins.operands[0]);
usedRegs.add(ins.operands[1]);
}
for (int regId : usedRegs) {
if (registerToLastSetLocalPos.containsKey(regId)) {
int setLocalPos = registerToLastSetLocalPos.get(regId);
setLocalPosToGetLocalPos.get(setLocalPos).add(ip);
@@ -564,7 +591,7 @@ public class AVM2Graph extends Graph {
}
ret = new ArrayList<>();
ret.addAll(output);
GraphTargetItem lop = checkLoop(part, stopPart, loops);
GraphTargetItem lop = checkLoop(new ArrayList<GraphTargetItem>(), part, stopPart, loops);
if (lop == null) {
TranslateStack st = (TranslateStack) stack.clone();
st.clear();
@@ -777,7 +804,7 @@ public class AVM2Graph extends Graph {
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = breakPart;
GraphTargetItem ti = checkLoop(next, stopPart, loops);
GraphTargetItem ti = checkLoop(new ArrayList<GraphTargetItem>() /*??*/, next, stopPart, loops);
//create switch as new loop break command detection to work
currentLoop = new Loop(loops.size(), null, next);
@@ -964,7 +991,7 @@ public class AVM2Graph extends Graph {
@Override
protected GraphTargetItem checkLoop(LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
if (loopItem instanceof WhileItem) {
WhileItem w = (WhileItem) loopItem;
@@ -1007,10 +1034,97 @@ public class AVM2Graph extends Graph {
if (w.commands.get(0) instanceof SetTypeAVM2Item) {
SetTypeAVM2Item sti = (SetTypeAVM2Item) w.commands.remove(0);
GraphTargetItem gti = sti.getValue().getNotCoerced();
GraphTargetItem varName = sti.getObject();
GraphTargetItem collection = hn.obj;
if (hn.obj instanceof LocalRegAVM2Item) {
int objRegIndex = ((LocalRegAVM2Item) hn.obj).regIndex;
for (int i = output.size() - 2 /*last is loop*/; i >= 0; i--) {
if (output.get(i) instanceof SetLocalAVM2Item) {
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(i);
if (setLocal.regIndex == objRegIndex) {
int setLocalIp = aLocalData.code.adr2pos(setLocal.getSrc().getAddress());
Set<Integer> objUsages = new HashSet<>(aLocalData.setLocalPosToGetLocalPos.get(setLocalIp));
int hnUsageIp = aLocalData.code.adr2pos(hn.getSrc().getAddress());
objUsages.remove(hnUsageIp);
if (gti instanceof NextValueAVM2Item) {
NextValueAVM2Item nextVal = (NextValueAVM2Item) gti;
if (nextVal.obj instanceof LocalRegAVM2Item) {
LocalRegAVM2Item nextValObjReg = (LocalRegAVM2Item) nextVal.obj;
if (nextValObjReg.regIndex == objRegIndex) {
int nextValUsage = aLocalData.code.adr2pos(nextValObjReg.getSrc().getAddress());
objUsages.remove(nextValUsage);
}
}
}
if (gti instanceof NextNameAVM2Item) {
NextNameAVM2Item nextName = (NextNameAVM2Item) gti;
if (nextName.obj instanceof LocalRegAVM2Item) {
LocalRegAVM2Item nextValObjReg = (LocalRegAVM2Item) nextName.obj;
if (nextValObjReg.regIndex == objRegIndex) {
int nextNameUsage = aLocalData.code.adr2pos(nextValObjReg.getSrc().getAddress());
objUsages.remove(nextNameUsage);
}
}
}
if (objUsages.isEmpty()) {
output.remove(i);
collection = setLocal.value;
}
}
} else {
break;
}
}
}
if (hn.index instanceof LocalRegAVM2Item) {
int indexRegIndex = ((LocalRegAVM2Item) hn.index).regIndex;
for (int i = output.size() - 2 /*last is loop*/; i >= 0; i--) {
if (output.get(i) instanceof SetLocalAVM2Item) {
SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(i);
if (setLocal.regIndex == indexRegIndex) {
int setLocalIp = aLocalData.code.adr2pos(setLocal.getSrc().getAddress());
Set<Integer> objUsages = new HashSet<>(aLocalData.setLocalPosToGetLocalPos.get(setLocalIp));
int hnUsageIp = aLocalData.code.adr2pos(hn.getSrc().getAddress());
objUsages.remove(hnUsageIp);
if (gti instanceof NextValueAVM2Item) {
NextValueAVM2Item nextVal = (NextValueAVM2Item) gti;
if (nextVal.index instanceof LocalRegAVM2Item) {
LocalRegAVM2Item nextValIndexReg = (LocalRegAVM2Item) nextVal.index;
if (nextValIndexReg.regIndex == indexRegIndex) {
int nextValUsage = aLocalData.code.adr2pos(nextValIndexReg.getSrc().getAddress());
objUsages.remove(nextValUsage);
}
}
}
if (gti instanceof NextNameAVM2Item) {
NextNameAVM2Item nextName = (NextNameAVM2Item) gti;
if (nextName.index instanceof LocalRegAVM2Item) {
LocalRegAVM2Item nextValIndexReg = (LocalRegAVM2Item) nextName.index;
if (nextValIndexReg.regIndex == indexRegIndex) {
int nextNameUsage = aLocalData.code.adr2pos(nextValIndexReg.getSrc().getAddress());
objUsages.remove(nextNameUsage);
}
}
}
if (objUsages.isEmpty()) {
output.remove(i);
}
}
} else {
break;
}
}
}
if (gti instanceof NextValueAVM2Item) {
return new ForEachInAVM2Item(w.getSrc(), w.getLineStartItem(), w.loop, new InAVM2Item(hn.getInstruction(), hn.getLineStartIns(), sti.getObject(), ((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).obj), w.commands);
return new ForEachInAVM2Item(w.getSrc(), w.getLineStartItem(), w.loop, new InAVM2Item(hn.getInstruction(), hn.getLineStartIns(), varName, collection), w.commands);
} else if (gti instanceof NextNameAVM2Item) {
return new ForInAVM2Item(w.getSrc(), w.getLineStartItem(), w.loop, new InAVM2Item(hn.getInstruction(), hn.getLineStartIns(), sti.getObject(), ((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).obj), w.commands);
return new ForInAVM2Item(w.getSrc(), w.getLineStartItem(), w.loop, new InAVM2Item(hn.getInstruction(), hn.getLineStartIns(), varName, collection), w.commands);
}
}
}

View File

@@ -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;
@@ -41,7 +42,10 @@ public class HasNext2Ins extends InstructionDefinition {
int objectReg = ins.operands[0];
int indexReg = ins.operands[1];
//stack.push("_loc_" + objectReg + ".hasNext(cnt=_loc_" + indexReg + ")");
//stack.push("_loc_" + objectReg + ".hasNext(cnt=_loc_" + indexReg + ")");
stack.push(new HasNextAVM2Item(ins, localData.lineStartInstruction,
new LocalRegAVM2Item(ins, localData.lineStartInstruction, indexReg, localData.localRegs.get(indexReg)),
new LocalRegAVM2Item(ins, localData.lineStartInstruction, objectReg, localData.localRegs.get(objectReg))
));
}
@Override

View File

@@ -34,9 +34,9 @@ import java.util.List;
*/
public class NextNameAVM2Item extends AVM2Item {
GraphTargetItem index;
public GraphTargetItem index;
GraphTargetItem obj;
public GraphTargetItem obj;
public NextNameAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem index, GraphTargetItem obj) {
super(instruction, lineStartIns, NOPRECEDENCE);

View File

@@ -34,9 +34,9 @@ import java.util.List;
*/
public class NextValueAVM2Item extends AVM2Item {
GraphTargetItem index;
public GraphTargetItem index;
GraphTargetItem obj;
public GraphTargetItem obj;
public NextValueAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem index, GraphTargetItem obj) {
super(instruction, lineStartIns, NOPRECEDENCE);

View File

@@ -471,7 +471,7 @@ public class ActionGraph extends Graph {
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = breakPart;
GraphTargetItem ti = checkLoop(next, stopPart, loops);
GraphTargetItem ti = checkLoop(new ArrayList<GraphTargetItem>(), next, stopPart, loops);
//create switch as new loop break command detection to work
currentLoop = new Loop(loops.size(), null, next);

View File

@@ -1460,7 +1460,7 @@ public class Graph {
return ret;
}
protected GraphTargetItem checkLoop(GraphPart part, List<GraphPart> stopPart, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, GraphPart part, List<GraphPart> stopPart, List<Loop> loops) {
if (stopPart.contains(part)) {
return null;
}
@@ -1817,7 +1817,7 @@ public class Graph {
return printGraph(foundGotos, gotoTargets, partCodes, partCodePos, new HashSet<>(), localData, stack, allParts, parent, part, stopPart, loops, null, staticOperation, path, 0);
}
protected GraphTargetItem checkLoop(LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
protected GraphTargetItem checkLoop(List<GraphTargetItem> output, LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
return loopItem;
}
@@ -2927,7 +2927,7 @@ public class Graph {
}
currentLoop.phase = 2;
GraphTargetItem replaced = checkLoop(li, localData, loops);
GraphTargetItem replaced = checkLoop(ret, li, localData, loops);
if (replaced != li) {
int index = ret.indexOf(li);
ret.remove(index);