forked from JavaTX/JavaCompilerCore
BCEL Library aktualisiert, Stackmaptable angefügt, Tests angepasst
This commit is contained in:
parent
a4ea466fe6
commit
b1d6b44fb9
Binary file not shown.
@ -10,6 +10,12 @@
|
|||||||
|
|
||||||
## BCEL Patch
|
## BCEL Patch
|
||||||
https://issues.apache.org/jira/browse/BCEL-268
|
https://issues.apache.org/jira/browse/BCEL-268
|
||||||
|
* Submitting patch: https://commons.apache.org/patches.html
|
||||||
|
### Änderungen im BCEL-Projekt
|
||||||
|
* Neue Datei StackMapTableGen
|
||||||
|
* Testen TODO:
|
||||||
|
* Mittels BCELifier Code generieren lassen, welcher Methoden erstellt, die Branches enthalten
|
||||||
|
* Dies dann dem StackMapTableGen übergeben und auf das erstellen von StackMapEntries abprüfen
|
||||||
|
|
||||||
# Literatur
|
# Literatur
|
||||||
* Zu JVM allgemein: http://blog.jamesdbloom.com/JVMInternals.html
|
* Zu JVM allgemein: http://blog.jamesdbloom.com/JVMInternals.html
|
||||||
|
12
notizen/stan/stackmaptable/StackMapTest5.java
Normal file
12
notizen/stan/stackmaptable/StackMapTest5.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class StackMapTest5{
|
||||||
|
|
||||||
|
void methode(){
|
||||||
|
int i = 0;
|
||||||
|
while(System.out == null){
|
||||||
|
i+=1;
|
||||||
|
while(true){
|
||||||
|
String s = "2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -95,7 +95,7 @@ public class ClassGenerator extends ClassGen{
|
|||||||
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
|
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
|
||||||
this.addAttribute(new InnerClasses(innerClassesUTF8,numberOfInnerClasses*8+2,innerClasses,this.getConstantPool().getConstantPool()));
|
this.addAttribute(new InnerClasses(innerClassesUTF8,numberOfInnerClasses*8+2,innerClasses,this.getConstantPool().getConstantPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addBootstrapMethod(BootstrapMethod bMethod) {
|
public int addBootstrapMethod(BootstrapMethod bMethod) {
|
||||||
int numberOfBootstrapMethods = 1;
|
int numberOfBootstrapMethods = 1;
|
||||||
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
|
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
|
||||||
|
@ -18,6 +18,7 @@ import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
|||||||
import org.apache.commons.bcel6.generic.Instruction;
|
import org.apache.commons.bcel6.generic.Instruction;
|
||||||
import org.apache.commons.bcel6.generic.InstructionList;
|
import org.apache.commons.bcel6.generic.InstructionList;
|
||||||
import org.apache.commons.bcel6.generic.MethodGen;
|
import org.apache.commons.bcel6.generic.MethodGen;
|
||||||
|
import org.apache.commons.bcel6.generic.StackMapTableGen;
|
||||||
import org.apache.commons.bcel6.generic.Type;
|
import org.apache.commons.bcel6.generic.Type;
|
||||||
|
|
||||||
import org.apache.commons.bcel6.Const;
|
import org.apache.commons.bcel6.Const;
|
||||||
@ -72,36 +73,13 @@ public class MethodGenerator extends MethodGen{
|
|||||||
String retTypeSig = retType.getBytecodeSignature(cg, rs);
|
String retTypeSig = retType.getBytecodeSignature(cg, rs);
|
||||||
|
|
||||||
method.addAttribute(factory.createSignatureAttribute(paramTypesSig+retTypeSig));
|
method.addAttribute(factory.createSignatureAttribute(paramTypesSig+retTypeSig));
|
||||||
StackMap stackMap = this.generateStackMapFrame();
|
|
||||||
|
StackMap stackMap = new StackMapTableGen(this.getInstructionList(), cp).getStackMap();
|
||||||
if(stackMap != null)method.addCodeAttribute(stackMap);
|
if(stackMap != null)method.addCodeAttribute(stackMap);
|
||||||
|
|
||||||
return method.getMethod();
|
return method.getMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return null - falls kein StackMapFrame für die Methode notwendig ist
|
|
||||||
*/
|
|
||||||
private StackMap generateStackMapFrame(){
|
|
||||||
int length=2; //+2 wegen NumberOfEntries
|
|
||||||
Menge<StackMapEntry> entries = CodeHelper.getStackMapEntries(getInstructionList(), cp);
|
|
||||||
if(entries.size()==0)return null;
|
|
||||||
StackMapEntry[] entryArray = new StackMapEntry[entries.size()];
|
|
||||||
for(int i = 0; i<entries.size();i++){
|
|
||||||
entryArray[i] = entries.get(i);
|
|
||||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
|
||||||
try {
|
|
||||||
entries.get(i).dump(new DataOutputStream(testOut));
|
|
||||||
} catch (IOException e) {
|
|
||||||
//Kann nicht auftreten. Es wird in Byte-Array geschrieben.
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
length+=testOut.size();
|
|
||||||
}
|
|
||||||
return new StackMap(cp.addUtf8(Const.getAttributeName(Const.ATTR_STACK_MAP_TABLE))
|
|
||||||
,length, entryArray,cp.getConstantPool());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import org.apache.commons.bcel6.generic.DSTORE;
|
|||||||
import org.apache.commons.bcel6.generic.GETFIELD;
|
import org.apache.commons.bcel6.generic.GETFIELD;
|
||||||
import org.apache.commons.bcel6.generic.GotoInstruction;
|
import org.apache.commons.bcel6.generic.GotoInstruction;
|
||||||
import org.apache.commons.bcel6.generic.IINC;
|
import org.apache.commons.bcel6.generic.IINC;
|
||||||
|
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
|
||||||
import org.apache.commons.bcel6.generic.INVOKEINTERFACE;
|
import org.apache.commons.bcel6.generic.INVOKEINTERFACE;
|
||||||
import org.apache.commons.bcel6.generic.Instruction;
|
import org.apache.commons.bcel6.generic.Instruction;
|
||||||
import org.apache.commons.bcel6.generic.InstructionHandle;
|
import org.apache.commons.bcel6.generic.InstructionHandle;
|
||||||
@ -25,6 +26,7 @@ import org.apache.commons.bcel6.generic.InstructionList;
|
|||||||
import org.apache.commons.bcel6.generic.InstructionTargeter;
|
import org.apache.commons.bcel6.generic.InstructionTargeter;
|
||||||
import org.apache.commons.bcel6.generic.InvokeInstruction;
|
import org.apache.commons.bcel6.generic.InvokeInstruction;
|
||||||
import org.apache.commons.bcel6.generic.LDC;
|
import org.apache.commons.bcel6.generic.LDC;
|
||||||
|
import org.apache.commons.bcel6.generic.NEW;
|
||||||
import org.apache.commons.bcel6.generic.ObjectType;
|
import org.apache.commons.bcel6.generic.ObjectType;
|
||||||
import org.apache.commons.bcel6.generic.PUTFIELD;
|
import org.apache.commons.bcel6.generic.PUTFIELD;
|
||||||
import org.apache.commons.bcel6.generic.ReferenceType;
|
import org.apache.commons.bcel6.generic.ReferenceType;
|
||||||
@ -130,6 +132,20 @@ class StackItemTop implements StackItem{
|
|||||||
return new StackMapType(Const.ITEM_Bogus,0,cp.getConstantPool());
|
return new StackMapType(Const.ITEM_Bogus,0,cp.getConstantPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
class StackItemUninitialized implements StackItem{
|
||||||
|
private NEW newIns;
|
||||||
|
private InstructionHandle handle;
|
||||||
|
public StackItemUninitialized(NEW newInstruction, InstructionHandle instructionHandle){
|
||||||
|
newIns = newInstruction;
|
||||||
|
handle = instructionHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StackMapType getType(ConstantPoolGen cp) {
|
||||||
|
return new StackMapType(Const.ITEM_NewObject,handle.getPosition(),cp.getConstantPool());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
class StackItemObject implements StackItem{
|
class StackItemObject implements StackItem{
|
||||||
@ -138,32 +154,10 @@ class StackItemObject implements StackItem{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
class StackState{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class LocalVarState{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Fields{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CodeHelper {
|
public class CodeHelper {
|
||||||
|
|
||||||
private ArrayList<Integer> outputStack = new ArrayList<>();
|
private ArrayList<Integer> outputStack = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* Pushes a new type onto the output frame stack.
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* the type that must be pushed.
|
|
||||||
*/
|
|
||||||
private void push(final int type) {
|
|
||||||
outputStack.add(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generiert die StackMapEntrys zu einer gegebenen Methode
|
* Generiert die StackMapEntrys zu einer gegebenen Methode
|
||||||
* @param forCode
|
* @param forCode
|
||||||
@ -177,10 +171,9 @@ public class CodeHelper {
|
|||||||
Instruction[] instructions = forCode.getInstructions();
|
Instruction[] instructions = forCode.getInstructions();
|
||||||
InstructionHandle[] instructionHandles = forCode.getInstructionHandles();
|
InstructionHandle[] instructionHandles = forCode.getInstructionHandles();
|
||||||
int lastPosition = 0;
|
int lastPosition = 0;
|
||||||
for(int i = 0; i<forCode.getLength();i++){
|
|
||||||
Instruction ins = instructions[i];
|
for(InstructionHandle ih : forCode.getInstructionHandles()){
|
||||||
InstructionHandle ih = instructionHandles[i];
|
getOutput(ih, state, cp);
|
||||||
getOutput(ins, state, cp);
|
|
||||||
if(isFrameEndpoint(ih, forCode)){
|
if(isFrameEndpoint(ih, forCode)){
|
||||||
if(!state.stack.isEmpty()){
|
if(!state.stack.isEmpty()){
|
||||||
StackMapEntry entry = generateFullFrame(ih.getPosition(),state, cp);
|
StackMapEntry entry = generateFullFrame(ih.getPosition(),state, cp);
|
||||||
@ -236,11 +229,12 @@ public class CodeHelper {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getOutput(Instruction ins, JVMState ret, ConstantPoolGen cp){
|
static void getOutput(InstructionHandle instructionHandle, JVMState ret, ConstantPoolGen cp){
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
* Berechnet den Output auf den Stack und ändert den LocalVarState und den StackState je nach Instruktion ab
|
* Berechnet den Output auf den Stack und ändert den LocalVarState und den StackState je nach Instruktion ab
|
||||||
*/
|
*/
|
||||||
|
Instruction ins = instructionHandle.getInstruction();
|
||||||
int opcode = ins.getOpcode();
|
int opcode = ins.getOpcode();
|
||||||
StackItem t1,t2,t3,t4;
|
StackItem t1,t2,t3,t4;
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
@ -618,6 +612,7 @@ public class CodeHelper {
|
|||||||
case Const.INVOKESPECIAL:
|
case Const.INVOKESPECIAL:
|
||||||
case Const.INVOKESTATIC:
|
case Const.INVOKESTATIC:
|
||||||
case Const.INVOKEINTERFACE:
|
case Const.INVOKEINTERFACE:
|
||||||
|
case Const.INVOKEDYNAMIC:
|
||||||
InvokeInstruction invokeIns = (InvokeInstruction) ins;
|
InvokeInstruction invokeIns = (InvokeInstruction) ins;
|
||||||
ret.pop(invokeIns.consumeStack(cp));
|
ret.pop(invokeIns.consumeStack(cp));
|
||||||
/*
|
/*
|
||||||
@ -648,14 +643,12 @@ public class CodeHelper {
|
|||||||
ret.push(new StackItemType((ReferenceType) retType));
|
ret.push(new StackItemType((ReferenceType) retType));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/*
|
|
||||||
case Const.INVOKEDYNAMIC:
|
|
||||||
ret.pop(item.strVal2);
|
|
||||||
ret.push(cw, item.strVal2);
|
|
||||||
break;
|
|
||||||
case Const.NEW:
|
case Const.NEW:
|
||||||
ret.push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
NEW newIns = (NEW) ins;
|
||||||
|
ret.push(new StackItemUninitialized(newIns, instructionHandle));
|
||||||
|
//ret.push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
case Const.NEWARRAY:
|
case Const.NEWARRAY:
|
||||||
ret.pop();
|
ret.pop();
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
@ -712,20 +705,6 @@ public class CodeHelper {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simulates the action of the given instruction on the output stack frame.
|
|
||||||
*
|
|
||||||
* @param opcode
|
|
||||||
* the opcode of the instruction.
|
|
||||||
* @param arg
|
|
||||||
* the operand of the instruction, if any.
|
|
||||||
* @param item
|
|
||||||
* the operand of the instructions, if any.
|
|
||||||
*/
|
|
||||||
void execute(Instruction ins) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
class IfElseStatement{
|
class IfElseIfStatement{
|
||||||
method(flag){
|
method(flag){
|
||||||
if(flag){
|
if(flag){
|
||||||
|
return 0;
|
||||||
}else if(flag){
|
}else if(flag){
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -9,6 +9,6 @@ public class IfElseIfStatementTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputFile);
|
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
test/bytecode/stackmaptable/IfStatement.jav
Normal file
10
test/bytecode/stackmaptable/IfStatement.jav
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class IfStatement{
|
||||||
|
Integer methode(Boolean b){
|
||||||
|
if(b){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
test/bytecode/stackmaptable/IfStatementTest.java
Normal file
16
test/bytecode/stackmaptable/IfStatementTest.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package bytecode.stackmaptable;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import bytecode.SingleClassTester;
|
||||||
|
|
||||||
|
public class IfStatementTest {
|
||||||
|
public final static String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/stackmaptable/";
|
||||||
|
public final static String testFile = "IfStatement.jav";
|
||||||
|
public final static String outputFile = "IfStatement.class";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory);
|
||||||
|
}
|
||||||
|
}
|
18
test/bytecode/types/OverloadingReplace.jav
Normal file
18
test/bytecode/types/OverloadingReplace.jav
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
class OverloadingReplace{
|
||||||
|
|
||||||
|
Vector<String> test;
|
||||||
|
|
||||||
|
void method(){
|
||||||
|
method(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
void method(Vector<String> v) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void method(Vector<Integer> v) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user