From 1211532667eacbed5bf270b3b1faec5b43f255f0 Mon Sep 17 00:00:00 2001 From: luc-blaeser Date: Fri, 5 Jul 2024 11:59:11 +0200 Subject: [PATCH 1/3] Stable option --- rts/motoko-rts-tests/src/main.rs | 2 + rts/motoko-rts-tests/src/stable_option.rs | 24 ++++++++ rts/motoko-rts/src/gc/incremental.rs | 10 ++-- .../src/gc/incremental/partitioned_heap.rs | 11 ++-- .../phases/evacuation_increment.rs | 5 +- .../gc/incremental/phases/mark_increment.rs | 5 +- .../gc/incremental/phases/update_increment.rs | 5 +- rts/motoko-rts/src/lib.rs | 2 + rts/motoko-rts/src/stable_option.rs | 55 +++++++++++++++++++ 9 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 rts/motoko-rts-tests/src/stable_option.rs create mode 100644 rts/motoko-rts/src/stable_option.rs diff --git a/rts/motoko-rts-tests/src/main.rs b/rts/motoko-rts-tests/src/main.rs index c1dd4f4e505..7e0b3e1dcfb 100644 --- a/rts/motoko-rts-tests/src/main.rs +++ b/rts/motoko-rts-tests/src/main.rs @@ -8,6 +8,7 @@ mod gc; mod leb128; mod memory; mod principal_id; +mod stable_option; mod text; mod utf8; @@ -28,6 +29,7 @@ fn main() { gc::test(); leb128::test(); principal_id::test(); + stable_option::test(); text::test(); utf8::test(); } diff --git a/rts/motoko-rts-tests/src/stable_option.rs b/rts/motoko-rts-tests/src/stable_option.rs new file mode 100644 index 00000000000..bf150dd54ba --- /dev/null +++ b/rts/motoko-rts-tests/src/stable_option.rs @@ -0,0 +1,24 @@ +use motoko_rts::stable_option::StableOption; + +pub fn test() { + println!("Testing StableOption ..."); + + let mut none: StableOption = StableOption::None; + assert!(none.is_none()); + assert!(!none.is_some()); + assert!(none.as_ref().is_none()); + assert!(!none.as_ref().is_some()); + assert!(none.as_mut().is_none()); + assert!(!none.as_mut().is_some()); + + const TEST_VALUE: usize = 123456; + let mut some = Some(TEST_VALUE); + assert!(!some.is_none()); + assert!(some.is_some()); + assert_eq!(some.unwrap(), TEST_VALUE); + assert_eq!(some.as_ref().unwrap(), &TEST_VALUE); + assert_eq!(*some.as_mut().unwrap(), TEST_VALUE); + + *some.as_mut().unwrap() = 0; + assert_eq!(some.unwrap(), 0); +} diff --git a/rts/motoko-rts/src/gc/incremental.rs b/rts/motoko-rts/src/gc/incremental.rs index 79f2f2bd66b..ce6d8956577 100644 --- a/rts/motoko-rts/src/gc/incremental.rs +++ b/rts/motoko-rts/src/gc/incremental.rs @@ -13,7 +13,7 @@ use motoko_rts_macros::ic_mem_fn; -use crate::{memory::Memory, types::*, visitor::visit_pointer_fields}; +use crate::{memory::Memory, stable_option::StableOption, types::*, visitor::visit_pointer_fields}; use self::{ partitioned_heap::{PartitionedHeap, PartitionedHeapIterator}, @@ -162,8 +162,8 @@ pub struct State { phase: Phase, partitioned_heap: PartitionedHeap, allocation_count: usize, // Number of allocations during an active GC run. - mark_state: Option, - iterator_state: Option, + mark_state: StableOption, + iterator_state: StableOption, statistics: Statistics, } @@ -191,8 +191,8 @@ impl<'a, M: Memory + 'a> IncrementalGC<'a, M> { phase: Phase::Pause, partitioned_heap, allocation_count: 0, - mark_state: None, - iterator_state: None, + mark_state: StableOption::None, + iterator_state: StableOption::None, statistics, } } diff --git a/rts/motoko-rts/src/gc/incremental/partitioned_heap.rs b/rts/motoko-rts/src/gc/incremental/partitioned_heap.rs index bb59667270e..3e9765da092 100644 --- a/rts/motoko-rts/src/gc/incremental/partitioned_heap.rs +++ b/rts/motoko-rts/src/gc/incremental/partitioned_heap.rs @@ -45,6 +45,7 @@ use crate::{ gc::incremental::mark_bitmap::BITMAP_ITERATION_END, memory::Memory, rts_trap_with, + stable_option::StableOption, types::*, }; @@ -231,7 +232,7 @@ impl Partition { #[repr(C)] pub struct PartitionedHeapIterator { partition_index: usize, - bitmap_iterator: Option, + bitmap_iterator: StableOption, visit_large_object: bool, } @@ -239,7 +240,7 @@ impl PartitionedHeapIterator { pub fn new(heap: &PartitionedHeap) -> PartitionedHeapIterator { let mut iterator = PartitionedHeapIterator { partition_index: 0, - bitmap_iterator: None, + bitmap_iterator: StableOption::None, visit_large_object: false, }; iterator.skip_empty_partitions(heap); @@ -286,15 +287,15 @@ impl PartitionedHeapIterator { fn start_object_iteration(&mut self, heap: &PartitionedHeap) { debug_assert!(self.partition_index <= MAX_PARTITIONS); if self.partition_index == MAX_PARTITIONS { - self.bitmap_iterator = None; + self.bitmap_iterator = StableOption::None; self.visit_large_object = false; } else { let partition = heap.get_partition(self.partition_index); if partition.has_large_content() { - self.bitmap_iterator = None; + self.bitmap_iterator = StableOption::None; self.visit_large_object = partition.marked_size() > 0 } else { - self.bitmap_iterator = Some(partition.get_bitmap().iterate()); + self.bitmap_iterator = StableOption::Some(partition.get_bitmap().iterate()); self.visit_large_object = false; } } diff --git a/rts/motoko-rts/src/gc/incremental/phases/evacuation_increment.rs b/rts/motoko-rts/src/gc/incremental/phases/evacuation_increment.rs index 58f90925f31..548f0f62b07 100644 --- a/rts/motoko-rts/src/gc/incremental/phases/evacuation_increment.rs +++ b/rts/motoko-rts/src/gc/incremental/phases/evacuation_increment.rs @@ -6,6 +6,7 @@ use crate::{ }, mem_utils::memcpy_words, memory::Memory, + stable_option::StableOption, types::*, }; @@ -20,13 +21,13 @@ impl<'a, M: Memory + 'a> EvacuationIncrement<'a, M> { pub unsafe fn start_phase(state: &mut State) { debug_assert!(state.iterator_state.is_none()); let heap = &mut state.partitioned_heap; - state.iterator_state = Some(PartitionedHeapIterator::new(heap)); + state.iterator_state = StableOption::Some(PartitionedHeapIterator::new(heap)); heap.plan_evacuations(); } pub unsafe fn complete_phase(state: &mut State) { debug_assert!(Self::evacuation_completed(state)); - state.iterator_state = None; + state.iterator_state = StableOption::None; } pub unsafe fn evacuation_completed(state: &State) -> bool { diff --git a/rts/motoko-rts/src/gc/incremental/phases/mark_increment.rs b/rts/motoko-rts/src/gc/incremental/phases/mark_increment.rs index 92fe4836a84..e71c8be3713 100644 --- a/rts/motoko-rts/src/gc/incremental/phases/mark_increment.rs +++ b/rts/motoko-rts/src/gc/incremental/phases/mark_increment.rs @@ -8,6 +8,7 @@ use crate::{ State, }, memory::Memory, + stable_option::StableOption, types::*, visitor::visit_pointer_fields, }; @@ -32,7 +33,7 @@ impl<'a, M: Memory + 'a> MarkIncrement<'a, M> { state.partitioned_heap.start_collection(mem, time); debug_assert!(state.mark_state.is_none()); let mark_stack = MarkStack::new(mem); - state.mark_state = Some(MarkState { + state.mark_state = StableOption::Some(MarkState { mark_stack, complete: false, }); @@ -40,7 +41,7 @@ impl<'a, M: Memory + 'a> MarkIncrement<'a, M> { pub unsafe fn complete_phase(state: &mut State) { debug_assert!(Self::mark_completed(state)); - state.mark_state = None; + state.mark_state = StableOption::None; } pub unsafe fn mark_completed(state: &State) -> bool { diff --git a/rts/motoko-rts/src/gc/incremental/phases/update_increment.rs b/rts/motoko-rts/src/gc/incremental/phases/update_increment.rs index 4403296c812..57e0dc21c54 100644 --- a/rts/motoko-rts/src/gc/incremental/phases/update_increment.rs +++ b/rts/motoko-rts/src/gc/incremental/phases/update_increment.rs @@ -6,6 +6,7 @@ use crate::{ time::BoundedTime, Roots, State, }, + stable_option::StableOption, types::*, visitor::visit_pointer_fields, }; @@ -21,14 +22,14 @@ impl<'a> UpdateIncrement<'a> { pub unsafe fn start_phase(state: &mut State) { debug_assert!(state.iterator_state.is_none()); let heap = &mut state.partitioned_heap; - state.iterator_state = Some(PartitionedHeapIterator::new(heap)); + state.iterator_state = StableOption::Some(PartitionedHeapIterator::new(heap)); heap.collect_large_objects(); heap.plan_updates(); } pub unsafe fn complete_phase(state: &mut State) { debug_assert!(Self::update_completed(state)); - state.iterator_state = None; + state.iterator_state = StableOption::None; state.partitioned_heap.complete_collection(); } diff --git a/rts/motoko-rts/src/lib.rs b/rts/motoko-rts/src/lib.rs index 8700941789a..52130eba35f 100644 --- a/rts/motoko-rts/src/lib.rs +++ b/rts/motoko-rts/src/lib.rs @@ -13,6 +13,8 @@ extern crate alloc; #[cfg(feature = "ic")] pub mod allocator; +pub mod stable_option; + #[macro_use] mod print; diff --git a/rts/motoko-rts/src/stable_option.rs b/rts/motoko-rts/src/stable_option.rs new file mode 100644 index 00000000000..9a5f9f9a1a1 --- /dev/null +++ b/rts/motoko-rts/src/stable_option.rs @@ -0,0 +1,55 @@ +//! Option type with a fixed C-representation. +//! This is used as a long-term option type in the persistent metata, +//! such as the garbage collector state. +//! As the native Rust type may change in future Rust releases, +//! the Motoko runtime system uses its own dedicated `Option` type +//! with a fixed long-term representation. This is used in the persistent +//! metadata, such as in the garbage collector state. +//! See: +//! * `gc::incremental::State` +//! * `gc::partitioned_heap::PartitionedHeapIterator` + +/// Stable option type used for orthogonal persistent state. +/// Analogous use like the Rust-native `Option`. +#[repr(C)] +pub enum StableOption { + None, + Some(T), +} + +impl StableOption { + pub const fn is_none(&self) -> bool { + match self { + Self::None => true, + Self::Some(_) => false, + } + } + + pub const fn is_some(&self) -> bool { + match self { + Self::None => false, + Self::Some(_) => true, + } + } + + pub fn unwrap(self) -> T { + match self { + Self::None => panic!("Unwrapping `None` on `StableOption`"), + Self::Some(x) => x, + } + } + + pub fn as_mut(&mut self) -> StableOption<&mut T> { + match *self { + Self::Some(ref mut x) => StableOption::Some(x), + Self::None => StableOption::None, + } + } + + pub const fn as_ref(&self) -> StableOption<&T> { + match *self { + Self::Some(ref x) => StableOption::Some(x), + Self::None => StableOption::None, + } + } +} From edb9a866ca93f0d00c0c79d78cabf90fc8e61868 Mon Sep 17 00:00:00 2001 From: Luc Blaeser <112870813+luc-blaeser@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:36:31 +0200 Subject: [PATCH 2/3] Refine comment --- rts/motoko-rts/src/stable_option.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/rts/motoko-rts/src/stable_option.rs b/rts/motoko-rts/src/stable_option.rs index 9a5f9f9a1a1..6344851d130 100644 --- a/rts/motoko-rts/src/stable_option.rs +++ b/rts/motoko-rts/src/stable_option.rs @@ -1,10 +1,8 @@ -//! Option type with a fixed C-representation. -//! This is used as a long-term option type in the persistent metata, -//! such as the garbage collector state. +//! Customized option type with a fixed C-representation. //! As the native Rust type may change in future Rust releases, -//! the Motoko runtime system uses its own dedicated `Option` type -//! with a fixed long-term representation. This is used in the persistent -//! metadata, such as in the garbage collector state. +//! the Motoko runtime system uses its own dedicated `StableOption` +//! type with a fixed long-term representation. This is used in the +//! persistent metadata, such as in the garbage collector state. //! See: //! * `gc::incremental::State` //! * `gc::partitioned_heap::PartitionedHeapIterator` From b0bfde19d685927d0b1fad9fbcbf25cf8f2ab898 Mon Sep 17 00:00:00 2001 From: luc-blaeser Date: Fri, 5 Jul 2024 14:52:47 +0200 Subject: [PATCH 3/3] Reformat --- rts/motoko-rts/src/stable_option.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rts/motoko-rts/src/stable_option.rs b/rts/motoko-rts/src/stable_option.rs index 6344851d130..48669954d98 100644 --- a/rts/motoko-rts/src/stable_option.rs +++ b/rts/motoko-rts/src/stable_option.rs @@ -1,7 +1,7 @@ //! Customized option type with a fixed C-representation. //! As the native Rust type may change in future Rust releases, -//! the Motoko runtime system uses its own dedicated `StableOption` -//! type with a fixed long-term representation. This is used in the +//! the Motoko runtime system uses its own dedicated `StableOption` +//! type with a fixed long-term representation. This is used in the //! persistent metadata, such as in the garbage collector state. //! See: //! * `gc::incremental::State`