Erster zusammengehackter Stand, bei dem Runnable.jav-Test funktioniert

This commit is contained in:
JanUlrich 2015-09-16 18:45:45 +02:00
parent bfe6b03605
commit a9611fdd90
19 changed files with 184 additions and 23 deletions

View File

@ -30,6 +30,7 @@ public class JavaToBCEL {
new BCELifier(new ClassParser(rootDirectory+"FieldDeclaration.class").parse(), new FileOutputStream(new File(rootDirectory+"FieldDeclarationCreator.java"))).start(); new BCELifier(new ClassParser(rootDirectory+"FieldDeclaration.class").parse(), new FileOutputStream(new File(rootDirectory+"FieldDeclarationCreator.java"))).start();
new BCELifier(new ClassParser(rootDirectory+"Null.class").parse(), new FileOutputStream(new File(rootDirectory+"NullCreator.java"))).start(); new BCELifier(new ClassParser(rootDirectory+"Null.class").parse(), new FileOutputStream(new File(rootDirectory+"NullCreator.java"))).start();
new BCELifier(new ClassParser(rootDirectory+"LocalVarAccess.class").parse(), new FileOutputStream(new File(rootDirectory+"LocalVarAccessCreator.java"))).start(); new BCELifier(new ClassParser(rootDirectory+"LocalVarAccess.class").parse(), new FileOutputStream(new File(rootDirectory+"LocalVarAccessCreator.java"))).start();
new BCELifier(new ClassParser(rootDirectory+"Wildcard.class").parse(), new FileOutputStream(new File(rootDirectory+"WildcardCreator.java"))).start();
} catch (ClassFormatException | IOException e) { } catch (ClassFormatException | IOException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -0,0 +1,5 @@
package bcelifier;
public class Wildcard<A> {
Wildcard<? super String> a;
}

View File

@ -0,0 +1,50 @@
package bcelifier;
import org.apache.commons.bcel6.generic.*;
import org.apache.commons.bcel6.classfile.*;
import org.apache.commons.bcel6.*;
import java.io.*;
public class WildcardCreator implements Constants {
private InstructionFactory _factory;
private ConstantPoolGen _cp;
private ClassGen _cg;
public WildcardCreator() {
_cg = new ClassGen("bcelifier.Wildcard", "java.lang.Object", "Wildcard.java", ACC_PUBLIC | ACC_SUPER, new String[] { });
_cp = _cg.getConstantPool();
_factory = new InstructionFactory(_cg, _cp);
}
public void create(OutputStream out) throws IOException {
createFields();
createMethod_0();
_cg.getJavaClass().dump(out);
}
private void createFields() {
FieldGen field;
field = new FieldGen(0, new ObjectType("bcelifier.Wildcard"), "a", _cp);
_cg.addField(field.getField());
}
private void createMethod_0() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] { }, "<init>", "bcelifier.Wildcard", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
il.append(_factory.createInvoke("java.lang.Object", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
InstructionHandle ih_4 = il.append(_factory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
public static void main(String[] args) throws Exception {
bcelifier.WildcardCreator creator = new bcelifier.WildcardCreator();
creator.create(new FileOutputStream("bcelifier.Wildcard.class"));
}
}

BIN
lib/bcel-5.2-src.zip Normal file

Binary file not shown.

View File

@ -1,5 +1,8 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode;
import org.apache.commons.bcel6.classfile.BootstrapMethod;
import org.apache.commons.bcel6.classfile.BootstrapMethods;
import org.apache.commons.bcel6.classfile.ConstantPool;
import org.apache.commons.bcel6.classfile.InnerClass; import org.apache.commons.bcel6.classfile.InnerClass;
import org.apache.commons.bcel6.classfile.InnerClasses; import org.apache.commons.bcel6.classfile.InnerClasses;
import org.apache.commons.bcel6.generic.ClassGen; import org.apache.commons.bcel6.generic.ClassGen;
@ -25,6 +28,8 @@ public class ClassGenerator extends ClassGen{
cp = (DHBWConstantPoolGen) super.getConstantPool(); cp = (DHBWConstantPoolGen) super.getConstantPool();
factory = new DHBWInstructionFactory(this, cp); factory = new DHBWInstructionFactory(this, cp);
this.setMajor(52); //Java 8 Version 52.0
this.setMinor(0);
} }
public DHBWInstructionFactory getInstructionFactory() { public DHBWInstructionFactory getInstructionFactory() {
@ -55,9 +60,21 @@ public class ClassGenerator extends ClassGen{
*/ */
public void addInnerClass(InnerClass innerClassAttribute) { public void addInnerClass(InnerClass innerClassAttribute) {
//TODO: Muss vor dem ausführen von getJavaClass ausgeführt werden. getJavaClass überschreiben! //TODO: Muss vor dem ausführen von getJavaClass ausgeführt werden. getJavaClass überschreiben!
InnerClass[] innerClasses = new InnerClass[1]; int numberOfInnerClasses = 1;
innerClasses[0] = innerClassAttribute; InnerClass[] innerClasses = new InnerClass[numberOfInnerClasses];
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClassses"); innerClasses[numberOfInnerClasses-1] = innerClassAttribute;
this.addAttribute(new InnerClasses(innerClassesUTF8,1,innerClasses,this.getConstantPool().getConstantPool())); int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
this.addAttribute(new InnerClasses(innerClassesUTF8,numberOfInnerClasses*8+2,innerClasses,this.getConstantPool().getConstantPool()));
}
public int addBootstrapMethod(BootstrapMethod bMethod) {
int numberOfBootstrapMethods = 1;
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
int length = 2 + numberOfBootstrapMethods * 4 + bMethod.getNumBootstrapArguments() * 2;
BootstrapMethod[] bootstrap_methods = new BootstrapMethod[numberOfBootstrapMethods];
bootstrap_methods[numberOfBootstrapMethods-1] = bMethod;
BootstrapMethods bootstrapAttribute = new BootstrapMethods(name_index, length, bootstrap_methods, this.getConstantPool().getConstantPool());
this.addAttribute(bootstrapAttribute);
return numberOfBootstrapMethods-1;
} }
} }

View File

@ -32,4 +32,5 @@ public class DHBWConstantPoolGen extends ConstantPoolGen{
constantTable.put(c, ret); constantTable.put(c, ret);
return ret; return ret;
} }
} }

View File

@ -30,7 +30,7 @@ public class DHBWInstructionFactory extends InstructionFactory{
this.cg = cg; this.cg = cg;
} }
public INVOKEDYNAMIC createInvokeDynamic( MethodGen lambdaMethod ) { public INVOKEDYNAMIC createInvokeDynamic( String interfaceMethodName, String lambdaTypeSignature, MethodGen lambdaMethod ) {
//Zuerst die Bootstrap-Methode erstellen: Diese müssen dann in ein BootstrapMethods-Attribut zusammengefasst und dem Classfile hinzugefügt werden //Zuerst die Bootstrap-Methode erstellen: Diese müssen dann in ein BootstrapMethods-Attribut zusammengefasst und dem Classfile hinzugefügt werden
//this.cp.addMethodref(lambdaMethod); //this.cp.addMethodref(lambdaMethod);
@ -49,12 +49,14 @@ public class DHBWInstructionFactory extends InstructionFactory{
* - instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it. * - instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.
*/ */
ConstantMethodType lambdaMethodType = new ConstantMethodType(this.cp.addUtf8(lambdaMethod.getSignature())); String lambdaTypeParameterList = "()";
ConstantMethodType lambdaMethodType = new ConstantMethodType(this.cp.addUtf8("()LRunnable;"));
ConstantMethodType lambdaMethodType1 = new ConstantMethodType(this.cp.addUtf8("()Ljava/lang/Object;"));
int implMethodKind = 7; // 7 = InvokeSpecial @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5 int implMethodKind = 7; // 7 = InvokeSpecial @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5
ConstantMethodHandle implMethod = new ConstantMethodHandle(implMethodKind,cg.getConstantPool().addMethodref(lambdaMethod)); //Das zweite Argument ist der MethodRef zur LambdaMethode ConstantMethodHandle implMethod = new ConstantMethodHandle(implMethodKind,cg.getConstantPool().addMethodref(lambdaMethod)); //Das zweite Argument ist der MethodRef zur LambdaMethode
//Argumentliste für die Bootstrap Methode zusammensetzen: //Argumentliste für die Bootstrap Methode zusammensetzen:
arguments.add(cp.addConstant(lambdaMethodType)); arguments.add(cp.addConstant(lambdaMethodType1));
arguments.add(cp.addConstant(implMethod)); arguments.add(cp.addConstant(implMethod));
arguments.add(cp.addConstant(lambdaMethodType)); arguments.add(cp.addConstant(lambdaMethodType));
@ -70,13 +72,16 @@ public class DHBWInstructionFactory extends InstructionFactory{
cg.addInnerClass(innerClassAttribute); cg.addInnerClass(innerClassAttribute);
String bootstrapSignature = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; String bootstrapSignature = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
int lambdaMethodIndex = cp.addMethodref("java.lang.invoke.LambdaMetafactory", "metafactory", bootstrapSignature); int lambdaMetafactoryRefIndex = cp.addMethodref("java.lang.invoke.LambdaMetafactory", "metafactory", bootstrapSignature);
//reference kind 6 steht für invokestatic
int lambdaMetafactoryHandle = cp.addConstant(new ConstantMethodHandle(6, lambdaMetafactoryRefIndex));
int[] argumentsArray = new int[arguments.size()]; int[] argumentsArray = new int[arguments.size()];
for(int i = 0; i<arguments.size();i++){ for(int i = 0; i<arguments.size();i++){
argumentsArray[i] = arguments.get(i); argumentsArray[i] = arguments.get(i);
} }
BootstrapMethod bMethod = new BootstrapMethod(lambdaMethodIndex, arguments.size(), argumentsArray); BootstrapMethod bMethod = new BootstrapMethod(lambdaMetafactoryHandle, arguments.size(), argumentsArray);
int index; int index;
@ -104,9 +109,9 @@ public class DHBWInstructionFactory extends InstructionFactory{
* *
*/ */
int bootstrap_method_attr_index = bMethod.getBootstrapMethodRef(); int bootstrap_method_attr_index = cg.addBootstrapMethod(bMethod);
//TODO: der Typ der Lambda Methode muss den Typ von this als erstes Argument enthalten, damit this innerhalb der Lambda Methode verwendet werden kann //TODO: der Typ der Lambda Methode muss den Typ von this als erstes Argument enthalten, damit this innerhalb der Lambda Methode verwendet werden kann
int name_and_type_index = cp.addNameAndType(lambdaMethod.getName(), lambdaMethod.getSignature()); int name_and_type_index = cp.addNameAndType(interfaceMethodName, lambdaTypeSignature);
ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, name_and_type_index); ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, name_and_type_index);

View File

@ -0,0 +1,16 @@
package de.dhbwstuttgart.bytecode;
import org.apache.commons.bcel6.generic.ConstantPoolGen;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.MethodGen;
import org.apache.commons.bcel6.generic.Type;
public class MethodGenerator extends MethodGen{
public MethodGenerator(int access_flags, Type return_type, Type[] arg_types, String[] arg_names, String method_name,
String class_name, InstructionList il, ConstantPoolGen cp) {
super(access_flags, return_type, arg_types, arg_names, method_name, class_name, il, cp);
}
}

View File

@ -0,0 +1,16 @@
package de.dhbwstuttgart.bytecode;
import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.classfile.Utility;
import org.apache.commons.bcel6.generic.ObjectType;
import org.apache.commons.bcel6.generic.ReferenceType;
import org.apache.commons.bcel6.generic.Type;
public class WildcardType extends ReferenceType{
public WildcardType(String class_name, String preString) {
super(Constants.T_REFERENCE, preString + "L" + class_name.replace('.', '/') + ";");
this.type = Constants.T_UNKNOWN;
}
}

View File

@ -20,6 +20,7 @@ import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen; import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory; import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.bytecode.MethodGenerator;
import de.dhbwstuttgart.core.IItemWithOffset; import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.core.MyCompiler; import de.dhbwstuttgart.core.MyCompiler;
import de.dhbwstuttgart.myexception.JVMCodeException; import de.dhbwstuttgart.myexception.JVMCodeException;
@ -764,7 +765,8 @@ public class Method extends Field implements IItemWithOffset, TypeInsertable
} }
//Methode generieren: //Methode generieren:
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg), argumentTypes , argumentNames, this.get_Method_Name(), parentClass.name, il, _cp); MethodGen method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg), argumentTypes , argumentNames, this.get_Method_Name(), parentClass.name, il, _cp);
method.stripAttributes(true);
Block block = this.get_Block(); Block block = this.get_Block();
InstructionList blockInstructions = block.genByteCode(cg); InstructionList blockInstructions = block.genByteCode(cg);

View File

@ -2,6 +2,7 @@ package de.dhbwstuttgart.syntaxtree.statement;
import java.util.Hashtable; import java.util.Hashtable;
import org.apache.bcel.Constants;
import org.apache.commons.bcel6.classfile.BootstrapMethod; import org.apache.commons.bcel6.classfile.BootstrapMethod;
import org.apache.commons.bcel6.classfile.ConstantPool; import org.apache.commons.bcel6.classfile.ConstantPool;
import org.apache.commons.bcel6.generic.BIPUSH; import org.apache.commons.bcel6.generic.BIPUSH;
@ -235,11 +236,24 @@ public class LambdaExpression extends Expr{
MethodGen lambdaMethod = new MethodGen(0, method_body.getType().getBytecodeType(cg), MethodGen lambdaMethod = new MethodGen(0, method_body.getType().getBytecodeType(cg),
params.getBytecodeTypeList(cg), params.getParameterNameArray(), cg.createLambdaMethodName(), params.getBytecodeTypeList(cg), params.getParameterNameArray(), cg.createLambdaMethodName(),
this.getParentClass().getName().toString(), new InstructionList(), cg.getConstantPool()); this.getParentClass().getName().toString(), new InstructionList(), cg.getConstantPool());
lambdaMethod.stripAttributes(true);
lambdaMethod.getInstructionList().append(this.method_body.genByteCode(cg));
il.append(cg.getInstructionFactory().createInvokeDynamic(lambdaMethod)); lambdaMethod.setAccessFlags(Constants.ACC_PRIVATE+Constants.ACC_SYNTHETIC);
String interfaceMethodName = "apply"; //Das ist ein Hack, funktioniert momentan, da nur FunN Interfaces für LambdaAusdrücke funktionieren
il.append(InstructionFactory.createLoad( org.apache.commons.bcel6.generic.Type.OBJECT, 0));
il.append(cg.getInstructionFactory().createInvokeDynamic(interfaceMethodName,this.getSAMSignature(cg),lambdaMethod));
lambdaMethod.setMaxLocals();
lambdaMethod.setMaxStack();
cg.addMethod(lambdaMethod.getMethod()); cg.addMethod(lambdaMethod.getMethod());
return il; return il;
} }
private String getSAMSignature(ClassGenerator cg){
String typeSignature = "(";
return "(LRunnable;)LFun0;";
}
} }

View File

@ -1,7 +1,7 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.typeinference.Menge; import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.JavaCodeResult; import de.dhbwstuttgart.typeinference.JavaCodeResult;
@ -156,4 +156,9 @@ public class ExtendsWildcardType extends WildcardType implements ITypeContainer,
this.innerType = (ObjectType) this.innerType.TYPE(ass, parent); this.innerType = (ObjectType) this.innerType.TYPE(ass, parent);
return super.TYPE(ass, parent); return super.TYPE(ass, parent);
} }
@Override
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
return new de.dhbwstuttgart.bytecode.WildcardType(this.innerType.get_Name(), "+");
}
} }

View File

@ -814,7 +814,21 @@ public class RefType extends ObjectType implements IMatchable
} }
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) { public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
return new org.apache.commons.bcel6.generic.ObjectType(this.getTypeName()); String paramString = "";
boolean printParameterList = false; //Die ParameterListe wird wohl nicht in allen Fällen gebraucht
if(printParameterList &&
this.parameter != null && this.parameter.size()>0){
paramString+="<";
Iterator<Type> it = this.parameter.iterator();
while(it.hasNext()){
Type param = it.next();
paramString+=param.getBytecodeType(cg);
//if(it.hasNext())
//paramString+=";"; //kein Delimiter zwischen den Typen
}
paramString+=">";
}
return new org.apache.commons.bcel6.generic.ObjectType(this.getTypeName()+paramString);
} }
} }

View File

@ -1,11 +1,12 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.typeinference.Menge; import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.JavaCodeResult; import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
/** /**
* Stellt eine Wildcard mit unterer Grenze dar. * Stellt eine Wildcard mit unterer Grenze dar.
@ -153,5 +154,9 @@ public class SuperWildcardType extends WildcardType implements ITypeContainer, I
return super.TYPE(ass, parent); return super.TYPE(ass, parent);
} }
@Override
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
return new de.dhbwstuttgart.bytecode.WildcardType(this.innerType.get_Name(), "-");
}
} }

View File

@ -1,11 +1,12 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.typeinference.Menge; import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.JavaCodeResult; import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
/** /**
@ -99,6 +100,11 @@ public class WildcardType extends Type{
} }
} }
@Override
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
return this.innerType.getBytecodeType(cg);
}
} }

3
test/bytecode/Fun0.java Normal file
View File

@ -0,0 +1,3 @@
interface Fun0<A>{
A apply();
}

View File

@ -2,7 +2,8 @@ class LambdaExpr {
void method() { void method() {
lambda; lambda = ()-> 1; lambda;
lambda = ()-> 1;
} }
} }

View File

@ -1,5 +1,5 @@
class Runnable{ class Runnable{
method() { return ()-> this; } Fun0<Runnable> method() { return ()-> this; }
} }

View File

@ -3,11 +3,11 @@
*/ */
class Test{ class Test{
public static void main(String[] args){ public static void main(String[] args){
new EmptyClass(); /*new EmptyClass();
new Assign(); new Assign();
System.out.println(new Return().method()); System.out.println(new Return().method());
new MethodCall().method(); new MethodCall().method();
System.out.println(new FieldDeclaration().field); System.out.println(new FieldDeclaration().field);*/
//new Runnable().method().run(); System.out.println(new Runnable().method().apply());
} }
} }