Fix simplejit's memory size computations.

@steffengy noticed that the code to round allocation sizes up to the
neareset page size was incorrect. It was masking off the low bits rather
than the high bits.

Also, while here, add more comments to `Memory`'s implementation.
This commit is contained in:
Dan Gohman
2018-04-30 16:46:14 -07:00
parent 9c87f3ac87
commit 8fa0e6da99

View File

@@ -4,12 +4,19 @@ use errno;
use libc; use libc;
use region; use region;
/// Round `size` up to the nearest multiple of `page_size`.
fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
(size + (page_size - 1)) & !(page_size - 1)
}
/// A simple struct consisting of a pointer and length.
struct PtrLen { struct PtrLen {
ptr: *mut u8, ptr: *mut u8,
len: usize, len: usize,
} }
impl PtrLen { impl PtrLen {
/// Create a new empty `PtrLen`.
fn new() -> Self { fn new() -> Self {
Self { Self {
ptr: ptr::null_mut(), ptr: ptr::null_mut(),
@@ -17,9 +24,11 @@ impl PtrLen {
} }
} }
/// Create a new `PtrLen` pointing to at least `size` bytes of memory,
/// suitably sized and aligned for memory protection.
fn with_size(size: usize) -> Result<Self, String> { fn with_size(size: usize) -> Result<Self, String> {
let page_size = region::page::size(); let page_size = region::page::size();
let alloc_size = (size + (page_size - 1)) & (page_size - 1); let alloc_size = round_up_to_page_size(size, page_size);
unsafe { unsafe {
let mut ptr: *mut libc::c_void = mem::uninitialized(); let mut ptr: *mut libc::c_void = mem::uninitialized();
let err = libc::posix_memalign(&mut ptr, page_size, alloc_size); let err = libc::posix_memalign(&mut ptr, page_size, alloc_size);
@@ -35,6 +44,8 @@ impl PtrLen {
} }
} }
/// JIT memory manager. This manages pages of suitably aligned and
/// accessible memory.
pub struct Memory { pub struct Memory {
allocations: Vec<PtrLen>, allocations: Vec<PtrLen>,
executable: usize, executable: usize,
@@ -77,6 +88,7 @@ impl Memory {
Ok(self.current.ptr) Ok(self.current.ptr)
} }
/// Set all memory allocated in this `Memory` up to now as executable.
pub fn set_executable(&mut self) { pub fn set_executable(&mut self) {
self.finish_current(); self.finish_current();
@@ -90,6 +102,7 @@ impl Memory {
} }
} }
/// Set all memory allocated in this `Memory` up to now as readonly.
pub fn set_readonly(&mut self) { pub fn set_readonly(&mut self) {
self.finish_current(); self.finish_current();
@@ -106,3 +119,16 @@ impl Memory {
} }
// TODO: Implement Drop to unprotect and deallocate the memory? // TODO: Implement Drop to unprotect and deallocate the memory?
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_round_up_to_page_size() {
assert_eq!(round_up_to_page_size(0, 4096), 0);
assert_eq!(round_up_to_page_size(1, 4096), 4096);
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
}
}