|
| 1 | +# ProXPL V2 Architecture: High-Performance Runtime |
| 2 | + |
| 3 | +## 1. Executive Summary |
| 4 | +This document outlines the architectural transformation of ProXPL from a tree-walking interpreter to a high-performance JIT-compiled runtime. |
| 5 | +**Goal:** Achieve performance parity with LuaJIT/V8 and >3x speedup over CPython 3.11. |
| 6 | + |
| 7 | +## 2. Core Components |
| 8 | + |
| 9 | +### 2.1 Compiler (Frontend) |
| 10 | +Separated from the runtime, responsible for: |
| 11 | +- **Lexing/Parsing**: Producing an AST. |
| 12 | +- **Bytecode Generation**: Traversing the AST and emitting Register Machine IR. |
| 13 | +- **Optimization**: Constant folding, dead code elimination. |
| 14 | + |
| 15 | +### 2.2 Register-Based Virtual Machine (Runtime) |
| 16 | +A register VM reduces instruction dispatch overhead compared to stack-based VMs. |
| 17 | + |
| 18 | +**Instruction Set Architecture (ISA)** |
| 19 | +Fixed-width 32-bit instructions for cache locality. |
| 20 | +Format: `[ OpCode (8) | A (8) | B (8) | C (8) ]` |
| 21 | + |
| 22 | +| Field | Bits | Purpose | |
| 23 | +|-------|------|---------| |
| 24 | +| OpCode| 0-7 | Operation identifier | |
| 25 | +| A | 8-15 | Destination Register / Operand | |
| 26 | +| B | 16-23| Source Register 1 | |
| 27 | +| C | 24-31| Source Register 2 / Immediate | |
| 28 | + |
| 29 | +**Core Instructions:** |
| 30 | +- `LOAD_CONST R(A), K(Bx)`: Load constant from pool at index Bx into R(A). |
| 31 | +- `MOV R(A), R(B)`: Move value from R(B) to R(A). |
| 32 | +- `ADD R(A), R(B), R(C)`: R(A) = R(B) + R(C) (Specialized for Int/Float). |
| 33 | +- `CALL R(A), R(B), C`: Call function at R(A) with args starting at R(B), count C. |
| 34 | +- `RETURN R(A)`: Return value in R(A). |
| 35 | +- `JMP_IF R(A), Offset(sBx)`: Conditional Jump. |
| 36 | + |
| 37 | +### 2.3 Memory Model (NaN-Boxing) |
| 38 | +All values are 64-bit doubles. |
| 39 | +- **Doubles**: Standard IEEE 754 doubles. |
| 40 | +- **Pointers/Tags**: Stored in the NaN space (top 16 bits). |
| 41 | + - `0xFFF8` prefix indicates NaN. |
| 42 | + - Low 48 bits are pointers or immediate values (Bool, Null, Int32). |
| 43 | + |
| 44 | +**Layout:** |
| 45 | +``` |
| 46 | +[ 111111111111 0000 | ... payload ... ] -> Double NaN |
| 47 | +[ 111111111111 0001 | ... address ... ] -> Object Pointer |
| 48 | +[ 111111111111 0010 | ... integer ... ] -> 32-bit Integer |
| 49 | +[ 111111111111 0011 | 0/1 ] -> Boolean |
| 50 | +``` |
| 51 | + |
| 52 | +### 2.4 Garbage Collection |
| 53 | +- **Generational GC**: |
| 54 | + - **Nursery**: Bump-pointer allocation (extremely fast). Logic: `ptr = top; top += size;` |
| 55 | + - **Old Gen**: Mark-and-Sweep. |
| 56 | + - **Write Barriers**: Required when Old Gen object points to Young Gen. |
| 57 | + |
| 58 | +### 2.5 JIT Compilation Strategy (Baseline) |
| 59 | +- **Template JIT**: |
| 60 | + - Pre-compile assembly snippets for each bytecode op. |
| 61 | + - At JIT time ($$ > 100 runs $$), `memcpy` snippets into a specialized buffer. |
| 62 | + - Patch jumps and immediate values. |
| 63 | +- **Deoptimization**: Support bailing out to interpreter if assumptions fail (e.g., type check failure in optimized code - primarily for later tracing JIT, but relevant for simple type guards). |
| 64 | + |
| 65 | +## 3. Project Structure Refactor |
| 66 | +``` |
| 67 | +src/ |
| 68 | +├── compiler/ # Frontend (Parser, AST, CodeGen) |
| 69 | +│ ├── lexer/ |
| 70 | +│ ├── parser/ |
| 71 | +│ └── codegen/ |
| 72 | +├── vm/ # Runtime (VM, GC, Loader) |
| 73 | +│ ├── core/ # Loop, Dispatch |
| 74 | +│ ├── gc/ # Allocator, Collector |
| 75 | +│ └── jit/ # Baseline JIT |
| 76 | +├── stdlib/ # Native implementations |
| 77 | +└── include/ # Public headers |
| 78 | +``` |
0 commit comments