diff --git a/src/memory.rs b/src/memory.rs index 038ab58..626fb7a 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -58,6 +58,7 @@ pub struct MemoryInstance { initial: Pages, current_size: Cell, maximum: Option, + lowest_used: Cell, } impl fmt::Debug for MemoryInstance { @@ -127,6 +128,7 @@ impl MemoryInstance { initial: initial, current_size: Cell::new(initial_size.0), maximum: maximum, + lowest_used: Cell::new(u32::max_value()), } } @@ -148,6 +150,16 @@ impl MemoryInstance { self.maximum } + /// Returns lowest offset ever written or `u32::max_value()` if none. + pub fn lowest_used(&self) -> u32 { + self.lowest_used.get() + } + + /// Resets tracked lowest offset. + pub fn reset_lowest_used(&self, addr: u32) { + self.lowest_used.set(addr) + } + /// Returns current linear memory size. /// /// Maximum memory size cannot exceed `65536` pages or 4GiB. @@ -171,6 +183,11 @@ impl MemoryInstance { Bytes(self.current_size.get()).round_up_to() } + /// Returns current used memory size in bytes. + pub fn used_size(&self) -> Bytes { + Bytes(self.buffer.borrow().len()) + } + /// Get value from memory at given offset. pub fn get_value(&self, offset: u32) -> Result { let mut buffer = self.buffer.borrow_mut(); @@ -213,6 +230,9 @@ impl MemoryInstance { .checked_region(&mut buffer, offset as usize, value.len())? .range(); + if offset < self.lowest_used.get() { + self.lowest_used.set(offset); + } buffer[range].copy_from_slice(value); Ok(()) @@ -224,6 +244,9 @@ impl MemoryInstance { let range = self .checked_region(&mut buffer, offset as usize, ::core::mem::size_of::())? .range(); + if offset < self.lowest_used.get() { + self.lowest_used.set(offset); + } value.into_little_endian(&mut buffer[range]); Ok(()) } @@ -474,7 +497,12 @@ impl MemoryInstance { /// /// Returns `Err` if the specified region is out of bounds. pub fn zero(&self, offset: usize, len: usize) -> Result<(), Error> { - self.clear(offset, 0, len) + if (offset + len) >= self.buffer.borrow().len() { + self.buffer.borrow_mut().resize(offset, 0u8); + Ok(()) + } else { + self.clear(offset, 0, len) + } } /// Provides direct access to the underlying memory buffer.