From b71efd65a0ff214f51ffeac42d9d03e75006d61e Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 19 Dec 2018 13:20:09 +0100 Subject: [PATCH] Tphs einer Methode, die groesser als Tphs der Felder, werden als Class-Generics definiert --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 52 +++++++++++++++++-- .../bytecode/BytecodeGenMethod.java | 19 ++++++- .../bytecode/signature/Signature.java | 38 ++++++++++++-- .../bytecode/utilities/Simplify.java | 4 +- test/bytecode/FieldTph2Test.java | 52 +++++++++++++++++++ test/bytecode/javFiles/FieldTph2.jav | 12 +++++ test/bytecode/simplifyalgo/CycleTest.java | 3 +- test/bytecode/simplifyalgo/SameLeftSide.java | 5 +- test/bytecode/simplifyalgo/SimpleCycle.java | 3 +- 9 files changed, 173 insertions(+), 15 deletions(-) create mode 100644 test/bytecode/FieldTph2Test.java create mode 100644 test/bytecode/javFiles/FieldTph2.jav diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 96a1c19bc..2ac10fccb 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; import java.util.Optional; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -62,6 +63,8 @@ public class BytecodeGen implements ASTVisitor { private String superClass; + private ArrayList tphsClass; + // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... HashMap paramsAndLocals = new HashMap<>(); // stores generics and their bounds of class @@ -138,12 +141,28 @@ public class BytecodeGen implements ASTVisitor { getCommonTPHS(tphExtractor); - ArrayList tphsClass = new ArrayList<>(); + tphsClass = new ArrayList<>(); for(TypePlaceholder t : tphExtractor.allTPHS.keySet()) { if(!tphExtractor.allTPHS.get(t)) tphsClass.add(t); } + ArrayList consClass = new ArrayList<>(); + for(TPHConstraint cons : tphExtractor.allCons) { + TypePlaceholder right = null; + for(TypePlaceholder tph : tphsClass) { + if(cons.getLeft().equals(tph.getName())) { + + consClass.add(cons); + right = getTPH(cons.getRight()); + } + } + if(right != null) { + tphsClass.add(right); + removeFromMethod(right.getName()); + right = null; + } + } String sig = null; /* if class has generics then creates signature * Signature looks like: @@ -152,7 +171,7 @@ public class BytecodeGen implements ASTVisitor { if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() || classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") || !tphsClass.isEmpty()) { - Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass); + Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); sig = signature.toString(); System.out.println("Signature: => " + sig); } @@ -184,6 +203,31 @@ public class BytecodeGen implements ASTVisitor { } + private void removeFromMethod(String name) { + for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + ArrayList toRemove = new ArrayList<>(); + for(String tph : m.getTphs()) { + if(tph.equals(name)) { + toRemove.add(tph); + } + } + + if(!toRemove.isEmpty()) { + m.getTphs().removeAll(toRemove); + return; + } + } + + } + + private TypePlaceholder getTPH(String name) { + for(TypePlaceholder tph: tphExtractor.allTPHS.keySet()) { + if(tph.getName().equals(name)) + return tph; + } + throw new NoSuchElementException("TPH "+name +" does not exist"); + } + private void getCommonTPHS(TPHExtractor tphExtractor) { // Gemeinsame TPHs ArrayList cTPHs = new ArrayList<>(); @@ -236,7 +280,7 @@ public class BytecodeGen implements ASTVisitor { } String sig = null; if(hasGen) { - HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor); + HashMap> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass); Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); } @@ -315,7 +359,7 @@ public class BytecodeGen implements ASTVisitor { System.out.println("ALL CONST: " + tphExtractor.allCons.size()); tphExtractor.allCons.forEach(c->System.out.println(c.toString())); System.out.println("----------------"); - HashMap> constraints = Simplify.simplifyConstraints(method.name, tphExtractor); + HashMap> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass); // ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); sig = signature.toString(); diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 1e1048ff6..6fc803479 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -708,7 +708,13 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(FieldVar fieldVar) { fieldName = fieldVar.fieldVarName; - fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; + fieldDesc = "L"; + if(resultSet.resolveType(fieldVar.getType()).resolvedType instanceof TypePlaceholder) { + fieldDesc += Type.getInternalName(Object.class); + } else { + fieldDesc += resultSet.resolveType(fieldVar.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + fieldDesc +=";"; fieldVar.receiver.accept(this); // test (if) @@ -1405,9 +1411,18 @@ public class BytecodeGenMethod implements StatementVisitor { // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); + String fDesc = "L"; + if(resultSet.resolveType(assignLeftSide.field.getType()).resolvedType instanceof TypePlaceholder) { + fDesc += Type.getInternalName(Object.class); + } else { + fDesc += resultSet.resolveType(assignLeftSide.field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + fDesc +=";"; + + System.out.println("Receiver = " + getResolvedType(assignLeftSide.field.receiver.getType())); mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), - assignLeftSide.field.fieldVarName, "L"+getResolvedType(assignLeftSide.field.getType())+";"); + assignLeftSide.field.fieldVarName, fDesc); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index ef0d1d475..995cdf17a 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -42,13 +42,15 @@ public class Signature { private ArrayList commonPairs; private HashMap> methodConstraints; private ArrayList tphsClass; + private ArrayList consClass; public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds, - ArrayList commonPairs, ArrayList tphsClass) { + ArrayList commonPairs, ArrayList tphsClass, ArrayList consClass) { this.classOrInterface = classOrInterface; this.genericsAndBounds = genericsAndBounds; this.commonPairs = commonPairs; this.tphsClass = tphsClass; + this.consClass = consClass; sw = new SignatureWriter(); createSignatureForClassOrInterface(); } @@ -370,7 +372,37 @@ public class Signature { GenericTypeVar g = itr.next(); getBoundsOfTypeVar(g,genericsAndBounds); } - if(!commonPairs.isEmpty()) { + + if(!consClass.isEmpty()) { + ArrayList types = new ArrayList<>(); + ArrayList superTypes = new ArrayList<>(); + + for(TPHConstraint cons : consClass) { + types.add(cons.getLeft()); + superTypes.add(cons.getRight()); + } + + for(TPHConstraint cons : consClass) { + String t = cons.getLeft()+"$"; + String bound = cons.getRight()+"$"; + sw.visitFormalTypeParameter(t); + sw.visitClassBound().visitTypeVariable(bound); + genericsAndBounds.put(t, bound); + } + + for(TPHConstraint cons : consClass) { + if(!types.contains(cons.getRight())) { + String t = cons.getRight()+"$"; + String bound = Type.getInternalName(Object.class); + sw.visitFormalTypeParameter(t); + sw.visitClassBound().visitClassType(bound); + genericsAndBounds.put(t, bound); + sw.visitClassBound().visitEnd(); + } + } + + } + /*if(!commonPairs.isEmpty()) { ArrayList types = new ArrayList<>(); ArrayList superTypes = new ArrayList<>(); @@ -405,7 +437,7 @@ public class Signature { sw.visitClassBound().visitClassType(bound); genericsAndBounds.put(n, bound); sw.visitClassBound().visitEnd(); - } + }*/ String sClass = classOrInterface.getSuperClass().acceptTV(new TypeToSignature()); sw.visitSuperclass().visitClassType(sClass.substring(1, sClass.length()-1)); sw.visitEnd(); diff --git a/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java index 3950b65ef..7a121fbaa 100644 --- a/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java +++ b/src/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -15,8 +15,8 @@ import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; public class Simplify { - private static int a = 6; - public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor) { + + public static HashMap> simplifyConstraints(String name, TPHExtractor tphExtractor, ArrayList tphsClass) { // 1. check if there are any simple cycles like L set L=R and: // * remove both constraints diff --git a/test/bytecode/FieldTph2Test.java b/test/bytecode/FieldTph2Test.java new file mode 100644 index 000000000..2ed19d330 --- /dev/null +++ b/test/bytecode/FieldTph2Test.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTph2Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/FieldTph2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("FieldTph2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + m2.invoke(instanceOfClass, 1); + + Method m = classToTest.getDeclaredMethod("m", Object.class); + Object result = m.invoke(instanceOfClass, 1); + + assertEquals(1,result); + } + +} diff --git a/test/bytecode/javFiles/FieldTph2.jav b/test/bytecode/javFiles/FieldTph2.jav new file mode 100644 index 000000000..7d60b683a --- /dev/null +++ b/test/bytecode/javFiles/FieldTph2.jav @@ -0,0 +1,12 @@ +public class FieldTph2 { + a; + + m(b){ + b = a; + return b; + } + + m2(c){ + a = c; + } +} \ No newline at end of file diff --git a/test/bytecode/simplifyalgo/CycleTest.java b/test/bytecode/simplifyalgo/CycleTest.java index 88697e6d9..f847eff47 100644 --- a/test/bytecode/simplifyalgo/CycleTest.java +++ b/test/bytecode/simplifyalgo/CycleTest.java @@ -5,6 +5,7 @@ package bytecode.simplifyalgo; import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -68,7 +69,7 @@ public class CycleTest { TPHConstraint k = new ExtendsConstraint("A", Type.getInternalName(Object.class), Relation.EXTENDS); result.put(k, equals); - HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor); + HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor,new ArrayList<>()); boolean areEquals = SimpleCycle.areMapsEqual(result, sim); assertTrue(areEquals); } diff --git a/test/bytecode/simplifyalgo/SameLeftSide.java b/test/bytecode/simplifyalgo/SameLeftSide.java index 402fe1e16..69d50c63b 100644 --- a/test/bytecode/simplifyalgo/SameLeftSide.java +++ b/test/bytecode/simplifyalgo/SameLeftSide.java @@ -2,6 +2,7 @@ package bytecode.simplifyalgo; import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -76,7 +77,7 @@ public class SameLeftSide { result.put(b, hs); - HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor); + HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor,new ArrayList<>()); boolean areEquals = SimpleCycle.areMapsEqual(result, sim); assertTrue(areEquals); } @@ -93,7 +94,7 @@ public class SameLeftSide { hs.add("B"); result.put(c, hs); - HashMap> sim = Simplify.simplifyConstraints(methName2, tphExtractor); + HashMap> sim = Simplify.simplifyConstraints(methName2, tphExtractor,new ArrayList<>()); boolean areEquals = SimpleCycle.areMapsEqual(result, sim); assertTrue(areEquals); } diff --git a/test/bytecode/simplifyalgo/SimpleCycle.java b/test/bytecode/simplifyalgo/SimpleCycle.java index 636eb026d..545b0514e 100644 --- a/test/bytecode/simplifyalgo/SimpleCycle.java +++ b/test/bytecode/simplifyalgo/SimpleCycle.java @@ -2,6 +2,7 @@ package bytecode.simplifyalgo; import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -45,7 +46,7 @@ public class SimpleCycle { TPHConstraint k = new ExtendsConstraint("B", Type.getInternalName(Object.class), Relation.EXTENDS); result.put(k, equals); - HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor); + HashMap> sim = Simplify.simplifyConstraints(methName, tphExtractor,new ArrayList<>()); boolean areEquals = areMapsEqual(result, sim); assertTrue(areEquals); }