diff --git a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index ff2c49a3..ef9b9946 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -744,6 +744,13 @@ public class BytecodeGenMethod implements StatementVisitor { statement = new IfStatement(ifStmt.expr, ifStmt.then_block, ifStmt.else_block); isBinaryExp = statement.isExprBinary(); ifStmt.expr.accept(this); + if(!(ifStmt.expr instanceof BinaryExpr)) { + doUnboxing(getResolvedType(ifStmt.expr.getType())); + Label branchLabel = new Label(); + Label endLabel = new Label(); + mv.visitJumpInsn(Opcodes.IFEQ, branchLabel); + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + } statement = null; } @@ -758,86 +765,90 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("In MethodCall = " + methodCall.name); String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); - ClassLoader cLoader = ClassLoader.getSystemClassLoader(); - // This will be used if the class is not standard class (not in API) - ClassLoader cLoader2; java.lang.reflect.Method methodRefl = null; String clazz = receiverName.replace("/", "."); - String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); - try { - if(receiverName.contains("<")) { - clazz = clazz.substring(0, receiverName.indexOf("<")); - } + if(!receiverName.equals(className)) { + ClassLoader cLoader = ClassLoader.getSystemClassLoader(); + // This will be used if the class is not standard class (not in API) + ClassLoader cLoader2; - java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); - System.out.println("Methods of " + receiverName + " "); - methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods); - - } catch (Exception e) { -// try { -// cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); -// java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); -// System.out.println("Methods of " + receiverName + " "); -// for(int i = 0; i allConstaints; + + public ConstraintsFinder(List allConstaints) { + super(); + this.allConstaints = allConstaints; + } + + public List> findConstraints() { + List> result = new ArrayList<>(); + + List visitedCons = new ArrayList<>(); + for(TPHConstraint c : allConstaints) { + // get constraints with the same left side + List cons = getConstraints(c,visitedCons); + if(cons.size()>1) + result.add(cons); + } + + return result; + } + + private List getConstraints(TPHConstraint c, List visitedCons) { + List res = new ArrayList<>(); + for(TPHConstraint cons : allConstaints) { + if(!isVisited(cons,visitedCons) && cons.getLeft().equals(c.getLeft())) { + res.add(cons); + visitedCons.add(cons); + } + } + return res; + } + + private boolean isVisited(TPHConstraint cons, List visitedCons) { + for(TPHConstraint c : visitedCons) { + if(c.getLeft().equals(cons.getLeft()) && c.getRight().equals(cons.getRight())) + return true; + } + return false; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java new file mode 100644 index 00000000..8b906eee --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java @@ -0,0 +1,44 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; + +public class NameReplacer { + private List constraints; + private List allConstraints; + private List tphs; + + public NameReplacer(List constraints, List allConstraints,List tphs) { + super(); + this.constraints = constraints; + this.allConstraints = allConstraints; + this.tphs = tphs; + } + + public Map> replaceNames() { + String newName = NameGenerator.makeNewName(); + ArrayList names = new ArrayList<>(); + for(TPHConstraint cons : constraints) { + names.add(cons.getRight()); + cons.setRight(newName); + } + + for(TPHConstraint cons : allConstraints) { + if(names.contains(cons.getLeft())) + cons.setLeft(newName); + if(names.contains(cons.getRight())) + cons.setRight(newName); + } + tphs.removeAll(names); + tphs.add(newName); + + HashMap> res = new HashMap<>(); + res.put(newName, names); + return res; + } +} diff --git a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java index 2e3ce775..83eb7cc7 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/utilities/Simplify.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; +import java.util.List; +import java.util.Map; import org.objectweb.asm.Type; @@ -177,7 +179,8 @@ public class Simplify { TPHConstraint cons = allCons.get(0); if(!result.containsKey(cons)) { result.put(cons, null); - result.put(new ExtendsConstraint(cons.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS), null); + if(!cons.getRight().equals(Type.getInternalName(Object.class))) + result.put(new ExtendsConstraint(cons.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS), null); } return result; @@ -198,50 +201,79 @@ public class Simplify { break; } } + + ConstraintsFinder finder = new ConstraintsFinder(allCons); + List> foundCons = finder.findConstraints(); + + ArrayList eqCons = new ArrayList<>(); + + for(List list : foundCons) { + NameReplacer replacer = new NameReplacer(list,allCons,methodTphs); + Map> replRes = replacer.replaceNames(); + + String key = replRes.keySet().iterator().next(); + for(String val : replRes.values().iterator().next()) { + EqualConstraint ec = new EqualConstraint(val, key, Relation.EQUAL); + eqCons.add(ec); + } + + updateEqualCons(replRes,eqCons); + + TPHConstraint c = list.get(0); + allCons.removeAll(list); + allCons.add(c); + } + // check if there are multiple constraint with the same left side. // if yes => check if the super type in the method, if not // then ignore it. +// HashMap subAndSuper = new HashMap<>(); +// ArrayList eqCons = new ArrayList<>(); +// for(TPHConstraint c : allCons) { +// if(subAndSuper.containsKey(c.getLeft())) { +// LinkedList all = new LinkedList<>(); +// all.add(c.getLeft()); +// String sup =c.getRight(); +// all.add(sup); +// HashMap ss = new HashMap<>(); +// for(TPHConstraint constr : allCons) { +// ss.put(constr.getLeft(), constr.getRight()); +// } +// while(ss.containsKey(sup)) { +// sup = ss.get(sup); +// all.add(sup); +// } +// if(!containTPH(methodTphs, all.getLast())) +// continue; +// } +// if(subAndSuper.containsKey(c.getLeft())) { +// System.out.println(c.getLeft()); +// String r = c.getRight(); +// String r2 = subAndSuper.get(c.getLeft()); +// EqualConstraint eq = new EqualConstraint(r2, r, Relation.EQUAL); +// eqCons.add(eq); +// substituteInMap(subAndSuper,eqCons,allCons,r,r2); +// } +// subAndSuper.put(c.getLeft(), c.getRight()); +// } +// +// System.out.println("SAME LEFT SIDE: "); +// subAndSuper.forEach((c,hs)->{ +// if(c!=null) { +// System.out.print(c+ " -> " + hs); +// +// } +// +// +// System.out.println(); +// }); +// System.out.println("----------------"); HashMap subAndSuper = new HashMap<>(); - ArrayList eqCons = new ArrayList<>(); + for(TPHConstraint c : allCons) { - if(subAndSuper.containsKey(c.getLeft())) { - LinkedList all = new LinkedList<>(); - all.add(c.getLeft()); - String sup =c.getRight(); - all.add(sup); - HashMap ss = new HashMap<>(); - for(TPHConstraint constr : allCons) { - ss.put(constr.getLeft(), constr.getRight()); - } - while(ss.containsKey(sup)) { - sup = ss.get(sup); - all.add(sup); - } - if(!containTPH(methodTphs, all.getLast())) - continue; - } - if(subAndSuper.containsKey(c.getLeft())) { - System.out.println(c.getLeft()); - String r = c.getRight(); - String r2 = subAndSuper.get(c.getLeft()); - EqualConstraint eq = new EqualConstraint(r2, r, Relation.EQUAL); - eqCons.add(eq); - substituteInMap(subAndSuper,eqCons,allCons,r,r2); - } subAndSuper.put(c.getLeft(), c.getRight()); } - System.out.println("SAME LEFT SIDE: "); - subAndSuper.forEach((c,hs)->{ - if(c!=null) { - System.out.print(c+ " -> " + hs); - - } - - - System.out.println(); - }); - System.out.println("----------------"); int numOfVisitedPairs = 0; for(String sub : subAndSuper.keySet()) { if(isTPHInConstraint(result,sub)) @@ -348,6 +380,19 @@ public class Simplify { } + private static void updateEqualCons(Map> replRes, ArrayList eqCons) { + List oldNames = replRes.values().iterator().next(); + String newName = replRes.keySet().iterator().next(); + for(TPHConstraint c : eqCons) { +// if(oldNames.contains(c.getLeft())) +// c.setLeft(newName); + if(oldNames.contains(c.getRight())) + c.setRight(newName); + } + + } + + public static HashMap> simplifyConstraintsClass(TPHExtractor tphExtractor, ArrayList tphsClass) { // all constraints that will be simplified ArrayList allCons = tphExtractor.allCons; diff --git a/src/test/java/bytecode/FieldTphMMethTest.java b/src/test/java/bytecode/FieldTphMMethTest.java index 58a9647a..f21adefe 100644 --- a/src/test/java/bytecode/FieldTphMMethTest.java +++ b/src/test/java/bytecode/FieldTphMMethTest.java @@ -33,20 +33,33 @@ public class FieldTphMMethTest { pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); classToTest = loader.loadClass("FieldTphMMeth"); + instanceOfClass = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,true); + instanceOfClass2 = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,false); } @Test - public void test() throws Exception { - instanceOfClass = classToTest.getConstructor(Object.class).newInstance("C",42,true); - instanceOfClass2 = classToTest.getConstructor(Object.class).newInstance("C",42,false); + public void testM() throws Exception { + + Method m = classToTest.getDeclaredMethod("m", Object.class,Object.class,Boolean.class); + Object result = m.invoke(instanceOfClass, "C",42,false); + + assertEquals(42,result); + } + + @Test + public void testWithTrue() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + assertEquals("C", a.get(instanceOfClass)); + + } + + @Test + public void testWithFalse() throws Exception { Field a = classToTest.getDeclaredField("a"); a.setAccessible(true); - Method m = classToTest.getDeclaredMethod("m", Object.class); - Object result = m.invoke(instanceOfClass, 42); - - assertEquals(42,result); - assertEquals("C", a.get(instanceOfClass)); assertEquals(42, a.get(instanceOfClass2)); } diff --git a/src/test/java/bytecode/InfTest.java b/src/test/java/bytecode/InfTest.java new file mode 100644 index 00000000..75608bfe --- /dev/null +++ b/src/test/java/bytecode/InfTest.java @@ -0,0 +1,37 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +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 InfTest { + + 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; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/Inf.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Inf"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/src/test/java/bytecode/simplifyalgo/FinderTest.java b/src/test/java/bytecode/simplifyalgo/FinderTest.java new file mode 100644 index 00000000..edf43605 --- /dev/null +++ b/src/test/java/bytecode/simplifyalgo/FinderTest.java @@ -0,0 +1,64 @@ +package bytecode.simplifyalgo; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.ConstraintsFinder; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.Simplify; +import de.dhbwstuttgart.typedeployment.TypeInsertPlacer; + +/** + * + * @author Fayez Abu Alia + * + */ +public class FinderTest { + + @Test + public void testM1() { + List allCons = new ArrayList<>(); + // L < M + TPHConstraint c1 = new ExtendsConstraint("L", "M", Relation.EXTENDS); + // L < N + TPHConstraint c2 = new ExtendsConstraint("L", "N", Relation.EXTENDS); + // M < O + TPHConstraint c3 = new ExtendsConstraint("M", "O", Relation.EXTENDS); + // M < P + TPHConstraint c4 = new ExtendsConstraint("M", "P", Relation.EXTENDS); + + allCons.add(c1); + allCons.add(c2); + allCons.add(c3); + allCons.add(c4); + List> res = new ArrayList<>(); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + + l1.add(c1); + l1.add(c2); + + l2.add(c3); + l2.add(c4); + + res.add(l1); + res.add(l2); + + ConstraintsFinder finder = new ConstraintsFinder(allCons); + + assertEquals(finder.findConstraints(), res); + } + +} diff --git a/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav b/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav index abc10a46..ad97edc4 100644 --- a/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav +++ b/src/test/resources/bytecode/javFiles/FieldTphMMeth.jav @@ -1,14 +1,17 @@ +import java.lang.Boolean; + public class FieldTphMMeth { a; - public FieldTphConsMeth(c,d,e) { + + public FieldTphMMeth(c,d,e) { a = m(c,d,e); } m(b,d,e) { if(e) { - return b; + return m3(b); } else{ - m2(d); + return m3(d); } } diff --git a/src/test/resources/bytecode/javFiles/Inf.jav b/src/test/resources/bytecode/javFiles/Inf.jav new file mode 100644 index 00000000..79b9dca1 --- /dev/null +++ b/src/test/resources/bytecode/javFiles/Inf.jav @@ -0,0 +1,14 @@ +public class Inf { + m(x,y,a){ + var z; + var v; + var w; + var b; + y=x; + z=x; + v=y; + w=y; + y=a; + b=a; + } +} \ No newline at end of file