//! Support for implementing the [`RuntimeLinearMemory`] trait in terms of a //! fixed allocation that cannot move. use crate::prelude::*; use crate::runtime::vm::MemoryBase; use crate::runtime::vm::memory::RuntimeLinearMemory; /// A "static" memory where the lifetime of the backing memory is managed /// elsewhere. Currently used with the pooling allocator. pub struct StaticMemory { /// The base pointer of this static memory, wrapped up in a send/sync /// wrapper. base: MemoryBase, /// The byte capacity of the `base` pointer. capacity: usize, /// The current size, in bytes, of this memory. size: usize, } impl StaticMemory { pub fn new( base: MemoryBase, base_capacity: usize, initial_size: usize, maximum_size: Option, ) -> Result { if base_capacity < initial_size { bail!( "initial memory size of {initial_size} exceeds the pooling allocator's \ configured maximum memory size of {base_capacity} bytes", ); } // Only use the part of the slice that is necessary. let base_capacity = match maximum_size { Some(max) if max < base_capacity => max, _ => base_capacity, }; Ok(Self { base, capacity: base_capacity, size: initial_size, }) } } impl RuntimeLinearMemory for StaticMemory { fn byte_size(&self) -> usize { self.size } fn byte_capacity(&self) -> usize { self.capacity } fn grow_to(&mut self, new_byte_size: usize) -> Result<()> { // Never exceed the static memory size; this check should have been made // prior to arriving here. assert!(new_byte_size <= self.capacity); // Update our accounting of the available size. self.size = new_byte_size; Ok(()) } fn set_byte_size(&mut self, len: usize) { self.size = len; } fn base(&self) -> MemoryBase { self.base.clone() } fn vmmemory(&self) -> crate::vm::VMMemoryDefinition { crate::vm::VMMemoryDefinition { base: self.base.as_non_null().into(), current_length: self.size.into(), } } }