Section notes: Week 12

CS 164, Fall 2005

General

Assembly exercises

Code generation example

See the SCAM compiler example (a separate handout).

Vtables in the MJ compiler

Our virtual machine has indirect call and indirect jump routines, which take an address from the stack. We can use these routines to bounce a method call to the appropriate place. I represent the vtable as a list of jump statements; to dispatch a method, I get the address of the start of this table of jumps, increment the address by some offset to pick the appropriate method, and then perform a calli (indirect call) instruction to go to the method.

As an example, here is a simple MiniJava program and the compiled result. This code is compiled with run-time checks off.


class Week9 {
    public static void main(String[] a) {
         System.out.println(new Counter().Init(1).Next());
    }
}

class Counter {
    int count;
    public Counter Init(int c) { count = c; return this; }
    public int     Next()      { count = count + 1; return count; }
}

    ;; Compiled form of week9.java
    PUSHI 0                ; Reserve space for Next() return
    PUSHI 0 
    PUSHI 0                ; Reserve space for Init() return
    PUSHI 0 
    PUSHI 2                ; Allocate space for a new object
    ALLOC 
    DUP 0                  ; Set the obj[0] to mjc-Counter+
    PUSHI 0 
    PUSHA mjc-Counter+ 
    SMEM 
    PUSHI 1                ; Push the function argument (1)
    DUP 1                  ; Get the vtable from the object
    PUSHI 0 
    MEM 
    ADDI 0                 ; Look up Init(int) in the vtable, call it
    CALLI 2 
    DUP 0                  ; Get the vtable from the returned object
    PUSHI 0
    MEM 
    ADDI 1                 ; Look up Next() in the vtable, call it
    CALLI 1 
    PRINT                  ; Print the result
    EXIT 0 
mjc-Counter+:              ; ---- Vtable ----
    JUMP mjc-Counter-Init 
    JUMP mjc-Counter-Next 
mjc-Counter-Init:          ; ---- int Counter.Init(int) ----
    FRAME 2                ; Make stack frame large enough for args + locals
    LVAR 1                 ; Get argument 1 (i)
    LVAR 0                 ; Get argument 0 (this)
    PUSHI 1                ; this.i = 1
    DUP 2 
    SMEM 
    POP
    LVAR 0                 ; return this
    RETURN 
mjc-Counter-Next:          ; ---- int Counter.Next() ----
    FRAME 1                ; Make stack frame large enough for args + locals
    LVAR 0                 ; Get argument 0 (this)
    PUSHI 1                ; Compute this.i + 1
    MEM 
    PUSHI 1
    SWAP 
    + 
    LVAR 0                 ; Assign result to this.i
    PUSHI 1 
    DUP 2 
    SMEM 
    POP 
    LVAR 0                 ; Return this.i
    PUSHI 1 
    MEM 
    RETURN