Umstieg auf BCEL6 SourceCode. Einführen von DHBWInstructionFactory
This commit is contained in:
parent
ccd25ab865
commit
bfe6b03605
@ -8,7 +8,7 @@
|
||||
<classpathentry kind="lib" path="lib/junit-4.0.jar" sourcepath="/home/janulrich/.m2/repository/junit/junit/4.0/junit-4.0-sources.jar"/>
|
||||
<classpathentry kind="lib" path="lib/cloning.jar"/>
|
||||
<classpathentry kind="lib" path="lib/guava-10.0.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-bcel6-6.0-SNAPSHOT.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-bcel6-6.0-SNAPSHOT.jar" sourcepath="/home/janulrich/Development/intellijworkspace/bcel/src/main/java"/>
|
||||
<classpathentry kind="lib" path="lib/bcel-6.0-SNAPSHOT.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -29,6 +29,7 @@ public class JavaToBCEL {
|
||||
new BCELifier(new ClassParser(rootDirectory+"MethodCall.class").parse(), new FileOutputStream(new File(rootDirectory+"MethodCallCreator.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+"LocalVarAccess.class").parse(), new FileOutputStream(new File(rootDirectory+"LocalVarAccessCreator.java"))).start();
|
||||
|
||||
} catch (ClassFormatException | IOException e) {
|
||||
e.printStackTrace();
|
||||
|
10
BCEL/bcelifier/LocalVarAccess.java
Normal file
10
BCEL/bcelifier/LocalVarAccess.java
Normal file
@ -0,0 +1,10 @@
|
||||
package bcelifier;
|
||||
|
||||
public class LocalVarAccess {
|
||||
Integer methode(Integer i){
|
||||
Integer var;
|
||||
var = 10 + i;
|
||||
return var;
|
||||
}
|
||||
|
||||
}
|
61
BCEL/bcelifier/LocalVarAccessCreator.java
Normal file
61
BCEL/bcelifier/LocalVarAccessCreator.java
Normal file
@ -0,0 +1,61 @@
|
||||
package bcelifier;
|
||||
|
||||
import org.apache.commons.bcel6.generic.*;
|
||||
import org.apache.commons.bcel6.classfile.*;
|
||||
import org.apache.commons.bcel6.*;
|
||||
import java.io.*;
|
||||
|
||||
public class LocalVarAccessCreator implements Constants {
|
||||
private InstructionFactory _factory;
|
||||
private ConstantPoolGen _cp;
|
||||
private ClassGen _cg;
|
||||
|
||||
public LocalVarAccessCreator() {
|
||||
_cg = new ClassGen("bcelifier.LocalVarAccess", "java.lang.Object", "LocalVarAccess.java", ACC_PUBLIC | ACC_SUPER, new String[] { });
|
||||
|
||||
_cp = _cg.getConstantPool();
|
||||
_factory = new InstructionFactory(_cg, _cp);
|
||||
}
|
||||
|
||||
public void create(OutputStream out) throws IOException {
|
||||
createMethod_0();
|
||||
createMethod_1();
|
||||
_cg.getJavaClass().dump(out);
|
||||
}
|
||||
|
||||
private void createMethod_0() {
|
||||
InstructionList il = new InstructionList();
|
||||
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] { }, "<init>", "bcelifier.LocalVarAccess", 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();
|
||||
}
|
||||
|
||||
private void createMethod_1() {
|
||||
InstructionList il = new InstructionList();
|
||||
MethodGen method = new MethodGen(0, new ObjectType("java.lang.Integer"), new Type[] { new ObjectType("java.lang.Integer") }, new String[] { "arg0" }, "methode", "bcelifier.LocalVarAccess", il, _cp);
|
||||
|
||||
InstructionHandle ih_0 = il.append(new PUSH(_cp, 10));
|
||||
il.append(_factory.createLoad(Type.OBJECT, 1));
|
||||
il.append(_factory.createInvoke("java.lang.Integer", "intValue", Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
|
||||
il.append(InstructionConstants.IADD);
|
||||
il.append(_factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new Type[] { Type.INT }, Constants.INVOKESTATIC));
|
||||
il.append(_factory.createStore(Type.OBJECT, 2));
|
||||
InstructionHandle ih_11 = il.append(_factory.createLoad(Type.OBJECT, 2));
|
||||
InstructionHandle ih_12 = il.append(_factory.createReturn(Type.OBJECT));
|
||||
method.setMaxStack();
|
||||
method.setMaxLocals();
|
||||
_cg.addMethod(method.getMethod());
|
||||
il.dispose();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
bcelifier.LocalVarAccessCreator creator = new bcelifier.LocalVarAccessCreator();
|
||||
creator.create(new FileOutputStream("bcelifier.LocalVarAccess.class"));
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import org.apache.commons.bcel6.classfile.InnerClass;
|
||||
import org.apache.commons.bcel6.classfile.InnerClasses;
|
||||
import org.apache.commons.bcel6.generic.ClassGen;
|
||||
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
|
||||
@ -7,16 +9,22 @@ import de.dhbwstuttgart.syntaxtree.type.Type;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.typeinference.ResultSet;
|
||||
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
|
||||
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
|
||||
|
||||
public class ClassGenerator extends ClassGen{
|
||||
|
||||
private DHBWInstructionFactory factory = new DHBWInstructionFactory(this, this.getConstantPool());
|
||||
private DHBWConstantPoolGen cp;
|
||||
private DHBWInstructionFactory factory;
|
||||
private TypeinferenceResultSet tiResult;
|
||||
private int lambdaMethodeNr = 0;
|
||||
|
||||
public ClassGenerator(String name, String get_Name, String string,
|
||||
short accPublic, String[] strings, TypeinferenceResultSet resultSet) {
|
||||
super(name,get_Name,string,accPublic,strings);
|
||||
super(name,get_Name,string,accPublic,strings, new DHBWConstantPoolGen());
|
||||
this.tiResult = resultSet;
|
||||
|
||||
cp = (DHBWConstantPoolGen) super.getConstantPool();
|
||||
factory = new DHBWInstructionFactory(this, cp);
|
||||
}
|
||||
|
||||
public DHBWInstructionFactory getInstructionFactory() {
|
||||
@ -27,4 +35,29 @@ public class ClassGenerator extends ClassGen{
|
||||
return tiResult.getTypeOfPlaceholder(typePlaceholder);
|
||||
}
|
||||
|
||||
public String createLambdaMethodName() {
|
||||
return "lambda$methode$"+(lambdaMethodeNr++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DHBWConstantPoolGen getConstantPool(){
|
||||
return this.cp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPool(ConstantPoolGen gen){
|
||||
throw new DebugException("Ungültige Operation. ClassGenerator muss ein DHBWConstantPool besitzen");
|
||||
}
|
||||
|
||||
/**
|
||||
* Anmerkung: Kann in diesem Zustand nur einmal aufgerufen werden.
|
||||
* @param innerClassAttribute
|
||||
*/
|
||||
public void addInnerClass(InnerClass innerClassAttribute) {
|
||||
//TODO: Muss vor dem ausführen von getJavaClass ausgeführt werden. getJavaClass überschreiben!
|
||||
InnerClass[] innerClasses = new InnerClass[1];
|
||||
innerClasses[0] = innerClassAttribute;
|
||||
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClassses");
|
||||
this.addAttribute(new InnerClasses(innerClassesUTF8,1,innerClasses,this.getConstantPool().getConstantPool()));
|
||||
}
|
||||
}
|
||||
|
35
src/de/dhbwstuttgart/bytecode/DHBWConstantPoolGen.java
Normal file
35
src/de/dhbwstuttgart/bytecode/DHBWConstantPoolGen.java
Normal file
@ -0,0 +1,35 @@
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.commons.bcel6.classfile.Constant;
|
||||
import org.apache.commons.bcel6.classfile.ConstantMethodHandle;
|
||||
import org.apache.commons.bcel6.classfile.ConstantMethodType;
|
||||
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
|
||||
public class DHBWConstantPoolGen extends ConstantPoolGen{
|
||||
private static final long serialVersionUID = -8282768548793548585L;
|
||||
|
||||
private final HashMap<Constant, Integer> constantTable = new HashMap<>();
|
||||
//private static final String DELIMITER = "$";
|
||||
|
||||
/*
|
||||
public int addConstantMethodType(ConstantMethodType methodType) {
|
||||
if(constantTable.containsKey(methodType))return constantTable.get(methodType);
|
||||
|
||||
}
|
||||
|
||||
public int addConstantMethodHandle(ConstantMethodHandle methodHandle) {
|
||||
if(constantTable.containsKey(methodHandle))return constantTable.get(methodHandle);
|
||||
int ret = this.index;
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
public int addConstant(Constant c){
|
||||
if(constantTable.containsKey(c))return constantTable.get(c);
|
||||
int ret = this.index;
|
||||
this.constants[this.index++] = c;
|
||||
constantTable.put(c, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -6,24 +6,28 @@ import java.util.ArrayList;
|
||||
import org.apache.commons.bcel6.Constants;
|
||||
import org.apache.commons.bcel6.classfile.BootstrapMethod;
|
||||
import org.apache.commons.bcel6.classfile.ConstantInvokeDynamic;
|
||||
import org.apache.commons.bcel6.classfile.ConstantMethodHandle;
|
||||
import org.apache.commons.bcel6.classfile.ConstantMethodType;
|
||||
import org.apache.commons.bcel6.classfile.InnerClass;
|
||||
import org.apache.commons.bcel6.classfile.Method;
|
||||
import org.apache.commons.bcel6.generic.ClassGen;
|
||||
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
|
||||
import org.apache.commons.bcel6.generic.InstructionFactory;
|
||||
import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.LocalVariableInstruction;
|
||||
import org.apache.commons.bcel6.generic.MethodGen;
|
||||
import org.apache.commons.bcel6.generic.Type;
|
||||
|
||||
public class DHBWInstructionFactory extends InstructionFactory{
|
||||
|
||||
public DHBWInstructionFactory(ClassGen cg, ConstantPoolGen cp) {
|
||||
super(cg, cp);
|
||||
}
|
||||
private DHBWConstantPoolGen cp;
|
||||
private ClassGenerator cg;
|
||||
|
||||
private BootstrapMethod createBootstrapMethod(){
|
||||
//TODO
|
||||
return null;
|
||||
public DHBWInstructionFactory(ClassGenerator cg, DHBWConstantPoolGen cp) {
|
||||
super(cg, cp);
|
||||
this.cp = cp;
|
||||
this.cg = cg;
|
||||
}
|
||||
|
||||
public INVOKEDYNAMIC createInvokeDynamic( MethodGen lambdaMethod ) {
|
||||
@ -38,11 +42,22 @@ public class DHBWInstructionFactory extends InstructionFactory{
|
||||
* #19 ()V
|
||||
*
|
||||
* #20 ist ein MethodHandle_info Structure
|
||||
* TODO: Rausfinden, was es mit den Argumenten auf sich hat:
|
||||
* -> Das sind Informationen die die Lambda Funktion zum Ausführen benötigt. (This-Referenz, Variablen, welche vom Lambda Ausdruck benutzt werden)
|
||||
* Anmerkung: Bei der momentanen Implementierung der Lambda Ausdrücke wird nur this übergeben.
|
||||
* Die Argumente werden der Bootstrap Methode beim Aufrufen übergeben: @see https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html#metafactory-java.lang.invoke.MethodHandles.Lookup-java.lang.String-java.lang.invoke.MethodType-java.lang.invoke.MethodType-java.lang.invoke.MethodHandle-java.lang.invoke.MethodType-
|
||||
* TODO: Die korrekten Argumente anfügen.
|
||||
* - samMethodType - Signature and return type of method to be implemented by the function object.
|
||||
* - implMethod - A direct method handle describing the implementation method which should be called (with suitable adaptation of argument types, return types, and with captured arguments prepended to the invocation arguments) at invocation time.
|
||||
* - 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()));
|
||||
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
|
||||
|
||||
//Argumentliste für die Bootstrap Methode zusammensetzen:
|
||||
arguments.add(cp.addConstant(lambdaMethodType));
|
||||
arguments.add(cp.addConstant(implMethod));
|
||||
arguments.add(cp.addConstant(lambdaMethodType));
|
||||
|
||||
|
||||
int innerClassIndex = cp.addClass("java.lang.invoke.MethodHandles$Lookup");
|
||||
int innerClassName = cp.addUtf8("Lookup");
|
||||
@ -52,6 +67,7 @@ public class DHBWInstructionFactory extends InstructionFactory{
|
||||
InnerClass innerClassAttribute = new InnerClass(innerClassIndex, outerClassIndex, innerClassName,accessFlags);
|
||||
//Diese InnereKlasse muss später im ClassFile vorkommen, da sie von der Bootstrap Methode benutzt wird.
|
||||
//TODO: Dies kann man möglicherweise auslagern. Die ClassGen Klasse erweiter, welche sich dann die InnerenKlassen mertk, welche gebraucht werden
|
||||
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;";
|
||||
int lambdaMethodIndex = cp.addMethodref("java.lang.invoke.LambdaMetafactory", "metafactory", bootstrapSignature);
|
||||
@ -62,18 +78,7 @@ public class DHBWInstructionFactory extends InstructionFactory{
|
||||
}
|
||||
BootstrapMethod bMethod = new BootstrapMethod(lambdaMethodIndex, arguments.size(), argumentsArray);
|
||||
|
||||
final short opcode = 186;
|
||||
int index;
|
||||
/*
|
||||
int nargs = 0;
|
||||
String signature = Type.getMethodSignature(ret_type, arg_types);
|
||||
for (int i = 0; i < arg_types.length; i++) {
|
||||
nargs += arg_types[i].getSize();
|
||||
}
|
||||
*/
|
||||
|
||||
//index = cp.addInvokeDynamic(bootstrap_index, name, signature);
|
||||
//Adding invokeDynamic to Constant_Pool:
|
||||
|
||||
/*
|
||||
* Spezifikation: @see https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
|
||||
@ -87,11 +92,13 @@ public class DHBWInstructionFactory extends InstructionFactory{
|
||||
|
||||
/*
|
||||
*
|
||||
* TODO: Rausfinden, was es mit der Inneren Klasse auf sich hat
|
||||
* Was es mit der Inneren Klasse auf sich hat:
|
||||
* (public static final #48= #47 of #51; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
|
||||
* Lösung: Ist wohl einfach nur nötig, um die Metafactory durch die Bootstrap-Methode aufzurufen
|
||||
*
|
||||
* TODO: Rausfinden was es mit dem NameAndType Eintrag in der InvokeDynamic_info Struktur auf sich hat:
|
||||
* Für ein Runnable ()->{}; ist es: run:(LLambda3;)Ljava/lang/Runnable;
|
||||
* Wieso das zusätzliche Argument vom Typ (this)
|
||||
*
|
||||
* TODO: bootstrap_methode den Klassenattributen hinzufügen
|
||||
*
|
||||
@ -99,13 +106,18 @@ public class DHBWInstructionFactory extends InstructionFactory{
|
||||
|
||||
int bootstrap_method_attr_index = bMethod.getBootstrapMethodRef();
|
||||
//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.getType().getSignature());
|
||||
int name_and_type_index = cp.addNameAndType(lambdaMethod.getName(), lambdaMethod.getSignature());
|
||||
|
||||
ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, name_and_type_index);
|
||||
|
||||
index = cp.addConstant(cInvokeDynamic, cp);
|
||||
index = cp.addConstant(cInvokeDynamic);
|
||||
|
||||
return new INVOKEDYNAMIC(index);
|
||||
}
|
||||
|
||||
public LocalVariableInstruction createLoad(org.apache.commons.bcel6.generic.Type bytecodeType, String variableName) {
|
||||
int index = 1; //TODO: Hier muss ein Logger her, welcher aufzeichnet, an welcher Position welche Variable liegt.
|
||||
return InstructionFactory.createLoad(bytecodeType, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ import de.dhbwstuttgart.logger.Logger;
|
||||
import de.dhbwstuttgart.logger.Section;
|
||||
import de.dhbwstuttgart.logger.SectionLogger;
|
||||
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
||||
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
|
||||
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
|
||||
import de.dhbwstuttgart.core.AClassOrInterface;
|
||||
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||
import de.dhbwstuttgart.parser.JavaClassName;
|
||||
@ -75,7 +77,7 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
|
||||
*/
|
||||
public ByteCodeResult genByteCode(TypeinferenceResultSet resultSet) {
|
||||
InstructionFactory _factory;
|
||||
ConstantPoolGen _cp;
|
||||
DHBWConstantPoolGen _cp;
|
||||
ClassGenerator _cg;
|
||||
|
||||
SectionLogger logger = Logger.getSectionLogger(this.getClass().getName(), Section.CODEGEN);
|
||||
@ -84,7 +86,7 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
|
||||
if(pkgName != null)throw new NotImplementedException();
|
||||
_cg = new ClassGenerator(name, superClass.get_Name(), name + ".java", Constants.ACC_PUBLIC , new String[] { }, resultSet); //letzter Parameter sind implementierte Interfaces
|
||||
_cp = _cg.getConstantPool();
|
||||
_factory = new InstructionFactory(_cg, _cp);
|
||||
_factory = new DHBWInstructionFactory(_cg, _cp);
|
||||
|
||||
//Die Felder in Methoden Felder und Konstruktoren aufteilen:
|
||||
Menge<FieldDeclaration> fieldDeclarations = new Menge<>();
|
||||
|
@ -11,6 +11,7 @@ import org.apache.commons.bcel6.generic.MethodGen;
|
||||
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
||||
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
|
||||
import de.dhbwstuttgart.myexception.JVMCodeException;
|
||||
import de.dhbwstuttgart.parser.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.misc.DeclId;
|
||||
@ -57,7 +58,7 @@ public class Constructor extends Method {
|
||||
}
|
||||
|
||||
public void genByteCode(ClassGenerator cg, InstructionList fieldInitializations){
|
||||
ConstantPoolGen _cp = cg.getConstantPool();
|
||||
DHBWConstantPoolGen _cp = cg.getConstantPool();
|
||||
InstructionList il = new InstructionList(); //sollte nicht new sein sondern aus Block kommen
|
||||
Class parentClass = this.getParentClass();
|
||||
|
||||
|
@ -18,6 +18,8 @@ import org.apache.commons.bcel6.generic.MethodGen;
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
import de.dhbwstuttgart.logger.Logger;
|
||||
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
||||
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
|
||||
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
|
||||
import de.dhbwstuttgart.core.IItemWithOffset;
|
||||
import de.dhbwstuttgart.core.MyCompiler;
|
||||
import de.dhbwstuttgart.myexception.JVMCodeException;
|
||||
@ -741,8 +743,8 @@ public class Method extends Field implements IItemWithOffset, TypeInsertable
|
||||
}
|
||||
|
||||
public void genByteCode(ClassGenerator cg) {
|
||||
ConstantPoolGen _cp = cg.getConstantPool();
|
||||
InstructionFactory _factory = new InstructionFactory(cg, _cp);
|
||||
DHBWConstantPoolGen _cp = cg.getConstantPool();
|
||||
DHBWInstructionFactory _factory = new DHBWInstructionFactory(cg, _cp);
|
||||
InstructionList il = new InstructionList();
|
||||
Class parentClass = this.getParentClass();
|
||||
|
||||
@ -751,7 +753,7 @@ public class Method extends Field implements IItemWithOffset, TypeInsertable
|
||||
String[] argumentNames = new String[]{};
|
||||
if(this.parameterlist != null &&
|
||||
this.parameterlist.size() > 0){
|
||||
argumentTypes = new org.apache.commons.bcel6.generic.Type[this.parameterlist.size()];
|
||||
argumentTypes = new org.apache.commons.bcel6.generic.Type[this.parameterlist.size()];
|
||||
argumentNames = new String[this.parameterlist.size()];
|
||||
int i = 0;
|
||||
for(FormalParameter parameter : this.parameterlist){
|
||||
|
@ -7,6 +7,7 @@ import de.dhbwstuttgart.typeinference.Menge;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.typeinference.JavaCodeResult;
|
||||
import de.dhbwstuttgart.typeinference.ResultSet;
|
||||
@ -144,5 +145,25 @@ public class ParameterList extends SyntaxTreeNode implements Iterable<FormalPara
|
||||
return this.formalparameter.size();
|
||||
}
|
||||
|
||||
public org.apache.commons.bcel6.generic.Type[] getBytecodeTypeList(ClassGenerator cg){
|
||||
org.apache.commons.bcel6.generic.Type[] ret = new org.apache.commons.bcel6.generic.Type[formalparameter.size()];
|
||||
int i = 0;
|
||||
for(FormalParameter f : formalparameter){
|
||||
ret[i] = f.getType().getBytecodeType(cg);
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String[] getParameterNameArray() {
|
||||
String[] ret = new String[formalparameter.size()];
|
||||
int i = 0;
|
||||
for(FormalParameter f : formalparameter){
|
||||
ret[i] = f.getIdentifier();
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
// ino.end
|
||||
|
@ -9,6 +9,7 @@ import org.apache.commons.bcel6.generic.ClassGen;
|
||||
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
import org.apache.commons.bcel6.generic.InstructionFactory;
|
||||
import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.MethodGen;
|
||||
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
|
||||
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
@ -230,23 +231,13 @@ public class LambdaExpression extends Expr{
|
||||
ConstantPoolGen cp = cg.getConstantPool();
|
||||
InstructionList il = new InstructionList();
|
||||
|
||||
/*
|
||||
* Invokedynamic 186 (0xBA)
|
||||
* - Auf dem Operanten Stack liegen die Argumente
|
||||
*
|
||||
* InvokeDynamik_Info Structure auf den der Indexzeiger zeigen muss: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10
|
||||
*
|
||||
* Ablauf:
|
||||
* 1. Methode erstellen, mit dem Inhalt der Lambda-Expression //Dabei wird das This-Stat
|
||||
* 2. Invokedynamic-Call erzeugen
|
||||
*
|
||||
*/
|
||||
new BootstrapMethod();
|
||||
|
||||
//---Variante 1 mit opcode----
|
||||
short opcode = 186;
|
||||
int index = 0; //indexbyte 1 und 2 müssen ein Zeiger auf ein call site specifier im Konstantenpool sein (InvokeDynamic_Info).
|
||||
il.append(new INVOKEDYNAMIC(opcode, index));
|
||||
MethodGen lambdaMethod = new MethodGen(0, method_body.getType().getBytecodeType(cg),
|
||||
params.getBytecodeTypeList(cg), params.getParameterNameArray(), cg.createLambdaMethodName(),
|
||||
this.getParentClass().getName().toString(), new InstructionList(), cg.getConstantPool());
|
||||
|
||||
il.append(cg.getInstructionFactory().createInvokeDynamic(lambdaMethod));
|
||||
cg.addMethod(lambdaMethod.getMethod());
|
||||
|
||||
return il;
|
||||
}
|
||||
|
@ -5,9 +5,13 @@ package de.dhbwstuttgart.syntaxtree.statement;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.apache.commons.bcel6.Constants;
|
||||
import org.apache.commons.bcel6.generic.ClassGen;
|
||||
import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.ObjectType;
|
||||
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
||||
import de.dhbwstuttgart.logger.Logger;
|
||||
import de.dhbwstuttgart.myexception.CTypeReconstructionException;
|
||||
import de.dhbwstuttgart.myexception.JVMCodeException;
|
||||
@ -24,6 +28,7 @@ import de.dhbwstuttgart.typeinference.ConstraintsSet;
|
||||
import de.dhbwstuttgart.typeinference.JavaCodeResult;
|
||||
import de.dhbwstuttgart.typeinference.ResultSet;
|
||||
import de.dhbwstuttgart.typeinference.SingleConstraint;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
|
||||
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
|
||||
import de.dhbwstuttgart.typeinference.unify.CSubstitutionSet;
|
||||
@ -40,6 +45,7 @@ public class LocalOrFieldVar extends Expr
|
||||
// ino.attribute.parserlog.25507.declaration
|
||||
protected static Logger parserlog = Logger.getLogger("parser");
|
||||
// ino.end
|
||||
private boolean isFieldAccess = false;
|
||||
|
||||
// ino.method.LocalOrFieldVar.25510.definition
|
||||
public LocalOrFieldVar(int offset, int variableLength)
|
||||
@ -117,6 +123,11 @@ public class LocalOrFieldVar extends Expr
|
||||
Type thisType = thisTypeAssumption.checkTYPE(assumptions, this);
|
||||
this.setType(thisType);
|
||||
//ret.add(new Constraint(thisTypeAssumption, this.getTypeVariable()));
|
||||
//Rausfinden, ob es Feld oder Locale Variable ist:
|
||||
for(FieldAssumption fAss : assumptions.getFieldVars(this.get_Name())){
|
||||
if(this.getParentClass().equals(fAss.getParentClass()))this.isFieldAccess = true;
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -136,9 +147,13 @@ public class LocalOrFieldVar extends Expr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void genByteCode(ClassGen _cg) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
public InstructionList genByteCode(ClassGenerator cg) {
|
||||
InstructionList il = new InstructionList();
|
||||
if(this.isFieldAccess){
|
||||
il.append(cg.getInstructionFactory().createFieldAccess(this.getParentClass().getName().toString(), this.get_Name(), this.getType().getBytecodeType(cg), Constants.GETFIELD));
|
||||
}
|
||||
il.append(cg.getInstructionFactory().createLoad(this.getType().getBytecodeType(cg), this.get_Name()));
|
||||
return il;
|
||||
}
|
||||
|
||||
}
|
||||
|
5
test/bytecode/Runnable.jav
Normal file
5
test/bytecode/Runnable.jav
Normal file
@ -0,0 +1,5 @@
|
||||
class Runnable{
|
||||
|
||||
method() { return ()-> this; }
|
||||
|
||||
}
|
14
test/bytecode/RunnableTest.java
Normal file
14
test/bytecode/RunnableTest.java
Normal file
@ -0,0 +1,14 @@
|
||||
package bytecode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RunnableTest {
|
||||
public final static String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/";
|
||||
public final static String testFile = "Runnable.jav";
|
||||
public final static String outputFile = "Runnable.class";
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputFile);
|
||||
}
|
||||
}
|
@ -8,5 +8,6 @@ public static void main(String[] args){
|
||||
System.out.println(new Return().method());
|
||||
new MethodCall().method();
|
||||
System.out.println(new FieldDeclaration().field);
|
||||
//new Runnable().method().run();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user