Skip to content

Commit

Permalink
Implement the GC in Rust (#1750)
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.
  • Loading branch information
osa1 authored Sep 3, 2020
1 parent 5a67f48 commit 1461f56
Show file tree
Hide file tree
Showing 14 changed files with 732 additions and 511 deletions.
1 change: 1 addition & 0 deletions rts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ mo-rts.wasm: $(RTS_RUST_WASM_O) $(RTS_WASM_O) $(TOMMATH_WASM_O) $(MUSL_WASM_O)
$(WASM_LD) -o $@ \
--import-memory --shared --no-entry --gc-sections \
--export=__wasm_call_ctors \
--export=memcpy \
--whole-archive \
$+

Expand Down
2 changes: 1 addition & 1 deletion rts/bigint.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) {
if (new_size > FIELD(r, 1)) {
void *newptr = mp_alloc(new_size);
if (old_size != FIELD(r, 1)) bigint_trap();
as_memcpy(newptr, ptr, old_size);
memcpy(newptr, ptr, old_size);
return newptr;
} else if (new_size == FIELD(r, 1)) {
// No need to grow
Expand Down
12 changes: 11 additions & 1 deletion rts/motoko-rts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ edition = "2018"
[dependencies.libc]
version = "0.2.73"

# added here so that it ends up in Cargo.lock, so that nix will pre-fetch it
# Added here so that it ends up in Cargo.lock, so that nix will pre-fetch it
[dependencies.compiler_builtins]
version = "0.1.32"
# Without this feature we get dozens of duplicate symbol errors when generating
# the final shared .wasm file:
#
# wasm-ld: error: duplicate symbol: __multi3
# >>> defined in _build/wasm/libmotoko_rts.a(compiler_builtins-d709bd899857aa61.compiler_builtins.3abndchk-cgu.0.rcgu.o)
# >>> defined in _build/wasm/libmotoko_rts.a(compiler_builtins-06d1ead628e1f468.compiler_builtins.6moz1ltd-cgu.0.rcgu.o)
#
# It seems like we're linking multiple versions of compiler_builtins in the same
# shared library, which we should fix at some point. TODO
features = ["mangled-names"]

[lib]
crate-type = ["staticlib"]
Expand Down
1 change: 0 additions & 1 deletion rts/motoko-rts/Xargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ stage = 0

[dependencies.compiler_builtins]
stage = 1
features = [ "mem" ]
version = "0.1.32"
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::{skew, Bytes, SkewedPtr, Words};

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

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

// Update heap pointer
let old_hp = gc::HP;
let new_hp = old_hp + bytes.0;
gc::HP = new_hp;

// Grow memory if needed
grow_memory(new_hp as usize);

skew(old_hp as usize)
}

/// 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 1461f56

Please sign in to comment.