VM Architecture

Deep dive into the Kode bytecode virtual machine.

Overview

The Kode VM is a stack-based bytecode interpreter with support for closures, first-class functions, and dynamic typing.

Stack-Based

Push-pop operations for efficient execution

Bytecode

Compiled to compact instruction format

Closures

Full support for lexical scoping

VM Structure

┌─────────────────────────────────┐
│        Kode VM (v0.3.3)         │
├─────────────────────────────────┤
│  Instruction Pointer (IP)       │
│  Stack Pointer (SP)              │
│  Frame Pointer (FP)              │
├─────────────────────────────────┤
│         Value Stack             │
│  ┌───────────────────────┐      │
│  │  Value                │      │
│  │  Value                │      │
│  │  ...                  │      │
│  └───────────────────────┘      │
├─────────────────────────────────┤
│        Call Frames              │
│  ┌───────────────────────┐      │
│  │  Return Address       │      │
│  │  Local Variables      │      │
│  │  Closure Env          │      │
│  └───────────────────────┘      │
├─────────────────────────────────┤
│         Heap                    │
│  - Objects                      │
│  - Strings                      │
│  - Arrays                       │
│  - Closures                     │
└─────────────────────────────────┘

Instruction Set

The VM supports 40+ bytecode instructions organized into categories:

Stack Operations

LOAD_CONST
Push constant
LOAD_VAR
Load variable
STORE_VAR
Store variable
POP
Pop stack top

Arithmetic

ADD
Addition
SUB
Subtraction
MUL
Multiplication
DIV
Division

Comparison

EQ
Equal
NEQ
Not equal
LT / GT
Less/Greater than
LTE / GTE
Less/Greater equal

Control Flow

JUMP
Unconditional jump
JUMP_IF_FALSE
Conditional jump
CALL
Function call
RETURN
Return from function

Execution Model

kode
fn add(a: int, b: int) -> int {
    return a + b
}

let result = add(10, 20)
print(result)

Compiles to bytecode:

0000  LOAD_CONST   0        // Load function 'add'
0002  STORE_VAR    add
0004  LOAD_VAR     add       // Prepare call
0006  LOAD_CONST   1         // Push arg: 10
0008  LOAD_CONST   2         // Push arg: 20
0010  CALL         2         // Call with 2 args
0012  STORE_VAR    result
0014  LOAD_VAR     print     // Built-in print
0016  LOAD_VAR     result
0018  CALL         1
0020  HALT

Memory Management

Stack Allocation

Primitive values (int, float, bool) are allocated on the value stack for fast access.

Heap Allocation

Complex types (strings, arrays, objects, closures) are heap-allocated with reference counting.

Garbage Collection

Currently uses reference counting. Mark-and-sweep GC planned for v0.4.0.

Closure Implementation

Closures capture their environment for lexical scoping:

kode
fn makeCounter() -> fn {
    let count = 0
    return fn() {
        count = count + 1
        return count
    }
}

let counter = makeCounter()
counter()  // 1
counter()  // 2

The VM creates a ClosureEnv that holds captured variables, allowing the inner function to access and mutate count across invocations.

Performance Characteristics

Fast Operations

  • • Stack operations: O(1)
  • • Local variable access: O(1)
  • • Function calls: O(1)
  • • Arithmetic operations: O(1)

Slower Operations

  • • Array operations: O(n)
  • • String concatenation: O(n)
  • • Object property lookup: O(1) hash
  • • Garbage collection: O(n)