diff --git a/lib/commons-bcel6-6.0-SNAPSHOT.jar b/lib/commons-bcel6-6.0-SNAPSHOT.jar index fb9a8ed3..1512826c 100644 Binary files a/lib/commons-bcel6-6.0-SNAPSHOT.jar and b/lib/commons-bcel6-6.0-SNAPSHOT.jar differ diff --git a/src/de/dhbwstuttgart/bytecode/ClassGenerator.java b/src/de/dhbwstuttgart/bytecode/ClassGenerator.java index bf5d7cd3..b05cf234 100644 --- a/src/de/dhbwstuttgart/bytecode/ClassGenerator.java +++ b/src/de/dhbwstuttgart/bytecode/ClassGenerator.java @@ -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; diff --git a/src/de/dhbwstuttgart/bytecode/MethodGenerator.java b/src/de/dhbwstuttgart/bytecode/MethodGenerator.java index 04bab9a8..25f558cd 100644 --- a/src/de/dhbwstuttgart/bytecode/MethodGenerator.java +++ b/src/de/dhbwstuttgart/bytecode/MethodGenerator.java @@ -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; diff --git a/src/de/dhbwstuttgart/bytecode/stackmaptable/CodeHelper.java b/src/de/dhbwstuttgart/bytecode/stackmaptable/CodeHelper.java deleted file mode 100644 index f03aadc5..00000000 --- a/src/de/dhbwstuttgart/bytecode/stackmaptable/CodeHelper.java +++ /dev/null @@ -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 localVars = new HashMap<>(); - Stack 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 getStackTypes(ConstantPoolGen cp){ - Menge ret = new Menge(); - for(StackItem si : stack){ - ret.add(si.getType(cp)); - } - return ret; - } - - public Menge getLocalTypes(ConstantPoolGen cp) { - Menge ret = new Menge(); - //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 outputStack = new ArrayList<>(); - - /** - * Generiert die StackMapEntrys zu einer gegebenen Methode - * @param forCode - * @return - */ - public static Menge getStackMapEntries(InstructionList forCode, ConstantPoolGen cp){ - Menge 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 stackTypes = state.getStackTypes(cp); - Menge 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; - */ - } - } - - -}