forked from JavaTX/JavaCompilerCore
StackMapTable funktioniert
This commit is contained in:
parent
81c8764fc6
commit
0896cf8236
Binary file not shown.
@ -172,8 +172,8 @@ public class ClassGenerator extends ClassGen{
|
||||
|
||||
@Override
|
||||
public void addMethod(Method m) {
|
||||
String methodNameAndTypes = m.getReturnType().toString()+m.getName()+Arrays.toString(m.getArgumentTypes());
|
||||
|
||||
//TODO: Die Prüfung, ob Methode bereits vorhanden vor die Bytecodegenerierung verlegen (Beispielsweise in Method)
|
||||
String methodNameAndTypes = m.getReturnType().toString()+";"+m.getName()+"("+Arrays.toString(m.getArgumentTypes());
|
||||
|
||||
if(methodsNamesAndTypes.contains(methodNameAndTypes)){
|
||||
return;
|
||||
|
@ -28,7 +28,6 @@ import org.apache.commons.bcel6.generic.Type;
|
||||
|
||||
import org.apache.commons.bcel6.Const;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.stackmaptable.CodeHelper;
|
||||
import de.dhbwstuttgart.logger.Logger;
|
||||
import de.dhbwstuttgart.logger.Section;
|
||||
import de.dhbwstuttgart.syntaxtree.FormalParameter;
|
||||
|
@ -1,710 +0,0 @@
|
||||
package de.dhbwstuttgart.bytecode.stackmaptable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.commons.bcel6.generic.ALOAD;
|
||||
import org.apache.commons.bcel6.generic.ASTORE;
|
||||
import org.apache.commons.bcel6.generic.ArrayType;
|
||||
import org.apache.commons.bcel6.generic.BasicType;
|
||||
import org.apache.commons.bcel6.generic.BranchInstruction;
|
||||
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
import org.apache.commons.bcel6.generic.DSTORE;
|
||||
import org.apache.commons.bcel6.generic.GETFIELD;
|
||||
import org.apache.commons.bcel6.generic.GotoInstruction;
|
||||
import org.apache.commons.bcel6.generic.IINC;
|
||||
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
|
||||
import org.apache.commons.bcel6.generic.INVOKEINTERFACE;
|
||||
import org.apache.commons.bcel6.generic.Instruction;
|
||||
import org.apache.commons.bcel6.generic.InstructionHandle;
|
||||
import org.apache.commons.bcel6.Const;
|
||||
import org.apache.commons.bcel6.classfile.ConstantPool;
|
||||
import org.apache.commons.bcel6.classfile.StackMapEntry;
|
||||
import org.apache.commons.bcel6.classfile.StackMapType;
|
||||
import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.InstructionTargeter;
|
||||
import org.apache.commons.bcel6.generic.InvokeInstruction;
|
||||
import org.apache.commons.bcel6.generic.LDC;
|
||||
import org.apache.commons.bcel6.generic.NEW;
|
||||
import org.apache.commons.bcel6.generic.ObjectType;
|
||||
import org.apache.commons.bcel6.generic.PUTFIELD;
|
||||
import org.apache.commons.bcel6.generic.ReferenceType;
|
||||
import org.apache.commons.bcel6.generic.StoreInstruction;
|
||||
import org.apache.commons.bcel6.generic.Type;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.MethodGenerator;
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
|
||||
class JVMState{
|
||||
|
||||
HashMap<Integer, StackItem> localVars = new HashMap<>();
|
||||
Stack<StackItem> stack = new Stack();
|
||||
|
||||
public StackItem getLocalType(int index) {
|
||||
return localVars.get(index);
|
||||
}
|
||||
|
||||
public void set(int index, StackItem objectRef) {
|
||||
localVars.put(index, objectRef);
|
||||
}
|
||||
|
||||
public void push(StackItem si){
|
||||
|
||||
}
|
||||
|
||||
void pop(int i){
|
||||
|
||||
}
|
||||
|
||||
public StackItem pop() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public Menge<StackMapType> getStackTypes(ConstantPoolGen cp){
|
||||
Menge<StackMapType> ret = new Menge<StackMapType>();
|
||||
for(StackItem si : stack){
|
||||
ret.add(si.getType(cp));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Menge<StackMapType> getLocalTypes(ConstantPoolGen cp) {
|
||||
Menge<StackMapType> ret = new Menge<StackMapType>();
|
||||
//TODO
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
interface StackItem{
|
||||
public static final StackItem NULL = new StackItemNull();
|
||||
public static final StackItem INTEGER = new StackItemType(BasicType.INT);
|
||||
public static final StackItem FLOAT = new StackItemType(BasicType.FLOAT);
|
||||
public static final StackItem LONG = new StackItemType(BasicType.LONG);
|
||||
public static final StackItem DOUBLE = new StackItemType(BasicType.DOUBLE);
|
||||
public static final StackItem TOP = new StackItemTop();
|
||||
|
||||
StackMapType getType(ConstantPoolGen cp);
|
||||
}
|
||||
|
||||
class StackItemNull implements StackItem{
|
||||
|
||||
@Override
|
||||
public StackMapType getType(ConstantPoolGen cp) {
|
||||
return new StackMapType(Const.ITEM_Null, 0, cp.getConstantPool());
|
||||
}
|
||||
}
|
||||
class StackItemType implements StackItem{
|
||||
|
||||
Type t = null;
|
||||
|
||||
//TODO: BasicType kann auch Void sein, dann ändert sich nichts am Stack
|
||||
public StackItemType(BasicType b){
|
||||
t=b;
|
||||
}
|
||||
public StackItemType(ReferenceType r){
|
||||
t=r;
|
||||
}
|
||||
public StackItemType(Type t){
|
||||
t=t;
|
||||
}
|
||||
@Override
|
||||
public StackMapType getType(ConstantPoolGen cp) {
|
||||
if(t instanceof BasicType){
|
||||
return null;//TODO
|
||||
}else if(t instanceof ObjectType){
|
||||
int classInfo = cp.addClass(((ObjectType)t));
|
||||
return new StackMapType(Const.ITEM_Object,classInfo,cp.getConstantPool());
|
||||
}else if(t instanceof ArrayType){
|
||||
return null; //TODO
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
class StackItemTop implements StackItem{
|
||||
|
||||
@Override
|
||||
public StackMapType getType(ConstantPoolGen cp) {
|
||||
return new StackMapType(Const.ITEM_Bogus,0,cp.getConstantPool());
|
||||
}
|
||||
|
||||
}
|
||||
class StackItemUninitialized implements StackItem{
|
||||
private NEW newIns;
|
||||
private InstructionHandle handle;
|
||||
public StackItemUninitialized(NEW newInstruction, InstructionHandle instructionHandle){
|
||||
newIns = newInstruction;
|
||||
handle = instructionHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackMapType getType(ConstantPoolGen cp) {
|
||||
return new StackMapType(Const.ITEM_NewObject,handle.getPosition(),cp.getConstantPool());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
class StackItemObject implements StackItem{
|
||||
public StackItemObject(String objName){
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
public class CodeHelper {
|
||||
|
||||
private ArrayList<Integer> outputStack = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Generiert die StackMapEntrys zu einer gegebenen Methode
|
||||
* @param forCode
|
||||
* @return
|
||||
*/
|
||||
public static Menge<StackMapEntry> getStackMapEntries(InstructionList forCode, ConstantPoolGen cp){
|
||||
Menge<StackMapEntry> ret = new Menge<>();
|
||||
JVMState state = new JVMState();
|
||||
if(forCode.isEmpty())return new Menge<>();
|
||||
forCode.setPositions(); //Otherwise InstructionHandle positions are wrong
|
||||
Instruction[] instructions = forCode.getInstructions();
|
||||
InstructionHandle[] instructionHandles = forCode.getInstructionHandles();
|
||||
int lastPosition = 0;
|
||||
|
||||
for(InstructionHandle ih : forCode.getInstructionHandles()){
|
||||
getOutput(ih, state, cp);
|
||||
if(isFrameEndpoint(ih, forCode)){
|
||||
if(!state.stack.isEmpty()){
|
||||
StackMapEntry entry = generateFullFrame(ih.getPosition(),state, cp);
|
||||
ret.add(entry);
|
||||
}else{
|
||||
int offset = ih.getPosition()-lastPosition;
|
||||
ret.add(new StackMapEntry(Const.SAME_FRAME + offset, 0, null, null, cp.getConstantPool()));
|
||||
}
|
||||
lastPosition = ih.getPosition()+1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static StackMapEntry generateFullFrame(int bytecodeOffset, JVMState state, ConstantPoolGen cp){
|
||||
Menge<StackMapType> stackTypes = state.getStackTypes(cp);
|
||||
Menge<StackMapType> localTypes = state.getLocalTypes(cp);
|
||||
StackMapType[] st = null;
|
||||
StackMapType[] lt = null;
|
||||
if(!stackTypes.isEmpty())st = stackTypes.toArray();
|
||||
if(!localTypes.isEmpty())lt = localTypes.toArray();
|
||||
StackMapEntry ret = new StackMapEntry(Const.FULL_FRAME,bytecodeOffset, lt, st, cp.getConstantPool());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Frame hört bei einem unconditionalBranch auf bzw. fängt bei dem Sprungziel eines Branches an.
|
||||
* @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1
|
||||
* @param position
|
||||
* @param inCode
|
||||
* @return
|
||||
*/
|
||||
private static boolean isFrameEndpoint(InstructionHandle position, InstructionList inCode){
|
||||
if(position.getInstruction() instanceof GotoInstruction){
|
||||
//Falls Instruktion ein unconditional Branch ist:
|
||||
return true;
|
||||
}
|
||||
for(InstructionHandle i : inCode.getInstructionHandles()){
|
||||
if(i.hasTargeters()){
|
||||
for(InstructionTargeter target : i.getTargeters()){
|
||||
if(target.containsTarget(position))return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(i instanceof BranchInstruction){
|
||||
inCode.getInstructionHandles()[1].getTargeters()
|
||||
if(((BranchInstruction) i).containsTarget(position)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void getOutput(InstructionHandle instructionHandle, JVMState ret, ConstantPoolGen cp){
|
||||
/*
|
||||
* TODO:
|
||||
* Berechnet den Output auf den Stack und ändert den LocalVarState und den StackState je nach Instruktion ab
|
||||
*/
|
||||
Instruction ins = instructionHandle.getInstruction();
|
||||
int opcode = ins.getOpcode();
|
||||
StackItem t1,t2,t3,t4;
|
||||
switch (opcode) {
|
||||
case Const.NOP:
|
||||
case Const.INEG:
|
||||
case Const.LNEG:
|
||||
case Const.FNEG:
|
||||
case Const.DNEG:
|
||||
case Const.I2B:
|
||||
case Const.I2C:
|
||||
case Const.I2S:
|
||||
case Const.GOTO:
|
||||
case Const.RETURN:
|
||||
break;
|
||||
case Const.ACONST_NULL:
|
||||
ret.push(StackItem.NULL);
|
||||
break;
|
||||
case Const.ICONST_M1:
|
||||
case Const.ICONST_0:
|
||||
case Const.ICONST_1:
|
||||
case Const.ICONST_2:
|
||||
case Const.ICONST_3:
|
||||
case Const.ICONST_4:
|
||||
case Const.ICONST_5:
|
||||
case Const.BIPUSH:
|
||||
case Const.SIPUSH:
|
||||
case Const.ILOAD:
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case Const.LCONST_0:
|
||||
case Const.LCONST_1:
|
||||
case Const.LLOAD:
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.FCONST_0:
|
||||
case Const.FCONST_1:
|
||||
case Const.FCONST_2:
|
||||
case Const.FLOAD:
|
||||
ret.push(StackItem.FLOAT);
|
||||
break;
|
||||
case Const.DCONST_0:
|
||||
case Const.DCONST_1:
|
||||
case Const.DLOAD:
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.LDC:
|
||||
LDC ldcIns = (LDC) ins;
|
||||
Type t = ldcIns.getType(cp);
|
||||
if(t.equals(Type.STRING)){
|
||||
ret.push(new StackItemType(Type.STRING));
|
||||
}else if(t.equals(Type.INT)){
|
||||
ret.push(StackItem.INTEGER);
|
||||
}else if(t.equals(Type.FLOAT)){
|
||||
ret.push(StackItem.FLOAT);
|
||||
}else if(t.equals(Type.DOUBLE)){
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
}else if(t.equals(Type.FLOAT)){
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
}else if(t.equals(Type.CLASS)){
|
||||
ret.push(new StackItemType(Type.CLASS));
|
||||
}
|
||||
/*
|
||||
switch (item.type) {
|
||||
case ClassWriter.INT:
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case ClassWriter.StackItem.LONG:
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case ClassWriter.StackItem.FLOAT:
|
||||
ret.push(StackItem.FLOAT);
|
||||
break;
|
||||
case ClassWriter.StackItem.DOUBLE:
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case ClassWriter.CLASS:
|
||||
ret.push(new StackItemOBJECT("java/lang/Class"));
|
||||
break;
|
||||
case ClassWriter.STR:
|
||||
ret.push(new StackItemOBJECT("java/lang/String"));
|
||||
break;
|
||||
case ClassWriter.MTYPE:
|
||||
ret.push(new StackItemOBJECT("java/lang/invoke/MethodType"));
|
||||
break;
|
||||
// case ClassWriter.HANDLE_BASE + [1..9]:
|
||||
default:
|
||||
ret.push(new StackItemOBJECT("java/lang/invoke/MethodHandle"));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case Const.ALOAD:
|
||||
ALOAD aloadIns = (ALOAD) ins;
|
||||
ret.push(ret.getLocalType(aloadIns.getIndex()));
|
||||
break;
|
||||
case Const.IALOAD:
|
||||
case Const.BALOAD:
|
||||
case Const.CALOAD:
|
||||
case Const.SALOAD:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case Const.LALOAD:
|
||||
case Const.D2L:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.FALOAD:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.FLOAT);
|
||||
break;
|
||||
case Const.DALOAD:
|
||||
case Const.L2D:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.AALOAD:
|
||||
ret.pop(1);
|
||||
StackItem arrayReference = ret.pop();
|
||||
ret.push(arrayReference); //TODO: Fixen, es darf nicht die ArrayReference sonder der Typ eines Elements des Arrays auf den Stack
|
||||
//ret.push(ELEMENT_OF + t1);
|
||||
break;
|
||||
case Const.ISTORE:
|
||||
case Const.FSTORE:
|
||||
case Const.ASTORE:
|
||||
StoreInstruction storeIns = (StoreInstruction)ins;
|
||||
t1 = ret.pop();
|
||||
ret.set(storeIns.getIndex(), t1);
|
||||
if (storeIns.getIndex() > 0) {
|
||||
t2 = ret.getLocalType(storeIns.getIndex() - 1);
|
||||
// if t2 is of kind STACK or LOCAL we cannot know its size!
|
||||
if (t2 == StackItem.LONG || t2 == StackItem.DOUBLE) {
|
||||
ret.set(storeIns.getIndex() - 1, StackItem.TOP);
|
||||
}
|
||||
//TODO:
|
||||
/*else if ((t2 & KIND) != BASE) {
|
||||
set(arg - 1, t2 | StackItem.TOP_IF_StackItem.LONG_OR_StackItem.DOUBLE);
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case Const.LSTORE:
|
||||
case Const.DSTORE:
|
||||
StoreInstruction largeStoreIns = (StoreInstruction)ins;
|
||||
ret.pop(1);
|
||||
t1 = ret.pop();
|
||||
ret.set(largeStoreIns.getIndex(), t1);
|
||||
ret.set(largeStoreIns.getIndex() + 1, StackItem.TOP);
|
||||
if (largeStoreIns.getIndex() > 0) {
|
||||
t2 = ret.getLocalType(largeStoreIns.getIndex() - 1);
|
||||
// if t2 is of kind STACK or LOCAL we cannot know its size!
|
||||
if (t2 == StackItem.LONG || t2 == StackItem.DOUBLE) {
|
||||
ret.set(largeStoreIns.getIndex() - 1, StackItem.TOP);
|
||||
} //TODO:
|
||||
/*else if ((t2 & KIND) != BASE) {
|
||||
set(arg - 1, t2 | StackItem.TOP_IF_StackItem.LONG_OR_StackItem.DOUBLE);
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case Const.IASTORE:
|
||||
case Const.BASTORE:
|
||||
case Const.CASTORE:
|
||||
case Const.SASTORE:
|
||||
case Const.FASTORE:
|
||||
case Const.AASTORE:
|
||||
ret.pop(3);
|
||||
break;
|
||||
case Const.LASTORE:
|
||||
case Const.DASTORE:
|
||||
ret.pop(4);
|
||||
break;
|
||||
case Const.POP:
|
||||
case Const.IFEQ:
|
||||
case Const.IFNE:
|
||||
case Const.IFLT:
|
||||
case Const.IFGE:
|
||||
case Const.IFGT:
|
||||
case Const.IFLE:
|
||||
case Const.IRETURN:
|
||||
case Const.FRETURN:
|
||||
case Const.ARETURN:
|
||||
case Const.TABLESWITCH:
|
||||
case Const.LOOKUPSWITCH:
|
||||
case Const.ATHROW:
|
||||
case Const.MONITORENTER:
|
||||
case Const.MONITOREXIT:
|
||||
case Const.IFNULL:
|
||||
case Const.IFNONNULL:
|
||||
ret.pop(1);
|
||||
break;
|
||||
case Const.POP2:
|
||||
case Const.IF_ICMPEQ:
|
||||
case Const.IF_ICMPNE:
|
||||
case Const.IF_ICMPLT:
|
||||
case Const.IF_ICMPGE:
|
||||
case Const.IF_ICMPGT:
|
||||
case Const.IF_ICMPLE:
|
||||
case Const.IF_ACMPEQ:
|
||||
case Const.IF_ACMPNE:
|
||||
case Const.LRETURN:
|
||||
case Const.DRETURN:
|
||||
ret.pop(2);
|
||||
break;
|
||||
case Const.DUP:
|
||||
t1 = ret.pop();
|
||||
ret.push(t1);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.DUP_X1:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
ret.push(t1);
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.DUP_X2:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
t3 = ret.pop();
|
||||
ret.push(t1);
|
||||
ret.push(t3);
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.DUP2:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.DUP2_X1:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
t3 = ret.pop();
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
ret.push(t3);
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.DUP2_X2:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
t3 = ret.pop();
|
||||
t4 = ret.pop();
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
ret.push(t4);
|
||||
ret.push(t3);
|
||||
ret.push(t2);
|
||||
ret.push(t1);
|
||||
break;
|
||||
case Const.SWAP:
|
||||
t1 = ret.pop();
|
||||
t2 = ret.pop();
|
||||
ret.push(t1);
|
||||
ret.push(t2);
|
||||
break;
|
||||
case Const.IADD:
|
||||
case Const.ISUB:
|
||||
case Const.IMUL:
|
||||
case Const.IDIV:
|
||||
case Const.IREM:
|
||||
case Const.IAND:
|
||||
case Const.IOR:
|
||||
case Const.IXOR:
|
||||
case Const.ISHL:
|
||||
case Const.ISHR:
|
||||
case Const.IUSHR:
|
||||
case Const.L2I:
|
||||
case Const.D2I:
|
||||
case Const.FCMPL:
|
||||
case Const.FCMPG:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case Const.LADD:
|
||||
case Const.LSUB:
|
||||
case Const.LMUL:
|
||||
case Const.LDIV:
|
||||
case Const.LREM:
|
||||
case Const.LAND:
|
||||
case Const.LOR:
|
||||
case Const.LXOR:
|
||||
ret.pop(4);
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.FADD:
|
||||
case Const.FSUB:
|
||||
case Const.FMUL:
|
||||
case Const.FDIV:
|
||||
case Const.FREM:
|
||||
case Const.L2F:
|
||||
case Const.D2F:
|
||||
ret.pop(2);
|
||||
ret.push(StackItem.FLOAT);
|
||||
break;
|
||||
case Const.DADD:
|
||||
case Const.DSUB:
|
||||
case Const.DMUL:
|
||||
case Const.DDIV:
|
||||
case Const.DREM:
|
||||
ret.pop(4);
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.LSHL:
|
||||
case Const.LSHR:
|
||||
case Const.LUSHR:
|
||||
ret.pop(3);
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.IINC:
|
||||
ret.set(((IINC)ins).getIndex(), StackItem.INTEGER);
|
||||
break;
|
||||
case Const.I2L:
|
||||
case Const.F2L:
|
||||
ret.pop(1);
|
||||
ret.push(StackItem.LONG);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.I2F:
|
||||
ret.pop(1);
|
||||
ret.push(StackItem.FLOAT);
|
||||
break;
|
||||
case Const.I2D:
|
||||
case Const.F2D:
|
||||
ret.pop(1);
|
||||
ret.push(StackItem.DOUBLE);
|
||||
ret.push(StackItem.TOP);
|
||||
break;
|
||||
case Const.F2I:
|
||||
case Const.ARRAYLENGTH:
|
||||
case Const.INSTANCEOF:
|
||||
ret.pop(1);
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case Const.LCMP:
|
||||
case Const.DCMPL:
|
||||
case Const.DCMPG:
|
||||
ret.pop(4);
|
||||
ret.push(StackItem.INTEGER);
|
||||
break;
|
||||
case Const.JSR:
|
||||
case Const.RET:
|
||||
throw new RuntimeException(
|
||||
"JSR/RET are not supported with computeFrames option"); //TODO: Fehlermeldung anpassen
|
||||
case Const.GETSTATIC:
|
||||
//ret.push(cw, item.strVal3); //TODO
|
||||
break;
|
||||
case Const.PUTSTATIC:
|
||||
//ret.pop(item.strVal3); //TODO
|
||||
break;
|
||||
case Const.GETFIELD:
|
||||
GETFIELD getfieldIns = (GETFIELD) ins;
|
||||
ret.pop(1);
|
||||
ret.push(new StackItemType(getfieldIns.getFieldType(cp)));
|
||||
break;
|
||||
case Const.PUTFIELD:
|
||||
PUTFIELD putfieldIns = (PUTFIELD) ins;
|
||||
ret.pop(putfieldIns.consumeStack(cp));
|
||||
break;
|
||||
case Const.INVOKEVIRTUAL:
|
||||
case Const.INVOKESPECIAL:
|
||||
case Const.INVOKESTATIC:
|
||||
case Const.INVOKEINTERFACE:
|
||||
case Const.INVOKEDYNAMIC:
|
||||
InvokeInstruction invokeIns = (InvokeInstruction) ins;
|
||||
ret.pop(invokeIns.consumeStack(cp));
|
||||
/*
|
||||
* TODO:
|
||||
* Hier return new StackItemOBJECT(returnTypeDerMethode);
|
||||
* returnTypeDerMethode bestimmen indem man im ConstantPool nach dem Argument für die Instruktion nachsieht.
|
||||
* Wie kann man bestimmen, ob es sich um Object oder primären Datentyp handelt. bcel-Typen verwenden? Müsste dann weiter oben auch gepatcht werden.
|
||||
*/
|
||||
/*
|
||||
ret.pop(item.strVal3);
|
||||
|
||||
if (opcode != Const.INVOKESTATIC) {
|
||||
t1 = ret.pop();
|
||||
if (opcode == Const.INVOKESPECIAL
|
||||
&& item.strVal2.charAt(0) == '<') {
|
||||
init(t1);
|
||||
}
|
||||
}
|
||||
|
||||
ret.push(cw, item.strVal3);
|
||||
*/
|
||||
Type retType = invokeIns.getReturnType(cp);
|
||||
if(retType instanceof BasicType){
|
||||
ret.push(new StackItemType((BasicType)retType));
|
||||
}else if(retType instanceof ArrayType){
|
||||
//TODO
|
||||
}else if(retType instanceof ReferenceType){
|
||||
ret.push(new StackItemType((ReferenceType) retType));
|
||||
}
|
||||
break;
|
||||
case Const.NEW:
|
||||
NEW newIns = (NEW) ins;
|
||||
ret.push(new StackItemUninitialized(newIns, instructionHandle));
|
||||
//ret.push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
||||
break;
|
||||
/*
|
||||
case Const.NEWARRAY:
|
||||
ret.pop();
|
||||
switch (arg) {
|
||||
case Const.T_BOOLEAN:
|
||||
ret.push(ARRAY_OF | BOOLEAN);
|
||||
break;
|
||||
case Const.T_CHAR:
|
||||
ret.push(ARRAY_OF | CHAR);
|
||||
break;
|
||||
case Const.T_BYTE:
|
||||
ret.push(ARRAY_OF | BYTE);
|
||||
break;
|
||||
case Const.T_SHORT:
|
||||
ret.push(ARRAY_OF | SHORT);
|
||||
break;
|
||||
case Const.T_INT:
|
||||
ret.push(ARRAY_OF | StackItem.INTEGER);
|
||||
break;
|
||||
case Const.T_StackItem.FLOAT:
|
||||
ret.push(ARRAY_OF | StackItem.FLOAT);
|
||||
break;
|
||||
case Const.T_StackItem.DOUBLE:
|
||||
ret.push(ARRAY_OF | StackItem.DOUBLE);
|
||||
break;
|
||||
// case Const.T_StackItem.LONG:
|
||||
default:
|
||||
ret.push(ARRAY_OF | StackItem.LONG);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Const.ANEWARRAY:
|
||||
String s = item.strVal1;
|
||||
ret.pop();
|
||||
if (s.charAt(0) == '[') {
|
||||
ret.push(cw, '[' + s);
|
||||
} else {
|
||||
ret.push(ARRAY_OF | OBJECT | cw.addType(s));
|
||||
}
|
||||
break;
|
||||
case Const.CHECKCAST:
|
||||
s = item.strVal1;
|
||||
ret.pop();
|
||||
if (s.charAt(0) == '[') {
|
||||
ret.push(cw, s);
|
||||
} else {
|
||||
ret.push(OBJECT | cw.addType(s));
|
||||
}
|
||||
break;
|
||||
// case Const.MULTIANEWARRAY:
|
||||
default:
|
||||
ret.pop(arg);
|
||||
ret.push(cw, item.strVal1);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user