Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7bb32aa
First approach at deduping blob.
alexandru-uta Sep 25, 2025
42d6c40
Improvements.
alexandru-uta Sep 25, 2025
efb40ca
fix
alexandru-uta Sep 25, 2025
29a37bd
Improvements for blob deduping and setting it through the RTS.
alexandru-uta Sep 29, 2025
e3649be
Fixes.
alexandru-uta Sep 29, 2025
d17ddbe
Fix.
alexandru-uta Sep 29, 2025
5036564
Fix build gating.
alexandru-uta Sep 30, 2025
c3d21c3
Fix CI build gating.
alexandru-uta Sep 30, 2025
05bbb9d
fix test output.
alexandru-uta Sep 30, 2025
57f6cb5
Fix blob bounds test.
alexandru-uta Sep 30, 2025
27bc671
Use original blob copy.
alexandru-uta Sep 30, 2025
bbc5826
Fix test output.
alexandru-uta Sep 30, 2025
e0ab497
Improve tests and polish.
alexandru-uta Oct 1, 2025
a622a27
Fix.
alexandru-uta Oct 1, 2025
032369d
Don't push null element.
alexandru-uta Oct 1, 2025
249c6db
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 1, 2025
9185088
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 2, 2025
a0e56f6
Add getDeadBlobs() and isBlobLive() functionality; fix bug.
alexandru-uta Oct 6, 2025
26acd0e
Fix test output.
alexandru-uta Oct 6, 2025
11ee310
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 6, 2025
ecb99cd
Merge with master and minor fix.
alexandru-uta Oct 6, 2025
def3582
prunde dead blobs functionality and more tests.
alexandru-uta Oct 7, 2025
7fc537c
Long test with 50K deduped blobs.
alexandru-uta Oct 7, 2025
ceeeac3
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 7, 2025
847a14a
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 8, 2025
929b4ff
Add test for classical --> eop migration.
alexandru-uta Oct 8, 2025
b80c768
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 8, 2025
832b0e5
Merge branch 'master' into alexuta/dedup-objs
alexandru-uta Oct 8, 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
11 changes: 11 additions & 0 deletions rts/motoko-rts/src/gc/incremental/roots/enhanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ pub unsafe fn visit_roots<C, V: Fn(&mut C, *mut Value)>(
visit_field(context, location);
}
}
#[cfg(feature = "ic")]
{
// Always visit the dedup table as well.
// Otherwise the dedup table will be garbage collected.
use crate::persistence::get_dedup_table_ptr;
let dedup_table = get_dedup_table_ptr();
if dedup_table.is_non_null_ptr() {
visit_field(context, dedup_table);
}
}
}

#[cfg(feature = "ic")]
Expand Down Expand Up @@ -67,6 +77,7 @@ pub unsafe fn initialize_static_variables<M: crate::memory::Memory>(mem: &mut M,
for index in 0..amount {
array.initialize(index, NULL_POINTER, mem);
}

let location = addr_of_mut!(STATIC_VARIABLES) as *mut Value;
write_with_barrier(mem, location, variables);
}
Expand Down
23 changes: 23 additions & 0 deletions rts/motoko-rts/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,26 @@ pub unsafe fn weak_ref_is_live<M: Memory>(_mem: &mut M, weak_ref: Value) -> bool
let weak_ref_obj = weak_ref.get_ptr() as *mut WeakRef;
return (*weak_ref_obj).is_live();
}

/// Get the dedup table.
#[enhanced_orthogonal_persistence]
#[ic_mem_fn]
#[cfg(feature = "ic")]
pub unsafe fn get_dedup_table<M: Memory>(_mem: &mut M) -> Value {
use crate::persistence::get_dedup_table_ptr;
*get_dedup_table_ptr()
}

/// Set the dedup table.
#[enhanced_orthogonal_persistence]
#[ic_mem_fn]
#[cfg(feature = "ic")]
pub unsafe fn set_dedup_table<M: Memory>(mem: &mut M, dedup_table: Value) {
use crate::persistence::set_dedup_table_ptr;
if !dedup_table.is_array() {
crate::rts_trap_with(
"set_dedup_table: Invalid dedup table pointer. This is a bug, report to the Motoko team.",
);
}
set_dedup_table_ptr(mem, dedup_table);
}
27 changes: 27 additions & 0 deletions rts/motoko-rts/src/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ struct PersistentMetadata {
/// A Value representing a pointer to a MarkStack object
/// used to collect weak references during the GC marking phase.
weak_ref_registry: Value,
/// Dedup metadata object. The dedup metadata object is an implementation of a hash table
/// which works like an array of a fixed size, and for collisions we have a linked list.
/// The implementation is done in the Motoko prelude file internals.mo, so it is entirely user-space.
/// We keep a pointer to this here so that we can keep if alive across upgrades.
/// To keep the dedup table live, we need to add it to roots as well.
dedup_table: Value,
}

/// Location of the persistent metadata. Prereserved and fixed forever.
Expand Down Expand Up @@ -105,6 +111,8 @@ impl PersistentMetadata {
(*self).upgrade_instructions = 0;
// Initialize the weak reference registry as the null pointer.
(*self).weak_ref_registry = NULL_POINTER;
// Initialize the dedup table as the null pointer.
(*self).dedup_table = NULL_POINTER;
}
}

Expand All @@ -122,6 +130,12 @@ pub unsafe fn initialize_memory<M: Memory>() {
// support. We need to initialize the weak reference registry to NULL_POINTER.
(*metadata).weak_ref_registry = NULL_POINTER;
}
// Explicit migration from a version of the RTS without dedup table support.
if (*metadata).dedup_table.get_raw() == 0 {
// This is the first upgrade from a version of the RTS without dedup table support.
// We need to initialize the dedup table to NULL_POINTER.
(*metadata).dedup_table = NULL_POINTER;
}
} else {
metadata.initialize::<M>();
}
Expand Down Expand Up @@ -335,3 +349,16 @@ unsafe fn is_weak_ref_registry_null() -> bool {
// thus marking of previous weak ref object is not needed.
(*metadata).weak_ref_registry == NULL_POINTER
}

/// Accessor method for the dedup table.
pub(crate) unsafe fn get_dedup_table_ptr() -> &'static mut Value {
let metadata = PersistentMetadata::get();
&mut (*metadata).dedup_table
}

/// Setter method for the dedup table.
pub(crate) unsafe fn set_dedup_table_ptr<M: Memory>(mem: &mut M, dedup_table: Value) {
let metadata = PersistentMetadata::get();
// Use barrier in case the dedup table is set during a GC phase.
write_with_barrier(mem, &mut (*metadata).dedup_table, dedup_table);
}
Loading