Klassendatei fuer FunN beim Methodaufruf wird erzeugt, wenn der Receiver

den Typ FunN besitzt.
Die Loesung vom Duplicate Field Problem wird angepasst.
This commit is contained in:
Fayez Abu Alia 2019-04-26 11:56:58 +02:00
parent 9ffc74467b
commit 73f412d22d
5 changed files with 310 additions and 239 deletions

View File

@ -47,7 +47,7 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
public class BytecodeGen implements ASTVisitor { public class BytecodeGen implements ASTVisitor {
ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
String type; String type;
@ -67,7 +67,8 @@ public class BytecodeGen implements ASTVisitor {
private ArrayList<String> tphsClass; private ArrayList<String> tphsClass;
// stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... // 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<>(); HashMap<String, Integer> paramsAndLocals = new HashMap<>();
// stores generics and their bounds of class // stores generics and their bounds of class
HashMap<String, String> genericsAndBounds = new HashMap<>(); HashMap<String, String> genericsAndBounds = new HashMap<>();
@ -77,9 +78,9 @@ public class BytecodeGen implements ASTVisitor {
private final TPHExtractor tphExtractor = new TPHExtractor(); private final TPHExtractor tphExtractor = new TPHExtractor();
private final ArrayList<GenericInsertPair> commonPairs = new ArrayList<>(); private final ArrayList<GenericInsertPair> commonPairs = new ArrayList<>();
HashMap<String,RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>(); HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> methodParamsAndTypes = new HashMap<>();
byte[] bytecode; byte[] bytecode;
HashMap<String,byte[]> classFiles; HashMap<String, byte[]> classFiles;
private final ArrayList<String> methodNameAndParamsT = new ArrayList<>(); private final ArrayList<String> methodNameAndParamsT = new ArrayList<>();
private final ArrayList<String> fieldNameAndParamsT = new ArrayList<>(); private final ArrayList<String> fieldNameAndParamsT = new ArrayList<>();
@ -87,6 +88,8 @@ public class BytecodeGen implements ASTVisitor {
private HashMap<String, SimplifyResult> simplifyResults = new HashMap<>(); private HashMap<String, SimplifyResult> simplifyResults = new HashMap<>();
private List<HashMap<String, SimplifyResult>> simplifyResultsList = new ArrayList<>(); private List<HashMap<String, SimplifyResult>> simplifyResultsList = new ArrayList<>();
private final ArrayList<String> fieldNameSignature = new ArrayList<>();
public List<HashMap<String, SimplifyResult>> getSimplifyResultsList() { public List<HashMap<String, SimplifyResult>> getSimplifyResultsList() {
return simplifyResultsList; return simplifyResultsList;
} }
@ -95,7 +98,8 @@ public class BytecodeGen implements ASTVisitor {
this.simplifyResultsList = simplifyResultsList; this.simplifyResultsList = simplifyResultsList;
} }
public BytecodeGen(HashMap<String,byte[]> classFiles, List<ResultSet> listOfResultSets,SourceFile sf ,String path) { public BytecodeGen(HashMap<String, byte[]> classFiles, List<ResultSet> listOfResultSets, SourceFile sf,
String path) {
this.classFiles = classFiles; this.classFiles = classFiles;
this.listOfResultSets = listOfResultSets; this.listOfResultSets = listOfResultSets;
this.sf = sf; this.sf = sf;
@ -104,7 +108,7 @@ public class BytecodeGen implements ASTVisitor {
@Override @Override
public void visit(SourceFile sourceFile) { public void visit(SourceFile sourceFile) {
for(ClassOrInterface cl : sourceFile.getClasses()) { for (ClassOrInterface cl : sourceFile.getClasses()) {
System.out.println("in Class: " + cl.getClassName().toString()); System.out.println("in Class: " + cl.getClassName().toString());
BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path); BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, sf, path);
cl.accept(classGen); cl.accept(classGen);
@ -114,8 +118,8 @@ public class BytecodeGen implements ASTVisitor {
} }
/** /**
* Associates the bytecode of the class that was build with the classWriter {@link #cw} * Associates the bytecode of the class that was build with the classWriter
* with the class name in the map {@link #classFiles} * {@link #cw} with the class name in the map {@link #classFiles}
* *
* @param name name of the class with which the the bytecode is to be associated * @param name name of the class with which the the bytecode is to be associated
*/ */
@ -125,59 +129,60 @@ public class BytecodeGen implements ASTVisitor {
} }
public HashMap<String,byte[]> getClassFiles() { public HashMap<String, byte[]> getClassFiles() {
return classFiles; return classFiles;
} }
@Override @Override
public void visit(ClassOrInterface classOrInterface) { public void visit(ClassOrInterface classOrInterface) {
className = classOrInterface.getClassName().toString(); className = classOrInterface.getClassName().toString();
cw.visitSource(className +".jav", null); cw.visitSource(className + ".jav", null);
isInterface = (classOrInterface.getModifiers()&512)==512; isInterface = (classOrInterface.getModifiers() & 512) == 512;
int acc = isInterface?classOrInterface.getModifiers()+Opcodes.ACC_ABSTRACT:classOrInterface.getModifiers()+Opcodes.ACC_SUPER; int acc = isInterface ? classOrInterface.getModifiers() + Opcodes.ACC_ABSTRACT
: classOrInterface.getModifiers() + Opcodes.ACC_SUPER;
fieldInitializations = classOrInterface.getfieldInitializations(); fieldInitializations = classOrInterface.getfieldInitializations();
// resultSet = listOfResultSets.get(0); // resultSet = listOfResultSets.get(0);
boolean isConsWithNoParamsVisited = false; boolean isConsWithNoParamsVisited = false;
boolean isVisited = false; boolean isVisited = false;
for(ResultSet rs : listOfResultSets) { for (ResultSet rs : listOfResultSets) {
superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor());
resultSet = rs; resultSet = rs;
tphExtractor.setResultSet(resultSet); tphExtractor.setResultSet(resultSet);
// Nur einmal ausführen!! // Nur einmal ausführen!!
if(!isVisited) { if (!isVisited) {
classOrInterface.accept(tphExtractor); classOrInterface.accept(tphExtractor);
getCommonTPHS(tphExtractor); getCommonTPHS(tphExtractor);
tphsClass = new ArrayList<>(); tphsClass = new ArrayList<>();
for(String t : tphExtractor.allTPHS.keySet()) { for (String t : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(t)) if (!tphExtractor.allTPHS.get(t))
tphsClass.add(t); tphsClass.add(t);
} }
String sig = null; String sig = null;
/* if class has generics then creates signature /*
* Signature looks like: * if class has generics then creates signature Signature looks like:
* <E:Ljava/...>Superclass * <E:Ljava/...>Superclass
*/ */
if(classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty() || if (classOrInterface.getGenerics().iterator().hasNext() || !commonPairs.isEmpty()
classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") || classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<")
|| !tphsClass.isEmpty()) { || !tphsClass.isEmpty()) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraintsClass(tphExtractor,tphsClass); HashMap<TPHConstraint, HashSet<String>> constraints = Simplify
.simplifyConstraintsClass(tphExtractor, tphsClass);
ArrayList<TPHConstraint> consClass = new ArrayList<>(); ArrayList<TPHConstraint> consClass = new ArrayList<>();
for(TPHConstraint cons : constraints.keySet()) { for (TPHConstraint cons : constraints.keySet()) {
String right = null; String right = null;
boolean isToAdd = false; boolean isToAdd = false;
for(String tph : tphsClass) { for (String tph : tphsClass) {
if(cons.getLeft().equals(tph)) { if (cons.getLeft().equals(tph)) {
consClass.add(cons); consClass.add(cons);
try { try {
@ -189,11 +194,11 @@ public class BytecodeGen implements ASTVisitor {
} }
} }
if(isToAdd) { if (isToAdd) {
tphsClass.add(right); tphsClass.add(right);
removeFromMethod(right); removeFromMethod(right);
right = null; right = null;
isToAdd= false; isToAdd = false;
} }
// if(right != null) { // if(right != null) {
// tphsClass.add(right); // tphsClass.add(right);
@ -205,22 +210,23 @@ public class BytecodeGen implements ASTVisitor {
SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>()); SimplifyResult sRes = new SimplifyResult(consClass, tphsClass, new HashMap<>());
simplifyResults.put(className, sRes); simplifyResults.put(className, sRes);
Signature signature = new Signature(classOrInterface, genericsAndBounds,commonPairs,tphsClass, consClass); Signature signature = new Signature(classOrInterface, genericsAndBounds, commonPairs, tphsClass,
consClass);
sig = signature.toString(); sig = signature.toString();
System.out.println("Signature: => " + sig); System.out.println("Signature: => " + sig);
} }
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString() cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString(), sig,
, sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
isVisited = true; isVisited = true;
} }
for(Field f : classOrInterface.getFieldDecl()) { for (Field f : classOrInterface.getFieldDecl()) {
f.accept(this); f.accept(this);
} }
for(Constructor c : classOrInterface.getConstructors()) { for (Constructor c : classOrInterface.getConstructors()) {
// if(!isConsWithNoParamsVisited) { // if(!isConsWithNoParamsVisited) {
c.accept(this); c.accept(this);
// } // }
@ -229,7 +235,7 @@ public class BytecodeGen implements ASTVisitor {
// isConsWithNoParamsVisited = true; // isConsWithNoParamsVisited = true;
} }
for(Method m : classOrInterface.getMethods()) { for (Method m : classOrInterface.getMethods()) {
m.accept(this); m.accept(this);
} }
@ -238,15 +244,15 @@ public class BytecodeGen implements ASTVisitor {
} }
private void removeFromMethod(String name) { private void removeFromMethod(String name) {
for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { for (MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) {
ArrayList<String> toRemove = new ArrayList<>(); ArrayList<String> toRemove = new ArrayList<>();
for(String tph : m.getTphs()) { for (String tph : m.getTphs()) {
if(tph.equals(name)) { if (tph.equals(name)) {
toRemove.add(tph); toRemove.add(tph);
} }
} }
if(!toRemove.isEmpty()) { if (!toRemove.isEmpty()) {
m.getTphs().removeAll(toRemove); m.getTphs().removeAll(toRemove);
return; return;
} }
@ -255,19 +261,19 @@ public class BytecodeGen implements ASTVisitor {
} }
private String getTPH(String name) { private String getTPH(String name) {
for(String tph: tphExtractor.allTPHS.keySet()) { for (String tph : tphExtractor.allTPHS.keySet()) {
if(tph.equals(name)) if (tph.equals(name))
return tph; return tph;
} }
throw new NoSuchElementException("TPH "+name +" does not exist"); throw new NoSuchElementException("TPH " + name + " does not exist");
} }
private void getCommonTPHS(TPHExtractor tphExtractor) { private void getCommonTPHS(TPHExtractor tphExtractor) {
// Gemeinsame TPHs // Gemeinsame TPHs
ArrayList<String> cTPHs = new ArrayList<>(); ArrayList<String> cTPHs = new ArrayList<>();
// Alle TPHs der Felder speichern // Alle TPHs der Felder speichern
for(String tph : tphExtractor.allTPHS.keySet()) { for (String tph : tphExtractor.allTPHS.keySet()) {
if(!tphExtractor.allTPHS.get(tph)) if (!tphExtractor.allTPHS.get(tph))
cTPHs.add(tph); cTPHs.add(tph);
} }
} }
@ -275,7 +281,7 @@ public class BytecodeGen implements ASTVisitor {
@Override @Override
public void visit(Constructor field) { public void visit(Constructor field) {
System.out.println("ResultSet: "); System.out.println("ResultSet: ");
resultSet.results.forEach(a->{ resultSet.results.forEach(a -> {
System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); System.out.println(a.getLeft().toString() + " = " + a.getRight().toString());
}); });
System.out.println("---------------"); System.out.println("---------------");
@ -285,46 +291,46 @@ public class BytecodeGen implements ASTVisitor {
field.getParameterList().accept(this); field.getParameterList().accept(this);
String methParamTypes = field.name+"%%"; String methParamTypes = field.name + "%%";
Iterator<FormalParameter> itr = field.getParameterList().iterator(); Iterator<FormalParameter> itr = field.getParameterList().iterator();
while(itr.hasNext()) { while (itr.hasNext()) {
FormalParameter fp = itr.next(); FormalParameter fp = itr.next();
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";";
// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; // methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";";
} }
if(methodNameAndParamsT.contains(methParamTypes)) { if (methodNameAndParamsT.contains(methParamTypes)) {
System.out.println("ignore - Method: "+field.name +" , paramsType: "+methParamTypes); System.out.println("ignore - Method: " + field.name + " , paramsType: " + methParamTypes);
return; return;
} }
methodNameAndParamsT.add(methParamTypes); methodNameAndParamsT.add(methParamTypes);
System.out.println("Method: "+field.name +" , paramsType: "+methParamTypes); System.out.println("Method: " + field.name + " , paramsType: " + methParamTypes);
String desc = null; String desc = null;
boolean hasGen = false; boolean hasGen = false;
for(String paramName : methodParamsAndTypes.keySet()) { for (String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature());
System.out.println(typeOfParam); System.out.println(typeOfParam);
if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.contains("$") if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("$") || typeOfParam.contains("<")) {
|| typeOfParam.contains("<")) {
hasGen = true; hasGen = true;
break; break;
} }
} }
String sig = null; String sig = null;
if(hasGen) { if (hasGen) {
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,tphsClass); HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(field.name, tphExtractor,
Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); tphsClass);
Signature signature = new Signature(field, genericsAndBounds, methodParamsAndTypes, resultSet, constraints);
sig = signature.toString(); sig = signature.toString();
} }
if(field.getParameterList().iterator().hasNext()) if (field.getParameterList().iterator().hasNext())
System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor())); System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor()));
NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); NormalConstructor constructor = new NormalConstructor(field, genericsAndBounds, hasGen);
desc = constructor.accept(new DescriptorToString(resultSet)); desc = constructor.accept(new DescriptorToString(resultSet));
System.out.println("Constructor: " + field.getName() + " Sig: "+ sig + " Desc: " + desc); System.out.println("Constructor: " + field.getName() + " Sig: " + sig + " Desc: " + desc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, sig, null);
mv.visitCode(); mv.visitCode();
@ -332,9 +338,10 @@ public class BytecodeGen implements ASTVisitor {
constructorPos += 1; constructorPos += 1;
BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,field, mv,paramsAndLocals,cw, BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, field, mv, paramsAndLocals, cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path, block, constructorPos); genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path, block, constructorPos);
if(!field.getParameterList().iterator().hasNext() && !(field.block.statements.get(field.block.statements.size()-1) instanceof ReturnVoid)) { if (!field.getParameterList().iterator().hasNext()
&& !(field.block.statements.get(field.block.statements.size() - 1) instanceof ReturnVoid)) {
mv.visitInsn(Opcodes.RETURN); mv.visitInsn(Opcodes.RETURN);
} }
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
@ -343,66 +350,76 @@ public class BytecodeGen implements ASTVisitor {
@Override @Override
public void visit(Method method) { public void visit(Method method) {
// TODO: check if the method is static => if static then the first param will be stored in pos 0 // TODO: check if the method is static => if static then the first param will be
// stored in pos 0
// else it will be stored in pos 1 and this will be stored in pos 0 // else it will be stored in pos 1 and this will be stored in pos 0
String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
// String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); // String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
String methParamTypes = retType+method.name+"%%"; String methParamTypes = retType + method.name + "%%";
method.getParameterList().accept(this); method.getParameterList().accept(this);
Iterator<FormalParameter> itr = method.getParameterList().iterator(); Iterator<FormalParameter> itr = method.getParameterList().iterator();
while(itr.hasNext()) { while (itr.hasNext()) {
FormalParameter fp = itr.next(); FormalParameter fp = itr.next();
methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()) + ";";
// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; // methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";";
} }
if(methodNameAndParamsT.contains(methParamTypes)) { if (methodNameAndParamsT.contains(methParamTypes)) {
return; return;
} }
methodNameAndParamsT.add(methParamTypes); methodNameAndParamsT.add(methParamTypes);
System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes); System.out.println("Method: " + method.name + " , paramsType: " + methParamTypes);
// stores generics and their bounds of method // stores generics and their bounds of method
HashMap<String, String> genericsAndBoundsMethod = new HashMap<>(); HashMap<String, String> genericsAndBoundsMethod = new HashMap<>();
String methDesc = null; String methDesc = null;
// Method getModifiers() ? // Method getModifiers() ?
int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier; int acc = isInterface ? Opcodes.ACC_ABSTRACT : method.modifier;
System.out.println(acc); System.out.println(acc);
/*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ /* Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist */
boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") || boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ")
resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()).contains("<"); || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature())
/*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, .contains("<");
* prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ /*
if(!hasGenInParameterList) { * Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature,
for(String paramName : methodParamsAndTypes.keySet()) { * wenn nicht, prüfe, ob einer der Parameter Typ-Variable als Typ hat
*/
if (!hasGenInParameterList) {
for (String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor());
String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature());
if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) { if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("TPH ")
|| sigOfParam.contains("<")) {
hasGenInParameterList = true; hasGenInParameterList = true;
break; break;
} }
} }
} }
//TODO: Test if the return-type or any of the parameter is a parameterized type. (VP) // TODO: Test if the return-type or any of the parameter is a parameterized
//then create the descriptor with the new syntax. // type. (VP)
// then create the descriptor with the new syntax.
String sig = null; String sig = null;
/* method.getGenerics: <....> RT method(..) /*
* */ * method.getGenerics: <....> RT method(..)
*/
boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList;
/* if method has generics or return type is TPH, create signature */ /* if method has generics or return type is TPH, create signature */
// zwite operand muss weggelassen werden // zwite operand muss weggelassen werden
if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) { if (hasGen || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString())
.equals("TPH")) {
System.out.println("ALL CONST: " + tphExtractor.allCons.size()); System.out.println("ALL CONST: " + tphExtractor.allCons.size());
tphExtractor.allCons.forEach(c->System.out.println(c.toString())); tphExtractor.allCons.forEach(c -> System.out.println(c.toString()));
System.out.println("----------------"); System.out.println("----------------");
HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name, tphExtractor, tphsClass); HashMap<TPHConstraint, HashSet<String>> constraints = Simplify.simplifyConstraints(method.name,
tphExtractor, tphsClass);
// ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); // ArrayList<GenericInsertPair> pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons);
Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet,constraints); Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,
methodParamsAndTypes, resultSet, constraints);
sig = signature.toString(); sig = signature.toString();
if(simplifyResults.containsKey(className)) { if (simplifyResults.containsKey(className)) {
simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints); simplifyResults.get(className).getMethodsConstraints().put(methParamTypes, constraints);
} else { } else {
SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>()); SimplifyResult sRes = new SimplifyResult(new ArrayList<>(), new ArrayList<>(), new HashMap<>());
@ -411,16 +428,16 @@ public class BytecodeGen implements ASTVisitor {
} }
} }
System.out.println(method.getName()+" ==> "+sig); System.out.println(method.getName() + " ==> " + sig);
NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen); NormalMethod meth = new NormalMethod(method, genericsAndBounds, genericsAndBoundsMethod, hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet)); methDesc = meth.accept(new DescriptorToString(resultSet));
// System.out.println(methDesc); // System.out.println(methDesc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null); MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + acc, method.getName(), methDesc, sig, null);
mv.visitCode(); mv.visitCode();
BytecodeGenMethod gen = new BytecodeGenMethod(className,superClass,resultSet,method, mv,paramsAndLocals,cw, BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, method, mv, paramsAndLocals, cw,
genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles, sf,path); genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path);
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
@ -436,7 +453,7 @@ public class BytecodeGen implements ASTVisitor {
methodParamsAndTypes = new HashMap<>(); methodParamsAndTypes = new HashMap<>();
Iterator<FormalParameter> itr = formalParameters.iterator(); Iterator<FormalParameter> itr = formalParameters.iterator();
int i = 1; int i = 1;
while(itr.hasNext()) { while (itr.hasNext()) {
FormalParameter fp = itr.next(); FormalParameter fp = itr.next();
paramsAndLocals.put(fp.getName(), i); paramsAndLocals.put(fp.getName(), i);
methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType);
@ -452,7 +469,7 @@ public class BytecodeGen implements ASTVisitor {
@Override @Override
public void visit(RefType refType) { public void visit(RefType refType) {
type = "L"+refType.toString()+";"; type = "L" + refType.toString() + ";";
} }
@Override @Override
@ -484,7 +501,8 @@ public class BytecodeGen implements ASTVisitor {
public void visit(FieldVar fieldVar) { public void visit(FieldVar fieldVar) {
System.out.println("In FieldVar ---"); System.out.println("In FieldVar ---");
// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); // cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString());
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null); FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L" + fieldVar.getType() + ";",
null, null);
fv.visitEnd(); fv.visitEnd();
} }
@ -492,28 +510,30 @@ public class BytecodeGen implements ASTVisitor {
public void visit(Field field) { public void visit(Field field) {
System.out.println("In Field ---"); System.out.println("In Field ---");
String des = "L"; String des = "L";
if(resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) { if (resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) {
des += Type.getInternalName(Object.class); des += Type.getInternalName(Object.class);
} else { } else {
des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor());
} }
des +=";"; des += ";";
System.out.println(des); System.out.println(des);
String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature()); String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature());
System.out.println(sig); System.out.println(sig);
if(sig.charAt(sig.length()-1) != (";").charAt(0)) { if (sig.charAt(sig.length() - 1) != (";").charAt(0)) {
sig +=";"; sig += ";";
} }
String nameAndDesc = field.getName() + "%%" + des; String nameAndDesc = field.getName() + "%%" + des;
String nameAndSig = field.getName() + "%%" + sig;
if(fieldNameAndParamsT.contains(nameAndDesc)) if (fieldNameAndParamsT.contains(nameAndDesc)) {
if (fieldNameSignature.contains(nameAndSig)) {
return;
}
throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature"); throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature");
}
fieldNameAndParamsT.add(nameAndDesc); fieldNameAndParamsT.add(nameAndDesc);
fieldNameSignature.add(nameAndSig);
cw.visitField(field.modifier, field.getName(), cw.visitField(field.modifier, field.getName(), des, sig, null);
des, sig,
null);
} }
@Override @Override
@ -694,5 +714,4 @@ public class BytecodeGen implements ASTVisitor {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@ -678,7 +678,7 @@ public class BytecodeGenMethod implements StatementVisitor {
} }
methSig.visitReturnType().visitTypeVariable("R"); methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds // ")"+lam.getReturn.getBounds
Signature sig = new Signature(lambdaExpression, numberOfParams); Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$"; String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null); Type.getInternalName(Object.class), null);
@ -778,9 +778,9 @@ public class BytecodeGenMethod implements StatementVisitor {
String mDesc = ""; String mDesc = "";
MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet); MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path);
boolean isCreated = false; boolean toCreate = false;
ClassLoader cLoader = ClassLoader.getSystemClassLoader(); ClassLoader cLoader = ClassLoader.getSystemClassLoader();
// This will be used if the class is not standard class (not in API) // This will be used if the class is not standard class (not in API)
@ -799,7 +799,6 @@ public class BytecodeGenMethod implements StatementVisitor {
} catch (Exception e) { } catch (Exception e) {
String superClass = ""; String superClass = "";
// TODO: Test SubMatrix.jav
while(true) { while(true) {
try { try {
superClass = helper.getSuperClass(receiverName); superClass = helper.getSuperClass(receiverName);
@ -833,14 +832,17 @@ public class BytecodeGenMethod implements StatementVisitor {
} }
if(methodRefl == null) { if(methodRefl == null) {
isCreated = !receiverName.equals(className) && helper.isInCurrPkg(clazz); toCreate = !receiverName.equals(className) && helper.isInCurrPkg(clazz);
if(isCreated) { if(toCreate) {
try { try {
mDesc = helper.getDesc(clazz); mDesc = helper.getDesc(clazz);
} catch (NotInCurrentPackageException | NotFoundException e) { } catch (NotInCurrentPackageException | NotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
} else if(!helper.isInCurrPkg(clazz)){ } else if(!helper.isInCurrPkg(clazz)){
if(clazz.contains("$$")) {
mDesc = helper.generateBCForFunN();
}else {
try { try {
cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)}); cLoader2 = new URLClassLoader(new URL[] {new URL("file://"+path)});
java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods();
@ -854,6 +856,7 @@ public class BytecodeGenMethod implements StatementVisitor {
e2.printStackTrace(); e2.printStackTrace();
} }
} }
}
} }

View File

@ -80,12 +80,12 @@ public class Signature {
createSignatureForConsOrMethod(this.method,false); createSignatureForConsOrMethod(this.method,false);
} }
public Signature(LambdaExpression lambdaExpression,int numberOfParams) { public Signature(int numberOfParams) {
sw = new SignatureWriter(); sw = new SignatureWriter();
createSignatureForFunN(lambdaExpression, numberOfParams); createSignatureForFunN(numberOfParams);
} }
private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) { private void createSignatureForFunN(int numberOfParams) {
// sw.visitClassBound().visitEnd(); // sw.visitClassBound().visitEnd();
for(int i = 0;i<numberOfParams;i++) { for(int i = 0;i<numberOfParams;i++) {

View File

@ -3,6 +3,10 @@
*/ */
package de.dhbwstuttgart.bytecode.utilities; package de.dhbwstuttgart.bytecode.utilities;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -11,11 +15,17 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.FormalParameter;
@ -23,6 +33,8 @@ import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall; import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
@ -38,16 +50,19 @@ public class MethodCallHelper {
private MethodCall methCall; private MethodCall methCall;
private SourceFile sourceFile; private SourceFile sourceFile;
private ResultSet resultSet; private ResultSet resultSet;
private String path;
/** /**
* @param methCall * @param methCall
* @param sourceFile * @param sourceFile
* @param resultSet * @param resultSet
* @param path TODO
*/ */
public MethodCallHelper(MethodCall methCall, SourceFile sourceFile, ResultSet resultSet) { public MethodCallHelper(MethodCall methCall, SourceFile sourceFile, ResultSet resultSet, String path) {
this.methCall = methCall; this.methCall = methCall;
this.sourceFile = sourceFile; this.sourceFile = sourceFile;
this.resultSet = resultSet; this.resultSet = resultSet;
this.path = path;
} }
public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
@ -189,19 +204,52 @@ public class MethodCallHelper {
} }
} }
private String createDesc(Method m) { public String generateBCForFunN() {
String desc = "("; ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
for (FormalParameter fp : m.getParameterList()) {
String typeName = getResolvedType(fp.getType());
RefTypeOrTPHOrWildcardOrGeneric type = resultSet.resolveType(fp.getType()).resolvedType;
if (type instanceof TypePlaceholder) {
desc += "L" + Type.getInternalName(Object.class) + ";";
} else if (type instanceof GenericRefType) {
GenericRefType grt = (GenericRefType) type;
SignatureWriter methSig = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator<Expression> itr1 = methCall.arglist.getArguments().iterator();
String methDesc = "(";
while(itr1.hasNext()) {
numberOfParams++;
// getBounds
paramVisitor.visitTypeVariable("T" + numberOfParams);
methDesc += "L" + Type.getInternalName(Object.class) + ";";
itr1.next();
} }
methDesc += ")L" + Type.getInternalName(Object.class) + ";";
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(numberOfParams);
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
methSig.toString(), null);
mvApply.visitEnd();
writeClassFile(classWriter.toByteArray(), name);
return methDesc;
} }
return null;
private void writeClassFile(byte[] bytecode, String name) {
FileOutputStream output;
try {
System.out.println("generating " + name + ".class file...");
output = new FileOutputStream(
new File(path + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} }
} }

View File

@ -23,6 +23,7 @@ public class MethodFromMethodCall {
this.genericsAndBounds = genericsAndBounds; this.genericsAndBounds = genericsAndBounds;
} }
public ArgumentList getArgList() { public ArgumentList getArgList() {
return argList; return argList;
} }