Enforce the linear-memory maximum size.
Also, support linear memories with no maximum, and dynamic remapping.
This commit is contained in:
@@ -11,21 +11,21 @@ const MAX_PAGES: u32 = 65536;
|
|||||||
pub struct LinearMemory {
|
pub struct LinearMemory {
|
||||||
mmap: memmap::MmapMut,
|
mmap: memmap::MmapMut,
|
||||||
current: u32,
|
current: u32,
|
||||||
maximum: u32,
|
maximum: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LinearMemory {
|
impl LinearMemory {
|
||||||
/// Create a new linear memory instance with specified initial and maximum number of pages.
|
/// Create a new linear memory instance with specified initial and maximum number of pages.
|
||||||
///
|
///
|
||||||
/// `maximum` cannot be set to more than `65536` pages. If `maximum` is `None` then it
|
/// `maximum` cannot be set to more than `65536` pages.
|
||||||
/// will be treated as `65336`.
|
|
||||||
pub fn new(initial: u32, maximum: Option<u32>) -> Self {
|
pub fn new(initial: u32, maximum: Option<u32>) -> Self {
|
||||||
let maximum = maximum.unwrap_or(MAX_PAGES);
|
|
||||||
|
|
||||||
assert!(initial <= MAX_PAGES);
|
assert!(initial <= MAX_PAGES);
|
||||||
assert!(maximum <= MAX_PAGES);
|
assert!(maximum.is_none() || maximum.unwrap() <= MAX_PAGES);
|
||||||
|
|
||||||
let len = maximum.saturating_mul(MAX_PAGES);
|
let len = PAGE_SIZE * match maximum {
|
||||||
|
Some(val) => val,
|
||||||
|
None => initial,
|
||||||
|
};
|
||||||
let mmap = memmap::MmapMut::map_anon(len as usize).unwrap();
|
let mmap = memmap::MmapMut::map_anon(len as usize).unwrap();
|
||||||
Self {
|
Self {
|
||||||
mmap,
|
mmap,
|
||||||
@@ -53,15 +53,29 @@ impl LinearMemory {
|
|||||||
Some(new_pages) => new_pages,
|
Some(new_pages) => new_pages,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
if let Some(val) = self.maximum {
|
||||||
|
if new_pages > val {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let prev_pages = self.current;
|
let prev_pages = self.current;
|
||||||
|
let new_bytes = (new_pages * PAGE_SIZE) as usize;
|
||||||
|
|
||||||
|
if self.mmap.len() < new_bytes {
|
||||||
|
assert!(self.maximum.is_none());
|
||||||
|
let mut new_mmap = memmap::MmapMut::map_anon(new_bytes).unwrap();
|
||||||
|
new_mmap.copy_from_slice(&self.mmap);
|
||||||
|
self.mmap = new_mmap;
|
||||||
|
}
|
||||||
|
|
||||||
self.current = new_pages;
|
self.current = new_pages;
|
||||||
|
|
||||||
// Ensure that newly allocated area is zeroed.
|
// Ensure that newly allocated area is zeroed.
|
||||||
let new_start_offset = (prev_pages * PAGE_SIZE) as usize;
|
let new_start_offset = (prev_pages * PAGE_SIZE) as usize;
|
||||||
let new_end_offset = (new_pages * PAGE_SIZE) as usize;
|
let new_end_offset = (new_pages * PAGE_SIZE) as usize;
|
||||||
for i in new_start_offset..new_end_offset - 1 {
|
for i in new_start_offset..new_end_offset {
|
||||||
self.mmap[i] = 0;
|
assert!(self.mmap[i] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(prev_pages)
|
Some(prev_pages)
|
||||||
|
|||||||
Reference in New Issue
Block a user