mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-03-14 06:03:50 +08:00
refactor bcel lib
This commit is contained in:
@@ -1,278 +0,0 @@
|
||||
package haidnor.jvm.runtime;
|
||||
|
||||
import haidnor.jvm.rtda.Instance;
|
||||
import haidnor.jvm.rtda.Klass;
|
||||
import haidnor.jvm.rtda.KlassMethod;
|
||||
import haidnor.jvm.util.CodeStream;
|
||||
import haidnor.jvm.util.ConstantPoolUtil;
|
||||
import org.apache.bcel.Const;
|
||||
import org.apache.bcel.classfile.Code;
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* JVM 线程栈帧
|
||||
*
|
||||
* @author wang xiang
|
||||
*/
|
||||
public class Frame {
|
||||
/**
|
||||
* 当前栈帧所处于的 JVM 线程
|
||||
*/
|
||||
private final JVMThread jvmThread;
|
||||
|
||||
/**
|
||||
* 栈帧所属的方法
|
||||
* <p>
|
||||
* <<深入理解JAVA虚拟机>>:
|
||||
* 每一个栈帧都包含一个指向运行时常量池中该栈帧所属的方法引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking)
|
||||
*/
|
||||
private final org.apache.bcel.classfile.Method method;
|
||||
|
||||
private final KlassMethod klassMethod;
|
||||
|
||||
/**
|
||||
* 每个栈帧中包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是为了支持当前方法实现动态链接
|
||||
* 有了这个引用,执行引擎就可以找到指定的方法,加载字节码指令
|
||||
*/
|
||||
public final Klass klass;
|
||||
|
||||
/**
|
||||
* 栈帧所属的方法代码对象
|
||||
*/
|
||||
private final Code code;
|
||||
|
||||
private final CodeStream codeStream;
|
||||
|
||||
private final ConstantPool constantPool;
|
||||
|
||||
private final ConstantPoolUtil constantPoolUtil;
|
||||
|
||||
/**
|
||||
* 操作数栈
|
||||
*/
|
||||
private final Stack<StackValue> operandStack = new Stack<>();
|
||||
|
||||
/**
|
||||
* 槽位
|
||||
*/
|
||||
private final Slot[] slots;
|
||||
|
||||
public Frame(JVMThread jvmThread, KlassMethod klassMethod) {
|
||||
this.jvmThread = jvmThread;
|
||||
this.klass = klassMethod.aKlass;
|
||||
this.klassMethod = klassMethod;
|
||||
this.method = klassMethod.javaMethod;
|
||||
this.code = method.getCode();
|
||||
this.constantPool = method.getConstantPool();
|
||||
this.constantPoolUtil = new ConstantPoolUtil(constantPool);
|
||||
this.codeStream = new CodeStream(method.getCode());
|
||||
this.slots = new Slot[code.getMaxLocals()];
|
||||
}
|
||||
|
||||
public JVMThread getJvmThread() {
|
||||
return jvmThread;
|
||||
}
|
||||
|
||||
public int getCodeLength() {
|
||||
return this.code.getCode().length;
|
||||
}
|
||||
|
||||
public CodeStream getCodeStream() {
|
||||
return codeStream;
|
||||
}
|
||||
|
||||
public org.apache.bcel.classfile.Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public ConstantPoolUtil getConstantPoolUtil() {
|
||||
return constantPoolUtil;
|
||||
}
|
||||
|
||||
public KlassMethod getMetaMethod() {
|
||||
return klassMethod;
|
||||
}
|
||||
|
||||
public Klass getMetaClass() {
|
||||
return klass;
|
||||
}
|
||||
|
||||
/* 操作数栈操作 --------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* 压入操作数栈
|
||||
*/
|
||||
public void push(StackValue stackValue) {
|
||||
this.operandStack.push(stackValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出操作数栈顶元素
|
||||
*/
|
||||
public StackValue pop() {
|
||||
return this.operandStack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出操作数栈顶元素
|
||||
*/
|
||||
public StackValue peek() {
|
||||
return this.operandStack.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从操作数栈中弹出指定数量的元素的值
|
||||
*/
|
||||
public Object[] popStacksValue(int num) {
|
||||
Object[] objArr = new Object[num];
|
||||
for (int i = num - 1; i >= 0; i--) {
|
||||
StackValue stackValue = operandStack.pop();
|
||||
switch (stackValue.getType()) {
|
||||
case Const.T_CHAR, Const.T_INT, Const.T_OBJECT, Const.T_LONG, Const.T_DOUBLE, Const.T_FLOAT:
|
||||
break;
|
||||
case Const.T_ARRAY:
|
||||
throw new Error("数组类型,未作处理");
|
||||
default:
|
||||
throw new Error("无法识别的参数类型");
|
||||
}
|
||||
objArr[i] = stackValue.getValue();
|
||||
}
|
||||
return objArr;
|
||||
}
|
||||
|
||||
|
||||
public int popInt() {
|
||||
StackValue stackValue = pop();
|
||||
return (int) stackValue.getValue();
|
||||
}
|
||||
|
||||
public void pushInt(int value) {
|
||||
push(new StackValue(Const.T_INT, value));
|
||||
}
|
||||
|
||||
public long popLong() {
|
||||
StackValue stackValue = pop();
|
||||
return (long) stackValue.getValue();
|
||||
}
|
||||
|
||||
public void pushLong(long value) {
|
||||
push(new StackValue(Const.T_LONG, value));
|
||||
}
|
||||
|
||||
public float popFloat() {
|
||||
StackValue stackValue = pop();
|
||||
return (float) stackValue.getValue();
|
||||
}
|
||||
|
||||
public void pushFloat(float value) {
|
||||
push(new StackValue(Const.T_FLOAT, value));
|
||||
}
|
||||
|
||||
public double popDouble() {
|
||||
StackValue stackValue = pop();
|
||||
return (double) stackValue.getValue();
|
||||
}
|
||||
|
||||
public void pushDouble(double value) {
|
||||
push(new StackValue(Const.T_DOUBLE, value));
|
||||
}
|
||||
|
||||
public Instance popRef() {
|
||||
StackValue stackValue = pop();
|
||||
return (Instance) stackValue.getValue();
|
||||
}
|
||||
|
||||
public void pushRef(Object value) {
|
||||
push(new StackValue(Const.T_OBJECT, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作数栈中元素的数量
|
||||
*/
|
||||
public int operandStackSize() {
|
||||
return this.operandStack.size();
|
||||
}
|
||||
|
||||
/* 局部变量表操作 --------------------------------------------------------------------------------------------------- */
|
||||
|
||||
public void slotSetInt(int index, int val) {
|
||||
slots[index] = new Slot(val);
|
||||
}
|
||||
|
||||
public int slotGetInt(int index) {
|
||||
return slots[index].num;
|
||||
}
|
||||
|
||||
public void slotSetFloat(int index, float val) {
|
||||
int tmp = Float.floatToIntBits(val);
|
||||
slots[index] = new Slot(tmp);
|
||||
}
|
||||
|
||||
public float slotGetFloat(int index) {
|
||||
int num = slots[index].num;
|
||||
return Float.intBitsToFloat(num);
|
||||
}
|
||||
|
||||
public long slotGetLong(int index) {
|
||||
int high = slots[index].num;
|
||||
int low = slots[index + 1].num;
|
||||
|
||||
long l1 = (high & 0x000000ffffffffL) << 32;
|
||||
long l2 = low & 0x00000000ffffffffL;
|
||||
return l1 | l2;
|
||||
}
|
||||
|
||||
public void slotSetLong(int index, long val) {
|
||||
// high 32
|
||||
int high = (int) (val >> 32);
|
||||
// low 32
|
||||
int low = (int) (val & 0x000000ffffffffL);
|
||||
|
||||
slots[index] = new Slot(high);
|
||||
slots[index + 1] = new Slot(low);
|
||||
}
|
||||
|
||||
public void slotSetDouble(int index, double val) {
|
||||
long tmp = Double.doubleToLongBits(val);
|
||||
// high 32
|
||||
int high = (int) (tmp >> 32);
|
||||
// low 32
|
||||
int low = (int) (tmp & 0x000000ffffffffL);
|
||||
|
||||
slots[index] = new Slot(high);
|
||||
slots[index + 1] = new Slot(low);
|
||||
}
|
||||
|
||||
public double slotGetDouble(int index) {
|
||||
long tmp = this.slotGetLong(index);
|
||||
return Double.longBitsToDouble(tmp);
|
||||
}
|
||||
|
||||
public void slotSetRef(int index, Object ref) {
|
||||
slots[index] = new Slot(ref);
|
||||
}
|
||||
|
||||
public Object slotGetRef(int index) {
|
||||
return slots[index].ref;
|
||||
}
|
||||
|
||||
public void slotSet(int index, StackValue stackValue) {
|
||||
switch (stackValue.getType()) {
|
||||
case Const.T_CHAR -> throw new Error("T_CHAR,未作处理");
|
||||
case Const.T_INT -> slotSetInt(index, (int) stackValue.getValue());
|
||||
case Const.T_OBJECT -> slotSetRef(index, stackValue.getValue());
|
||||
case Const.T_LONG -> slotSetLong(index, (long) stackValue.getValue());
|
||||
case Const.T_DOUBLE -> slotSetDouble(index, (double) stackValue.getValue());
|
||||
case Const.T_FLOAT -> slotSetFloat(index, (float) stackValue.getValue());
|
||||
case Const.T_ARRAY -> throw new Error("T_ARRAY,未作处理");
|
||||
default -> throw new Error("无法识别的参数类型");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user