Skip to content

Commit

Permalink
Implement the GC in Rust
Browse files Browse the repository at this point in the history
This implements the current garbage collector in Rust. No changes were
made to the GC design -- it's just ports the one implemented in code
generator to Rust.

The goals are:

- Evaluate Rust for Motoko's RTS implementation
- Make the collector easier to read, understand, modify, and extend.

Currently passes the tests locally. We can't run this branch on CI yet
as it needs to download rustc nightly and xargo and the domains are not
allowed on the CI. I think in the final version we'll have to build
rustc outselves instead of downloading.

(Nightly rustc is needed as "core" distributed with rustc is not built
with PIC relocation model on wam32, so we can't use it to generate a
shared wasm32 library)

Main changes:

- New Rust crate "motoko-rts" introduced, which currently implements the
  garbage collector. It also has some utilities for printing the heap or
  individual objects, to be used when debugging.

- Nix files updated to download rustc and xargo. These are used to build
  Rust's "core" library with PIC relocation model for wasm32.

- We no longer build memset and memcpy of musl as those are provided by
  Rust's "core" now.

The main algorithm is in `gc.rs`. Rest of the Rust files are helpers,
mainly for debugging.

Other changes:

- I had to update lots of ic-ref-run outputs. See #1854 for the details.

Remaining work and issues:

- Figure out how to use rustc nightly (with PIC wasm32 libraries) in CI.

Note to reviewers:

- The main algorithm is in `gc.rs`, everything else is helpers. Start
  reading from `gc.rs`.
  • Loading branch information
osa1 committed Sep 2, 2020
1 parent 55042e6 commit 2288f9b
Show file tree
Hide file tree
Showing 5 changed files with 667 additions and 460 deletions.
41 changes: 41 additions & 0 deletions rts/motoko-rts/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Implements allocation routines used by the generated code and the GC.

use core::arch::wasm32;

use crate::gc;
use crate::rts_trap_with;
use crate::types::{bytes_to_words, skew, words_to_bytes, Bytes, SkewedPtr, Words};

#[no_mangle]
pub unsafe extern "C" fn alloc_bytes(n: Bytes<u32>) -> SkewedPtr {
alloc_words(bytes_to_words(n))
}

#[no_mangle]
pub unsafe extern "C" fn alloc_words(n: Words<u32>) -> SkewedPtr {
let bytes = words_to_bytes(n);
// Update ALLOCATED
gc::ALLOCATED.0 += bytes.0 as u64;

// Update heap pointer
let old_hp = gc::get_hp();
let new_hp = old_hp + bytes.0 as usize;
gc::set_hp(new_hp);

// Grow memory if needed
grow_memory(new_hp);

skew(old_hp)
}

/// Page allocation. Ensures that the memory up to the given pointer is allocated.
pub(crate) unsafe fn grow_memory(ptr: usize) {
let total_pages_needed = ((ptr / 65536) + 1) as i32;
let current_pages = wasm32::memory_size(0) as i32;
let new_pages_needed = total_pages_needed - current_pages;
if new_pages_needed > 0 {
if wasm32::memory_grow(0, new_pages_needed as usize) == core::usize::MAX {
rts_trap_with("Cannot grow memory\0".as_ptr());
}
}
}
Loading

0 comments on commit 2288f9b

Please sign in to comment.