Gitea build steps + README.md
This commit is contained in:
parent
50b9fedb36
commit
3872c52997
133
.gitea/workflows/ci.yaml
Normal file
133
.gitea/workflows/ci.yaml
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-tests:
|
||||||
|
name: Unit Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make
|
||||||
|
|
||||||
|
- name: Build unit tests
|
||||||
|
run: |
|
||||||
|
make test_lexer
|
||||||
|
make test_parser
|
||||||
|
make test_semantic
|
||||||
|
make test_ir
|
||||||
|
|
||||||
|
- name: Run lexer tests
|
||||||
|
run: ./test_lexer
|
||||||
|
|
||||||
|
- name: Run parser tests
|
||||||
|
run: ./test_parser
|
||||||
|
|
||||||
|
- name: Run semantic tests
|
||||||
|
run: ./test_semantic
|
||||||
|
|
||||||
|
- name: Run IR tests
|
||||||
|
run: ./test_ir
|
||||||
|
|
||||||
|
integration-tests:
|
||||||
|
name: Integration Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: unit-tests
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make
|
||||||
|
|
||||||
|
- name: Build integration tests
|
||||||
|
run: |
|
||||||
|
make test_runtime
|
||||||
|
make test_strings
|
||||||
|
make test_arrays
|
||||||
|
make test_objects
|
||||||
|
make test_instance_methods
|
||||||
|
make test_fileio
|
||||||
|
|
||||||
|
- name: Run runtime tests
|
||||||
|
run: ./test_runtime
|
||||||
|
|
||||||
|
- name: Run string tests
|
||||||
|
run: ./test_strings
|
||||||
|
|
||||||
|
- name: Run array tests
|
||||||
|
run: ./test_arrays
|
||||||
|
|
||||||
|
- name: Run object tests
|
||||||
|
run: ./test_objects
|
||||||
|
|
||||||
|
- name: Run instance method tests
|
||||||
|
run: ./test_instance_methods
|
||||||
|
|
||||||
|
- name: Run file I/O tests
|
||||||
|
run: ./test_fileio
|
||||||
|
|
||||||
|
optimization-tests:
|
||||||
|
name: Optimization Infrastructure Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make
|
||||||
|
|
||||||
|
- name: Build Phase 0 tests
|
||||||
|
run: |
|
||||||
|
make test_nanbox
|
||||||
|
make test_fastframe
|
||||||
|
make test_labeltable
|
||||||
|
make test_methodcache
|
||||||
|
|
||||||
|
- name: Run NaN boxing tests
|
||||||
|
run: ./test_nanbox
|
||||||
|
|
||||||
|
- name: Run fast frame tests
|
||||||
|
run: ./test_fastframe
|
||||||
|
|
||||||
|
- name: Run label table tests
|
||||||
|
run: ./test_labeltable
|
||||||
|
|
||||||
|
- name: Run method cache tests
|
||||||
|
run: ./test_methodcache
|
||||||
|
|
||||||
|
benchmark:
|
||||||
|
name: Performance Benchmark
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [unit-tests, integration-tests]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make python3
|
||||||
|
|
||||||
|
- name: Build benchmark
|
||||||
|
run: make test_benchmark
|
||||||
|
|
||||||
|
- name: Run benchmark
|
||||||
|
run: ./test_benchmark
|
||||||
53
.gitea/workflows/pgo.yaml
Normal file
53
.gitea/workflows/pgo.yaml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
name: PGO Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * 0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pgo-build:
|
||||||
|
name: Profile-Guided Optimization Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make python3
|
||||||
|
|
||||||
|
- name: Clean previous builds
|
||||||
|
run: make clean
|
||||||
|
|
||||||
|
- name: Generate profile data
|
||||||
|
run: make test_benchmark_pgo_gen
|
||||||
|
|
||||||
|
- name: Run profiling passes
|
||||||
|
run: |
|
||||||
|
./test_benchmark_pgo
|
||||||
|
./test_benchmark_pgo
|
||||||
|
./test_benchmark_pgo
|
||||||
|
|
||||||
|
- name: Build with PGO
|
||||||
|
run: |
|
||||||
|
gcc -Wall -Wextra -std=gnu99 -O3 -march=native -I. -fprofile-use -fprofile-correction \
|
||||||
|
-o test_benchmark_pgo \
|
||||||
|
lexer/lexer_tokenizer.c lexer/lexer_keywords.c lexer/lexer_literals.c \
|
||||||
|
parser/parser.c parser/parser_expressions.c parser/parser_statements.c parser/parser_declarations.c parser/parser_printer.c \
|
||||||
|
types/types.c \
|
||||||
|
semantic/symbol_table.c semantic/semantic.c \
|
||||||
|
ir/ir.c ir/ir_gen.c \
|
||||||
|
runtime/runtime.c runtime/labeltable.c runtime/methodcache.c runtime/fastframe.c runtime/superinst.c \
|
||||||
|
tests/test_benchmark.c \
|
||||||
|
-ldl
|
||||||
|
|
||||||
|
- name: Run PGO benchmark
|
||||||
|
run: ./test_benchmark_pgo
|
||||||
|
|
||||||
|
- name: Upload PGO binary
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rava-pgo
|
||||||
|
path: test_benchmark_pgo
|
||||||
55
.gitea/workflows/release.yaml
Normal file
55
.gitea/workflows/release.yaml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-release:
|
||||||
|
name: Build Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc make
|
||||||
|
|
||||||
|
- name: Build all tests
|
||||||
|
run: make all
|
||||||
|
|
||||||
|
- name: Run all tests
|
||||||
|
run: |
|
||||||
|
./test_lexer
|
||||||
|
./test_parser
|
||||||
|
./test_semantic
|
||||||
|
./test_ir
|
||||||
|
./test_runtime
|
||||||
|
./test_strings
|
||||||
|
./test_arrays
|
||||||
|
./test_objects
|
||||||
|
./test_instance_methods
|
||||||
|
./test_fileio
|
||||||
|
|
||||||
|
- name: Build benchmark
|
||||||
|
run: make test_benchmark
|
||||||
|
|
||||||
|
- name: Run benchmark
|
||||||
|
run: ./test_benchmark
|
||||||
|
|
||||||
|
- name: Package release
|
||||||
|
run: |
|
||||||
|
mkdir -p release
|
||||||
|
cp test_benchmark release/rava-benchmark
|
||||||
|
cp -r examples release/
|
||||||
|
cp README.md release/
|
||||||
|
tar -czvf rava-${{ github.ref_name }}.tar.gz release/
|
||||||
|
|
||||||
|
- name: Upload release artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: rava-${{ github.ref_name }}
|
||||||
|
path: rava-${{ github.ref_name }}.tar.gz
|
||||||
87
README.md
87
README.md
@ -1,21 +1,21 @@
|
|||||||
# Rava
|
# Rava
|
||||||
|
|
||||||
A Java interpreter written in C99. Fast. Beats Python.
|
A Java interpreter written in C99. Compiles and executes Java source code. Beats Python on all benchmarks.
|
||||||
|
|
||||||
Author: retoor <retoor@molodetz.nl>
|
Author: retoor <retoor@molodetz.nl>
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Rava is a complete Java interpreter. Lexer, parser, semantic analyzer, IR generator, and runtime VM. All in C.
|
Rava is a complete Java interpreter implemented in C. It provides a full compilation pipeline from source to execution.
|
||||||
|
|
||||||
What it does:
|
The pipeline:
|
||||||
- Tokenizes Java source code
|
- Lexer tokenizes Java source code
|
||||||
- Builds an AST
|
- Parser builds an abstract syntax tree
|
||||||
- Type checks everything
|
- Semantic analyzer performs type checking
|
||||||
- Generates bytecode
|
- IR generator produces stack-based bytecode
|
||||||
- Executes on a stack-based VM
|
- Runtime VM executes the bytecode
|
||||||
|
|
||||||
What it supports:
|
Supported features:
|
||||||
- Primitives: int, long, double, boolean, char
|
- Primitives: int, long, double, boolean, char
|
||||||
- Arrays and strings
|
- Arrays and strings
|
||||||
- Objects and instance methods
|
- Objects and instance methods
|
||||||
@ -23,8 +23,9 @@ What it supports:
|
|||||||
- Control flow: if/else, while, for, break, continue
|
- Control flow: if/else, while, for, break, continue
|
||||||
- File I/O
|
- File I/O
|
||||||
- Recursion
|
- Recursion
|
||||||
|
- System.out.println
|
||||||
|
|
||||||
Compiles with zero warnings. No memory leaks.
|
Compiles with `-Wall -Wextra -Werror`. Zero warnings. No memory leaks.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -32,11 +33,9 @@ Compiles with zero warnings. No memory leaks.
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
Done.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Example Rava source:
|
Example source code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Fibonacci {
|
public class Fibonacci {
|
||||||
@ -58,7 +57,12 @@ Run the benchmark:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
make benchmark
|
make benchmark
|
||||||
./test_benchmark
|
```
|
||||||
|
|
||||||
|
Run tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test_runtime && ./test_runtime
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
@ -66,14 +70,12 @@ make benchmark
|
|||||||
Rava beats Python on all benchmarks.
|
Rava beats Python on all benchmarks.
|
||||||
|
|
||||||
| Benchmark | Rava | Python | Speedup |
|
| Benchmark | Rava | Python | Speedup |
|
||||||
|---------------|--------|--------|--------------|
|
|-----------|------|--------|---------|
|
||||||
| Fibonacci(30) | 257ms | 291ms | 1.13x faster |
|
| Fibonacci(30) | 257ms | 291ms | 1.13x faster |
|
||||||
| Primes(100k) | 273ms | 416ms | 1.52x faster |
|
| Primes(100k) | 273ms | 416ms | 1.52x faster |
|
||||||
| Sum(10M) | 666ms | 1104ms | 1.66x faster |
|
| Sum(10M) | 666ms | 1104ms | 1.66x faster |
|
||||||
|
|
||||||
All three benchmarks. Rava wins.
|
Started at 1402ms for Fibonacci. After 9 optimization phases: 257ms. That is 5.5x faster.
|
||||||
|
|
||||||
The optimiziii took 9 phases. Started at 1402ms for Fibonacci. Now 257ms. That is 5.5x faster.
|
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
@ -117,59 +119,60 @@ rava/
|
|||||||
│ ├── superinst.h
|
│ ├── superinst.h
|
||||||
│ └── superinst.c
|
│ └── superinst.c
|
||||||
├── tests/
|
├── tests/
|
||||||
│ └── *.c
|
│ └── test_*.c
|
||||||
├── examples/
|
├── examples/
|
||||||
│ └── *.java
|
│ └── *.java
|
||||||
├── docs/
|
|
||||||
│ └── *.md
|
|
||||||
└── Makefile
|
└── Makefile
|
||||||
```
|
```
|
||||||
|
|
||||||
## Optimization
|
## Optimization
|
||||||
|
|
||||||
Rava implements proven interpreter optimization techniques. Same stuff V8, LuaJIT, and CPython use.
|
Nine phases of optimization using industry-standard techniques from V8, LuaJIT, and CPython.
|
||||||
|
|
||||||
### NaN Boxing
|
### NaN Boxing
|
||||||
|
|
||||||
64-bit value representation. Packs all types into 8 bytes instead of 16. Half the memory. Faster stack ops.
|
64-bit value representation using IEEE 754 NaN space. Invented by Andreas Gal for SpiderMonkey. All types packed into 8 bytes instead of 16. Branchless type checking via bitwise operations.
|
||||||
|
|
||||||
Location: `runtime/nanbox.h`
|
Location: `runtime/nanbox.h`
|
||||||
|
|
||||||
### Fast Frames
|
### Fast Frames
|
||||||
|
|
||||||
Pre-allocated frame pool. No heap allocation per function call. Stack discipline. Eliminates thousands of mallocs.
|
Pre-allocated frame pool with LIFO stack discipline. Standard technique from Lua and LuaJIT. No heap allocation per function call. Constant-time allocation. Cache-friendly contiguous memory.
|
||||||
|
|
||||||
Location: `runtime/fastframe.h`, `runtime/fastframe.c`
|
Location: `runtime/fastframe.h`, `runtime/fastframe.c`
|
||||||
|
|
||||||
### Label Table
|
### Label Table
|
||||||
|
|
||||||
O(1) jump resolution. Pre-computes label to PC mapping. Replaces O(n) linear search. Loops go 5-10x fastiii.
|
O(1) jump resolution via pre-computed label to PC mapping. Used in all bytecode interpreters including CPython and LuaJIT. Replaces O(n) linear search.
|
||||||
|
|
||||||
Location: `runtime/labeltable.h`, `runtime/labeltable.c`
|
Location: `runtime/labeltable.h`, `runtime/labeltable.c`
|
||||||
|
|
||||||
### Method Cache
|
### Method Cache
|
||||||
|
|
||||||
Hash-based method lookup. O(1) instead of O(n*m). Caches class+method pairs.
|
Hash-based method lookup cache. Based on inline cache technique from V8 and Hotspot JVM. O(1) instead of O(n*m) nested search. Cache hit rate typically above 90%.
|
||||||
|
|
||||||
Location: `runtime/methodcache.h`, `runtime/methodcache.c`
|
Location: `runtime/methodcache.h`, `runtime/methodcache.c`
|
||||||
|
|
||||||
### Superinstructions
|
### Superinstructions
|
||||||
|
|
||||||
Combines common opcode sequences into single instructions:
|
Bytecode fusion combining common opcode sequences. Developed by Ertl and Krall, used in LuaJIT and CPython 3.11+. Reduces instruction dispatch overhead.
|
||||||
- INC_LOCAL: load + const 1 + add + store combined
|
|
||||||
- DEC_LOCAL: load + const 1 + sub + store combined
|
Fused opcodes:
|
||||||
|
- INC_LOCAL: load + const 1 + add + store
|
||||||
|
- DEC_LOCAL: load + const 1 + sub + store
|
||||||
- ADD_LOCAL_TO_LOCAL: fused accumulator pattern
|
- ADD_LOCAL_TO_LOCAL: fused accumulator pattern
|
||||||
- LOAD_LOCAL_CONST_LT_JUMPFALSE: fused loop condition
|
- LOAD_LOCAL_CONST_LT_JUMPFALSE: fused loop condition
|
||||||
|
- LOAD_TWO_LOCALS: combined local loads
|
||||||
|
|
||||||
Location: `runtime/superinst.h`, `runtime/superinst.c`
|
Location: `runtime/superinst.h`, `runtime/superinst.c`
|
||||||
|
|
||||||
### Computed Goto
|
### Computed Goto
|
||||||
|
|
||||||
GCC extension for faster dispatch. Jump table instead of switch.
|
GCC extension for faster opcode dispatch. Uses jump table instead of switch statement. Eliminates branch prediction overhead.
|
||||||
|
|
||||||
### PGO Build
|
### Profile-Guided Optimization
|
||||||
|
|
||||||
Profile-guided optimization targets in Makefile. Run benchmarks, collect profile, rebuild.
|
PGO build using GCC profile instrumentation. Collects runtime data from benchmark runs. Rebuilds with optimization hints for hot paths.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make pgo
|
make pgo
|
||||||
@ -177,5 +180,23 @@ make pgo
|
|||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- Dataset library: https://dataset.readthedocs.io/en/latest/index.html
|
### Source Repositories
|
||||||
|
- V8 JavaScript Engine: https://github.com/v8/v8
|
||||||
|
- LuaJIT: https://github.com/LuaJIT/LuaJIT
|
||||||
|
- CPython: https://github.com/python/cpython
|
||||||
|
- PyPy: https://github.com/pypy/pypy
|
||||||
|
- OpenJDK Hotspot: https://github.com/openjdk/jdk
|
||||||
|
- SpiderMonkey: https://github.com/anthropics/mozilla-central
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- Lua Manual: https://www.lua.org/manual/5.4/
|
||||||
|
- GCC Optimization: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
|
||||||
|
- LLVM Documentation: https://llvm.org/docs/
|
||||||
|
- JVM Specification: https://docs.oracle.com/javase/specs/
|
||||||
|
|
||||||
|
### Standards
|
||||||
|
- IEEE 754 Floating Point: https://ieeexplore.ieee.org/document/8766229
|
||||||
|
|
||||||
|
### Performance Resources
|
||||||
|
- Agner Fog CPU Optimization: https://www.agner.org/optimize/
|
||||||
|
- Systems Performance by Brendan Gregg: http://www.brendangregg.com/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user