package com.github.HarryHook.coding2017.jvm.engine;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import com.github.HarryHook.coding2017.jvm.cmd.ByteCodeCommand;
import com.github.HarryHook.coding2017.jvm.method.Method;
public class StackFrame {
private List<JavaObject> localVariableTable = new ArrayList<JavaObject>();
private Stack<JavaObject> oprandStack = new Stack<JavaObject>();
int index = 0;
private Method m = null;
private StackFrame callerFrame = null;
public StackFrame getCallerFrame() {
return callerFrame;
}
public void setCallerFrame(StackFrame callerFrame) {
this.callerFrame = callerFrame;
}
public static StackFrame create(Method m) {
StackFrame frame = new StackFrame(m);
return frame;
}
private StackFrame(Method m) {
this.m = m;
}
public JavaObject getLocalVariableValue(int index) {
return this.localVariableTable.get(index);
}
public Stack<JavaObject> getOprandStack() {
return this.oprandStack;
}
public int getNextCommandIndex(int offset) {
ByteCodeCommand[] cmds = m.getCodeAttr().getCmds();
for (int i = 0; i < cmds.length; i++) {
if (cmds[i].getOffset() == offset) {
return i;
}
}
throw new RuntimeException("Can't find next command");
}
public ExecutionResult execute() {
ByteCodeCommand[] cmds = m.getCmds();
while (index < cmds.length) {
ExecutionResult result = new ExecutionResult();
// 缺省值是执行下一条命令
result.setNextAction(ExecutionResult.RUN_NEXT_CMD);
System.out.println(cmds[index].toString());
cmds[index].execute(this, result);
if (result.isRunNextCmd()) {
index++;
} else if (result.isExitCurrentFrame()) {
return result;
} else if (result.isPauseAndRunNewFrame()) {
index++;
return result;
} else if (result.isJump()) {
int offset = result.getNextCmdOffset();
this.index = getNextCommandIndex(offset);
} else {
index++;
}
}
// 当前StackFrmae的指令全部执行完毕,可以退出了
ExecutionResult result = new ExecutionResult();
result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME);
return result;
}
public void setLocalVariableTable(List<JavaObject> values) {
this.localVariableTable = values;
}
public void setLocalVariableValue(int index, JavaObject jo) {
// 问题: 为什么要这么做??
if (this.localVariableTable.size() - 1 < index) {
for (int i = this.localVariableTable.size(); i <= index; i++) {
this.localVariableTable.add(null);
}
}
this.localVariableTable.set(index, jo);
}
public Method getMethod() {
return m;
}
}