Tphs einer Methode, die groesser als Tphs der Felder, werden als Class-Generics definiert

This commit is contained in:
Fayez Abu Alia 2018-12-19 13:20:09 +01:00
parent e380c77ce6
commit b71efd65a0
9 changed files with 173 additions and 15 deletions

View File

@ -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<TypePlaceholder> tphsClass;
// stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,...
HashMap<String, Integer> paramsAndLocals = new HashMap<>();
// stores generics and their bounds of class
@ -138,12 +141,28 @@ public class BytecodeGen implements ASTVisitor {
getCommonTPHS(tphExtractor);
ArrayList<TypePlaceholder> tphsClass = new ArrayList<>();
tphsClass = new ArrayList<>();
for(TypePlaceholder t : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(t))
tphsClass.add(t);
}
ArrayList<TPHConstraint> 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<String> 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<TypePlaceholder> cTPHs = new ArrayList<>();
@ -236,7 +280,7 @@ public class BytecodeGen implements ASTVisitor {
}
String sig = null;
if(hasGen) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> 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<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass);
// ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons);
Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints);
sig = signature.toString();

View File

@ -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

View File

@ -42,13 +42,15 @@ public class Signature {
private ArrayList<GenericInsertPair> commonPairs;
private HashMap<TPHConstraint,HashSet<String>> methodConstraints;
private ArrayList<TypePlaceholder> tphsClass;
private ArrayList<TPHConstraint> consClass;
public Signature(ClassOrInterface classOrInterface, HashMap<String, String> genericsAndBounds,
ArrayList<GenericInsertPair> commonPairs, ArrayList<TypePlaceholder> tphsClass) {
ArrayList<GenericInsertPair> commonPairs, ArrayList<TypePlaceholder> tphsClass, ArrayList<TPHConstraint> 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<String> types = new ArrayList<>();
ArrayList<String> 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<TypePlaceholder> types = new ArrayList<>();
ArrayList<TypePlaceholder> 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();

View File

@ -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<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor) {
public static HashMap<TPHConstraint, HashSet<String>> simplifyConstraints(String name, TPHExtractor tphExtractor, ArrayList<TypePlaceholder> tphsClass) {
// 1. check if there are any simple cycles like L<R and R<L:
// a) yes => set L=R and:
// * remove both constraints

View File

@ -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);
}
}

View File

@ -0,0 +1,12 @@
public class FieldTph2 {
a;
m(b){
b = a;
return b;
}
m2(c){
a = c;
}
}

View File

@ -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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor,new ArrayList<>());
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
assertTrue(areEquals);
}

View File

@ -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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> 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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName2, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName2, tphExtractor,new ArrayList<>());
boolean areEquals = SimpleCycle.areMapsEqual(result, sim);
assertTrue(areEquals);
}

View File

@ -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<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor);
HashMap<TPHConstraint, HashSet<String>> sim = Simplify.simplifyConstraints(methName, tphExtractor,new ArrayList<>());
boolean areEquals = areMapsEqual(result, sim);
assertTrue(areEquals);
}