package haidnor.jvm.runtime; import haidnor.jvm.bcel.Const; import haidnor.jvm.bcel.classfile.Code; import haidnor.jvm.bcel.classfile.JavaClass; import haidnor.jvm.bcel.classfile.JavaMethod; import haidnor.jvm.rtda.Instance; import haidnor.jvm.util.CodeStream; import lombok.Getter; import java.util.Stack; /** * JVM 线程栈帧 */ public class Frame { /** * 每个栈帧中包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是为了支持当前方法实现动态链接 * 有了这个引用,执行引擎就可以找到指定的方法,加载字节码指令 */ @Getter public final JavaClass javaClass; /** * 当前栈帧所处于的 JVM 线程 */ @Getter private final JVMThread jvmThread; /** * 栈帧所属的方法 *

* <<深入理解JAVA虚拟机>>: * 每一个栈帧都包含一个指向运行时常量池中该栈帧所属的方法引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking) */ @Getter private final JavaMethod javaMethod; /** * 栈帧所属的方法代码对象 */ private final Code code; @Getter private final CodeStream codeStream; /** * 操作数栈 */ private final Stack operandStack = new Stack<>(); /** * 槽位 */ private final Slot[] slots; public Frame(JVMThread thread, JavaMethod javaMethod) { this.jvmThread = thread; this.javaClass = javaMethod.getJavaClass(); this.javaMethod = javaMethod; this.code = javaMethod.getCode(); this.codeStream = new CodeStream(javaMethod.getCode()); this.slots = new Slot[code.getMaxLocals()]; } public int getCodeLength() { return this.code.getCode().length; } public JavaMethod getMetaMethod() { return javaMethod; } /* 操作数栈操作 --------------------------------------------------------------------------------------------------- */ /** * 压入操作数栈 */ 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.getValueType()) { 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.getValueType()) { 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("无法识别的参数类型"); } } }