The goal of liblg is to create a reasonably fast, minimal stack-based VM in C. It currently implements just enough functionality to generate the Fibonacci sequence using recursion, tail-recursion and iteration. The general idea is that it's potentially useful to have access to stack vm functionality in library form, for implementing custom DSLs on top etc.
liblg requires a C compiler and CMake to build.
$ git clone https://github.com/codr7/liblg.git
$ cd liblg
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./fibrec
148810us
The VM is currently significantly faster than Python3 and an order of magnitude slower than Go, ideas on how to improve the performance further without making a mess are most welcome.
$ python3 bench/fibrec.py
353813us
$ go run bench/fibrec.go
14170us
$ build/lgasm --bench 100 bench/fibtail.lga
147us
$ python3 bench/fibtail.py
543us
$ go run bench/fibtail.go
9us
$ build/lgasm --bench 100 bench/fibiter.lga
126us
$ python3 bench/fibiter.py
173us
$ go run bench/fibiter.go
4us
The core loop uses computed goto, which means that new instructions must be added in identical order here and here.
Fundamental types are global (as in not tied to a specific VM instance), new types may be added here and initialized here.
Values are represented as tagged unions.
liblg comes equipped with a simple custom assembler that provides a transparent interface to it's functionality.
Pop and add the top of the stack to the previous item.
Branch to $label if the stack value att $offset is equal to $value.
Branch to $label if the stack value att $offset is greater than $value.
Branch to $label if the stack value att $offset is less than $value.
Push the program counter on the call stack and jump to $label.
Push a copy of the value at stack $offset.
Decrease the value att stack $offset by one.
Drop $count items from stack $offset.
Jump to $label.
Push $value on the stack.
Return from the current call.
Stop execution.
Swap the top two items on the stack.