Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 0 additions & 38 deletions rts/motoko-rts-tests/src/closure_table.rs

This file was deleted.

43 changes: 43 additions & 0 deletions rts/motoko-rts-tests/src/continuation_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::memory::TestMemory;

use motoko_rts::continuation_table::{
continuation_count, recall_continuation, remember_continuation,
};
use motoko_rts::types::{SkewedPtr, Words};

pub unsafe fn test() {
println!("Testing continuation table ...");

assert_eq!(continuation_count(), 0);

const N: usize = 2000; // >256, to exercise `double_continuation_table`

// Array will be doubled 3 times, so 256 + 512 + 1024 + 2048 = 3840 words, plus each array will
// have 2 word header.
let mut heap = TestMemory::new(Words(3848));

let mut references: [u32; N] = [0; N];
for i in 0..N {
references[i] = remember_continuation(&mut heap, SkewedPtr((i << 2).wrapping_sub(1)));
assert_eq!(continuation_count(), (i + 1) as u32);
}

for i in 0..N / 2 {
let c = recall_continuation(references[i]);
assert_eq!(c.0, (i << 2).wrapping_sub(1));
assert_eq!(continuation_count(), (N - i - 1) as u32);
}

for i in 0..N / 2 {
references[i] = remember_continuation(&mut heap, SkewedPtr((i << 2).wrapping_sub(1)));
assert_eq!(continuation_count(), (N / 2 + i + 1) as u32);
}

for i in (0..N).rev() {
assert_eq!(
recall_continuation(references[i]).0,
(i << 2).wrapping_sub(1)
);
assert_eq!(continuation_count(), i as u32);
}
}
57 changes: 29 additions & 28 deletions rts/motoko-rts-tests/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn test_heaps() -> Vec<TestHeap> {
3 => vec![3],
},
roots: vec![0, 2, 3],
closure_table: vec![0],
continuation_table: vec![0],
},
// Tests pointing to the same object in multiple fields of an object. Also has unreachable
// objects.
Expand All @@ -53,7 +53,7 @@ fn test_heaps() -> Vec<TestHeap> {
2 => vec![],
},
roots: vec![1],
closure_table: vec![0, 0],
continuation_table: vec![0, 0],
},
// Root points backwards in heap. Caught a bug in mark-compact collector.
TestHeap {
Expand All @@ -63,7 +63,7 @@ fn test_heaps() -> Vec<TestHeap> {
2 => vec![1],
},
roots: vec![2],
closure_table: vec![],
continuation_table: vec![],
},
]
}
Expand All @@ -72,7 +72,7 @@ fn test_heaps() -> Vec<TestHeap> {
struct TestHeap {
heap: HashMap<ObjectIdx, Vec<ObjectIdx>>,
roots: Vec<ObjectIdx>,
closure_table: Vec<ObjectIdx>,
continuation_table: Vec<ObjectIdx>,
}

/// Test all GC implementations with the given heap
Expand All @@ -82,7 +82,7 @@ fn test_gcs(heap_descr: &TestHeap) {
*gc,
&heap_descr.heap,
&heap_descr.roots,
&heap_descr.closure_table,
&heap_descr.continuation_table,
);
}
}
Expand All @@ -91,37 +91,37 @@ fn test_gc(
gc: GC,
refs: &HashMap<ObjectIdx, Vec<ObjectIdx>>,
roots: &[ObjectIdx],
closure_table: &[ObjectIdx],
continuation_table: &[ObjectIdx],
) {
let heap = MotokoHeap::new(refs, roots, closure_table, gc);
let heap = MotokoHeap::new(refs, roots, continuation_table, gc);

// Check `create_dynamic_heap` sanity
check_dynamic_heap(
false, // before gc
refs,
roots,
closure_table,
continuation_table,
&**heap.heap(),
heap.heap_base_offset(),
heap.heap_ptr_offset(),
heap.closure_table_ptr_offset(),
heap.continuation_table_ptr_offset(),
);

for _ in 0..3 {
gc.run(heap.clone());

let heap_base_offset = heap.heap_base_offset();
let heap_ptr_offset = heap.heap_ptr_offset();
let closure_table_ptr_offset = heap.closure_table_ptr_offset();
let continuation_table_ptr_offset = heap.continuation_table_ptr_offset();
check_dynamic_heap(
true, // after gc
refs,
roots,
closure_table,
continuation_table,
&**heap.heap(),
heap_base_offset,
heap_ptr_offset,
closure_table_ptr_offset,
continuation_table_ptr_offset,
);
}
}
Expand All @@ -139,30 +139,30 @@ fn check_dynamic_heap(
post_gc: bool,
objects: &HashMap<ObjectIdx, Vec<ObjectIdx>>,
roots: &[ObjectIdx],
closure_table: &[ObjectIdx],
continuation_table: &[ObjectIdx],
heap: &[u8],
heap_base_offset: usize,
heap_ptr_offset: usize,
closure_table_ptr_offset: usize,
continuation_table_ptr_offset: usize,
) {
// Current offset in the heap
let mut offset = heap_base_offset;

// Maps objects to their addresses (not offsets!). Used when debugging duplicate objects.
let mut seen: HashMap<ObjectIdx, usize> = Default::default();

let closure_table_addr = unskew_pointer(read_word(heap, closure_table_ptr_offset));
let closure_table_offset = closure_table_addr as usize - heap.as_ptr() as usize;
let continuation_table_addr = unskew_pointer(read_word(heap, continuation_table_ptr_offset));
let continuation_table_offset = continuation_table_addr as usize - heap.as_ptr() as usize;

while offset < heap_ptr_offset {
let object_offset = offset;

// Address of the current object. Used for debugging.
let address = offset as usize + heap.as_ptr() as usize;

if object_offset == closure_table_offset {
check_closure_table(object_offset, closure_table, heap);
offset += (size_of::<Array>() + Words(closure_table.len() as u32))
if object_offset == continuation_table_offset {
check_continuation_table(object_offset, continuation_table, heap);
offset += (size_of::<Array>() + Words(continuation_table.len() as u32))
.to_bytes()
.0 as usize;
continue;
Expand Down Expand Up @@ -217,7 +217,7 @@ fn check_dynamic_heap(
// At this point we've checked that all seen objects point to the expected objects (as
// specified by `objects`). Check that we've seen the reachable objects and only the reachable
// objects.
let reachable_objects = compute_reachable_objects(roots, closure_table, objects);
let reachable_objects = compute_reachable_objects(roots, continuation_table, objects);

// Objects we've seen in the heap
let seen_objects: HashSet<ObjectIdx> = seen.keys().copied().collect();
Expand Down Expand Up @@ -268,10 +268,10 @@ fn check_dynamic_heap(

fn compute_reachable_objects(
roots: &[ObjectIdx],
closure_table: &[ObjectIdx],
continuation_table: &[ObjectIdx],
heap: &HashMap<ObjectIdx, Vec<ObjectIdx>>,
) -> HashSet<ObjectIdx> {
let root_iter = roots.iter().chain(closure_table.iter()).copied();
let root_iter = roots.iter().chain(continuation_table.iter()).copied();

let mut closure: HashSet<ObjectIdx> = root_iter.clone().collect();
let mut work_list: Vec<ObjectIdx> = root_iter.collect();
Expand All @@ -291,14 +291,14 @@ fn compute_reachable_objects(
closure
}

fn check_closure_table(mut offset: usize, closure_table: &[ObjectIdx], heap: &[u8]) {
fn check_continuation_table(mut offset: usize, continuation_table: &[ObjectIdx], heap: &[u8]) {
assert_eq!(read_word(heap, offset), TAG_ARRAY);
offset += WORD_SIZE;

assert_eq!(read_word(heap, offset), closure_table.len() as u32);
assert_eq!(read_word(heap, offset), continuation_table.len() as u32);
offset += WORD_SIZE;

for obj in closure_table.iter() {
for obj in continuation_table.iter() {
let ptr = unskew_pointer(read_word(heap, offset));
offset += WORD_SIZE;

Expand All @@ -314,7 +314,8 @@ impl GC {
fn run(&self, mut heap: MotokoHeap) {
let heap_base = heap.heap_base_address() as u32;
let static_roots = skew(heap.static_root_array_address());
let closure_table_ptr_address = heap.closure_table_ptr_address() as *mut SkewedPtr;
let continuation_table_ptr_address =
heap.continuation_table_ptr_address() as *mut SkewedPtr;

let heap_1 = heap.clone();
let heap_2 = heap.clone();
Expand All @@ -330,7 +331,7 @@ impl GC {
// set_hp
move |hp| heap_2.set_heap_ptr_address(hp as usize),
static_roots,
closure_table_ptr_address,
continuation_table_ptr_address,
// note_live_size
|_live_size| {},
// note_reclaimed
Expand All @@ -349,7 +350,7 @@ impl GC {
// set_hp
move |hp| heap_2.set_heap_ptr_address(hp as usize),
static_roots,
closure_table_ptr_address,
continuation_table_ptr_address,
// note_live_size
|_live_size| {},
// note_reclaimed
Expand Down
Loading