From 7c3ca93c0b213402d142b1d040d3643ee0144dcc Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Tue, 10 Jul 2018 22:15:26 +0200 Subject: [PATCH] =?UTF-8?q?Bug=2088=20gefixt.=20=09new=20file:=20=20=20src?= =?UTF-8?q?/de/dhbwstuttgart/bytecode/ArgumentVisitor.java=20Visitor=20f?= =?UTF-8?q?=C3=BCr=20Argumente=20des=20Method=20Call=20einer=20Methode=20a?= =?UTF-8?q?us=20Standard-Bibliothek=20und=20dient=20dazu,=20wenn=20die=20A?= =?UTF-8?q?rgument=20eine=20primitive=20Typ=20besitzt=20dann=20wird=20unbo?= =?UTF-8?q?xing=20gemacht.=20Signatur=20von=20Konstruktoren=20angepasst.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/ArgumentVisitor.java | 255 ++++++++++++++++++ .../dhbwstuttgart/bytecode/BytecodeGen.java | 9 +- .../bytecode/BytecodeGenMethod.java | 64 ++--- .../bytecode/signature/Signature.java | 46 ++-- test/bytecode/javFiles/Matrix.jav | 17 +- 5 files changed, 330 insertions(+), 61 deletions(-) create mode 100644 src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java diff --git a/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java new file mode 100644 index 00000000..be0e1bc7 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/ArgumentVisitor.java @@ -0,0 +1,255 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; + +public class ArgumentVisitor implements StatementVisitor { + private List argListMethCall; + private BytecodeGenMethod bytecodeGenMethod; + + public ArgumentVisitor(List argListMethCall, BytecodeGenMethod bytecodeGenMethod) { + this.argListMethCall = argListMethCall; + this.bytecodeGenMethod = bytecodeGenMethod; + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.accept(bytecodeGenMethod); + // Zieltype des Lambas ist Funktionale Interface + // kann nie primitiv sein => un-/boxing wird hier nicht gebraucht + argListMethCall.remove(0); + } + + @Override + public void visit(Assign assign) { + assign.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(assign.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(BinaryExpr binary) { + binary.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(binary.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + castExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(castExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(fieldVar.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + instanceOf.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(instanceOf.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVar localVar) { + localVar.accept(bytecodeGenMethod); + if(!bytecodeGenMethod.isBinaryExp) { + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(localVar.getType())); + } + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewClass methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + aThis.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(aThis.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(WhileStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(unaryExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Literal literal) { + literal.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolvedType(literal.getType())); + argListMethCall.remove(0); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index a8dce3cf..7e3bcac5 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -16,6 +16,7 @@ import org.objectweb.asm.Type; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToString; import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; @@ -179,15 +180,17 @@ public class BytecodeGen implements ASTVisitor { boolean hasGen = false; for(String paramName : methodParamsAndTypes.keySet()) { - String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); - if(genericsAndBounds.containsKey(typeOfParam)) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam) ||typeOfParam.substring(0, 4).equals("TPH ") + || typeOfParam.contains("<")) { hasGen = true; break; } } String sig = null; if(hasGen) { - Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes); + ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs); + Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); sig = signature.toString(); } NormalConstructor constructor = new NormalConstructor(field,genericsAndBounds,hasGen); diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index b3bf8650..6b24d23b 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -13,6 +13,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -61,13 +63,14 @@ public class BytecodeGenMethod implements StatementVisitor { private boolean isInterface; private HashMap genericsAndBoundsMethod; private HashMap genericsAndBounds; - private boolean isBinaryExp = false; + public boolean isBinaryExp = false; private String superClass; private String path; private SourceFile sf; private IStatement statement = null; - private Map argListMethRefl = new LinkedHashMap<>(); +// private int numMethodCalls = 0; + // for tests ** private String fieldName; private String fieldDesc; @@ -125,7 +128,7 @@ public class BytecodeGenMethod implements StatementVisitor { this.isBinaryExp =isBinary; } - private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); } @@ -133,6 +136,11 @@ public class BytecodeGenMethod implements StatementVisitor { public void visit(Block block) { for (Statement stmt : block.getStatements()) { stmt.accept(this); + if(stmt instanceof MethodCall) { + String ret = getResolvedType(((MethodCall) stmt).getType()); + if(!ret.equals("void")) + mv.visitInsn(Opcodes.POP); + } } } @@ -151,17 +159,10 @@ public class BytecodeGenMethod implements StatementVisitor { // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. System.out.println(localVar.name); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); - // Für Matrix Test + if (isBinaryExp) { doUnboxing(getResolvedType(localVar.getType())); } - if(!argListMethRefl.isEmpty() && !isBinaryExp) { - System.out.println("is Empty?? " + argListMethRefl.isEmpty()); - argListMethRefl.forEach((k,v) -> System.out.println(k + "->" + v)); - System.out.println("Local Var= " + localVar.name); - if(argListMethRefl.get(localVar.name)) - doUnboxing(getResolvedType(localVar.getType())); - } } // ?? @@ -212,7 +213,7 @@ public class BytecodeGenMethod implements StatementVisitor { String largerType = getLargerType(lexpType, rexpType); String typeOfBinary = getResolvedType(binary.getType()); - + if (typeOfBinary.equals(Type.getInternalName(String.class))) { mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); mv.visitInsn(Opcodes.DUP); @@ -607,7 +608,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(CastExpr castExpr) { - // TODO Auto-generated method stub } @@ -619,7 +619,6 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(FieldVar fieldVar) { - fieldName = fieldVar.fieldVarName; fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";"; @@ -647,14 +646,12 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(InstanceOf instanceOf) { - // TODO Auto-generated method stub } @Override public void visit(MethodCall methodCall) { System.out.println("In MethodCall = " + methodCall.name); - //ClassLoader.getSystemClassLoader().loadClass(className).getMethod(name, parameterTypes) String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); ClassLoader cLoader = ClassLoader.getSystemClassLoader(); @@ -664,7 +661,6 @@ public class BytecodeGenMethod implements StatementVisitor { if(receiverName.contains("<")) { clazz = clazz.substring(0, receiverName.indexOf("<")); } -// java.lang.reflect.Method[] methods = cl.loadClass("java.util.Vector").getMethods(); java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); System.out.println("Methods of " + receiverName + " "); for(java.lang.reflect.Method m : methods) { @@ -675,10 +671,8 @@ public class BytecodeGenMethod implements StatementVisitor { } } catch (Exception e) { String superClass = ""; -// boolean findSuper = true; // TODO: Test SubMatrix.jav while(true) { -// findSuper = false; for(ClassOrInterface cl : sf.getClasses()) { if(receiverName.equals(cl.getClassName().toString())) { superClass = cl.getSuperClass().getName().toString(); @@ -707,7 +701,6 @@ public class BytecodeGenMethod implements StatementVisitor { break; } catch (Exception e2) { -// findSuper = true; receiverName = superClass; continue; } @@ -718,31 +711,30 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor())); String mDesc = ""; + List argListMethCall = new LinkedList<>(); if(methodRefl == null) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); + methodCall.arglist.accept(this); } else { for(Parameter p:methodRefl.getParameters()) { System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); - argListMethRefl.put(p.getName(), p.getType().isPrimitive()); - } - int i = 0; - for(Expression a:methodCall.arglist.getArguments()) { - if(a instanceof LocalVar) { - LocalVar lv = (LocalVar) a; - Boolean isPrim = argListMethRefl.remove("arg"+i); - argListMethRefl.put(lv.name, isPrim); - } - i++; + argListMethCall.add(p.getType().isPrimitive()); } mDesc = getMethodDesc(methodRefl); + for (Expression al : methodCall.arglist.getArguments()) { + statement = new ArgumentExpr(al); + ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this); + al.accept(argV); + statement = null; + } } System.out.println("Methodcall Desc : " + mDesc); - methodCall.arglist.accept(this); +// methodCall.arglist.accept(this); // is methodCall.receiver functional Interface)? if (varsFunInterface.contains(methodCall.receiver.getType())) { @@ -752,10 +744,7 @@ public class BytecodeGenMethod implements StatementVisitor { mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name, mDesc, isInterface); } - // test - // if(!methodCall.getType().toString().equals("V")) { - // mv.visitInsn(Opcodes.POP); - // } + if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) { if(methodRefl.getReturnType().equals(Object.class)) { String checkCast = getResolvedType(methodCall.getType()); @@ -767,7 +756,7 @@ public class BytecodeGenMethod implements StatementVisitor { if(isBinaryExp) doUnboxing(getResolvedType(methodCall.getType())); } - argListMethRefl.clear(); + } private String getMethodDesc(java.lang.reflect.Method methodRefl) { @@ -839,6 +828,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); Operation op = unaryExpr.operation; @@ -986,7 +976,7 @@ public class BytecodeGenMethod implements StatementVisitor { } // Unboxing: RefType -> prim - private void doUnboxing(String type) { + public void doUnboxing(String type) { switch (type) { case "java/lang/String": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", diff --git a/src/de/dhbwstuttgart/bytecode/signature/Signature.java b/src/de/dhbwstuttgart/bytecode/signature/Signature.java index 0509c678..8c3fb466 100644 --- a/src/de/dhbwstuttgart/bytecode/signature/Signature.java +++ b/src/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -44,10 +44,13 @@ public class Signature { createSignatureForClassOrInterface(); } - public Signature(Constructor constructor, HashMap genericsAndBounds, HashMap methodParamsAndTypes) { + public Signature(Constructor constructor, HashMap genericsAndBounds, + HashMap methodParamsAndTypes,ResultSet resultSet,ArrayList methodPairs) { this.constructor = constructor; this.genericsAndBounds = genericsAndBounds; this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + this.methodPairs = methodPairs; sw = new SignatureWriter(); createSignatureForConsOrMethod(this.constructor,true); } @@ -107,25 +110,28 @@ public class Signature { // Wenn die RückgabeType eine TPH ist, wird als generic behandelt // z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object - String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); - if(ret.substring(0,4).equals("TPH ")) { - String g = ret.substring(4,ret.length())+"$"; - if(genericsAndBounds.containsKey(g)) { - genericsAndBoundsMethod.put(g, genericsAndBounds.get(g)); - }else { - sw.visitFormalTypeParameter(g); - sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); - genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class)); - sw.visitClassBound().visitEnd(); - } - } - - if(ret.contains("<")) { - RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; - if(hasTPHs(ref)) { - createSignatureForParameterizedType(ref); - } + if(!isConstructor) { + String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + System.out.println("RET:::: " + ret); +// if(ret.substring(0,4).equals("TPH ")) { +// String g = ret.substring(4,ret.length())+"$"; + if(genericsAndBounds.containsKey(ret)) { + genericsAndBoundsMethod.put(ret, genericsAndBounds.get(ret)); + }else { + sw.visitFormalTypeParameter(ret); + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + genericsAndBoundsMethod.put(ret, Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } +// } + if(ret.contains("<")) { + RefType ref = (RefType) resultSet.resolveType(method.getReturnType()).resolvedType; + if(hasTPHs(ref)) { + createSignatureForParameterizedType(ref); + } + + } } // Parameters @@ -142,7 +148,7 @@ public class Signature { String bound = Type.getInternalName(Object.class); boolean isTypeVar = false; for(GenericInsertPair pair : methodPairs) { - if(pT.substring(4).equals(pair.TA1.getName())) { + if(pT.substring(0,pT.length()).equals(pair.TA1.getName())) { bound = pair.TA2.getName()+"$"; isTypeVar = true; break; diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index 64132861..60b9c298 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -3,7 +3,21 @@ import java.lang.Integer; import java.lang.Boolean; public class Matrix extends Vector> { - mul(m) { + + Matrix () { + } + + Matrix(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + mul(m) { var ret = new Matrix(); var i = 0; while(i < size()) { @@ -17,6 +31,7 @@ public class Matrix extends Vector> { erg = erg + v1.elementAt(k) * m.elementAt(k).elementAt(j); k++; } +// v2.addElement(new Integer(erg)); v2.addElement(erg); j++; } ret.addElement(v2);