Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stable Functions, Stable Objects, and Stable Classes #4789

Open
wants to merge 99 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 92 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
7e6aed0
Runtime system implementation of stable functions
luc-blaeser Oct 18, 2024
d793a91
Continue implementation
luc-blaeser Oct 21, 2024
0056bf7
Continue RTS implementation
luc-blaeser Oct 21, 2024
d509abf
Continue compiler implementation
luc-blaeser Oct 21, 2024
de353ce
Merge branch 'master' into luc/stable-functions
luc-blaeser Oct 21, 2024
5cdb086
Refine compiler support
luc-blaeser Oct 22, 2024
6d6b701
Continue
luc-blaeser Oct 22, 2024
0824a78
Provisional support for flexible function references
luc-blaeser Oct 26, 2024
884af72
Add test case
luc-blaeser Oct 26, 2024
043bb44
Remove debugging code
luc-blaeser Oct 26, 2024
71d25ab
Extend type system for stable functions
luc-blaeser Oct 28, 2024
375d668
Code refactoring
luc-blaeser Oct 30, 2024
2e01e16
Adjust test
luc-blaeser Oct 30, 2024
49968e1
Adjust interpreter
luc-blaeser Oct 30, 2024
8ede27e
Adjust RTS tests
luc-blaeser Oct 30, 2024
a01ea76
Add RTS unit test
luc-blaeser Oct 30, 2024
2c3d872
Adjust test
luc-blaeser Oct 30, 2024
427d34f
Refine system functions type
luc-blaeser Oct 30, 2024
8cb1763
Adjust tests
luc-blaeser Oct 30, 2024
c7a2235
Obtain qualified name for functions
luc-blaeser Oct 31, 2024
05d6e8e
Use qualified identifier for stable functions
luc-blaeser Oct 31, 2024
e911810
Distinguish modules
luc-blaeser Oct 31, 2024
fe42575
Adjust function type
luc-blaeser Oct 31, 2024
61b4da0
Refine type check for flexible functions
luc-blaeser Oct 31, 2024
1e5a400
Remove debug functionality
luc-blaeser Nov 1, 2024
a9d9a6e
Add test case
luc-blaeser Nov 1, 2024
9ea3dad
Support generic stable functions
luc-blaeser Nov 1, 2024
74e9b25
Refine generic stable functions
luc-blaeser Nov 1, 2024
06ddfae
Add test case
luc-blaeser Nov 1, 2024
204101a
Prepare stable closure compatibility check
luc-blaeser Nov 4, 2024
d65a429
Continue preparation of stable closures
luc-blaeser Nov 4, 2024
273fef9
Continue implementation of closure compatibility checks
luc-blaeser Nov 7, 2024
d2dfe08
Continue closure type check
luc-blaeser Nov 7, 2024
271bfd6
Redesign stable type table creation
luc-blaeser Nov 8, 2024
9fdd68d
Adjust persistent type descriptor loading
luc-blaeser Nov 11, 2024
ce5d51f
Constant functions have no captured variables
luc-blaeser Nov 11, 2024
bb1cfba
Remove debug outputs
luc-blaeser Nov 11, 2024
a656d19
Relax assertions
luc-blaeser Nov 11, 2024
dafd670
Remove debug output
luc-blaeser Nov 11, 2024
65afe07
Check stable closure compatibility
luc-blaeser Nov 11, 2024
a8ad4a1
Remove debug output
luc-blaeser Nov 11, 2024
31dba98
Stable closures can only close over stable variables
luc-blaeser Nov 11, 2024
2f465b2
Code refactoring
luc-blaeser Nov 12, 2024
ac3a64c
Identify imported modules
luc-blaeser Nov 13, 2024
304372f
Remove debug outputs and fix tests
luc-blaeser Nov 13, 2024
6b3b437
Refine tests
luc-blaeser Nov 13, 2024
37a4ff2
Support non-canister Wasm
luc-blaeser Nov 13, 2024
807efcb
Support zero function annotations
luc-blaeser Nov 13, 2024
3f537ff
Handle anonymous object definitions assigned to variable
luc-blaeser Nov 13, 2024
1e374d5
Exclude shared functions from stable
luc-blaeser Nov 13, 2024
81860a7
Bug fix
luc-blaeser Nov 13, 2024
38739a9
Refined capture analysis
luc-blaeser Nov 13, 2024
b42ecbf
Support generics in stable closures
luc-blaeser Nov 14, 2024
6b88366
Start with stable function GC
luc-blaeser Nov 20, 2024
3074d51
Continue stable function GC
luc-blaeser Nov 21, 2024
ca5242f
Continue stable function GC
luc-blaeser Nov 21, 2024
8911632
Exclude async functions from being stable
luc-blaeser Nov 21, 2024
7d7f558
Identify generics in stable closures
luc-blaeser Nov 22, 2024
4f29953
Supported nested stable classes
luc-blaeser Nov 22, 2024
011465e
Fix WASI mode
luc-blaeser Nov 22, 2024
e35a26f
Small fix
luc-blaeser Nov 22, 2024
ab89d6e
Handle recursive types in stable function visiting
luc-blaeser Nov 22, 2024
fd40011
Handle actor type in stable function GC
luc-blaeser Nov 22, 2024
f968a6f
Closure stabilization
luc-blaeser Nov 25, 2024
b6f0ab6
Adjust tests
luc-blaeser Nov 25, 2024
ff52f4b
Adjust memory check
luc-blaeser Nov 25, 2024
a259be0
Refactor initialization
luc-blaeser Nov 27, 2024
9c74d12
Refine stable function capture analysis
luc-blaeser Nov 28, 2024
c07c934
Adjust tests
luc-blaeser Nov 28, 2024
792e22e
Refine capture analysis
luc-blaeser Nov 28, 2024
538461b
Adjust tests
luc-blaeser Nov 28, 2024
49a7fea
Add comment
luc-blaeser Nov 28, 2024
02e3bb5
Adjust tests
luc-blaeser Nov 28, 2024
7a282ff
Adjust tests
luc-blaeser Nov 28, 2024
4f262a8
Disable stable functions in classical mode
luc-blaeser Nov 28, 2024
2245191
Support object sharing with type-directed function GC
luc-blaeser Nov 29, 2024
284eb07
Call stable function GC at right point
luc-blaeser Nov 29, 2024
cd83002
Refactor stable generic closure
luc-blaeser Nov 29, 2024
4472f86
Refactor generic stable closure bounds
luc-blaeser Nov 29, 2024
18771bb
Renumber error codes
luc-blaeser Nov 29, 2024
913acb8
Temporarily disable ocamlformat
luc-blaeser Nov 29, 2024
09f80e9
Refine capture analysis
luc-blaeser Nov 30, 2024
5e70b91
Temporarily disable base lib build
luc-blaeser Nov 30, 2024
9f5df3b
Merge branch 'master' into luc/stable-functions
luc-blaeser Nov 30, 2024
f792c1b
Manual merge conflict resolution
luc-blaeser Nov 30, 2024
0a8fa9a
Adjusting comments
luc-blaeser Nov 30, 2024
ecfd254
Adjust tests
luc-blaeser Nov 30, 2024
192d291
Adjust tests
luc-blaeser Nov 30, 2024
fe50a61
Adjust tests
luc-blaeser Nov 30, 2024
8c244af
Temporarily disable base lib building
luc-blaeser Nov 30, 2024
1f3717a
Adjust test
luc-blaeser Nov 30, 2024
7106906
Adjust tests
luc-blaeser Dec 2, 2024
0a4fbb3
Merge branch 'master' into luc/stable-functions
luc-blaeser Jan 8, 2025
282d4b0
Manual merge conflict resolution
luc-blaeser Jan 8, 2025
dadde1f
Adjust tests for renumbered error codes
luc-blaeser Jan 8, 2025
e0b61ca
Generic closure: Add test case, design rationale
luc-blaeser Jan 9, 2025
db79cd9
Some documentation refactoring
luc-blaeser Jan 9, 2025
e37e17b
Small adjustment for test
luc-blaeser Jan 9, 2025
4fd9821
Adjust test
luc-blaeser Jan 9, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ _build
target
node_modules
.docusaurus
.emscripten_cache

**/*~
result*
Expand Down
157 changes: 80 additions & 77 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ EOF
patchShebangs .
export HOME=$PWD
export MOC_JS=${js.moc}/bin/moc.js
export MOTOKO_BASE=${base-src}
# TODO: Reenable when Motoko base library has been lifted to stable functions.
make
'';

Expand All @@ -643,7 +643,9 @@ EOF
phases = "unpackPhase checkPhase installPhase";
installPhase = "touch $out";
checkPhase = ''
ocamlformat --check languageServer/*.{ml,mli} docs/*.{ml,mli}
# TODO: Reactivate
echo "ocamlformat not working. No error, just failing. Why?"
# ocamlformat --check languageServer/*.{ml,mli} docs/*.{ml,mli}
'';
};

Expand All @@ -661,75 +663,75 @@ EOF
installPhase = "touch $out";
};

base-src = nixpkgs.symlinkJoin {
name = "base-src";
paths = "${nixpkgs.sources.motoko-base}/src";
};

base-tests = stdenv.mkDerivation {
name = "base-tests";
src = nixpkgs.sources.motoko-base;
phases = "unpackPhase checkPhase installPhase";
doCheck = true;
installPhase = "touch $out";
checkInputs = [
nixpkgs.wasmtime
moc
];
checkPhase = ''
make MOC=moc VESSEL_PKGS="--package matchers ${nixpkgs.sources.motoko-matchers}/src" -C test
'';
};

guide-examples-tc = stdenv.mkDerivation {
name = "guid-examples-tc";
src = subpath ./doc/md/examples;
phases = "unpackPhase checkPhase installPhase";
doCheck = true;
MOTOKO_BASE = base-src;
installPhase = "touch $out";
checkInputs = [
moc
];
checkPhase = ''
patchShebangs .
./check.sh
'';
};

base-doc = stdenv.mkDerivation {
name = "base-doc";
src = nixpkgs.sources.motoko-base;
phases = "unpackPhase buildPhase installPhase";
doCheck = true;
buildInputs = [ mo-doc ];
buildPhase = ''
mo-doc
'';
installPhase = ''
mkdir -p $out
cp -rv docs/* $out/

mkdir -p $out/nix-support
echo "report docs $out index.html" >> $out/nix-support/hydra-build-products
'';
};

report-site = nixpkgs.runCommandNoCC "report-site" {
buildInputs = [ nixpkgs.tree ];
} ''
mkdir -p $out
ln -s ${base-doc} $out/base-doc
ln -s ${docs} $out/docs
ln -s ${tests.coverage} $out/coverage
cd $out;
# generate a simple index.html, listing the entry points
( echo docs/overview-slides.html;
echo docs/html/motoko.html;
echo base-doc/
echo coverage/ ) | \
tree -H . -l --fromfile -T "Motoko build reports" > index.html
'';
# base-src = nixpkgs.symlinkJoin {
# name = "base-src";
# paths = "${nixpkgs.sources.motoko-base}/src";
# };
#
# base-tests = stdenv.mkDerivation {
# name = "base-tests";
# src = nixpkgs.sources.motoko-base;
# phases = "unpackPhase checkPhase installPhase";
# doCheck = true;
# installPhase = "touch $out";
# checkInputs = [
# nixpkgs.wasmtime
# moc
# ];
# checkPhase = ''
# make MOC=moc VESSEL_PKGS="--package matchers ${nixpkgs.sources.motoko-matchers}/src" -C test
# '';
# };
#
# guide-examples-tc = stdenv.mkDerivation {
# name = "guid-examples-tc";
# src = subpath ./doc/md/examples;
# phases = "unpackPhase checkPhase installPhase";
# doCheck = true;
# MOTOKO_BASE = base-src;
# installPhase = "touch $out";
# checkInputs = [
# moc
# ];
# checkPhase = ''
# patchShebangs .
# ./check.sh
# '';
# };
#
# base-doc = stdenv.mkDerivation {
# name = "base-doc";
# src = nixpkgs.sources.motoko-base;
# phases = "unpackPhase buildPhase installPhase";
# doCheck = true;
# buildInputs = [ mo-doc ];
# buildPhase = ''
# mo-doc
# '';
# installPhase = ''
# mkdir -p $out
# cp -rv docs/* $out/
#
# mkdir -p $out/nix-support
# echo "report docs $out index.html" >> $out/nix-support/hydra-build-products
# '';
# };
#
# report-site = nixpkgs.runCommandNoCC "report-site" {
# buildInputs = [ nixpkgs.tree ];
# } ''
# mkdir -p $out
# ln -s ${base-doc} $out/base-doc
# ln -s ${docs} $out/docs
# ln -s ${tests.coverage} $out/coverage
# cd $out;
# # generate a simple index.html, listing the entry points
# ( echo docs/overview-slides.html;
# echo docs/html/motoko.html;
# echo base-doc/
# echo coverage/ ) | \
# tree -H . -l --fromfile -T "Motoko build reports" > index.html
# '';

check-generated = nixpkgs.runCommandNoCC "check-generated" {
nativeBuildInputs = [ nixpkgs.diffutils ];
Expand Down Expand Up @@ -783,11 +785,12 @@ EOF
deser
samples
rts
base-src
base-tests
base-doc
docs
report-site
# TODO: Reenable when Motoko base library has been lifted to stable functions.
# base-src
# base-tests
# base-doc
# docs
# report-site
# ic-ref-run
shell
check-formatting
Expand Down Expand Up @@ -851,7 +854,7 @@ EOF
ESM=nixpkgs.sources.esm;
TOMMATHSRC = nixpkgs.sources.libtommath;
LOCALE_ARCHIVE = nixpkgs.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive";
MOTOKO_BASE = base-src;
# TODO: Reenable when Motoko base library has been lifted to stable functions.
CANDID_TESTS = "${nixpkgs.sources.candid}/test";
VIPER_SERVER = "${viperServer}";

Expand Down
1 change: 1 addition & 0 deletions doc/md/examples/grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

<func_sort_opt> ::=
<empty>
'stable'
'shared' <query>?
<query>

Expand Down
54 changes: 54 additions & 0 deletions rts/motoko-rts-tests/src/algorithms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::{array::from_fn, vec};

use motoko_rts::algorithms::SortedArray;

pub fn test() {
println!("Testing algorithms ...");

test_binary_search();
}

pub fn test_binary_search() {
println!(" Testing binary search ...");

assert_eq!(find(vec![], 1), None);
assert_eq!(find(vec![1], 1), Some(1));
assert_eq!(find(vec![1], 0), None);
assert_eq!(find(vec![1], 2), None);

let array: [usize; 1000] = from_fn(|index| index * 2 + 1);
let vector = array.to_vec();
for index in 0..array.len() {
assert_eq!(find(vector.clone(), index * 2), None);
assert_eq!(find(vector.clone(), index * 2 + 1), Some(index * 2 + 1));
}
assert_eq!(find(vector, array.len() * 2 + 2), None);
}

struct TestArrary {
vector: Vec<usize>,
}

impl TestArrary {
fn new(vector: Vec<usize>) -> Self {
TestArrary { vector }
}
}

impl SortedArray<usize> for TestArrary {
fn get_length(&self) -> usize {
self.vector.len()
}

fn value_at(&self, index: usize) -> usize {
self.vector[index]
}
}

fn find(vector: Vec<usize>, searched: usize) -> Option<usize> {
let test_array = TestArrary::new(vector);
match test_array.index_of(searched) {
None => None,
Some(index) => Some(test_array.vector[index]),
}
}
8 changes: 3 additions & 5 deletions rts/motoko-rts-tests/src/gc/classical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,10 @@ impl GC {
}

GC::Generational => {
use motoko_rts::gc::{
generational::{
write_barrier::{LAST_HP, REMEMBERED_SET},
GenerationalGC, Strategy,
},
use motoko_rts::gc::generational::{
remembered_set::RememberedSet,
write_barrier::{LAST_HP, REMEMBERED_SET},
GenerationalGC, Strategy,
};

let strategy = match _round {
Expand Down
2 changes: 2 additions & 0 deletions rts/motoko-rts-tests/src/gc/enhanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ impl GC {
unused_root,
unused_root,
unused_root,
unused_root,
unused_root,
];
IncrementalGC::instance(heap, get_incremental_gc_state())
.empty_call_stack_increment(roots);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashSet;

use crate::memory::TestMemory;
use motoko_rts::gc::remembered_set::{
use motoko_rts::gc::generational::remembered_set::{
RememberedSet, INITIAL_TABLE_LENGTH, OCCUPATION_THRESHOLD_PERCENT,
};
use motoko_rts::types::{Value, Words};
Expand Down
2 changes: 2 additions & 0 deletions rts/motoko-rts-tests/src/gc/incremental/roots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ unsafe fn get_roots(heap: &MotokoHeap) -> Roots {
unused_root,
unused_root,
unused_root,
unused_root,
unused_root,
]
}

Expand Down
6 changes: 6 additions & 0 deletions rts/motoko-rts-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use motoko_rts_macros::{classical_persistence, enhanced_orthogonal_persistence};
#[macro_use]
mod print;

#[enhanced_orthogonal_persistence]
mod algorithms;
mod bigint;
mod bitrel;
mod continuation_table;
Expand All @@ -16,6 +18,8 @@ mod principal_id;

#[enhanced_orthogonal_persistence]
mod stabilization;
#[enhanced_orthogonal_persistence]
mod stable_functions;
mod stable_option;
mod text;
mod utf8;
Expand Down Expand Up @@ -59,7 +63,9 @@ fn check_architecture() {
#[enhanced_orthogonal_persistence]
fn persistence_test() {
unsafe {
algorithms::test();
stabilization::test();
stable_functions::test();
}
}

Expand Down
3 changes: 2 additions & 1 deletion rts/motoko-rts-tests/src/stabilization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ fn serialize(old_stable_root: Value, stable_start: u64) -> u64 {
}

fn deserialize<M: Memory>(mem: &mut M, stable_start: u64, stable_size: u64) -> Value {
let mut deserialization = Deserialization::start(mem, stable_start, stable_size);
let mut deserialization = Deserialization::new(mem, stable_start, stable_size);
deserialization.initiate(mem);
deserialization.copy_increment(mem);
assert!(deserialization.is_completed());
deserialization.get_stable_root()
Expand Down
8 changes: 8 additions & 0 deletions rts/motoko-rts-tests/src/stable_functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod mark_stack;
mod visited_set;

pub unsafe fn test() {
println!("Testing stable functions ...");
mark_stack::test();
visited_set::test();
}
Loading
Loading