Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5f60718
Remove redundant function
pliniker Aug 1, 2023
88613eb
Fix logic hole in Array
pliniker Jun 6, 2024
82d2348
Fix logic hole in VM
pliniker Aug 28, 2024
be91860
Suppress ignored args warnings
pliniker Aug 28, 2024
012093a
Remove a TODO
pliniker Sep 1, 2024
d16be8f
Rename vm run functions
pliniker Sep 1, 2024
fb2bca3
Refactor thread exec iterations
pliniker Sep 9, 2024
d2090f8
Various fixes towards safe rooting
pliniker Dec 16, 2024
50fae84
PoC for conservative stack scan
pliniker Apr 26, 2025
9b2dea1
PoC for conservative stack scan - reordering problem, crashes
pliniker Apr 29, 2025
ca0acd8
PoC for conservative stack scan - reordering problem, crashes - intro…
pliniker May 1, 2025
492132c
PoC for conservative stack scan - reordering problem, crashes - scopi…
pliniker May 4, 2025
ad25f5a
add root pinning test
pliniker May 11, 2025
361f70f
thoughts
pliniker May 15, 2025
fe6f3cc
Add permaseal example
pliniker May 17, 2025
f045274
Interior mutability plus scoped access
pliniker May 17, 2025
3455ce0
Unescapable roots
pliniker May 18, 2025
e695beb
Clean up repl code a bit
pliniker Jun 7, 2025
33ea21f
Remove unsafe Mutator trait
pliniker Jun 7, 2025
1dce8f5
Remove unsafe pointer conversion, mark others as unsafe
pliniker Jun 7, 2025
b16374f
Remove unused functions
pliniker Jun 18, 2025
98bbedc
Cleaning up, linting
pliniker Jun 28, 2025
44f8de9
Cleaning up, linting
pliniker Jun 29, 2025
18df9dc
Cleaning up, linting
pliniker Jun 29, 2025
d5140fd
Attempt to fix GitHub Actions
pliniker Jun 30, 2025
ff1353f
Apply rust formatting
pliniker Jun 30, 2025
a5c0869
Rename stickyimmix to immixcons
pliniker Aug 28, 2025
7c83cd5
Rename stickyimmix to immixcons - GHA
pliniker Aug 28, 2025
ac5fb25
Apply rustfmt
pliniker Aug 28, 2025
5a36c17
Cleaning up, linting
pliniker Sep 1, 2025
5075c48
Cleaning up, linting
pliniker Sep 1, 2025
40880e3
Cleaning up, linting
pliniker Sep 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/book.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
uses: peaceiris/actions-mdbook@v2
with:
mdbook-version: '0.4.5'
# mdbook-version: 'latest'
# mdbook-version: '0.4.5'
mdbook-version: 'latest'

- run: mdbook build

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
publish_dir: ./book
18 changes: 7 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Use latest stable
run: rustup update stable

- name: Cargo fmt check blockalloc
working-directory: ./blockalloc
run: cargo fmt --all -- --check

- name: Cargo fmt check stickyimmix
working-directory: ./stickyimmix
- name: Cargo fmt check immixcons
working-directory: ./immixcons
run: cargo fmt --all -- --check

- name: Cargo fmt check interpreter
Expand All @@ -37,8 +33,8 @@ jobs:
working-directory: ./blockalloc
run: cargo test

- name: Cargo test stickyimmix
working-directory: ./stickyimmix
- name: Cargo test immixcons
working-directory: ./immixcons
run: cargo test

- name: Cargo test interpreter
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
book
target
29 changes: 8 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,17 @@ interpreter in Rust including:

## Project vision

From CPython to Ruby's YARV, V8 and SpiderMonkey, GHC to the JVM, most language
From Python to Ruby, V8 and SpiderMonkey, GHC to the JVM, most language
runtimes are written in C/C++.

We believe that Rust is eminently suitable for implementing languages and can
provide significant productivity improvements over C and C++ while retaining
the performance advantages and low level control of both.

While there are a number of languages implemented in Rust available now, in
varying states of completeness - interpreters, AOT compilers and
JIT-compiled - our vision is singular:

_To create a well documented reference compiler and runtime,
permissively licensed, such that you can fork and morph it into your own
programming language._

That is, a platform for bootstrapping other languages, written in Rust.
To that end, the implementation provided here is not intended to be feature
complete and cannot possibly represent every variation of programming
language or local optimization.

It is a lofty goal, and it certainly won't be the right approach for
everybody. However, we hope it will help shift the landscape in favor of more
memory-safe language implementations.
Rust is eminently suitable for implementing languages and can provide
significant productivity improvements over C and C++ while retaining the
performance advantages and low level control of both through safe and unsafe
abstractions.

The goal of this book is to provide well documented compiler and runtime
building blocks as a reference for learning how to build your own. The code is
permissively licensed and thus may be forked and modified as desired.

## Getting involved

Expand Down
2 changes: 2 additions & 0 deletions blockalloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ impl Block {
self.size
}

/// # Safety
///
/// Unsafely reassemble from pointer and size
pub unsafe fn from_raw_parts(ptr: BlockPtr, size: BlockSize) -> Block {
Block { ptr, size }
Expand Down
2 changes: 1 addition & 1 deletion booksrc/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- [Alignment](./chapter-alignment.md)
- [Obtaining blocks of memory](./chapter-blocks.md)
- [The type of allocation](./chapter-what-is-alloc.md)
- [An allocator: Sticky Immix](./part-stickyimmix.md)
- [An allocator: Sticky Immix](./part-immixcons.md)
- [Bump allocation](./chapter-simple-bump.md)
- [Allocating into multiple blocks](./chapter-managing-blocks.md)
- [Defining the allocation API](./chapter-allocation-api.md)
Expand Down
12 changes: 6 additions & 6 deletions booksrc/chapter-allocation-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ than checking a pointer for being null. We'll allow for distinguishing between
Out Of Memory and an allocation request that for whatever reason is invalid.

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocError}}
{{#include ../immixcons/src/allocator.rs:DefAllocError}}
```

The second change is that instead of a `*const T` value in the success
Expand All @@ -37,7 +37,7 @@ will amount to little more than containing a `std::ptr::NonNull` instance
and some functions to access the pointer.

```rust,ignore
{{#include ../stickyimmix/src/rawptr.rs:DefRawPtr}}
{{#include ../immixcons/src/rawptr.rs:DefRawPtr}}
```

This'll be better to work with on the user-of-the-crate side.
Expand All @@ -63,7 +63,7 @@ collector in _this_ crate need.
We'll define a trait for the user to implement.

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocHeader}}
{{#include ../immixcons/src/allocator.rs:DefAllocHeader}}
```

Now we have a bunch more questions to answer! Some of these trait methods are
Expand Down Expand Up @@ -95,7 +95,7 @@ pub trait AllocHeader: Sized {
where `AllocTypeId` is define simply as:

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocTypeId}}
{{#include ../immixcons/src/allocator.rs:DefAllocTypeId}}
```

This means the interpreter is free to implement a type identifier type however
Expand Down Expand Up @@ -124,7 +124,7 @@ header is being instantiated for.
And what is `AllocObject`? Simply:

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocObject}}
{{#include ../immixcons/src/allocator.rs:DefAllocObject}}
```

In summary, we have:
Expand Down Expand Up @@ -367,7 +367,7 @@ pub trait AllocRaw {
Our complete `AllocRaw` trait definition now looks like this:

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocRaw}}
{{#include ../immixcons/src/allocator.rs:DefAllocRaw}}
```

In the next chapter we'll build out the `AllocRaw` trait implementation.
8 changes: 4 additions & 4 deletions booksrc/chapter-allocation-impl.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Let's look at the implementation.

```rust,ignore
impl<H: AllocHeader> AllocRaw for StickyImmixHeap<H> {
{{#include ../stickyimmix/src/heap.rs:DefAlloc}}
{{#include ../immixcons/src/heap.rs:DefAlloc}}
}
```

Expand All @@ -49,7 +49,7 @@ write into the array itself.

```rust,ignore
impl<H: AllocHeader> AllocRaw for StickyImmixHeap<H> {
{{#include ../stickyimmix/src/heap.rs:DefAllocArray}}
{{#include ../immixcons/src/heap.rs:DefAllocArray}}
}
```

Expand All @@ -69,7 +69,7 @@ pointer.

```rust,ignore
impl<H: AllocHeader> AllocRaw for StickyImmixHeap<H> {
{{#include ../stickyimmix/src/heap.rs:DefGetHeader}}
{{#include ../immixcons/src/heap.rs:DefGetHeader}}
}
```

Expand All @@ -78,7 +78,7 @@ to the header pointer results in the object pointer:

```rust,ignore
impl<H: AllocHeader> AllocRaw for StickyImmixHeap<H> {
{{#include ../stickyimmix/src/heap.rs:DefGetObject}}
{{#include ../immixcons/src/heap.rs:DefGetObject}}
}
```

Expand Down
2 changes: 1 addition & 1 deletion booksrc/chapter-interp-alloc.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defined in the Sticky Immix crate.
Let's first recall this interface:

```rust,ignore
{{#include ../stickyimmix/src/allocator.rs:DefAllocRaw}}
{{#include ../immixcons/src/allocator.rs:DefAllocRaw}}
```

These are the functions we'll be calling. When we allocate an object, we'll get
Expand Down
4 changes: 2 additions & 2 deletions booksrc/chapter-managing-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ blocks so we can allocate - in theory - indefinitely.
We'll need a new struct for wrapping multiple blocks:

```rust,ignore
{{#include ../stickyimmix/src/heap.rs:DefBlockList}}
{{#include ../immixcons/src/heap.rs:DefBlockList}}
```

Immix maintains several lists of blocks. We won't include them all in the first
Expand Down Expand Up @@ -172,7 +172,7 @@ struct definition below there is reference to a generic type `H` that
the _user_ of the heap will define as the object header.

```rust,ignore
{{#include ../stickyimmix/src/heap.rs:DefStickyImmixHeap}}
{{#include ../immixcons/src/heap.rs:DefStickyImmixHeap}}
```

Since object headers are not owned directly by the heap struct, we need a
Expand Down
12 changes: 6 additions & 6 deletions booksrc/chapter-simple-bump.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ original [Immix paper][1]. This size can be any power of two though and
different use cases may show different optimal sizes.

```rust,ignore
{{#include ../stickyimmix/src/constants.rs:ConstBlockSize}}
{{#include ../immixcons/src/constants.rs:ConstBlockSize}}
```

Now we'll define a struct that wraps the block with a bump pointer and garbage
collection metadata:

```rust,ignore
{{#include ../stickyimmix/src/bumpblock.rs:DefBumpBlock}}
{{#include ../immixcons/src/bumpblock.rs:DefBumpBlock}}
```

## Bump allocation basics
Expand Down Expand Up @@ -118,7 +118,7 @@ but first some constants that we need in order to know
- how many bytes remain in the `Block` for allocating into

```rust,ignore
{{#include ../stickyimmix/src/constants.rs:ConstLineSize}}
{{#include ../immixcons/src/constants.rs:ConstLineSize}}
```

For clarity, let's put some numbers to the definitions we've made so far:
Expand All @@ -141,7 +141,7 @@ The definition of `BumpBlock` contains member `meta` which is of type
need to represent a pointer to the line mark section at the end of the `Block`:

```rust,ignore
{{#include ../stickyimmix/src/blockmeta.rs:DefBlockMeta}}
{{#include ../immixcons/src/blockmeta.rs:DefBlockMeta}}
```

This pointer could be easily calculated, of course, so this is just a handy
Expand All @@ -154,7 +154,7 @@ shortcut.
The struct `BlockMeta` contains one function we will study:

```rust,ignore
{{#include ../stickyimmix/src/blockmeta.rs:DefFindNextHole}}
{{#include ../immixcons/src/blockmeta.rs:DefFindNextHole}}
```

The purpose of this function is to locate a gap of unmarked lines of sufficient
Expand Down Expand Up @@ -288,7 +288,7 @@ reached the end of the block, exhausting our options.
The new definition of `BumpBlock::inner_alloc()` reads as follows:

```rust,ignore
{{#include ../stickyimmix/src/bumpblock.rs:DefBumpBlockAlloc}}
{{#include ../immixcons/src/bumpblock.rs:DefBumpBlockAlloc}}
```

and as you can see, this implementation is recursive.
Expand Down
2 changes: 1 addition & 1 deletion booksrc/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ All the links below are acknowledged as inspiration or prior art.

* Bob Nystrom's [Crafting Interpreters](http://craftinginterpreters.com/)
* [The Inko programming language](https://inko-lang.org/)
* kyren - [luster](https://github.com/kyren/luster) and [gc-arena](https://github.com/kyren/gc-arena)
* kyren - [piccolo](https://github.com/kyren/piccolo) and [gc-arena](https://github.com/kyren/gc-arena)

### Memory management

Expand Down
2 changes: 1 addition & 1 deletion booksrc/part-stickyimmix.md → booksrc/part-immixcons.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Each block is divided into lines. In the original paper, blocks are sized at 32k
and lines at 128 bytes. Objects are allocated into blocks using bump allocation
and objects can cross line boundaries.

![StickyImmix Block](img/stickyimmix_block.png)
![StickyImmix Block](img/immixcons_block.png)

During tracing to discover live objects, objects are marked as live, but the
line, or lines, that each object occupies are also marked as live. This can mean, of
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion stickyimmix/Cargo.lock → immixcons/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion stickyimmix/Cargo.toml → immixcons/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "stickyimmix"
name = "immixcons"
version = "0.1.0"
authors = ["Peter Liniker <[email protected]>"]
edition = "2018"
Expand Down
File renamed without changes.
File renamed without changes.
17 changes: 2 additions & 15 deletions stickyimmix/src/allocator.rs → immixcons/src/allocator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::mem::size_of;
use std::ptr::NonNull;

use crate::constants;
Expand Down Expand Up @@ -107,10 +106,10 @@ pub trait AllocHeader: Sized {
fn new_array(size: ArraySize, size_class: SizeClass, mark: Mark) -> Self;

/// Set the Mark value to "marked"
fn mark(&mut self);
fn mark(&mut self, value: Mark);

/// Get the current Mark value
fn is_marked(&self) -> bool;
fn mark_is(&self, value: Mark) -> bool;

/// Get the size class of the object
fn size_class(&self) -> SizeClass;
Expand All @@ -122,15 +121,3 @@ pub trait AllocHeader: Sized {
fn type_id(&self) -> Self::TypeId;
}
// ANCHOR_END: DefAllocHeader

/// Return the allocated size of an object as it's size_of::<T>() value rounded
/// up to a double-word boundary
///
/// TODO this isn't correctly implemented, as aligning the object to a double-word
/// boundary while considering header size (which is not known to this libarary
/// until compile time) means touching numerous bump-allocation code points with
/// some math and bitwise ops I haven't worked out yet
pub fn alloc_size_of(object_size: usize) -> usize {
let align = size_of::<usize>(); // * 2;
(object_size + (align - 1)) & !(align - 1)
}
Loading