Skip to content
Jan Noha edited this page Nov 23, 2015 · 6 revisions

Stack layout

  • The stack is dynamic and it grows upwards.
  • Each stack element is a pointer (4 or 8 bytes wide).
  • Alignment is therefore always the same and we use indices for addressing.
  • Each method has its stack frame.
  • We use these pointers to work with the stack:
    1. AP - points to the first argument given by the caller
    2. FP - points to the beginning of method's stack frame
    3. SP - points to the stack top (after the last element pushed or 0 when the stack is empty)

Layout of instance method stack-frame

     -----------------------
AP+0 | arg 0               |   <-- AP
     | arg 1               |
     | ...                 |
     | arg n-1             |
     -----------------------
AP+n | instance ptr (this) |
     -----------------------
     | return address      |
     -----------------------
     | caller AP           |
     | caller FP           |
     -----------------------
FP+0 | exception info ptr  |   <-- FP
FP+1 | local var 0         |
     | local var 1         |
     | ...                 |
FP+n | local var n-1       |
     -----------------------
     |                     |   <-- SP
     v                     v

Layout of class (static) method stack-frame

     -----------------------
AP+0 | arg 0               |   <-- AP
     | arg 1               |
     | ...                 |
     | arg n-1             |
     -----------------------
AP+n | class ptr           |
     -----------------------
     | return address      |
     -----------------------
     | caller AP           |
     | caller FP           |
     -----------------------
FP+0 | exception info ptr  |   <-- FP
FP+1 | local var 0         |
     | local var 1         |
     | ...                 |
FP+n | local var n-1       |
     -----------------------
     |                     |   <-- SP
     v                     v

Stack operations

CALLE

  1. PUSH the return address (instruction after the call)
  2. PUSH AP
  3. AP = SP - arg_cnt - 3
  4. PUSH FP
  5. FP = SP
  6. SP = SP + locals_cnt + 1 (reserve space for ex. info ptr and locals)
  7. JMP to method entry point

In case of non-external call the VM pushes the value of stack[AP+n] onto the stack before making the call.

In case of external call the class/instance pointer is already pushed by the preceding operation.

RET

  1. POP retVal
  2. SP = AP
  3. retAddr = stack[FP-3]
  4. AP = stack[FP-2]
  5. FP = stack[FP-1]
  6. PUSH retVal
  7. JMP to retAddr

Clone this wiki locally