1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-18 19:31:04 +00:00

feat(core/rust): add option to Gc-allocate with finaliser

[no changelog]
This commit is contained in:
matejcik 2024-05-29 10:47:27 +02:00 committed by TychoVrahe
parent 288c855868
commit 813d9b7687
2 changed files with 37 additions and 3 deletions

View File

@ -235,6 +235,7 @@ fn generate_micropython_bindings() {
.allowlist_var("mp_type_fun_builtin_var")
// gc
.allowlist_function("gc_alloc")
.allowlist_var("GC_ALLOC_FLAG_HAS_FINALISER")
// iter
.allowlist_type("mp_obj_iter_buf_t")
.allowlist_function("mp_getiter")

View File

@ -21,8 +21,17 @@ impl<T: ?Sized> Copy for Gc<T> {}
impl<T> Gc<T> {
/// Allocate memory on the heap managed by the MicroPython garbage collector
/// and then place `v` into it. `v` will _not_ get its destructor called.
pub fn new(v: T) -> Result<Self, Error> {
/// and then place `v` into it.
///
/// `flags` can be an int value built out of constants in the ffi module.
/// The current MicroPython only supports GC_ALLOC_FLAG_HAS_FINALISER, which
/// will cause the __del__ method to be called when the object is
/// garbage collected.
///
/// SAFETY:
/// Flag GC_ALLOC_FLAG_HAS_FINALISER can only be used with Python objects
/// that have a base as their first element
unsafe fn alloc(v: T, flags: u32) -> Result<Self, Error> {
let layout = Layout::for_value(&v);
// TODO: Assert that `layout.align()` is the same as the GC alignment.
// SAFETY:
@ -32,7 +41,7 @@ impl<T> Gc<T> {
// or the MicroPython heap.
// EXCEPTION: Returns null instead of raising.
unsafe {
let raw = ffi::gc_alloc(layout.size(), 0);
let raw = ffi::gc_alloc(layout.size(), flags);
if raw.is_null() {
return Err(Error::AllocationFailed);
}
@ -41,6 +50,30 @@ impl<T> Gc<T> {
Ok(Self::from_raw(typed))
}
}
/// Allocate memory on the heap managed by the MicroPython garbage collector
/// and then place `v` into it. `v` will _not_ get its destructor called.
pub fn new(v: T) -> Result<Self, Error> {
unsafe {
// SAFETY: No flag is used
Self::alloc(v, 0)
}
}
/// Allocate memory on the heap managed by the MicroPython garbage
/// collector, place `v` into it, and register for finalisation.
///
/// `v` will **not** get its destructor called automatically! However, if
/// `v` is a Python-style object (has a base as its first field), and
/// has a `__del__` method, it will be called when the object is garbage
/// collected. You can use this to implement custom finalisation, in
/// which you can, e.g., invoke the Drop implementation.
/// SAFETY:
/// Can only be used with Python objects that have a base as their
/// first element
pub unsafe fn new_with_custom_finaliser(v: T) -> Result<Self, Error> {
unsafe { Self::alloc(v, ffi::GC_ALLOC_FLAG_HAS_FINALISER) }
}
}
impl<T: Default> Gc<[T]> {