Skip to content

Commit

Permalink
broke apart the Context[] stack into a linked-list with invokingConte…
Browse files Browse the repository at this point in the history
…xt as parent pointer to caller. added call stack for trace.
  • Loading branch information
parrt committed Apr 15, 2015
1 parent e398984 commit 2c84176
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 31 deletions.
8 changes: 6 additions & 2 deletions src/vm/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

/** To call, push one of these and pop to return */
public class Context {
Context invokingContext; // parent in the stack or "caller"
FuncMetaData metadata; // info about function we're executing
int returnip;
int[] locals; // args + locals, indexed from 0

public Context(int returnip, int nlocals) {
public Context(Context invokingContext, int returnip, FuncMetaData metadata) {
this.invokingContext = invokingContext;
this.returnip = returnip;
locals = new int[nlocals];
this.metadata = metadata;
locals = new int[metadata.nargs+metadata.nlocals];
}
}
28 changes: 15 additions & 13 deletions src/vm/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ public class Test {
// PRINT "LOOPED "+N+" TIMES."
HALT // 24
};
static FuncMetaData[] loop_metadata = {
new FuncMetaData("main", 0, 0, 0)
};

static int FACTORIAL_INDEX = 0;
static int FACTORIAL_INDEX = 1;
static int FACTORIAL_ADDRESS = 0;
static int MAIN_ADDRESS = 21;
static int[] factorial = {
Expand Down Expand Up @@ -88,15 +91,15 @@ public class Test {
};
static FuncMetaData[] factorial_metadata = {
//.def factorial: ARGS=1, LOCALS=0 ADDRESS
new FuncMetaData("main", 0, 0, MAIN_ADDRESS),
new FuncMetaData("factorial", 1, 0, FACTORIAL_ADDRESS)
};


static int[] f = {
// ADDRESS
//.def main() { print f(10); }
ICONST, 10, // 0
CALL, 0, // 2
CALL, 1, // 2
PRINT, // 4
HALT, // 5
//.def f(x): ARGS=1, LOCALS=1
Expand All @@ -110,22 +113,21 @@ public class Test {
RET
};
static FuncMetaData[] f_metadata = {
//.def factorial: ARGS=1, LOCALS=0 ADDRESS
new FuncMetaData("main", 0, 0, 0),
new FuncMetaData("f", 1, 1, 6)
};


public static void main(String[] args) {
VM vm = new VM(factorial, MAIN_ADDRESS, 0, factorial_metadata);
vm.trace = true;
vm.exec();
VM vm = new VM(factorial, 0, factorial_metadata);
vm.trace = false;
vm.exec(factorial_metadata[0].address);

vm = new VM(f, 0, 2, f_metadata);
vm.trace = true;
vm.exec();
vm = new VM(f, 2, f_metadata);
vm.exec(f_metadata[0].address);
vm.dumpDataMemory();

vm = new VM(loop, 0, 2, null);
vm.trace = true;
vm.exec();
vm = new VM(loop, 2, loop_metadata);
vm.exec(loop_metadata[0].address);
}
}
40 changes: 24 additions & 16 deletions src/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,12 @@ public class VM {
// registers
int ip; // instruction pointer register
int sp = -1; // stack pointer register
int callsp = -1; // call stack pointer register

int startip = 0; // where execution begins

// memory
int[] code; // word-addressable code memory but still bytecodes.
int[] globals; // global variable space
int[] stack; // Operand stack, grows upwards
Context[] callstack;// call stack, grows upwards
Context ctx; // the active context

/** Metadata about the functions allows us to refer to functions by
* their index in this table. It makes code generation easier for
Expand All @@ -54,17 +51,16 @@ public class VM {

public boolean trace = false;

public VM(int[] code, int startip, int nglobals, FuncMetaData[] metadata) {
public VM(int[] code, int nglobals, FuncMetaData[] metadata) {
this.code = code;
this.startip = startip;
globals = new int[nglobals];
stack = new int[DEFAULT_STACK_SIZE];
callstack = new Context[DEFAULT_CALL_STACK_SIZE];
this.metadata = metadata;
}

public void exec() {
public void exec(int startip) {
ip = startip;
ctx = new Context(null,0,metadata[0]); // simulate a call to main()
cpu();
}

Expand Down Expand Up @@ -124,7 +120,7 @@ protected void cpu() {
break;
case STORE :
regnum = code[ip++];
callstack[callsp].locals[regnum] = stack[sp--];
ctx.locals[regnum] = stack[sp--];
break;
case GSTORE :
addr = code[ip++];
Expand All @@ -140,22 +136,22 @@ protected void cpu() {
// expects all args on stack
int findex = code[ip++]; // index of target function
int nargs = metadata[findex].nargs; // how many args got pushed
int nlocals = metadata[findex].nlocals;
callstack[++callsp] = new Context(ip,nargs+nlocals);
ctx = new Context(ctx,ip,metadata[findex]);
// copy args into new context
for (int i=0; i<nargs; i++) {
callstack[callsp].locals[i] = stack[sp-i];
ctx.locals[i] = stack[sp-i];
}
sp -= nargs;
ip = metadata[findex].address; // jump to function
break;
case RET:
ip = callstack[callsp--].returnip;
ip = ctx.returnip;
ctx = ctx.invokingContext; // pop
break;
default :
throw new Error("invalid opcode: "+opcode+" at ip="+(ip-1));
}
if ( trace ) System.err.println(stackString());
if ( trace ) System.err.printf("%-22s %s\n", stackString(), callStackString());
opcode = code[ip];
}
if ( trace ) System.err.printf("%-35s", disInstr());
Expand All @@ -166,10 +162,10 @@ protected void cpu() {
private void load() {
int regnum;
regnum = code[ip++];
stack[++sp] = callstack[callsp].locals[regnum];
stack[++sp] = ctx.locals[regnum];
}

protected String stackString() {
protected String stackString() {
StringBuilder buf = new StringBuilder();
buf.append("stack=[");
for (int i = 0; i <= sp; i++) {
Expand All @@ -181,6 +177,18 @@ protected String stackString() {
return buf.toString();
}

protected String callStackString() {
List<String> stack = new ArrayList<String>();
Context c = ctx;
while ( c!=null ) {
if ( c.metadata!=null ) {
stack.add(0, c.metadata.name);
}
c = c.invokingContext;
}
return "calls="+stack.toString();
}

protected String disInstr() {
int opcode = code[ip];
String opName = Bytecode.instructions[opcode].name;
Expand Down

0 comments on commit 2c84176

Please sign in to comment.