Skip to content

Commit b1a21de

Browse files
committed
Implement the GC in Rust
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. Current status: the code is complete in the sense that there aren't any missing features/passes etc., but it's has bugs. I'm not sure how to debug Wasm yet. There are also lots of TODOs in the code, mostly for documentation. Submitting a PR to get early feedback.
1 parent 0737389 commit b1a21de

File tree

16 files changed

+759
-151
lines changed

16 files changed

+759
-151
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
_out
44
_output
55
_build
6+
target
67

78
**/*~
89
/result*

default.nix

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ let haskellPackages = nixpkgs.haskellPackages.override {
1919
overrides = import nix/haskell-packages.nix nixpkgs subpath;
2020
}; in
2121
let
22-
llvmBuildInputs = [
22+
rtsBuildInputs = [
2323
nixpkgs.clang_10 # for native/wasm building
2424
nixpkgs.lld_10 # for wasm building
25+
nixpkgs.rustc
26+
nixpkgs.cargo
2527
];
2628

27-
# When compiling natively, we want to use `clang` (which is a nixpkgs
28-
# provided wrapper that sets various include paths etc).
29-
# But for some reason it does not handle building for Wasm well, so
30-
# there we use plain clang-10. There is no stdlib there anyways.
3129
llvmEnv = ''
30+
# When compiling natively, we want to use `clang` (which is a nixpkgs
31+
# provided wrapper that sets various include paths etc).
32+
# But for some reason it does not handle building for Wasm well, so
33+
# there we use plain clang-10. There is no stdlib there anyways.
3234
export CLANG="${nixpkgs.clang_10}/bin/clang"
3335
export WASM_CLANG="clang-10"
3436
export WASM_LD=wasm-ld
@@ -126,7 +128,7 @@ rec {
126128
src = subpath ./rts;
127129
nativeBuildInputs = [ nixpkgs.makeWrapper ];
128130

129-
buildInputs = llvmBuildInputs;
131+
buildInputs = rtsBuildInputs;
130132

131133
preBuild = ''
132134
${llvmEnv}
@@ -200,7 +202,7 @@ rec {
200202
wasmtime
201203
nixpkgs.sources.esm
202204
] ++
203-
llvmBuildInputs;
205+
rtsBuildInputs;
204206

205207
checkPhase = ''
206208
patchShebangs .

nix/default.nix

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ let
3434
wasmtime = self.callPackage ./wasmtime.nix {};
3535
}
3636
)
37+
# nixpkgs's rustc does not include the wasm32-unknown-unknown target, so
38+
# lets add it here.
39+
(self: super: {
40+
rustc = super.rustc.overrideAttrs (old: {
41+
configureFlags = self.lib.lists.forEach old.configureFlags (flag:
42+
if self.lib.strings.hasPrefix "--target=" flag
43+
then flag + ",wasm32-unknown-unknown,wasm32-unknown-emscripten"
44+
else flag
45+
);
46+
});
47+
})
3748
];
3849
};
3950
in

rts/Makefile

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
SHELL:=bash -O globstar
2+
13
CLANG ?= clang-10
24
WASM_CLANG ?= clang-10
35
WASM_LD ?= wasm-ld-10
@@ -154,14 +156,28 @@ _build/native/tommath_%.o: %.c rts.h buf.h | _build/native
154156
_build/wasm/musl_%.o: %.c | _build/wasm
155157
$(WASM_CLANG) $(CLANG_FLAGS) $(WASM_FLAGS) $(MUSL_FLAGS) $< --output $@
156158

159+
.PHONY: _build/wasm/motoko_rts.o
160+
_build/wasm/motoko_rts.o: | _build/wasm
161+
cd motoko-rts && \
162+
cargo rustc --target=wasm32-unknown-emscripten --release -v -- -Crelocation-model=pic --emit=obj
163+
cp motoko-rts/target/wasm32-unknown-emscripten/release/deps/motoko_rts*.o $@
164+
165+
.PHONY: _build/native/motoko_rts.o
166+
_build/native/motoko_rts.o: | _build/native
167+
cd motoko-rts && \
168+
cargo rustc --release -v -- -Crelocation-model=pic --emit=obj
169+
cp motoko-rts/target/release/deps/motoko_rts*.o $@
170+
157171
RTS_WASM_O=$(RTSFILES:%=_build/wasm/%.o)
158172
RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o)
173+
RTS_RUST_WASM_O=_build/wasm/motoko_rts.o
174+
RTS_RUST_NATIVE_O=_build/native/motoko_rts.o
159175

160176
#
161177
# The actual RTS, as we ship it with the compiler
162178
#
163179

164-
mo-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) $(MUSL_WASM_O)
180+
mo-rts.wasm: $(RTS_WASM_O) $(RTS_RUST_WASM_O) $(TOMMATH_WASM_O) $(MUSL_WASM_O)
165181
$(WASM_LD) -o $@ \
166182
--import-memory --shared --no-entry --gc-sections \
167183
--export=__wasm_call_ctors \
@@ -171,12 +187,11 @@ mo-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) $(MUSL_WASM_O)
171187
# A simple program to do simple tests of rts.c, using native compilation
172188
#
173189

174-
test_rts: test_rts.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O)
190+
test_rts: test_rts.c $(RTS_NATIVE_O) $(RTS_RUST_NATIVE_O) $(TOMMATH_NATIVE_O)
175191
$(CLANG) -o $@ $+
176192

177-
test_leb128: test_leb128.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O)
193+
test_leb128: test_leb128.c $(RTS_NATIVE_O) $(RTS_RUST_NATIVE_O) $(TOMMATH_NATIVE_O)
178194
$(CLANG) -o $@ $+
179195

180196
clean:
181-
rm -rf _build mo-rts.wasm test_rts test_leb128
182-
197+
rm -rf _build mo-rts.wasm test_rts test_leb128 motoko-rts/target
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rust-analyzer.cargo.target": "wasm32-unknown-emscripten"
3+
}

rts/motoko-rts/Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rts/motoko-rts/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "motoko-rts"
3+
version = "0.1.0"
4+
authors = ["Ömer Sinan Ağacan <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]

rts/motoko-rts/src/array.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use crate::common::rts_trap_with;
2+
use crate::types::{skew, Array, SkewedPtr};
3+
4+
/// Returns address of Nth payload field of an array
5+
#[no_mangle]
6+
pub unsafe extern "C" fn array_field_addr(array: SkewedPtr, idx: u32) -> SkewedPtr {
7+
let array_ptr = array.unskew() as *const Array;
8+
9+
if idx >= (*array_ptr).len {
10+
rts_trap_with("Array index out of bounds\0".as_ptr());
11+
}
12+
13+
let payload_begin = array_ptr.offset(1) as *const u32;
14+
skew(payload_begin.offset(idx as isize) as usize)
15+
}
16+
17+
/// Index an array. Does not check bounds.
18+
pub unsafe fn array_idx_unchecked(array_ptr: *const Array, idx: u32) -> SkewedPtr {
19+
let payload_begin = array_ptr.offset(1) as *const u32;
20+
SkewedPtr(*payload_begin.offset(idx as isize) as usize)
21+
}

rts/motoko-rts/src/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extern "C" {
2+
pub fn rts_trap_with(msg: *const u8) -> !;
3+
}

0 commit comments

Comments
 (0)