AS3 parser - filling code stats

This commit is contained in:
Jindra Pet��k
2014-03-29 21:25:42 +01:00
parent 7f2cc41c10
commit 58951c068e
8 changed files with 134 additions and 94 deletions
@@ -895,11 +895,6 @@ public class ABC {
return ret;
}
public void autoFillAllBodyParams() {
for (int i = 0; i < bodies.size(); i++) {
bodies.get(i).autoFillStats(this);
}
}
public int findMethodInfoByName(int classId, String methodName) {
if (classId > -1) {
@@ -1856,8 +1856,11 @@ public class AVM2Code implements Serializable {
stats.instructionStats[pos].stackpos = stack;
stats.instructionStats[pos].scopepos = scope;
AVM2Instruction ins = code.get(pos);
stack += ins.definition.getStackDelta(ins, abc);
scope += ins.definition.getScopeStackDelta(ins, abc);
int stackDelta = ins.definition.getStackDelta(ins, abc);
stack += stackDelta;
int scopeDelta = ins.definition.getScopeStackDelta(ins, abc);
//System.out.println(""+ins+" stack:"+(stackDelta>0?"+"+stackDelta:stackDelta)+" scope:"+(scopeDelta>0?"+"+scopeDelta:scopeDelta));
scope += scopeDelta;
if (stack > stats.maxstack) {
stats.maxstack = stack;
}
@@ -1872,13 +1875,15 @@ public class AVM2Code implements Serializable {
}
if (ins.definition instanceof SetLocalTypeIns) {
handleRegister(stats, ((SetLocalTypeIns) ins.definition).getRegisterId(ins));
} else if (ins.definition instanceof GetLocalTypeIns) {
handleRegister(stats, ((GetLocalTypeIns) ins.definition).getRegisterId(ins));
} else {
for (int i = 0; i < ins.definition.operands.length; i++) {
if (ins.definition.operands[i] == DAT_REGISTER_INDEX) {
handleRegister(stats, ins.operands[i]);
}
}
}
}
if (ins.definition instanceof ReturnValueIns) {
//check stack=1
return true;
@@ -1919,9 +1924,9 @@ public class AVM2Code implements Serializable {
return true;
}
public CodeStats getStats(ABC abc, MethodBody body) {
CodeStats stats = new CodeStats(this);
if (!walkCode(stats, 0, 0, 0, abc)) {
public CodeStats getStats(ABC abc, MethodBody body, int initScope) {
CodeStats stats = new CodeStats(this);
if (!walkCode(stats, 0, 0, initScope, abc)) {
return null;
}
for (ABCException ex : body.exceptions) {
@@ -29,7 +29,7 @@ public class CodeStats {
public int maxstack = 0;
public int maxscope = 0;
public int maxlocal = 0;
public int maxlocal = -1;
public boolean has_set_dxns = false;
public boolean has_activation = false;
public InstructionStats[] instructionStats;
@@ -44,7 +44,9 @@ public class GetLexIns extends InstructionDefinition {
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 1; //multiname may not be runtime
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
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.InitPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
@@ -563,35 +564,32 @@ public class AVM2SourceGenerator implements SourceGenerator {
return abc;
}
public void generateClass(PackageAVM2Item pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List<GraphTargetItem> implementsStr, GraphTargetItem constructor, List<GraphTargetItem> traitItems) throws ParseException {
public void generateClass(int initScope, PackageAVM2Item pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List<GraphTargetItem> implementsStr, GraphTargetItem constructor, List<GraphTargetItem> traitItems) throws ParseException {
List<GraphSourceItem> ret = new ArrayList<>();
if (extendsVal == null && !isInterface) {
extendsVal = new TypeItem("Object");
}
ParsedSymbol s = null;
instanceInfo.name_index = abc.constants.addMultiname(new Multiname(Multiname.QNAME, abc.constants.getStringId(name, true),
abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(pkg.packageName, true)), 0, true), 0, 0, new ArrayList<Integer>()));
generateTraits(pkg, name, superName, false, localData, traitItems, instanceInfo.instance_traits);
generateTraits(pkg, name, superName, true, localData, traitItems, classInfo.static_traits);
Trait[] it = generateTraitsPhase1(pkg, name, superName, false, localData, traitItems, instanceInfo.instance_traits);
Trait[] st = generateTraitsPhase1(pkg, name, superName, true, localData, traitItems, classInfo.static_traits);
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(false,false,0,name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<GraphTargetItem>(), new ArrayList<String>(), new ArrayList<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), TypeItem.UNBOUNDED/*?? FIXME*/);
instanceInfo.iinit_index = method(initScope+1, false, false, 0, name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<GraphTargetItem>(), new ArrayList<String>(), new ArrayList<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), TypeItem.UNBOUNDED/*?? FIXME*/);
} else {
MethodAVM2Item m = (MethodAVM2Item) constructor;
Reference<Boolean> hasArgs=new Reference<>(Boolean.FALSE);
calcRegisters(localData, m,hasArgs);
instanceInfo.iinit_index = method(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*/);
Reference<Boolean> 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*/);
}
if (extendsVal != null) {
instanceInfo.super_index = typeName(localData, extendsVal);
} else if (!isInterface) {
instanceInfo.super_index = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str("Object"), namespace(Namespace.KIND_PACKAGE, ""), 0, 0, new ArrayList<Integer>()), true);
}
//Class initializer
MethodInfo mi = new MethodInfo(new int[0], 0, str(""), 0, new ValueKind[0], new int[0]);
MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]);
MethodBody mb = new MethodBody();
mb.method_info = abc.addMethodInfo(mi);
mb.code = new AVM2Code();
@@ -611,7 +609,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
}
mb.code.code.add(ins(new ReturnVoidIns()));
mb.autoFillStats(abc);
mb.autoFillStats(abc, initScope);
abc.addMethodBody(mb);
@@ -639,22 +637,27 @@ public class AVM2SourceGenerator implements SourceGenerator {
return ret;
}
public int generateClass(PackageAVM2Item pkg, SourceGeneratorLocalData localData, AVM2Item cls) throws ParseException {
ClassInfo ci = new ClassInfo();
InstanceInfo ii = new InstanceInfo();
abc.class_info.add(ci);
abc.instance_info.add(ii);
public int generateClass(ClassInfo ci, InstanceInfo ii, int initScope, PackageAVM2Item pkg, SourceGeneratorLocalData localData, AVM2Item cls) throws ParseException {
/*ClassInfo ci = new ClassInfo();
InstanceInfo ii = new InstanceInfo();
abc.class_info.add(ci);
abc.instance_info.add(ii);
*/
if (cls instanceof ClassAVM2Item) {
ClassAVM2Item cai = (ClassAVM2Item) cls;
generateClass(pkg, ci, ii, localData, false, cai.className, cai.extendsOp.toString(), cai.extendsOp, cai.implementsOp, cai.constructor, cai.traits);
generateClass(initScope, pkg, ci, ii, localData, false, cai.className, cai.extendsOp.toString(), cai.extendsOp, cai.implementsOp, cai.constructor, cai.traits);
if (!cai.isDynamic) {
ii.flags |= InstanceInfo.CLASS_SEALED;
}
if(cai.isFinal){
ii.flags |= InstanceInfo.CLASS_FINAL;
}
ii.flags |= InstanceInfo.CLASS_PROTECTEDNS;
ii.protectedNS = abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PROTECTED, abc.constants.getStringId(pkg.packageName.equals("")?cai.className:pkg.packageName+":"+cai.className, true)), 0, true);
}
if (cls instanceof InterfaceAVM2Item) {
InterfaceAVM2Item iai = (InterfaceAVM2Item) cls;
generateClass(pkg, ci, ii, localData, true, iai.name, null, null, iai.superInterfaces, null, iai.methods);
generateClass(initScope, pkg, ci, ii, localData, true, iai.name, null, null, iai.superInterfaces, null, iai.methods);
ii.flags |= InstanceInfo.CLASS_INTERFACE;
}
@@ -760,7 +763,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
return false;
}
public int method(boolean hasRest,boolean hasArguments,int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, GraphTargetItem retType) throws ParseException {
public int method(int initScope, boolean hasRest, boolean hasArguments, int line, String className, String superType, boolean constructor, SourceGeneratorLocalData localData, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, GraphTargetItem retType) throws ParseException {
int param_types[] = new int[paramTypes.size()];
ValueKind optional[] = new ValueKind[paramValues.size()];
int param_names[] = new int[paramNames.size()];
@@ -773,20 +776,18 @@ public class AVM2SourceGenerator implements SourceGenerator {
optional[i] = getValueKind(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);
if(hasArguments){
if (hasArguments) {
mi.setFlagNeed_Arguments();
}
mi.setFlagHas_paramnames();
if(!paramValues.isEmpty()){
if (!paramValues.isEmpty()) {
mi.setFlagHas_optional();
}
if(hasRest){
}
if (hasRest) {
mi.setFlagNeed_rest();
}
}
MethodBody mbody = new MethodBody();
mbody.method_info = abc.addMethodInfo(mi);
List<GraphSourceItem> src = generate(localData, body);
@@ -840,7 +841,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
mbody.code.code.add(new AVM2Instruction(0, new ReturnValueIns(), new int[]{}, new byte[0]));
}
}
mbody.autoFillStats(abc);
mbody.autoFillStats(abc, initScope);
abc.addMethodBody(mbody);
//TODO: Exceptions
@@ -887,13 +888,50 @@ public class AVM2SourceGenerator implements SourceGenerator {
return null;
}
public void generateTraits(PackageAVM2Item pkg, String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List<GraphTargetItem> items, Traits ts) throws ParseException {
public void generateTraitsPhase2(int initScope, PackageAVM2Item pkg, String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List<GraphTargetItem> items, Traits ts, Trait[] traits) throws ParseException {
//Note: Names must be generated first before accesed in inner subs
for (int k = 0; k < items.size(); k++) {
GraphTargetItem item = items.get(k);
if (traits[k] == null) {
continue;
}
if (item instanceof InterfaceAVM2Item) {
generateClass(abc.class_info.get(((TraitClass) traits[k]).class_info),abc.instance_info.get(((TraitClass) traits[k]).class_info), initScope, pkg, localData, (InterfaceAVM2Item) item);
}
if (item instanceof ClassAVM2Item) {
generateClass(abc.class_info.get(((TraitClass) traits[k]).class_info),abc.instance_info.get(((TraitClass) traits[k]).class_info) , initScope, pkg, localData, (ClassAVM2Item) item);
}
if ((item instanceof MethodAVM2Item) || (item instanceof GetterAVM2Item) || (item instanceof SetterAVM2Item)) {
MethodAVM2Item mai = (MethodAVM2Item) item;
if (mai.isStatic() != generateStatic) {
continue;
}
Reference<Boolean> 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);
} else if (item instanceof FunctionAVM2Item) {
FunctionAVM2Item fai = (FunctionAVM2Item) item;
Reference<Boolean> 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);
}
}
}
public Trait[] generateTraitsPhase1(PackageAVM2Item pkg, String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List<GraphTargetItem> items, Traits ts) throws ParseException {
Trait[] traits = new Trait[items.size()];
int slot_id = 1;
for (int k = 0; k < items.size(); k++) {
GraphTargetItem item = items.get(k);
if (item instanceof InterfaceAVM2Item) {
TraitClass tc = new TraitClass();
ClassInfo ci = new ClassInfo();
InstanceInfo ii = new InstanceInfo();
abc.class_info.add(ci);
abc.instance_info.add(ii);
tc.class_info = abc.instance_info.size()-1;
tc.kindType = Trait.TRAIT_CLASS;
tc.name_index = traitName(pkg.packageName, className, ((InterfaceAVM2Item) item).namespaceKind, ((InterfaceAVM2Item) item).name);
tc.slot_id = slot_id++;
@@ -903,6 +941,23 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (item instanceof ClassAVM2Item) {
TraitClass tc = new TraitClass();
ClassInfo ci = new ClassInfo();
InstanceInfo instanceInfo = new InstanceInfo();
abc.class_info.add(ci);
abc.instance_info.add(instanceInfo);
tc.class_info = abc.instance_info.size()-1;
instanceInfo.name_index = abc.constants.addMultiname(new Multiname(Multiname.QNAME, abc.constants.getStringId(((ClassAVM2Item) item).className, true),
abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(pkg.packageName, true)), 0, true), 0, 0, new ArrayList<Integer>()));
if (((ClassAVM2Item)item).extendsOp != null) {
instanceInfo.super_index = typeName(localData, ((ClassAVM2Item)item).extendsOp);
} else if (true) { //(!isInterface) {
instanceInfo.super_index = abc.constants.getMultinameId(new Multiname(Multiname.QNAME, str("Object"), namespace(Namespace.KIND_PACKAGE, ""), 0, 0, new ArrayList<Integer>()), true);
}
tc.kindType = Trait.TRAIT_CLASS;
tc.name_index = traitName(pkg.packageName, className, ((ClassAVM2Item) item).namespaceKind, ((ClassAVM2Item) item).className);
tc.slot_id = slot_id++;
@@ -979,40 +1034,12 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
}
//Note: Names must be generated first before accesed in inner subs
for (int k = 0; k < items.size(); k++) {
GraphTargetItem item = items.get(k);
if (traits[k] == null) {
continue;
}
if (item instanceof InterfaceAVM2Item) {
((TraitClass) traits[k]).class_info = generateClass(pkg, localData, (InterfaceAVM2Item) item);
}
if (item instanceof ClassAVM2Item) {
((TraitClass) traits[k]).class_info = generateClass(pkg, localData, (ClassAVM2Item) item);
}
if ((item instanceof MethodAVM2Item) || (item instanceof GetterAVM2Item) || (item instanceof SetterAVM2Item)) {
MethodAVM2Item mai = (MethodAVM2Item) item;
if (mai.isStatic() != generateStatic) {
continue;
}
Reference<Boolean> hasArgs=new Reference<>(Boolean.FALSE);
calcRegisters(localData, mai, hasArgs);
((TraitMethodGetterSetter) traits[k]).method_info = method(mai.hasRest,hasArgs.getVal(),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<Boolean> hasArgs=new Reference<>(Boolean.FALSE);
calcRegisters(localData, fai, hasArgs);
((TraitFunction) traits[k]).method_info = method(fai.hasRest,hasArgs.getVal(),fai.line,className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType);
}
}
return traits;
}
public ScriptInfo generateScriptInfo(PackageAVM2Item pkg, SourceGeneratorLocalData localData, List<GraphTargetItem> commands) throws ParseException {
public ScriptInfo generateScriptInfo(PackageAVM2Item pkg, SourceGeneratorLocalData localData, List<GraphTargetItem> commands, boolean documentClass) throws ParseException {
ScriptInfo si = new ScriptInfo();
generateTraits(pkg, null, null, false, localData, commands, si.traits);
Trait[] traitArr = generateTraitsPhase1(pkg, null, null, false, localData, commands, si.traits);
MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]);
MethodBody mb = new MethodBody();
@@ -1021,16 +1048,24 @@ public class AVM2SourceGenerator implements SourceGenerator {
mb.code.code.add(ins(new GetLocal0Ins()));
mb.code.code.add(ins(new PushScopeIns()));
int traitScope = 1;
for (Trait t : si.traits.traits) {
if (t instanceof TraitClass) {
TraitClass tc = (TraitClass) t;
List<Integer> parents = new ArrayList<>();
parentNamesAddNames(abc, allABCs, abc.instance_info.get(tc.class_info).name_index, parents, new ArrayList<String>(), new ArrayList<String>());
NamespaceSet nsset = new NamespaceSet(new int[]{abc.constants.constant_multiname.get(tc.name_index).namespace_index});
mb.code.code.add(ins(new FindPropertyStrictIns(), abc.constants.getMultinameId(new Multiname(Multiname.MULTINAME, abc.constants.constant_multiname.get(tc.name_index).name_index, 0, abc.constants.getNamespaceSetId(nsset, true), 0, new ArrayList<Integer>()), true)));
if (documentClass) {
mb.code.code.add(ins(new GetScopeObjectIns(), 0));
traitScope++;
} else {
NamespaceSet nsset = new NamespaceSet(new int[]{abc.constants.constant_multiname.get(tc.name_index).namespace_index});
mb.code.code.add(ins(new FindPropertyStrictIns(), abc.constants.getMultinameId(new Multiname(Multiname.MULTINAME, abc.constants.constant_multiname.get(tc.name_index).name_index, 0, abc.constants.getNamespaceSetId(nsset, true), 0, new ArrayList<Integer>()), true)));
}
for (int i = parents.size() - 1; i >= 1; i--) {
mb.code.code.add(ins(new GetLexIns(), parents.get(i)));
mb.code.code.add(ins(new PushScopeIns()));
traitScope++;
}
mb.code.code.add(ins(new GetLexIns(), parents.get(1)));
mb.code.code.add(ins(new NewClassIns(), tc.class_info));
@@ -1042,9 +1077,12 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
mb.code.code.add(ins(new ReturnVoidIns()));
mb.autoFillStats(abc);
System.out.println("---------------script---------------");
mb.autoFillStats(abc, documentClass ? 1 : 0);
System.out.println("/--------------script---------------");
abc.addMethodBody(mb);
si.init_index = mb.method_info;
generateTraitsPhase2(traitScope, pkg, null, null, false, localData, commands, si.traits, traitArr);
return si;
}
@@ -1153,7 +1191,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
registerNames.addAll(fun.paramNames);
localData.registerVars.clear();
for (NameAVM2Item n : fun.subvariables) {
if (n.getVariableName().equals("arguments")&!n.isDefinition()) {
if (n.getVariableName().equals("arguments") & !n.isDefinition()) {
registerNames.add("arguments");
hasArguments.setVal(Boolean.TRUE);
break;
@@ -1767,7 +1767,7 @@ public class ActionScriptParser {
return ret;
}
public void addScriptFromTree(PackageAVM2Item pkg) throws ParseException {
public void addScriptFromTree(PackageAVM2Item pkg, boolean documentClass) throws ParseException {
AVM2SourceGenerator gen = new AVM2SourceGenerator(abc, otherABCs);
List<AVM2Instruction> ret = new ArrayList<>();
SourceGeneratorLocalData localData = new SourceGeneratorLocalData(
@@ -1778,12 +1778,12 @@ public class ActionScriptParser {
className = ((ClassAVM2Item) it).className;
}
}
abc.script_info.add(gen.generateScriptInfo(pkg, localData, pkg.items));
abc.script_info.add(gen.generateScriptInfo(pkg, localData, pkg.items, documentClass));
}
public void addScript(String s) throws ParseException, IOException {
public void addScript(String s, boolean documentClass) throws ParseException, IOException {
PackageAVM2Item pkg = packageFromString(s);
addScriptFromTree(pkg);
addScriptFromTree(pkg, documentClass);
}
public ActionScriptParser(ABC abc, List<ABC> otherABCs) {
@@ -1809,7 +1809,7 @@ public class ActionScriptParser {
}
ABC abc = new ABC(swf);
ActionScriptParser parser = new ActionScriptParser(abc, playerABCs);
parser.addScript(new String(Helper.readFile(src), "UTF-8"));
parser.addScript(new String(Helper.readFile(src), "UTF-8"),true);
abc.saveToStream(new FileOutputStream(new File(dst)));
} catch (Exception ex) {
Logger.getLogger(ActionScriptParser.class.getName()).log(Level.SEVERE, null, ex);
@@ -10,5 +10,4 @@ TODO List for AS3 parser/compiler:
- pre/post in/decrements
- with
- delete property
- default xml namespace
- method body correct code stats
- default xml namespace
@@ -219,14 +219,15 @@ public class MethodBody implements Cloneable, Serializable {
return ret;
}
public boolean autoFillStats(ABC abc) {
CodeStats stats = code.getStats(abc, this);
public boolean autoFillStats(ABC abc, int initScope) {
CodeStats stats = code.getStats(abc, this, initScope);
if (stats == null) {
return false;
}
max_stack = stats.maxstack;
max_scope_depth = init_scope_depth + stats.maxscope;
max_regs = stats.maxlocal;
init_scope_depth = initScope;
abc.method_info.get(method_info).setFlagSetsdxns(stats.has_set_dxns);
abc.method_info.get(method_info).setFlagNeed_activation(stats.has_activation);
return true;