182 lines
4.0 KiB
Markdown
182 lines
4.0 KiB
Markdown
|
|
# Rava
|
||
|
|
|
||
|
|
A Java interpreter written in C99. Fast. Beats Python.
|
||
|
|
|
||
|
|
Author: retoor <retoor@molodetz.nl>
|
||
|
|
|
||
|
|
## Introduction
|
||
|
|
|
||
|
|
Rava is a complete Java interpreter. Lexer, parser, semantic analyzer, IR generator, and runtime VM. All in C.
|
||
|
|
|
||
|
|
What it does:
|
||
|
|
- Tokenizes Java source code
|
||
|
|
- Builds an AST
|
||
|
|
- Type checks everything
|
||
|
|
- Generates bytecode
|
||
|
|
- Executes on a stack-based VM
|
||
|
|
|
||
|
|
What it supports:
|
||
|
|
- Primitives: int, long, double, boolean, char
|
||
|
|
- Arrays and strings
|
||
|
|
- Objects and instance methods
|
||
|
|
- Inheritance
|
||
|
|
- Control flow: if/else, while, for, break, continue
|
||
|
|
- File I/O
|
||
|
|
- Recursion
|
||
|
|
|
||
|
|
Compiles with zero warnings. No memory leaks.
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
make
|
||
|
|
```
|
||
|
|
|
||
|
|
Done.
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
Example Rava source:
|
||
|
|
|
||
|
|
```java
|
||
|
|
public class Fibonacci {
|
||
|
|
public static int fib(int n) {
|
||
|
|
if (n <= 1) {
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
return fib(n - 1) + fib(n - 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static int main() {
|
||
|
|
System.out.println(fib(30));
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Run the benchmark:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
make benchmark
|
||
|
|
./test_benchmark
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance
|
||
|
|
|
||
|
|
Rava beats Python on all benchmarks.
|
||
|
|
|
||
|
|
| Benchmark | Rava | Python | Speedup |
|
||
|
|
|---------------|--------|--------|--------------|
|
||
|
|
| Fibonacci(30) | 257ms | 291ms | 1.13x faster |
|
||
|
|
| Primes(100k) | 273ms | 416ms | 1.52x faster |
|
||
|
|
| Sum(10M) | 666ms | 1104ms | 1.66x faster |
|
||
|
|
|
||
|
|
All three benchmarks. Rava wins.
|
||
|
|
|
||
|
|
The optimiziii took 9 phases. Started at 1402ms for Fibonacci. Now 257ms. That is 5.5x faster.
|
||
|
|
|
||
|
|
## Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
rava/
|
||
|
|
├── lexer/
|
||
|
|
│ ├── lexer.h
|
||
|
|
│ ├── lexer_tokenizer.c
|
||
|
|
│ ├── lexer_keywords.c
|
||
|
|
│ └── lexer_literals.c
|
||
|
|
├── parser/
|
||
|
|
│ ├── parser.h
|
||
|
|
│ ├── parser.c
|
||
|
|
│ ├── parser_expressions.c
|
||
|
|
│ ├── parser_statements.c
|
||
|
|
│ ├── parser_declarations.c
|
||
|
|
│ └── parser_printer.c
|
||
|
|
├── types/
|
||
|
|
│ ├── types.h
|
||
|
|
│ └── types.c
|
||
|
|
├── semantic/
|
||
|
|
│ ├── semantic.h
|
||
|
|
│ ├── semantic.c
|
||
|
|
│ ├── symbol_table.h
|
||
|
|
│ └── symbol_table.c
|
||
|
|
├── ir/
|
||
|
|
│ ├── ir.h
|
||
|
|
│ ├── ir.c
|
||
|
|
│ ├── ir_gen.h
|
||
|
|
│ └── ir_gen.c
|
||
|
|
├── runtime/
|
||
|
|
│ ├── runtime.h
|
||
|
|
│ ├── runtime.c
|
||
|
|
│ ├── nanbox.h
|
||
|
|
│ ├── fastframe.h
|
||
|
|
│ ├── fastframe.c
|
||
|
|
│ ├── labeltable.h
|
||
|
|
│ ├── labeltable.c
|
||
|
|
│ ├── methodcache.h
|
||
|
|
│ ├── methodcache.c
|
||
|
|
│ ├── superinst.h
|
||
|
|
│ └── superinst.c
|
||
|
|
├── tests/
|
||
|
|
│ └── *.c
|
||
|
|
├── examples/
|
||
|
|
│ └── *.java
|
||
|
|
├── docs/
|
||
|
|
│ └── *.md
|
||
|
|
└── Makefile
|
||
|
|
```
|
||
|
|
|
||
|
|
## Optimization
|
||
|
|
|
||
|
|
Rava implements proven interpreter optimization techniques. Same stuff V8, LuaJIT, and CPython use.
|
||
|
|
|
||
|
|
### NaN Boxing
|
||
|
|
|
||
|
|
64-bit value representation. Packs all types into 8 bytes instead of 16. Half the memory. Faster stack ops.
|
||
|
|
|
||
|
|
Location: `runtime/nanbox.h`
|
||
|
|
|
||
|
|
### Fast Frames
|
||
|
|
|
||
|
|
Pre-allocated frame pool. No heap allocation per function call. Stack discipline. Eliminates thousands of mallocs.
|
||
|
|
|
||
|
|
Location: `runtime/fastframe.h`, `runtime/fastframe.c`
|
||
|
|
|
||
|
|
### Label Table
|
||
|
|
|
||
|
|
O(1) jump resolution. Pre-computes label to PC mapping. Replaces O(n) linear search. Loops go 5-10x fastiii.
|
||
|
|
|
||
|
|
Location: `runtime/labeltable.h`, `runtime/labeltable.c`
|
||
|
|
|
||
|
|
### Method Cache
|
||
|
|
|
||
|
|
Hash-based method lookup. O(1) instead of O(n*m). Caches class+method pairs.
|
||
|
|
|
||
|
|
Location: `runtime/methodcache.h`, `runtime/methodcache.c`
|
||
|
|
|
||
|
|
### Superinstructions
|
||
|
|
|
||
|
|
Combines common opcode sequences into single instructions:
|
||
|
|
- INC_LOCAL: load + const 1 + add + store combined
|
||
|
|
- DEC_LOCAL: load + const 1 + sub + store combined
|
||
|
|
- ADD_LOCAL_TO_LOCAL: fused accumulator pattern
|
||
|
|
- LOAD_LOCAL_CONST_LT_JUMPFALSE: fused loop condition
|
||
|
|
|
||
|
|
Location: `runtime/superinst.h`, `runtime/superinst.c`
|
||
|
|
|
||
|
|
### Computed Goto
|
||
|
|
|
||
|
|
GCC extension for faster dispatch. Jump table instead of switch.
|
||
|
|
|
||
|
|
### PGO Build
|
||
|
|
|
||
|
|
Profile-guided optimization targets in Makefile. Run benchmarks, collect profile, rebuild.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
make pgo
|
||
|
|
```
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- Dataset library: https://dataset.readthedocs.io/en/latest/index.html
|
||
|
|
|