diff --git a/lib/simplejit/src/memory.rs b/lib/simplejit/src/memory.rs index 1ea654e924..2158352cc8 100644 --- a/lib/simplejit/src/memory.rs +++ b/lib/simplejit/src/memory.rs @@ -4,12 +4,19 @@ use errno; use libc; 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 { ptr: *mut u8, len: usize, } impl PtrLen { + /// Create a new empty `PtrLen`. fn new() -> Self { Self { 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 { 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 { let mut ptr: *mut libc::c_void = mem::uninitialized(); 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 { allocations: Vec, executable: usize, @@ -77,6 +88,7 @@ impl Memory { Ok(self.current.ptr) } + /// Set all memory allocated in this `Memory` up to now as executable. pub fn set_executable(&mut self) { 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) { self.finish_current(); @@ -106,3 +119,16 @@ impl 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); + } +}