From 7e19be36c8cd1d0494157011de230758ea542f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 6 Apr 2014 09:36:10 +0200 Subject: [PATCH] AS3 parser: try..catch, activation, slots --- .../flash/SourceGeneratorLocalData.java | 12 +- .../decompiler/flash/abc/avm2/AVM2Code.java | 22 +- .../abc/avm2/model/clauses/TryAVM2Item.java | 11 + .../parser/script/AVM2SourceGenerator.java | 383 ++++++++++++++---- .../parser/script/ActionScriptParser.java | 82 ++-- .../parser/script/AssignableAVM2Item.java | 27 ++ .../script/ExceptionMarkAVM2Instruction.java | 2 + .../avm2/parser/script/FunctionAVM2Item.java | 4 +- .../avm2/parser/script/GetterAVM2Item.java | 4 +- .../avm2/parser/script/MethodAVM2Item.java | 4 +- .../abc/avm2/parser/script/NameAVM2Item.java | 68 +++- .../avm2/parser/script/SetterAVM2Item.java | 4 +- .../flash/abc/avm2/parser/script/todo.txt | 3 +- .../flash/abc/types/MethodBody.java | 5 +- 14 files changed, 477 insertions(+), 154 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index 4845dea4e..ef0749e3f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/trunk/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -32,19 +32,9 @@ public class SourceGeneratorLocalData implements Serializable { public Integer inFunction; public Boolean inMethod; public Integer forInLevel; - //public List openedNamespaces = new ArrayList<>(); - //public List openedNamespacesKinds = new ArrayList<>(); public List exceptions = new ArrayList<>(); public String currentClass; - /* - public void addNamespace(int kind, String ns) { - addNamespace(kind, ns, openedNamespaces.size() - 1); - } - - public void addNamespace(int kind, String ns, int index) { - openedNamespaces.add(index, ns); - openedNamespacesKinds.add(index, kind); - }*/ + public int activationReg = 0; public SourceGeneratorLocalData(HashMap registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) { this.registerVars = registerVars; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 2a8108c16..6d7b9aab6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1934,15 +1934,33 @@ public class AVM2Code implements Serializable { if (!walkCode(stats, 0, 0, initScope, abc)) { return null; } + int scopePos = -1; for (ABCException ex : body.exceptions) { try { - int exStart = adr2pos(ex.start); - if (!walkCode(stats, adr2pos(ex.target), stats.instructionStats[exStart].stackpos, stats.instructionStats[exStart].scopepos, abc)) { + if(scopePos==-1){ + scopePos=stats.instructionStats[adr2pos(ex.end)-1].scopepos; + } + List visited = new ArrayList<>(); + for(int i=0;i toSource(SourceGeneratorLocalData localData, SourceGenerator generator) { + return ((AVM2SourceGenerator)generator).generate(localData, this); + } + + } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 9aca73582..f4b459d2c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -24,6 +24,8 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewActivationIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewClassIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns; @@ -43,16 +45,19 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextNameIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextValueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; @@ -101,6 +106,7 @@ import com.jpexs.decompiler.graph.model.WhileItem; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Array; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -117,6 +123,10 @@ public class AVM2SourceGenerator implements SourceGenerator { public final ABC abc; public List allABCs; + public static final int MARK_E_START = 0; + public static final int MARK_E_END = 1; + public static final int MARK_E_TARGET = 2; + private AVM2Instruction ins(InstructionDefinition def, int... operands) { return new AVM2Instruction(0, def, operands, new byte[0]); } @@ -560,15 +570,76 @@ public class AVM2SourceGenerator implements SourceGenerator { return ret; } + + private List shiftExc(List list,int shift){ + for(AVM2Instruction ins:list){ + if(ins instanceof ExceptionMarkAVM2Instruction){ + ExceptionMarkAVM2Instruction e=(ExceptionMarkAVM2Instruction)ins; + e.exceptionId+=shift; + } + } + return list; + } + public List generate(SourceGeneratorLocalData localData, TryAVM2Item item) { List ret = new ArrayList<>(); + + + + int firstId = 0; + List newex=new ArrayList<>(); for (NameAVM2Item e : item.catchExceptions2) { ABCException aex = new ABCException(); - aex.name_index = str(e.getVariableName()); + aex.name_index = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId(e.getVariableName(), true), abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("", true)), 0, true), 0,0,new ArrayList()),true); aex.type_index = typeName(localData, e.type); - localData.exceptions.add(aex); - //TODO + newex.add(aex); } + + List tryCmds=generateToActionList(localData, item.tryCommands); + List> catchCmds=new ArrayList<>(); + for(int c=0;c catches=new ArrayList<>(); + Reference tempReg=new Reference<>(0); + for (int c=item.catchCommands.size()-1;c>=0;c--) { + List preCatches=new ArrayList<>(); + preCatches.add(ins(new GetLocal0Ins())); + preCatches.add(ins(new PushScopeIns())); + preCatches.add(AssignableAVM2Item.generateGetLoc(localData.activationReg)); + preCatches.add(ins(new PushScopeIns())); + preCatches.add(ins(new NewCatchIns(),i)); + preCatches.addAll(toInsList(AssignableAVM2Item.dupSetTemp(localData, this, tempReg))); + preCatches.add(ins(new DupIns())); + preCatches.add(ins(new PushScopeIns())); + preCatches.add(ins(new SwapIns())); + preCatches.add(ins(new SetSlotIns(),1)); + preCatches.addAll(catchCmds.get(c)); + preCatches.add(ins(new PopScopeIns())); + preCatches.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempReg)))); + catches.addAll(0,preCatches); + catches.add(0,new ExceptionMarkAVM2Instruction(i, MARK_E_TARGET)); + i--; + catches.add(0,ins(new JumpIns(), insToBytes(catches).length)); + } + ret.addAll(catches); + localData.exceptions.addAll(newex); //TODO: finally return ret; } @@ -664,12 +735,10 @@ public class AVM2SourceGenerator implements SourceGenerator { generateTraitsPhase2(initScope, pkg, name, superName, false, localData, traitItems, instanceInfo.instance_traits, it); generateTraitsPhase2(initScope, pkg, name, superName, true, localData, traitItems, classInfo.static_traits, st); if (constructor == null) { - instanceInfo.iinit_index = method(initScope + 1, false, false, 0, name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = method(pkg.packageName,false,new ArrayList(),initScope + 1, false, 0, name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), TypeItem.UNBOUNDED/*?? FIXME*/); } else { MethodAVM2Item m = (MethodAVM2Item) constructor; - Reference hasArgs = new Reference<>(Boolean.FALSE); - calcRegisters(localData, m, hasArgs); - instanceInfo.iinit_index = method(initScope + 1, m.hasRest, hasArgs.getVal(), m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); + instanceInfo.iinit_index = method(pkg.packageName,m.needsActivation,m.subvariables,initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/); } //Class initializer @@ -759,6 +828,9 @@ public class AVM2SourceGenerator implements SourceGenerator { String pkg = ""; String name = type.toString(); + if("*".equals(name)){ + return 0; + } TypeItem nameItem = (TypeItem) type; if (name.contains(".")) { pkg = name.substring(0, name.lastIndexOf('.')); @@ -847,26 +919,175 @@ public class AVM2SourceGenerator implements SourceGenerator { return false; } - public int method(int initScope, boolean hasRest, boolean hasArguments, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List paramTypes, List paramNames, List paramValues, List body, GraphTargetItem retType) throws ParseException { + public int method(String pkg,boolean needsActivation,List subvariables,int initScope, boolean hasRest, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List paramTypes, List paramNames, List paramValues, List body, GraphTargetItem retType) throws ParseException { + //Reference hasArgs = new Reference<>(Boolean.FALSE); + //calcRegisters(localData,needsActivation,paramNames,subvariables,body, hasArgs); + localData.activationReg = 0; + + for (NameAVM2Item n : subvariables) { + if (n.unresolved) { + GraphTargetItem resolved = null; + List abcs = new ArrayList<>(); + abcs.add(abc); + abcs.addAll(allABCs); + + for (int i = 0; i < n.openedNamespaces.size(); i++) { + int nsIndex = n.openedNamespaces.get(i); + Namespace ns = abc.constants.constant_namespace.get(nsIndex); + int nsKind = ns.kind; + loopabc: + for (ABC a : abcs) { + for (int h = 0; h < a.instance_info.size(); h++) { + InstanceInfo ii = a.instance_info.get(h); + Multiname nm = a.constants.constant_multiname.get(ii.name_index); + if (nm.getNamespace(a.constants).getName(a.constants).equals(ns.getName(abc.constants)) && nm.getNamespace(a.constants).kind == nsKind) { + + //found opened class + Reference outName = new Reference<>(""); + Reference outNs = new Reference<>(""); + Reference outPropNs = new Reference<>(""); + Reference outPropNsKind = new Reference<>(1); + Reference outPropType = new Reference<>(""); + if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nm.getNamespace(a.constants).getName(a.constants), nm.getName(a.constants, new ArrayList()), n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropType)) { + resolved = new PropertyAVM2Item(null, n.getVariableName(), n.getIndex(), abc, allABCs, n.openedNamespaces); + } + } + } + } + } + n.redirect = resolved; + if (resolved == null) { + throw new ParseException("Unknown variable or property:" + n.getVariableName(), n.line); + } + } + } + + + boolean hasArguments = false; + List slotNames = new ArrayList<>(); + List slotTypes = new ArrayList<>(); + slotNames.add("--first"); + slotTypes.add("-"); + + List registerNames = new ArrayList<>(); + List registerTypes = new ArrayList<>(); + registerTypes.add(pkg.equals("")?className:pkg+"."+className); + registerNames.add("this"); + for(GraphTargetItem t:paramTypes){ + registerTypes.add(t.toString()); + slotTypes.add(t.toString()); + } + registerNames.addAll(paramNames); + slotNames.addAll(paramNames); + localData.registerVars.clear(); + for (NameAVM2Item n : subvariables) { + if (n.getVariableName().equals("arguments") & !n.isDefinition()) { + registerNames.add("arguments"); + registerTypes.add("Object"); + hasArguments = true; + break; + } + } + int paramRegCount = registerNames.size(); + + if(needsActivation){ + registerNames.add("+$activation"); + localData.activationReg = registerNames.size()-1; + registerTypes.add("Object"); + } + for (NameAVM2Item n : subvariables) { + if (n.isDefinition()) { + if(!needsActivation || (n.getSlotScope()<=0)){ + registerNames.add(n.getVariableName()); + registerTypes.add(n.type.toString()); + slotNames.add(n.getVariableName()); + slotTypes.add(n.type.toString()); + } + } + } + + + + int slotScope = 1; //? + + for (NameAVM2Item n : subvariables) { + if (n.getVariableName() != null) { + if(needsActivation){ + if(n.getSlotNumber() <= 0){ + n.setSlotNumber(slotNames.indexOf(n.getVariableName())); + n.setSlotScope(slotScope); + } + }else{ + n.setRegNumber(registerNames.indexOf(n.getVariableName())); + } + } + } + + for (int i = 0; i < registerNames.size(); i++) { + if(needsActivation && i>localData.activationReg){ + break; + } + localData.registerVars.put(registerNames.get(i), i); + } + List declarations=new ArrayList<>(); + loopn:for (NameAVM2Item n : subvariables) { + if(!n.isDefinition()){ + continue; + } + if(n.getSlotScope()!=slotScope){ + continue; + } + for(NameAVM2Item d:declarations){ + if(n.getVariableName()!=null && n.getVariableName().equals(d.getVariableName())){ + continue loopn; + } + } + for(GraphTargetItem it:body){ //search first level of commands + if(it instanceof NameAVM2Item){ + NameAVM2Item n2=(NameAVM2Item)it; + if(n2.isDefinition() && n2.getAssignedValue()!=null && n2.getVariableName().equals(n.getVariableName())){ + continue loopn; + } + if(!n2.isDefinition() && n2.getVariableName()!=null && n2.getVariableName().equals(n.getVariableName())){ //used earlier than defined + break; + } + } + } + NameAVM2Item d=new NameAVM2Item(n.type, n.line, n.getVariableName(), NameAVM2Item.getDefaultValue(""+n.type), true, n.openedNamespaces); + if(needsActivation){ + if(d.getSlotNumber() <= 0) + { + d.setSlotNumber(n.getSlotNumber()); + d.setSlotScope(n.getSlotScope()); + } + }else{ + d.setRegNumber(n.getRegNumber()); + } + declarations.add(d); + } + + int param_types[] = new int[paramTypes.size()]; ValueKind optional[] = new ValueKind[paramValues.size()]; - int param_names[] = new int[paramNames.size()]; + //int param_names[] = new int[paramNames.size()]; for (int i = 0; i < paramTypes.size(); i++) { param_types[i] = typeName(localData, paramTypes.get(i)); - param_names[i] = str(paramNames.get(i)); + //param_names[i] = str(paramNames.get(i)); } for (int i = 0; i < paramValues.size(); i++) { optional[i] = getValueKind(Namespace.KIND_NAMESPACE/*FIXME*/, paramTypes.get(paramTypes.size() - paramValues.size() + i), paramTypes.get(i)); } - MethodInfo mi = new MethodInfo(param_types, constructor ? 0 : typeName(localData, retType), 0/*name_index*/, 0, optional, param_names); + MethodInfo mi = new MethodInfo(param_types, constructor ? 0 : typeName(localData, retType), 0/*name_index*/, 0, optional, new int[0]/*no param_names*/); if (hasArguments) { mi.setFlagNeed_Arguments(); } + //No param names like in official + /* if (!paramNames.isEmpty()) { mi.setFlagHas_paramnames(); - } + }*/ if (!paramValues.isEmpty()) { mi.setFlagHas_optional(); } @@ -876,10 +1097,47 @@ public class AVM2SourceGenerator implements SourceGenerator { MethodBody mbody = new MethodBody(); mbody.method_info = abc.addMethodInfo(mi); + + mbody.traits = new Traits(); + int slotId = 1; + for(int i=1;i()), true); + tsc.type_index = typeName(localData, new TypeItem(slotTypes.get(i))); + mbody.traits.traits.add(tsc); + } + + if(needsActivation){ + for(int i=1;i()); + param.setRegNumber(i); + NameAVM2Item d=new NameAVM2Item(new TypeItem(registerTypes.get(i)), 0, registerNames.get(i), param, true, new ArrayList()); + d.setSlotScope(slotScope); + d.setSlotNumber(slotNames.indexOf(registerNames.get(i))); + declarations.add(d); + } + } + body.addAll(0,declarations); + + localData.exceptions = new ArrayList<>(); List src = generate(localData, body); mbody.code = new AVM2Code(); mbody.code.code = toInsList(src); + if(needsActivation){ + List acts=new ArrayList<>(); + acts.add(ins(new NewActivationIns())); + acts.add(ins(new DupIns())); + acts.add(AssignableAVM2Item.generateSetLoc(localData.activationReg)); + acts.add(ins(new PushScopeIns())); + + + + + mbody.code.code.addAll(0,acts); + } + if (constructor) { List abcs = new ArrayList<>(); abcs.add(abc); @@ -927,6 +1185,26 @@ public class AVM2SourceGenerator implements SourceGenerator { mbody.code.code.add(new AVM2Instruction(0, new ReturnValueIns(), new int[]{}, new byte[0])); } } + mbody.exceptions = localData.exceptions.toArray(new ABCException[localData.exceptions.size()]); + int offset = 0; + for (AVM2Instruction ins : mbody.code.code) { + if(ins instanceof ExceptionMarkAVM2Instruction){ + ExceptionMarkAVM2Instruction m=(ExceptionMarkAVM2Instruction)ins; + switch(m.markType){ + case MARK_E_START: + mbody.exceptions[m.exceptionId].start = offset; + break; + case MARK_E_END: + mbody.exceptions[m.exceptionId].end = offset; + break; + case MARK_E_TARGET: + mbody.exceptions[m.exceptionId].target = offset; + break; + } + } + offset+=ins.getBytes().length; + } + mbody.autoFillStats(abc, initScope); abc.addMethodBody(mbody); @@ -998,14 +1276,10 @@ public class AVM2SourceGenerator implements SourceGenerator { if (mai.isStatic() != generateStatic) { continue; } - Reference hasArgs = new Reference<>(Boolean.FALSE); - calcRegisters(localData, mai, hasArgs); - ((TraitMethodGetterSetter) traits[k]).method_info = method(initScope + 1/*class scope*/, mai.hasRest, hasArgs.getVal(), mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); + ((TraitMethodGetterSetter) traits[k]).method_info = method(pkg.packageName,mai.needsActivation,mai.subvariables,initScope + 1/*class scope*/, mai.hasRest,mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType); } else if (item instanceof FunctionAVM2Item) { FunctionAVM2Item fai = (FunctionAVM2Item) item; - Reference hasArgs = new Reference<>(Boolean.FALSE); - calcRegisters(localData, fai, hasArgs); - ((TraitFunction) traits[k]).method_info = method(initScope, fai.hasRest, hasArgs.getVal(), fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); + ((TraitFunction) traits[k]).method_info = method(pkg.packageName,fai.needsActivation,fai.subvariables,initScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType); } } } @@ -1318,76 +1592,9 @@ public class AVM2SourceGenerator implements SourceGenerator { } } - public void calcRegisters(SourceGeneratorLocalData localData, FunctionAVM2Item fun, Reference hasArguments) throws ParseException { - List registerNames = new ArrayList<>(); - registerNames.add("this"); - registerNames.addAll(fun.paramNames); - localData.registerVars.clear(); - for (NameAVM2Item n : fun.subvariables) { - if (n.getVariableName().equals("arguments") & !n.isDefinition()) { - registerNames.add("arguments"); - hasArguments.setVal(Boolean.TRUE); - break; - } - } - for (NameAVM2Item n : fun.subvariables) { - if (n.isDefinition()) { - registerNames.add(n.getVariableName()); - } - } - for (NameAVM2Item n : fun.subvariables) { - if (n.unresolved) { - GraphTargetItem resolved = null; - List abcs = new ArrayList<>(); - abcs.add(abc); - abcs.addAll(allABCs); - - for (int i = 0; i < n.openedNamespaces.size(); i++) { - int nsIndex = n.openedNamespaces.get(i); - Namespace ns = abc.constants.constant_namespace.get(nsIndex); - int nsKind = ns.kind; - loopabc: - for (ABC a : abcs) { - for (int h = 0; h < a.instance_info.size(); h++) { - InstanceInfo ii = a.instance_info.get(h); - Multiname nm = a.constants.constant_multiname.get(ii.name_index); - if (nm.getNamespace(a.constants).getName(a.constants).equals(ns.getName(abc.constants)) && nm.getNamespace(a.constants).kind == nsKind) { - - //found opened class - Reference outName = new Reference<>(""); - Reference outNs = new Reference<>(""); - Reference outPropNs = new Reference<>(""); - Reference outPropNsKind = new Reference<>(1); - Reference outPropType = new Reference<>(""); - if (AVM2SourceGenerator.searchPrototypeChain(false, abcs, nm.getNamespace(a.constants).getName(a.constants), nm.getName(a.constants, new ArrayList()), n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropType)) { - resolved = new PropertyAVM2Item(null, n.getVariableName(), n.getIndex(), abc, allABCs, n.openedNamespaces); - } - } - } - } - } - n.redirect = resolved; - if (resolved == null) { - throw new ParseException("Unknown variable or property:" + n.getVariableName(), n.line); - } - } - if (n.getVariableName() != null) { - n.setRegNumber(registerNames.indexOf(n.getVariableName())); - } - } - for (int i = 0; i < registerNames.size(); i++) { - localData.registerVars.put(registerNames.get(i), i); - } - List declarations=new ArrayList<>(); - for (NameAVM2Item n : fun.subvariables) { - if(n.isDefinition() && n.getAssignedValue() == null){ - NameAVM2Item d=new NameAVM2Item(n.type, n.line, n.getVariableName(), NameAVM2Item.getDefaultValue(""+n.type), true, n.openedNamespaces); - d.setRegNumber(n.getRegNumber()); - declarations.add(d); - } - } - fun.body.addAll(0,declarations); - } + /* public void calcRegisters(Reference activationReg, SourceGeneratorLocalData localData, boolean needsActivation, List funParamNames,List funSubVariables,List funBody, Reference hasArguments) throws ParseException { + + }*/ public int resolveType(String objType) { if (objType.equals("*")) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index cdc4b326c..f2bf5a0df 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ThrowAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item; @@ -128,13 +129,13 @@ public class ActionScriptParser { return uniqLast; } - private List commands(List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, ParseException { + private List commands(Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables) throws IOException, ParseException { List ret = new ArrayList<>(); if (debugMode) { System.out.println("commands:"); } GraphTargetItem cmd = null; - while ((cmd = command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)) != null) { + while ((cmd = command(needsActivation,importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)) != null) { ret.add(cmd); } if (debugMode) { @@ -400,7 +401,7 @@ public class ActionScriptParser { private MethodAVM2Item method(List importedClasses, boolean override, boolean isFinal, GraphTargetItem thisType, List openedNamespaces, boolean isStatic, int namespace, boolean withBody, String functionName, boolean isMethod, List variables) throws IOException, ParseException { FunctionAVM2Item f = function(importedClasses, namespace, thisType, openedNamespaces, withBody, functionName, isMethod, variables); - return new MethodAVM2Item(f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType); + return new MethodAVM2Item(f.needsActivation,f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType); } private FunctionAVM2Item function(List importedClasses, int namespace, GraphTargetItem thisType, List openedNamespaces, boolean withBody, String functionName, boolean isMethod, List variables) throws IOException, ParseException { @@ -464,17 +465,17 @@ public class ActionScriptParser { } subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), "arguments", null, true, openedNamespaces)); int parCnt = subvariables.size(); + Reference needsActivation = new Reference<>(false); if (withBody) { - expectedType(SymbolType.CURLY_OPEN); - - body = commands(importedClasses, openedNamespaces, new Stack(), new HashMap(), new HashMap(), true, isMethod, 0, subvariables); + expectedType(SymbolType.CURLY_OPEN); + body = commands(needsActivation, importedClasses, openedNamespaces, new Stack(), new HashMap(), new HashMap(), true, isMethod, 0, subvariables); expectedType(SymbolType.CURLY_CLOSE); } for (int i = 0; i < parCnt; i++) { subvariables.remove(0); } - return new FunctionAVM2Item(namespace, hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); + return new FunctionAVM2Item(needsActivation.getVal(), namespace, hasRest, line, functionName, paramTypes, paramNames, paramValues, body, subvariables, retType); } private GraphTargetItem traits(List importedClasses, int privateNs, int protectedNs, int publicNs, int packageInternalNs, int protectedStaticNs, List openedNamespaces, String packageName, String classNameStr, boolean isInterface, List traits) throws ParseException, IOException { @@ -662,13 +663,13 @@ public class ActionScriptParser { if (!ft.paramTypes.isEmpty()) { throw new ParseException("Getter can't have any parameters", lexer.yyline()); } - GetterAVM2Item g = new GetterAVM2Item(ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType); + GetterAVM2Item g = new GetterAVM2Item(ft.needsActivation,ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType); t = g; } else if (isSetter) { if (ft.paramTypes.size() != 1) { throw new ParseException("Getter must have exactly one parameter", lexer.yyline()); } - SetterAVM2Item st = new SetterAVM2Item(ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType); + SetterAVM2Item st = new SetterAVM2Item(ft.needsActivation,ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType); t = st; } else { t = ft; @@ -831,7 +832,7 @@ public class ActionScriptParser { //return ret; } - private GraphTargetItem command(List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, ParseException { + private GraphTargetItem command(Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables) throws IOException, ParseException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); GraphTargetItem ret = null; @@ -868,7 +869,7 @@ public class ActionScriptParser { } expectedType(SymbolType.PARENT_CLOSE); expectedType(SymbolType.CURLY_OPEN); - List wcmd = commands(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); + List wcmd = commands(needsActivation,importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); expectedType(SymbolType.CURLY_CLOSE); ret = new WithAVM2Item(null, wvar, wcmd); break; @@ -916,7 +917,7 @@ public class ActionScriptParser { } break; case CURLY_OPEN: - ret = new BlockItem(null, commands(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); + ret = new BlockItem(null, commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); expectedType(SymbolType.CURLY_CLOSE); break; /*case INCREMENT: //preincrement @@ -945,14 +946,14 @@ public class ActionScriptParser { expectedType(SymbolType.PARENT_OPEN); GraphTargetItem ifExpr = (expression(importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables)); expectedType(SymbolType.PARENT_CLOSE); - GraphTargetItem onTrue = command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables); + GraphTargetItem onTrue = command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables); List onTrueList = new ArrayList<>(); onTrueList.add(onTrue); s = lex(); List onFalseList = null; if (s.type == SymbolType.ELSE) { onFalseList = new ArrayList<>(); - onFalseList.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + onFalseList.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); } else { lexer.pushback(s); } @@ -961,7 +962,7 @@ public class ActionScriptParser { case WHILE: expectedType(SymbolType.PARENT_OPEN); List whileExpr = new ArrayList<>(); - whileExpr.add(commaExpression(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); + whileExpr.add(commaExpression(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); expectedType(SymbolType.PARENT_CLOSE); List whileBody = new ArrayList<>(); Loop wloop = new Loop(uniqId(), null, null); @@ -969,7 +970,7 @@ public class ActionScriptParser { loopLabels.put(wloop, loopLabel); } loops.push(wloop); - whileBody.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + whileBody.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); ret = new WhileItem(null, wloop, whileExpr, whileBody); break; case DO: @@ -979,11 +980,11 @@ public class ActionScriptParser { if (loopLabel != null) { loopLabels.put(dloop, loopLabel); } - doBody.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + doBody.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); expectedType(SymbolType.WHILE); expectedType(SymbolType.PARENT_OPEN); List doExpr = new ArrayList<>(); - doExpr.add(commaExpression(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); + doExpr.add(commaExpression(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables)); expectedType(SymbolType.PARENT_CLOSE); ret = new DoWhileItem(null, dloop, doBody, doExpr); break; @@ -998,7 +999,7 @@ public class ActionScriptParser { s = lex(); } expected(s, lexer.yyline(), SymbolType.PARENT_OPEN); - GraphTargetItem firstCommand=command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, false, variables); + GraphTargetItem firstCommand=command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, false, variables); if(firstCommand instanceof NameAVM2Item){ NameAVM2Item nai=(NameAVM2Item)firstCommand; if(nai.isDefinition() && nai.getAssignedValue() == null){ @@ -1024,17 +1025,17 @@ public class ActionScriptParser { GraphTargetItem forExpr = null; List forFirstCommands = new ArrayList<>(); if (!forin) { - //GraphTargetItem firstCommand = command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables); + //GraphTargetItem firstCommand = command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables); if (firstCommand != null) { //can be empty command forFirstCommands.add(firstCommand); } forExpr = (expression(importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables)); expectedType(SymbolType.SEMICOLON); - forFinalCommands.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + forFinalCommands.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); } expectedType(SymbolType.PARENT_CLOSE); List forBody = new ArrayList<>(); - forBody.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forin ? forinlevel + 1 : forinlevel, true, variables)); + forBody.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forin ? forinlevel + 1 : forinlevel, true, variables)); if (forin) { if (each) { ret = new ForEachInAVM2Item(null, floop, inexpr, forBody); @@ -1083,14 +1084,14 @@ public class ActionScriptParser { } pos++; lexer.pushback(s); - List caseCmd = commands(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); + List caseCmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); caseCmds.add(caseCmd); s = lex(); } List defCmd = new ArrayList<>(); if (s.type == SymbolType.DEFAULT) { expectedType(SymbolType.COLON); - defCmd = commands(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); + defCmd = commands(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables); s = lexer.lex(); } expected(s, lexer.yyline(), SymbolType.CURLY_CLOSE); @@ -1163,13 +1164,15 @@ public class ActionScriptParser { } break; case TRY: + needsActivation.setVal(true); List tryCommands = new ArrayList<>(); - tryCommands.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + tryCommands.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); s = lex(); boolean found = false; - List> catchCommands = null; + List> catchCommands = new ArrayList<>(); List catchExceptions = new ArrayList<>(); - if (s.type == SymbolType.CATCH) { + int varCnt = variables.size(); + while (s.type == SymbolType.CATCH) { expectedType(SymbolType.PARENT_OPEN); s = lex(); expected(s, lexer.yyline(), SymbolType.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP); @@ -1177,20 +1180,31 @@ public class ActionScriptParser { String enamestr = s.value.toString(); expectedType(SymbolType.COLON); GraphTargetItem etype = type(importedClasses, openedNamespaces, variables); - NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), enamestr, null, false/*?*/, openedNamespaces); + NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), enamestr, new ExceptionAVM2Item(null)/*?*/, true/*?*/, openedNamespaces); + variables.add(e); catchExceptions.add(e); - expectedType(SymbolType.PARENT_CLOSE); - catchCommands = new ArrayList<>(); + e.setSlotNumber(1); + e.setSlotScope(2); //? + expectedType(SymbolType.PARENT_CLOSE); List cc = new ArrayList<>(); - cc.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + cc.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); catchCommands.add(cc); s = lex(); found = true; } + for(int i=varCnt;i finallyCommands = null; if (s.type == SymbolType.FINALLY) { finallyCommands = new ArrayList<>(); - finallyCommands.add(command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); + finallyCommands.add(command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables)); found = true; s = lex(); } @@ -1513,12 +1527,12 @@ public class ActionScriptParser { return arrCnt; } - private GraphTargetItem commaExpression(List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, ParseException { + private GraphTargetItem commaExpression(Reference needsActivation,List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forInLevel, List variables) throws IOException, ParseException { GraphTargetItem cmd = null; List expr = new ArrayList<>(); ParsedSymbol s; do { - cmd = command(importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forInLevel, false, variables); + cmd = command(needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forInLevel, false, variables); if (cmd != null) { expr.add(cmd); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java index d36bb3924..8b2f6d3eb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java @@ -29,6 +29,9 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal1Ins; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal2Ins; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal3Ins; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.graph.GraphSourceItem; @@ -113,6 +116,8 @@ public abstract class AssignableAVM2Item extends AVM2Item { public static AVM2Instruction generateSetLoc(int regNumber) { switch (regNumber) { + case -1: + return null; case 0: return ins(new SetLocal0Ins()); case 1: @@ -128,6 +133,8 @@ public abstract class AssignableAVM2Item extends AVM2Item { public static AVM2Instruction generateGetLoc(int regNumber) { switch (regNumber) { + case -1: + return null; case 0: return ins(new GetLocal0Ins()); case 1: @@ -140,5 +147,25 @@ public abstract class AssignableAVM2Item extends AVM2Item { return ins(new GetLocalIns(), regNumber); } } + + public static List generateGetSlot(int slotScope,int slotNumber){ + if(slotNumber==-1){ + return null; + } + List ret = new ArrayList<>(); + ret.add(ins(new GetScopeObjectIns(),slotScope)); + ret.add(ins(new GetSlotIns(),slotNumber)); + return ret; + } + public static List generateSetSlot(SourceGeneratorLocalData localData,SourceGenerator generator, GraphTargetItem val,int slotScope,int slotNumber){ + if(slotNumber==-1){ + return null; + } + List ret = new ArrayList<>(); + ret.add(ins(new GetScopeObjectIns(),slotScope)); + ret.addAll(val.toSource(localData, generator)); + ret.add(ins(new SetSlotIns(),slotNumber)); + return ret; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java index 997bf79a2..6a64913cd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; /** * @@ -31,6 +32,7 @@ public class ExceptionMarkAVM2Instruction extends AVM2Instruction { super(0, null, new int[0], new byte[0]); this.markType = markType; this.exceptionId = exceptionId; + this.definition = new InstructionDefinition(0, "--mark", new int[0]); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/FunctionAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/FunctionAVM2Item.java index 039771278..c1253a58c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/FunctionAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/FunctionAVM2Item.java @@ -39,9 +39,11 @@ public class FunctionAVM2Item extends AVM2Item { public GraphTargetItem retType; public int line; public boolean hasRest; + public boolean needsActivation; - public FunctionAVM2Item(int namespace, boolean hasRest, int line, String functionName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { + public FunctionAVM2Item(boolean needsActivation, int namespace, boolean hasRest, int line, String functionName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { super(null, NOPRECEDENCE); + this.needsActivation = needsActivation; this.namespace = namespace; this.paramNames = paramNames; this.body = body; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/GetterAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/GetterAVM2Item.java index bd7bb445f..c7d169b12 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/GetterAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/GetterAVM2Item.java @@ -25,8 +25,8 @@ import java.util.List; */ public class GetterAVM2Item extends MethodAVM2Item { - public GetterAVM2Item(boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { - super(hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); + public GetterAVM2Item(boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { + super(needsActivation,hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/MethodAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/MethodAVM2Item.java index f040db2cd..69c44bf39 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/MethodAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/MethodAVM2Item.java @@ -31,8 +31,8 @@ public class MethodAVM2Item extends FunctionAVM2Item { private boolean isFinal; private boolean override; - public MethodAVM2Item(boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { - super(namespace, hasRest, line, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); + public MethodAVM2Item(boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { + super(needsActivation,namespace, hasRest, line, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); this.isStatic = isStatic; this.override = override; this.isFinal = isFinal; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java index 1e365158e..22c62ef0d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java @@ -27,7 +27,9 @@ 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.other.FindPropertyStrictIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; @@ -36,6 +38,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertDIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertSIns; +import static com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item.ins; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NanAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; @@ -69,6 +72,8 @@ public class NameAVM2Item extends AssignableAVM2Item { private GraphTargetItem ns = null; private int regNumber = -1; public boolean unresolved = false; + private int slotNumber = -1; + private int slotScope = 0; public GraphTargetItem redirect; @@ -82,6 +87,17 @@ public class NameAVM2Item extends AssignableAVM2Item { c.setIndex(index); return c; } + + public void setSlotScope(int slotScope) { + this.slotScope = slotScope; + } + + public int getSlotScope() { + return slotScope; + } + + + @@ -93,6 +109,14 @@ public class NameAVM2Item extends AssignableAVM2Item { this.regNumber = regNumber; } + public int getSlotNumber() { + return slotNumber; + } + + public void setSlotNumber(int slotNumber) { + this.slotNumber = slotNumber; + } + public int getRegNumber() { return regNumber; } @@ -199,8 +223,8 @@ public class NameAVM2Item extends AssignableAVM2Item { } private List toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn) { - if (variableName != null && regNumber == -1 && ns == null) { - throw new RuntimeException("No register set for " + variableName); + if (variableName != null && regNumber == -1 && slotNumber == -1 && ns == null) { + throw new RuntimeException("No register or slot set for " + variableName); } if (definition && assignedValue == null) { return new ArrayList(); @@ -252,7 +276,7 @@ public class NameAVM2Item extends AssignableAVM2Item { if (index != null) { if (assignedValue != null) { return toSourceMerge(localData, generator, - generateGetLoc(regNumber), 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()), true)), needsReturn ? getTemp(localData, generator, ret_temp) : null, @@ -269,10 +293,24 @@ public class NameAVM2Item extends AssignableAVM2Item { if (assignedValue != null) { List 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), + return toSourceMerge(localData, generator, generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber), needsReturn ? null : ins(new PopIns())); } } @@ -393,7 +431,7 @@ public class NameAVM2Item extends AssignableAVM2Item { if (index != null) { return toSourceMerge(localData, generator, - generateGetLoc(regNumber), 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()), true)), @@ -412,19 +450,31 @@ public class NameAVM2Item extends AssignableAVM2Item { } if(!needsReturn){ - return toSourceMerge(localData, generator, - ins(isInteger?new IncLocalIIns():new IncLocalIns(),regNumber)); + if(slotNumber>-1){ + return toSourceMerge(localData, generator, + ins(new GetScopeObjectIns(),slotScope), + generateGetSlot(slotScope,slotNumber), + (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())), + ins(new SetSlotIns(),slotNumber) + ); + }else{ + return toSourceMerge(localData, generator, + ins(isInteger?new IncLocalIIns():new IncLocalIns(),regNumber)); + } } return toSourceMerge(localData, generator, + slotNumber>-1?ins(new GetScopeObjectIns(),slotScope):null, //Start get original - generateGetLoc(regNumber), + generateGetLoc(regNumber),generateGetSlot(slotScope,slotNumber), //End get original !isInteger ? ins(new ConvertDIns()) : null, //End get original (!post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, needsReturn ? ins(new DupIns()) : null, (post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, - generateSetLoc(regNumber)); + generateSetLoc(regNumber), + slotNumber>-1?ins(new SetSlotIns(),slotNumber):null + ); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SetterAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SetterAVM2Item.java index 211b11076..c503f7328 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SetterAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SetterAVM2Item.java @@ -25,8 +25,8 @@ import java.util.List; */ public class SetterAVM2Item extends MethodAVM2Item { - public SetterAVM2Item(boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { - super(hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); + public SetterAVM2Item(boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List paramTypes, List paramNames, List paramValues, List body, List subvariables, GraphTargetItem retType) { + super(needsActivation,hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt index 0e9867e80..fcbb2edc5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/todo.txt @@ -1,11 +1,10 @@ TODO List for AS3 parser/compiler: ------------------------------ -- exceptions (try/catch) - finally clause - E4X (XML) - typenames (Vectors) - inner functions (activation, slots, etc.) -- with +- with (+ in catch clause) - delete property - default xml namespace - custom namespace modifiers \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 17207cebf..b732af1fa 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -224,8 +224,11 @@ public class MethodBody implements Cloneable, Serializable { if (stats == null) { return false; } + if(stats.has_activation){ + initScope++; + } max_stack = stats.maxstack; - max_scope_depth = init_scope_depth + stats.maxscope; + max_scope_depth = stats.maxscope+(stats.has_activation?1:0); max_regs = stats.maxlocal; init_scope_depth = initScope; abc.method_info.get(method_info).setFlagSetsdxns(stats.has_set_dxns);