Issue #420: some EmptyStackExceptions fixed

This commit is contained in:
Honfika
2013-11-25 19:57:11 +01:00
parent f53d825915
commit abfc07ca59
4 changed files with 101 additions and 3 deletions
@@ -226,7 +226,7 @@ public class AVM2Code implements Serializable {
new EqualsIns(),
new EscXAttrIns(),
new EscXElemIns(),
new InstructionDefinition(0x5f, "finddef", new int[]{AVM2Code.DAT_MULTINAME_INDEX}),
new FindDefIns(),
/* //Duplicate OPCODE with deldescendants. Prefering deldescendants (found in FLEX compiler)
new InstructionDefinition(0x5b,"findpropglobalstrict",new int[]{AVM2Code.DAT_MULTINAME_INDEX}){
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2010-2013 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.instructions.other;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.FindDefAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class FindDefIns extends InstructionDefinition {
public FindDefIns() {
super(0x5f, "finddef", new int[]{AVM2Code.DAT_MULTINAME_INDEX});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int multinameIndex = ins.operands[0];
Multiname multiname = constants.getMultiname(multinameIndex);
stack.push(new FindDefAVM2Item(ins, multiname));
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 1; //multiname may not be runtime
}
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2010-2013 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.model;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.model.LocalData;
public class FindDefAVM2Item extends AVM2Item {
public Multiname propertyName;
public FindDefAVM2Item(AVM2Instruction instruction, Multiname propertyName) {
super(instruction, PRECEDENCE_PRIMARY);
this.propertyName = propertyName;
}
@Override
protected GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) {
return writer.append(propertyName.getNamespace(localData.constantsAvm2).getName(localData.constantsAvm2));
}
}
@@ -1769,13 +1769,24 @@ public class Graph {
if (!isEmpty) {
onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, staticOperation, path);
}
if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() > trueStackSizeBefore) && (falseStack.size() > falseStackSizeBefore)) {
if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) {
stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop()));
} else {
currentRet.add(new IfItem(null, expr, onTrue, onFalse));
}
if (next != null) {
printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path);
if (trueStack.size() != trueStackSizeBefore || falseStack.size() != falseStackSizeBefore) {
// it's a hack, because duplicates all instructions in the next part, but better than EmptyStackException
onTrue = printGraph(visited, localData, trueStack, allParts, part, next, stopPart, loops, null, staticOperation, path);
onFalse = printGraph(visited, localData, falseStack, allParts, part, next, stopPart, loops, null, staticOperation, path);
if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() == trueStackSizeBefore + 1) && (falseStack.size() == falseStackSizeBefore + 1)) {
stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop()));
} else {
currentRet.add(new IfItem(null, expr, onTrue, onFalse));
}
} else {
printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet, staticOperation, path);
}
//currentRet.addAll();
}
}