diff --git a/rts/motoko-rts-tests/src/closure_table.rs b/rts/motoko-rts-tests/src/closure_table.rs deleted file mode 100644 index 49ed9d673f4..00000000000 --- a/rts/motoko-rts-tests/src/closure_table.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::memory::TestMemory; - -use motoko_rts::closure_table::{closure_count, recall_closure, remember_closure}; -use motoko_rts::types::{SkewedPtr, Words}; - -pub unsafe fn test() { - println!("Testing closure table ..."); - - assert_eq!(closure_count(), 0); - - const N: usize = 2000; // >256, to exercise `double_closure_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_closure(&mut heap, SkewedPtr((i << 2).wrapping_sub(1))); - assert_eq!(closure_count(), (i + 1) as u32); - } - - for i in 0..N / 2 { - let c = recall_closure(references[i]); - assert_eq!(c.0, (i << 2).wrapping_sub(1)); - assert_eq!(closure_count(), (N - i - 1) as u32); - } - - for i in 0..N / 2 { - references[i] = remember_closure(&mut heap, SkewedPtr((i << 2).wrapping_sub(1))); - assert_eq!(closure_count(), (N / 2 + i + 1) as u32); - } - - for i in (0..N).rev() { - assert_eq!(recall_closure(references[i]).0, (i << 2).wrapping_sub(1)); - assert_eq!(closure_count(), i as u32); - } -} diff --git a/rts/motoko-rts-tests/src/continuation_table.rs b/rts/motoko-rts-tests/src/continuation_table.rs new file mode 100644 index 00000000000..191cb4bc6bd --- /dev/null +++ b/rts/motoko-rts-tests/src/continuation_table.rs @@ -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); + } +} diff --git a/rts/motoko-rts-tests/src/gc.rs b/rts/motoko-rts-tests/src/gc.rs index 199d1209b2b..fecb740039a 100644 --- a/rts/motoko-rts-tests/src/gc.rs +++ b/rts/motoko-rts-tests/src/gc.rs @@ -42,7 +42,7 @@ fn test_heaps() -> Vec { 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. @@ -53,7 +53,7 @@ fn test_heaps() -> Vec { 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 { @@ -63,7 +63,7 @@ fn test_heaps() -> Vec { 2 => vec![1], }, roots: vec![2], - closure_table: vec![], + continuation_table: vec![], }, ] } @@ -72,7 +72,7 @@ fn test_heaps() -> Vec { struct TestHeap { heap: HashMap>, roots: Vec, - closure_table: Vec, + continuation_table: Vec, } /// Test all GC implementations with the given heap @@ -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, ); } } @@ -91,20 +91,20 @@ fn test_gc( gc: GC, refs: &HashMap>, 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 { @@ -112,16 +112,16 @@ fn test_gc( 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, ); } } @@ -139,11 +139,11 @@ fn check_dynamic_heap( post_gc: bool, objects: &HashMap>, 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; @@ -151,8 +151,8 @@ fn check_dynamic_heap( // Maps objects to their addresses (not offsets!). Used when debugging duplicate objects. let mut seen: HashMap = 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; @@ -160,9 +160,9 @@ fn check_dynamic_heap( // 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::() + Words(closure_table.len() as u32)) + if object_offset == continuation_table_offset { + check_continuation_table(object_offset, continuation_table, heap); + offset += (size_of::() + Words(continuation_table.len() as u32)) .to_bytes() .0 as usize; continue; @@ -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 = seen.keys().copied().collect(); @@ -268,10 +268,10 @@ fn check_dynamic_heap( fn compute_reachable_objects( roots: &[ObjectIdx], - closure_table: &[ObjectIdx], + continuation_table: &[ObjectIdx], heap: &HashMap>, ) -> HashSet { - let root_iter = roots.iter().chain(closure_table.iter()).copied(); + let root_iter = roots.iter().chain(continuation_table.iter()).copied(); let mut closure: HashSet = root_iter.clone().collect(); let mut work_list: Vec = root_iter.collect(); @@ -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; @@ -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(); @@ -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 @@ -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 diff --git a/rts/motoko-rts-tests/src/gc/heap.rs b/rts/motoko-rts-tests/src/gc/heap.rs index 7b2f45e477f..e9c81b99f1f 100644 --- a/rts/motoko-rts-tests/src/gc/heap.rs +++ b/rts/motoko-rts-tests/src/gc/heap.rs @@ -34,14 +34,14 @@ impl MotokoHeap { pub fn new( map: &HashMap>, roots: &[ObjectIdx], - closure_table: &[ObjectIdx], + continuation_table: &[ObjectIdx], gc: GC, ) -> MotokoHeap { MotokoHeap { inner: Rc::new(RefCell::new(MotokoHeapInner::new( map, roots, - closure_table, + continuation_table, gc, ))), } @@ -78,14 +78,14 @@ impl MotokoHeap { self.inner.borrow().static_root_array_address() } - /// Get the offset of the closure table pointer - pub fn closure_table_ptr_offset(&self) -> usize { - self.inner.borrow().closure_table_ptr_offset + /// Get the offset of the continuation table pointer + pub fn continuation_table_ptr_offset(&self) -> usize { + self.inner.borrow().continuation_table_ptr_offset } - /// Get the address of the closure table pointer - pub fn closure_table_ptr_address(&self) -> usize { - self.inner.borrow().closure_table_ptr_address() + /// Get the address of the continuation table pointer + pub fn continuation_table_ptr_address(&self) -> usize { + self.inner.borrow().continuation_table_ptr_address() } /// Get the heap as an array. Use `offset` values returned by the methods above to read. @@ -108,11 +108,11 @@ struct MotokoHeapInner { /// Offset of the static root array: an array of pointers below `heap_base` static_root_array_offset: usize, - /// Offset of the closure table pointer. + /// Offset of the continuation table pointer. /// /// Reminder: this location is in static heap and will have pointer to an array in dynamic /// heap. - closure_table_ptr_offset: usize, + continuation_table_ptr_offset: usize, } impl MotokoHeapInner { @@ -144,30 +144,30 @@ impl MotokoHeapInner { self.offset_to_address(self.static_root_array_offset) } - /// Get the address of the closure table pointer - fn closure_table_ptr_address(&self) -> usize { - self.offset_to_address(self.closure_table_ptr_offset) + /// Get the address of the continuation table pointer + fn continuation_table_ptr_address(&self) -> usize { + self.offset_to_address(self.continuation_table_ptr_offset) } fn new( map: &HashMap>, roots: &[ObjectIdx], - closure_table: &[ObjectIdx], + continuation_table: &[ObjectIdx], gc: GC, ) -> MotokoHeapInner { // Each object will be 3 words per object + one word for each reference. Static heap will // have an array (header + length) with one element, one MutBox for each root. +1 for - // closure table pointer. + // continuation table pointer. let static_heap_size_bytes = (2 + roots.len() + (roots.len() * 2) + 1) * WORD_SIZE; - let dynamic_heap_size_without_closure_table_bytes = { + let dynamic_heap_size_without_continuation_table_bytes = { let object_headers_words = map.len() * 3; let references_words = map.values().map(Vec::len).sum::(); (object_headers_words + references_words) * WORD_SIZE }; - let dynamic_heap_size_bytes = dynamic_heap_size_without_closure_table_bytes - + (size_of::() + Words(closure_table.len() as u32)) + let dynamic_heap_size_bytes = dynamic_heap_size_without_continuation_table_bytes + + (size_of::() + Words(continuation_table.len() as u32)) .to_bytes() .0 as usize; @@ -184,15 +184,15 @@ impl MotokoHeapInner { // Maps `ObjectIdx`s into their offsets in the heap let object_addrs: HashMap = - create_dynamic_heap(map, closure_table, &mut heap[static_heap_size_bytes..]); + create_dynamic_heap(map, continuation_table, &mut heap[static_heap_size_bytes..]); // Closure table pointer is the last word in static heap - let closure_table_ptr_offset = static_heap_size_bytes - WORD_SIZE; + let continuation_table_ptr_offset = static_heap_size_bytes - WORD_SIZE; create_static_heap( roots, &object_addrs, - closure_table_ptr_offset, - static_heap_size_bytes + dynamic_heap_size_without_closure_table_bytes, + continuation_table_ptr_offset, + static_heap_size_bytes + dynamic_heap_size_without_continuation_table_bytes, &mut heap[..static_heap_size_bytes], ); @@ -201,7 +201,7 @@ impl MotokoHeapInner { heap_base_offset: static_heap_size_bytes, heap_ptr_offset: total_heap_size_bytes, static_root_array_offset: 0, - closure_table_ptr_offset: closure_table_ptr_offset, + continuation_table_ptr_offset: continuation_table_ptr_offset, } } @@ -274,7 +274,7 @@ fn heap_size_for_gc( /// documentation for "offset" and "address" definitions). fn create_dynamic_heap( refs: &HashMap>, - closure_table: &[ObjectIdx], + continuation_table: &[ObjectIdx], dynamic_heap: &mut [u8], ) -> HashMap { let heap_start = dynamic_heap.as_ptr() as usize; @@ -324,23 +324,23 @@ fn create_dynamic_heap( } } - // Add the closure table + // Add the continuation table let n_objects = refs.len(); // fields+1 for the scalar field (idx) let n_fields: usize = refs.values().map(|fields| fields.len() + 1).sum(); - let closure_table_offset = + let continuation_table_offset = (size_of::() * n_objects as u32).to_bytes().0 as usize + n_fields * WORD_SIZE; { - let mut heap_offset = closure_table_offset; + let mut heap_offset = continuation_table_offset; - write_word(dynamic_heap, closure_table_offset, TAG_ARRAY); + write_word(dynamic_heap, continuation_table_offset, TAG_ARRAY); heap_offset += WORD_SIZE; - write_word(dynamic_heap, heap_offset, closure_table.len() as u32); + write_word(dynamic_heap, heap_offset, continuation_table.len() as u32); heap_offset += WORD_SIZE; - for idx in closure_table { + for idx in continuation_table { let idx_ptr = *object_addrs.get(idx).unwrap(); write_word(dynamic_heap, heap_offset, make_pointer(idx_ptr as u32)); heap_offset += WORD_SIZE; @@ -356,8 +356,8 @@ fn create_dynamic_heap( fn create_static_heap( roots: &[ObjectIdx], object_addrs: &HashMap, - closure_table_ptr_offset: usize, - closure_table_offset: usize, + continuation_table_ptr_offset: usize, + continuation_table_offset: usize, heap: &mut [u8], ) { let root_addresses: Vec = roots @@ -396,11 +396,11 @@ fn create_static_heap( mutbox_offset += size_of::().to_bytes().0 as usize; } - // Write closure table pointer as the last word in static heap - let closure_table_ptr = closure_table_offset as u32 + heap.as_ptr() as u32; + // Write continuation table pointer as the last word in static heap + let continuation_table_ptr = continuation_table_offset as u32 + heap.as_ptr() as u32; write_word( heap, - closure_table_ptr_offset, - make_pointer(closure_table_ptr), + continuation_table_ptr_offset, + make_pointer(continuation_table_ptr), ); } diff --git a/rts/motoko-rts-tests/src/main.rs b/rts/motoko-rts-tests/src/main.rs index 8e3c0ddbb10..c4ca2492ffa 100644 --- a/rts/motoko-rts-tests/src/main.rs +++ b/rts/motoko-rts-tests/src/main.rs @@ -2,7 +2,7 @@ mod bigint; mod bitmap; -mod closure_table; +mod continuation_table; mod crc32; mod gc; mod leb128; @@ -26,7 +26,7 @@ fn main() { unsafe { bigint::test(); bitmap::test(); - closure_table::test(); + continuation_table::test(); crc32::test(); gc::test(); leb128::test(); diff --git a/rts/motoko-rts/src/closure_table.rs b/rts/motoko-rts/src/continuation_table.rs similarity index 58% rename from rts/motoko-rts/src/closure_table.rs rename to rts/motoko-rts/src/continuation_table.rs index cc654814f5a..f6415eb49f8 100644 --- a/rts/motoko-rts/src/closure_table.rs +++ b/rts/motoko-rts/src/continuation_table.rs @@ -1,18 +1,21 @@ //! This file implements the data structure the Motoko runtime uses to keep track of outstanding -//! closures. It needs to support the following operations +//! continuations. It needs to support the following operations //! -//! 1. Adding a closure (any heap pointer) and getting an index (i32) -//! 2. Looking up a closure by index, which also frees it -//! 3. GC must be able to traverse and move closures in the table +//! 1. Adding a continuation (any heap pointer) and getting an index (i32) +//! 2. Looking up a continuation by index, which also frees it +//! 3. Peek into an existing continuation and hand back additional data +//! 4. GC must be able to traverse and move continuations in the table //! -//! Current implementation stores the closures in heap-allocated Motoko array. +//! By a continuation we understand any collection of callables that help to advance +//! the actor's control flow. +//! The current implementation stores the continuations in heap-allocated Motoko array. //! //! To efficiently look up the next free index, we use an implicit free list: `FREE_SLOT` is the //! index into the array payload of the next free item. Each free item contains the index of the //! next free item, shifted 2 bits to the left (to make the index a scalar and traverse them in //! GC). //! -//! The last item will have value `TABLE.len() << 2`, so after adding a closure to the last free +//! The last item will have value `TABLE.len() << 2`, so after adding a continuation to the last free //! slot `FREE_SLOT` will be `table_size`, which is when we see that the array is full. //! //! When the table is full, we double the size, copy the existing table, and add the second half to @@ -31,16 +34,16 @@ const INITIAL_SIZE: u32 = 256; // location to the GC. static mut TABLE: SkewedPtr = SkewedPtr(0); -// Number of currently live closures -static mut N_CLOSURES: u32 = 0; +// Number of currently live continuations +static mut N_CONTINUATIONS: u32 = 0; // Next free slot static mut FREE_SLOT: u32 = 0; -unsafe fn create_closure_table(mem: &mut M) { +unsafe fn create_continuation_table(mem: &mut M) { TABLE = alloc_array(mem, INITIAL_SIZE); FREE_SLOT = 0; - N_CLOSURES = 0; + N_CONTINUATIONS = 0; let table = TABLE.as_array(); for i in 0..INITIAL_SIZE { @@ -48,7 +51,7 @@ unsafe fn create_closure_table(mem: &mut M) { } } -unsafe fn double_closure_table(mem: &mut M) { +unsafe fn double_continuation_table(mem: &mut M) { let old_array = TABLE.as_array(); let old_size = old_array.len(); @@ -69,60 +72,60 @@ unsafe fn double_closure_table(mem: &mut M) { } #[ic_mem_fn] -pub unsafe fn remember_closure(mem: &mut M, ptr: SkewedPtr) -> u32 { +pub unsafe fn remember_continuation(mem: &mut M, ptr: SkewedPtr) -> u32 { if TABLE.0 == 0 { - create_closure_table(mem); + create_continuation_table(mem); } if FREE_SLOT == TABLE.as_array().len() { - double_closure_table(mem); + double_continuation_table(mem); } // Just as a sanity check make sure the ptr is really skewed if ptr.is_tagged_scalar() { - rts_trap_with("remember_closure: Argument is not a skewed pointer"); + rts_trap_with("remember_continuation: Argument is not a skewed pointer"); } let idx = FREE_SLOT; FREE_SLOT = (TABLE.as_array().get(idx).0 >> 2) as u32; TABLE.as_array().set(idx, ptr); - N_CLOSURES += 1; + N_CONTINUATIONS += 1; idx } -// Position of the future in explicit self-send ClosureTable entries +// Position of the future in explicit self-send ContinuationTable entries // Invariant: keep this synchronised with compiler.ml (see future_array_index) const FUTURE_ARRAY_INDEX: u32 = 2; #[no_mangle] -pub unsafe extern "C" fn peek_future_closure(idx: u32) -> SkewedPtr { +pub unsafe extern "C" fn peek_future_continuation(idx: u32) -> SkewedPtr { if TABLE.0 == 0 { - rts_trap_with("peek_future_closure: Closure table not allocated"); + rts_trap_with("peek_future_continuation: Continuation table not allocated"); } if idx >= TABLE.as_array().len() { - rts_trap_with("peek_future_closure: Closure index out of range"); + rts_trap_with("peek_future_continuation: Continuation index out of range"); } let ptr = TABLE.as_array().get(idx); if ptr.0 & 0b1 != 1 { - rts_trap_with("peek_future_closure: Closure index not in table"); + rts_trap_with("peek_future_continuation: Continuation index not in table"); } ptr.as_array().get(FUTURE_ARRAY_INDEX) } #[no_mangle] -pub unsafe extern "C" fn recall_closure(idx: u32) -> SkewedPtr { +pub unsafe extern "C" fn recall_continuation(idx: u32) -> SkewedPtr { if TABLE.0 == 0 { - rts_trap_with("recall_closure: Closure table not allocated"); + rts_trap_with("recall_continuation: Continuation table not allocated"); } if idx >= TABLE.as_array().len() { - rts_trap_with("recall_closure: Closure index out of range"); + rts_trap_with("recall_continuation: Continuation index out of range"); } let ptr = TABLE.as_array().get(idx); @@ -132,28 +135,28 @@ pub unsafe extern "C" fn recall_closure(idx: u32) -> SkewedPtr { .set(idx, SkewedPtr((FREE_SLOT << 2) as usize)); FREE_SLOT = idx; - N_CLOSURES -= 1; + N_CONTINUATIONS -= 1; if ptr.0 & 0b1 != 1 { - rts_trap_with("recall_closure: Closure index not in table"); + rts_trap_with("recall_continuation: Continuation index not in table"); } ptr } #[no_mangle] -pub unsafe extern "C" fn closure_count() -> u32 { - N_CLOSURES +pub unsafe extern "C" fn continuation_count() -> u32 { + N_CONTINUATIONS } #[cfg(feature = "ic")] -pub(crate) unsafe fn closure_table_loc() -> *mut SkewedPtr { +pub(crate) unsafe fn continuation_table_loc() -> *mut SkewedPtr { &mut TABLE } #[cfg(feature = "ic")] #[no_mangle] -unsafe extern "C" fn closure_table_size() -> u32 { +unsafe extern "C" fn continuation_table_size() -> u32 { if TABLE.0 == 0 { 0 } else { diff --git a/rts/motoko-rts/src/debug.rs b/rts/motoko-rts/src/debug.rs index 8c395af836d..d8ce4469c39 100644 --- a/rts/motoko-rts/src/debug.rs +++ b/rts/motoko-rts/src/debug.rs @@ -25,14 +25,14 @@ pub unsafe fn dump_heap( heap_base: u32, hp: u32, static_roots: SkewedPtr, - closure_table_loc: *mut SkewedPtr, + continuation_table_loc: *mut SkewedPtr, ) { - print_closure_table(closure_table_loc); + print_continuation_table(continuation_table_loc); print_static_roots(static_roots); print_heap(heap_base, hp); } -pub(crate) unsafe fn print_closure_table(closure_tbl_loc: *mut SkewedPtr) { +pub(crate) unsafe fn print_continuation_table(closure_tbl_loc: *mut SkewedPtr) { if (*closure_tbl_loc).0 == 0 { println!(100, "Closure table not initialized"); return; diff --git a/rts/motoko-rts/src/gc/copying.rs b/rts/motoko-rts/src/gc/copying.rs index 8e4cc48a265..8ab2ec531cb 100644 --- a/rts/motoko-rts/src/gc/copying.rs +++ b/rts/motoko-rts/src/gc/copying.rs @@ -23,7 +23,7 @@ unsafe fn copying_gc(mem: &mut M) { // set_hp |hp| ic::HP = hp, ic::get_static_roots(), - crate::closure_table::closure_table_loc(), + crate::continuation_table::continuation_table_loc(), // note_live_size |live_size| ic::MAX_LIVE = ::core::cmp::max(ic::MAX_LIVE, live_size), // note_reclaimed @@ -45,7 +45,7 @@ pub unsafe fn copying_gc_internal< get_hp: GetHp, mut set_hp: SetHp, static_roots: SkewedPtr, - closure_table_loc: *mut SkewedPtr, + continuation_table_loc: *mut SkewedPtr, note_live_size: NoteLiveSize, note_reclaimed: NoteReclaimed, ) { @@ -58,12 +58,12 @@ pub unsafe fn copying_gc_internal< // Evacuate roots evac_static_roots(mem, begin_from_space, begin_to_space, static_roots); - if (*closure_table_loc).unskew() >= begin_from_space { + if (*continuation_table_loc).unskew() >= begin_from_space { evac( mem, begin_from_space, begin_to_space, - closure_table_loc as usize, + continuation_table_loc as usize, ); } diff --git a/rts/motoko-rts/src/gc/mark_compact.rs b/rts/motoko-rts/src/gc/mark_compact.rs index 2cada0be88f..0cd2d30b385 100644 --- a/rts/motoko-rts/src/gc/mark_compact.rs +++ b/rts/motoko-rts/src/gc/mark_compact.rs @@ -35,7 +35,7 @@ unsafe fn compacting_gc(mem: &mut M) { // set_hp |hp| ic::HP = hp, ic::get_static_roots(), - crate::closure_table::closure_table_loc(), + crate::continuation_table::continuation_table_loc(), // note_live_size |live_size| ic::MAX_LIVE = ::core::cmp::max(ic::MAX_LIVE, live_size), // note_reclaimed @@ -57,7 +57,7 @@ pub unsafe fn compacting_gc_internal< get_hp: GetHp, set_hp: SetHp, static_roots: SkewedPtr, - closure_table_ptr_loc: *mut SkewedPtr, + continuation_table_ptr_loc: *mut SkewedPtr, note_live_size: NoteLiveSize, note_reclaimed: NoteReclaimed, ) { @@ -69,7 +69,7 @@ pub unsafe fn compacting_gc_internal< heap_base, old_hp, static_roots, - closure_table_ptr_loc, + continuation_table_ptr_loc, ); let reclaimed = old_hp - (get_hp() as u32); @@ -85,7 +85,7 @@ unsafe fn mark_compact( heap_base: u32, heap_end: u32, static_roots: SkewedPtr, - closure_table_ptr_loc: *mut SkewedPtr, + continuation_table_ptr_loc: *mut SkewedPtr, ) { let mem_size = Bytes(heap_end - heap_base); @@ -94,12 +94,12 @@ unsafe fn mark_compact( mark_static_roots(mem, static_roots, heap_base); - if (*closure_table_ptr_loc).unskew() >= heap_base as usize { - // TODO: No need to check if closure table is already marked - mark_object(mem, *closure_table_ptr_loc, heap_base); - // Similar to `mark_root_mutbox_fields`, `closure_table_ptr_loc` is in static heap so it - // will be readable when we unthread closure table - thread(closure_table_ptr_loc); + if (*continuation_table_ptr_loc).unskew() >= heap_base as usize { + // TODO: No need to check if continuation table is already marked + mark_object(mem, *continuation_table_ptr_loc, heap_base); + // Similar to `mark_root_mutbox_fields`, `continuation_table_ptr_loc` is in static heap so it + // will be readable when we unthread continuation table + thread(continuation_table_ptr_loc); } mark_stack(mem, heap_base); diff --git a/rts/motoko-rts/src/lib.rs b/rts/motoko-rts/src/lib.rs index dffe486b34b..db5743153a0 100644 --- a/rts/motoko-rts/src/lib.rs +++ b/rts/motoko-rts/src/lib.rs @@ -20,8 +20,8 @@ pub mod bigint; mod blob_iter; pub mod buf; mod char; -pub mod closure_table; pub mod constants; +pub mod continuation_table; pub mod gc; pub mod leb128; mod mem_utils; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index bf1b3c5db61..eb89b40fcc9 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -788,11 +788,11 @@ module RTS = struct E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "find_field" [I32Type; I32Type; I32Type; I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "skip_fields" [I32Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "rts" "remember_closure" [I32Type] [I32Type]; - E.add_func_import env "rts" "recall_closure" [I32Type] [I32Type]; - E.add_func_import env "rts" "peek_future_closure" [I32Type] [I32Type]; - E.add_func_import env "rts" "closure_count" [] [I32Type]; - E.add_func_import env "rts" "closure_table_size" [] [I32Type]; + E.add_func_import env "rts" "remember_continuation" [I32Type] [I32Type]; + E.add_func_import env "rts" "recall_continuation" [I32Type] [I32Type]; + E.add_func_import env "rts" "peek_future_continuation" [I32Type] [I32Type]; + E.add_func_import env "rts" "continuation_count" [] [I32Type]; + E.add_func_import env "rts" "continuation_table_size" [] [I32Type]; E.add_func_import env "rts" "blob_of_text" [I32Type] [I32Type]; E.add_func_import env "rts" "text_compare" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "text_concat" [I32Type; I32Type] [I32Type]; @@ -990,14 +990,14 @@ module Stack = struct end (* Stack *) -module ClosureTable = struct +module ContinuationTable = struct (* See rts/motoko-rts/src/closure_table.rs *) - let remember env : G.t = E.call_import env "rts" "remember_closure" - let recall env : G.t = E.call_import env "rts" "recall_closure" - let peek_future env : G.t = E.call_import env "rts" "peek_future_closure" - let count env : G.t = E.call_import env "rts" "closure_count" - let size env : G.t = E.call_import env "rts" "closure_table_size" -end (* ClosureTable *) + let remember env : G.t = E.call_import env "rts" "remember_continuation" + let recall env : G.t = E.call_import env "rts" "recall_continuation" + let peek_future env : G.t = E.call_import env "rts" "peek_future_continuation" + let count env : G.t = E.call_import env "rts" "continuation_count" + let size env : G.t = E.call_import env "rts" "continuation_table_size" +end (* ContinuationTable *) module Bool = struct (* Boolean literals are either 0 or 1, @@ -3490,7 +3490,7 @@ module IC = struct G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ G.if_ [] (G.nop) - (ClosureTable.count env ^^ + (ContinuationTable.count env ^^ E.then_trap_with env "canister_pre_upgrade attempted with outstanding message callbacks (try stopping the canister before upgrade)") ^^ (* call pre_upgrade expression & any system method *) (G.i (Call (nr (E.built_in env "pre_exp")))) ^^ @@ -5728,7 +5728,7 @@ module FuncDec = struct StackRep.adjust env sr SR.Vanilla (* Takes the reply and reject callbacks, tuples them up (with administrative extras), - adds them to the closure table, and returns the two callbacks expected by + adds them to the continuation table, and returns the two callbacks expected by ic.call_new. The tupling is necessary because we want to free _both_/_all_ closures @@ -5742,10 +5742,10 @@ module FuncDec = struct let reply_name = "@callback<" ^ Typ_hash.typ_hash (Type.Tup ts) ^ ">" in Func.define_built_in env reply_name ["env", I32Type] [] (fun env -> message_start env (Type.Shared Type.Write) ^^ - (* Look up closure *) + (* Look up continuation *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall env ^^ + ContinuationTable.recall env ^^ Arr.load_field 0l ^^ (* get the reply closure *) set_closure ^^ get_closure ^^ @@ -5762,10 +5762,10 @@ module FuncDec = struct let reject_name = "@reject_callback" in Func.define_built_in env reject_name ["env", I32Type] [] (fun env -> message_start env (Type.Shared Type.Write) ^^ - (* Look up closure *) + (* Look up continuation *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall env ^^ + ContinuationTable.recall env ^^ Arr.load_field 1l ^^ (* get the reject closure *) set_closure ^^ get_closure ^^ @@ -5785,7 +5785,7 @@ module FuncDec = struct fun closure_getters -> let (set_cb_index, get_cb_index) = new_local env "cb_index" in Arr.lit env closure_getters ^^ - ClosureTable.remember env ^^ + ContinuationTable.remember env ^^ set_cb_index ^^ (* return arguments for the ic.call *) @@ -5803,7 +5803,7 @@ module FuncDec = struct let name = "@cleanup_callback" in Func.define_built_in env name ["env", I32Type] [] (fun env -> G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall env ^^ + ContinuationTable.recall env ^^ G.i Drop); compile_unboxed_const (E.add_fun_ptr env (E.built_in env name)) @@ -5849,7 +5849,7 @@ module FuncDec = struct env "self call" get_meth_pair - (* Storing the tuple away, future_array_index = 2, keep in sync with rts/closure_table.rs *) + (* Storing the tuple away, future_array_index = 2, keep in sync with rts/continuation_table.rs *) (closures_to_reply_reject_callbacks env ts [get_k; get_r; get_future]) (fun get_cb_index -> get_cb_index ^^ @@ -5910,10 +5910,10 @@ module FuncDec = struct (* Check that we are calling this *) IC.assert_caller_self env ^^ - (* Deserialize and look up closure argument *) + (* Deserialize and look up continuation argument *) Serialization.deserialize env Type.[Prim Nat32] ^^ BoxedSmallWord.unbox env ^^ - ClosureTable.peek_future env ^^ + ContinuationTable.peek_future env ^^ set_closure ^^ get_closure ^^ get_closure ^^ Closure.call_closure env 0 0 ^^ message_cleanup env (Type.Shared Type.Write) @@ -7264,11 +7264,11 @@ and compile_exp (env : E.t) ae exp = | OtherPrim "rts_callback_table_count", [] -> SR.Vanilla, - ClosureTable.count env ^^ Prim.prim_word32toNat env + ContinuationTable.count env ^^ Prim.prim_word32toNat env | OtherPrim "rts_callback_table_size", [] -> SR.Vanilla, - ClosureTable.size env ^^ Prim.prim_word32toNat env + ContinuationTable.size env ^^ Prim.prim_word32toNat env | OtherPrim "crc32Hash", [e] -> SR.UnboxedWord32,