mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 16:10:45 +00:00
AS3 parser: try..finally
This commit is contained in:
@@ -16,11 +16,15 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -33,6 +37,9 @@ public class SourceGeneratorLocalData implements Serializable {
|
||||
public Boolean inMethod;
|
||||
public Integer forInLevel;
|
||||
public List<ABCException> exceptions = new ArrayList<>();
|
||||
public List<Integer> finallyCatches = new ArrayList<Integer>();
|
||||
public Map<Integer,Integer> finallyCounter = new HashMap<>();
|
||||
public int finallyRegister = -1;
|
||||
public String currentClass;
|
||||
public int activationReg = 0;
|
||||
|
||||
|
||||
@@ -1848,14 +1848,15 @@ public class AVM2Code implements Serializable {
|
||||
|
||||
private boolean walkCode(CodeStats stats, int pos, int stack, int scope, ABC abc) {
|
||||
while (pos < code.size()) {
|
||||
AVM2Instruction ins = code.get(pos);
|
||||
if (stats.instructionStats[pos].seen) {
|
||||
//check stack mismatch here
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
stats.instructionStats[pos].seen = true;
|
||||
stats.instructionStats[pos].stackpos = stack;
|
||||
stats.instructionStats[pos].scopepos = scope;
|
||||
AVM2Instruction ins = code.get(pos);
|
||||
|
||||
int stackDelta = ins.definition.getStackDelta(ins, abc);
|
||||
int scopeDelta = ins.definition.getScopeStackDelta(ins, abc);
|
||||
int oldStack = stack;
|
||||
@@ -1864,6 +1865,9 @@ public class AVM2Code implements Serializable {
|
||||
stack += stackDelta;
|
||||
scope += scopeDelta;
|
||||
|
||||
stats.instructionStats[pos].stackpos_after = stack;
|
||||
stats.instructionStats[pos].scopepos_after = scope;
|
||||
|
||||
if (stack > stats.maxstack) {
|
||||
stats.maxstack = stack;
|
||||
}
|
||||
@@ -1914,6 +1918,9 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
if (ins.definition instanceof LookupSwitchIns) {
|
||||
for (int i = 0; i < ins.operands.length; i++) {
|
||||
if (i == 1) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int newpos = adr2pos(pos2adr(pos) + ins.operands[i]);
|
||||
if (!walkCode(stats, newpos, stack, scope, abc)) {
|
||||
@@ -1935,29 +1942,51 @@ public class AVM2Code implements Serializable {
|
||||
return null;
|
||||
}
|
||||
int scopePos = -1;
|
||||
for (ABCException ex : body.exceptions) {
|
||||
int prevStart = 0;
|
||||
for (int e=0;e<body.exceptions.length;e++) {
|
||||
ABCException ex = body.exceptions[e];
|
||||
try {
|
||||
if(scopePos==-1){
|
||||
scopePos=stats.instructionStats[adr2pos(ex.end)-1].scopepos;
|
||||
if (scopePos == -1) {
|
||||
scopePos = stats.instructionStats[adr2pos(ex.end) - 1].scopepos_after;
|
||||
}
|
||||
List<Integer> visited = new ArrayList<>();
|
||||
for(int i=0;i<stats.instructionStats.length;i++){
|
||||
if(stats.instructionStats[i].seen){
|
||||
for (int i = 0; i < stats.instructionStats.length; i++) {
|
||||
if (stats.instructionStats[i].seen) {
|
||||
visited.add(i);
|
||||
}
|
||||
}
|
||||
if (!walkCode(stats, adr2pos(ex.target), 1/*exception*/, scopePos, abc)) {
|
||||
if (!walkCode(stats, adr2pos(ex.target), 1 + (ex.isFinally() ? 1 : 0), scopePos, abc)) {
|
||||
return null;
|
||||
}
|
||||
int maxIp = 0;
|
||||
//searching for visited instruction in second run which has maximum position
|
||||
for(int i=0;i<stats.instructionStats.length;i++){
|
||||
if(stats.instructionStats[i].seen && !visited.contains(i)){
|
||||
for (int i = 0; i < stats.instructionStats.length; i++) {
|
||||
if (stats.instructionStats[i].seen && !visited.contains(i)) {
|
||||
maxIp = i;
|
||||
}
|
||||
}
|
||||
scopePos = stats.instructionStats[maxIp].scopepos;
|
||||
scopePos = stats.instructionStats[maxIp].scopepos_after;
|
||||
int stackPos = stats.instructionStats[maxIp].stackpos_after;
|
||||
int nextIp = maxIp + 1;
|
||||
if(code.get(maxIp).definition instanceof JumpIns){
|
||||
nextIp = adr2pos(pos2adr(nextIp)+code.get(maxIp).operands[0]);
|
||||
}
|
||||
int origScopePos = stats.instructionStats[nextIp].scopepos;
|
||||
int origStackPos = stats.instructionStats[nextIp].stackpos;
|
||||
|
||||
if (prevStart==ex.start && ex.isFinally() && !code.get(nextIp).isExit() && stats.instructionStats[nextIp].seen) {
|
||||
for (int i = 0; i < stats.instructionStats.length; i++) {
|
||||
stats.instructionStats[i].seen = false;
|
||||
}
|
||||
//Rerun rest with new scopePos, stackPos
|
||||
if (!walkCode(stats, nextIp, origStackPos+1/*magic!*/, scopePos - 1 /*magic!*/, abc)) {
|
||||
return null;
|
||||
}
|
||||
scopePos--;
|
||||
}
|
||||
prevStart = ex.start;
|
||||
} catch (ConvertException ex1) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
//stats.maxscope+=initScope;
|
||||
|
||||
@@ -27,6 +27,8 @@ public class InstructionStats {
|
||||
public boolean seen = false;
|
||||
public int stackpos = 0;
|
||||
public int scopepos = 0;
|
||||
public int stackpos_after = 0;
|
||||
public int scopepos_after = 0;
|
||||
public AVM2Instruction ins;
|
||||
|
||||
public InstructionStats(AVM2Instruction ins) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
@@ -26,6 +27,7 @@ import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.ExitItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ReturnValueAVM2Item extends AVM2Item implements ExitItem {
|
||||
@@ -44,9 +46,7 @@ public class ReturnValueAVM2Item extends AVM2Item implements ExitItem {
|
||||
|
||||
@Override
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) {
|
||||
return toSourceMerge(localData, generator, value,
|
||||
new AVM2Instruction(0, new ReturnValueIns(), new int[]{}, new byte[0])
|
||||
);
|
||||
return ((AVM2SourceGenerator)generator).generate(localData, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
@@ -41,8 +42,7 @@ public class ReturnVoidAVM2Item extends AVM2Item implements ExitItem {
|
||||
|
||||
@Override
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) {
|
||||
return toSourceMerge(localData, generator, new AVM2Instruction(0, new ReturnVoidIns(), new int[]{}, new byte[0])
|
||||
);
|
||||
return ((AVM2SourceGenerator)generator).generate(localData, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import java.util.List;
|
||||
|
||||
public class ThrowAVM2Item extends AVM2Item {
|
||||
|
||||
@@ -45,4 +50,11 @@ public class ThrowAVM2Item extends AVM2Item {
|
||||
public boolean hasReturnValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) {
|
||||
return ((AVM2SourceGenerator)generator).generate(localData, this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+526
-240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class FinallyJumpIns extends JumpIns {
|
||||
|
||||
private long finallyClauseId;
|
||||
|
||||
public FinallyJumpIns(long finallyClauseId) {
|
||||
this.finallyClauseId = finallyClauseId;
|
||||
}
|
||||
|
||||
public long getClauseId() {
|
||||
return finallyClauseId;
|
||||
}
|
||||
}
|
||||
@@ -95,11 +95,6 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
public int getSlotScope() {
|
||||
return slotScope;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void setNs(GraphTargetItem ns) {
|
||||
this.ns = ns;
|
||||
@@ -111,12 +106,12 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
|
||||
public int getSlotNumber() {
|
||||
return slotNumber;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSlotNumber(int slotNumber) {
|
||||
this.slotNumber = slotNumber;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getRegNumber() {
|
||||
return regNumber;
|
||||
}
|
||||
@@ -189,8 +184,8 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
return abc.constants.getNamespaceSetId(new NamespaceSet(nssa), true);
|
||||
}
|
||||
|
||||
public static GraphTargetItem getDefaultValue(String type){
|
||||
switch(type){
|
||||
public static GraphTargetItem getDefaultValue(String type) {
|
||||
switch (type) {
|
||||
case "*":
|
||||
return new UndefinedAVM2Item(null);
|
||||
case "int":
|
||||
@@ -201,7 +196,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
return new NullAVM2Item(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static AVM2Instruction generateCoerce(SourceGenerator generator, String type) {
|
||||
AVM2Instruction ins;
|
||||
switch (type) {
|
||||
@@ -223,10 +218,10 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
}
|
||||
|
||||
private List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn) {
|
||||
if (variableName != null && regNumber == -1 && slotNumber == -1 && ns == null) {
|
||||
if (variableName != null && regNumber == -1 && slotNumber == -1 && ns == null) {
|
||||
throw new RuntimeException("No register or slot set for " + variableName);
|
||||
}
|
||||
if (definition && assignedValue == null) {
|
||||
if (definition && assignedValue == null) {
|
||||
return new ArrayList<GraphSourceItem>();
|
||||
}
|
||||
AVM2SourceGenerator g = (AVM2SourceGenerator) generator;
|
||||
@@ -276,7 +271,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
if (index != null) {
|
||||
if (assignedValue != null) {
|
||||
return toSourceMerge(localData, generator,
|
||||
generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber), index, assignedValue,
|
||||
generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), index, assignedValue,
|
||||
needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
|
||||
ins(new SetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, 0, 0, allNsSet(g.abc), 0, new ArrayList<Integer>()), true)),
|
||||
needsReturn ? getTemp(localData, generator, ret_temp) : null,
|
||||
@@ -292,25 +287,23 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
}
|
||||
|
||||
if (assignedValue != null) {
|
||||
List<String> basicTypes = Arrays.asList("int","Number");
|
||||
if(slotNumber>-1)
|
||||
{
|
||||
return toSourceMerge(localData, generator,
|
||||
ins(new GetScopeObjectIns(),slotScope),
|
||||
assignedValue, !((""+assignedValue.returnType()).equals(""+type)&&(basicTypes.contains(""+type))) ? generateCoerce(generator, "" + type) : null, needsReturn
|
||||
? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber),slotNumber>-1?
|
||||
ins(new SetSlotIns(),slotNumber)
|
||||
:null,
|
||||
needsReturn?getTemp(localData, generator, ret_temp):null,
|
||||
killTemp(localData, generator, Arrays.asList(ret_temp)));
|
||||
}
|
||||
else{
|
||||
|
||||
return toSourceMerge(localData, generator, assignedValue, !((""+assignedValue.returnType()).equals(""+type)&&(basicTypes.contains(""+type))) ? generateCoerce(generator, "" + type) : null, needsReturn
|
||||
? ins(new DupIns()) : null, generateSetLoc(regNumber));
|
||||
List<String> basicTypes = Arrays.asList("int", "Number");
|
||||
if (slotNumber > -1) {
|
||||
return toSourceMerge(localData, generator,
|
||||
ins(new GetScopeObjectIns(), slotScope),
|
||||
assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, "" + type) : null, needsReturn
|
||||
? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
|
||||
? ins(new SetSlotIns(), slotNumber)
|
||||
: null,
|
||||
needsReturn ? getTemp(localData, generator, ret_temp) : null,
|
||||
killTemp(localData, generator, Arrays.asList(ret_temp)));
|
||||
} else {
|
||||
|
||||
return toSourceMerge(localData, generator, assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(generator, "" + type) : null, needsReturn
|
||||
? ins(new DupIns()) : null, generateSetLoc(regNumber));
|
||||
}
|
||||
} else {
|
||||
return toSourceMerge(localData, generator, generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber),
|
||||
return toSourceMerge(localData, generator, generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber),
|
||||
needsReturn ? null : ins(new PopIns()));
|
||||
}
|
||||
}
|
||||
@@ -431,7 +424,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
|
||||
if (index != null) {
|
||||
return toSourceMerge(localData, generator,
|
||||
generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber), dupSetTemp(localData, generator, name_temp), index, dupSetTemp(localData, generator, index_temp),
|
||||
generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), dupSetTemp(localData, generator, name_temp), index, dupSetTemp(localData, generator, index_temp),
|
||||
//Start get original
|
||||
//generateGetLoc(regNumber), getTemp(localData, generator, index_temp),
|
||||
ins(new GetPropertyIns(), g.abc.constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, 0, 0, allNsSet(g.abc), 0, new ArrayList<Integer>()), true)),
|
||||
@@ -449,23 +442,23 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
);
|
||||
}
|
||||
|
||||
if(!needsReturn){
|
||||
if(slotNumber>-1){
|
||||
if (!needsReturn) {
|
||||
if (slotNumber > -1) {
|
||||
return toSourceMerge(localData, generator,
|
||||
ins(new GetScopeObjectIns(),slotScope),
|
||||
generateGetSlot(slotScope,slotNumber),
|
||||
ins(new GetScopeObjectIns(), slotScope),
|
||||
generateGetSlot(slotScope, slotNumber),
|
||||
(decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())),
|
||||
ins(new SetSlotIns(),slotNumber)
|
||||
ins(new SetSlotIns(), slotNumber)
|
||||
);
|
||||
}else{
|
||||
} else {
|
||||
return toSourceMerge(localData, generator,
|
||||
ins(isInteger?new IncLocalIIns():new IncLocalIns(),regNumber));
|
||||
ins(isInteger ? new IncLocalIIns() : new IncLocalIns(), regNumber));
|
||||
}
|
||||
}
|
||||
return toSourceMerge(localData, generator,
|
||||
slotNumber>-1?ins(new GetScopeObjectIns(),slotScope):null,
|
||||
slotNumber > -1 ? ins(new GetScopeObjectIns(), slotScope) : null,
|
||||
//Start get original
|
||||
generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber),
|
||||
generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber),
|
||||
//End get original
|
||||
!isInteger ? ins(new ConvertDIns()) : null,
|
||||
//End get original
|
||||
@@ -473,7 +466,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
|
||||
needsReturn ? ins(new DupIns()) : null,
|
||||
(post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null,
|
||||
generateSetLoc(regNumber),
|
||||
slotNumber>-1?ins(new SetSlotIns(),slotNumber):null
|
||||
slotNumber > -1 ? ins(new SetSlotIns(), slotNumber) : null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
TODO List for AS3 parser/compiler:
|
||||
------------------------------
|
||||
- finally clause
|
||||
- E4X (XML)
|
||||
- typenames (Vectors)
|
||||
- inner functions (activation, slots, etc.)
|
||||
|
||||
Reference in New Issue
Block a user