Enforce the linear-memory maximum size.

Also, support linear memories with no maximum, and dynamic remapping.
This commit is contained in:
Dan Gohman
2018-08-11 07:12:44 -07:00
parent 7b222190f5
commit c12ae182c3

View File

@@ -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)