about summary refs log tree commit diff
path: root/src/libarena
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-05-02 08:02:57 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-05-27 17:28:35 +0200
commit6c2d875261e10105dcfcbd9be84d05a730edd235 (patch)
tree490055facae889ab36bd2025ef326eae63767333 /src/libarena
parenta52b01bc67068fbd30206db53f2a3461f65e629e (diff)
Make &Slice a thin pointer
Diffstat (limited to 'src/libarena')
-rw-r--r--src/libarena/lib.rs59
1 files changed, 34 insertions, 25 deletions
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index f7143a4f981..b6a81596d06 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -314,8 +314,7 @@ impl DroplessArena {
         false
     }
 
-    fn align_for<T>(&self) {
-        let align = mem::align_of::<T>();
+    fn align(&self, align: usize) {
         let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
         self.ptr.set(final_address as *mut u8);
         assert!(self.ptr <= self.end);
@@ -323,8 +322,7 @@ impl DroplessArena {
 
     #[inline(never)]
     #[cold]
-    fn grow<T>(&self, n: usize) {
-        let needed_bytes = n * mem::size_of::<T>();
+    fn grow(&self, needed_bytes: usize) {
         unsafe {
             let mut chunks = self.chunks.borrow_mut();
             let (chunk, mut new_capacity);
@@ -356,25 +354,38 @@ impl DroplessArena {
     }
 
     #[inline]
-    pub fn alloc<T>(&self, object: T) -> &mut T {
+    pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
         unsafe {
-            assert!(!mem::needs_drop::<T>());
-            assert!(mem::size_of::<T>() != 0);
+            assert!(bytes != 0);
+
+            self.align(align);
 
-            self.align_for::<T>();
-            let future_end = intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize);
+            let future_end = intrinsics::arith_offset(self.ptr.get(), bytes as isize);
             if (future_end as *mut u8) >= self.end.get() {
-                self.grow::<T>(1)
+                self.grow(bytes);
             }
 
             let ptr = self.ptr.get();
             // Set the pointer past ourselves
             self.ptr.set(
-                intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize) as *mut u8,
+                intrinsics::arith_offset(self.ptr.get(), bytes as isize) as *mut u8,
             );
+            slice::from_raw_parts_mut(ptr, bytes)
+        }
+    }
+
+    #[inline]
+    pub fn alloc<T>(&self, object: T) -> &mut T {
+        assert!(!mem::needs_drop::<T>());
+
+        let mem = self.alloc_raw(
+            mem::size_of::<T>(),
+            mem::align_of::<T>()) as *mut _ as *mut T;
+
+        unsafe {
             // Write into uninitialized memory.
-            ptr::write(ptr as *mut T, object);
-            &mut *(ptr as *mut T)
+            ptr::write(mem, object);
+            &mut *mem
         }
     }
 
@@ -393,21 +404,13 @@ impl DroplessArena {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
-        self.align_for::<T>();
 
-        let future_end = unsafe {
-            intrinsics::arith_offset(self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize)
-        };
-        if (future_end as *mut u8) >= self.end.get() {
-            self.grow::<T>(slice.len());
-        }
+        let mem = self.alloc_raw(
+            slice.len() * mem::size_of::<T>(),
+            mem::align_of::<T>()) as *mut _ as *mut T;
 
         unsafe {
-            let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
-            self.ptr.set(intrinsics::arith_offset(
-                self.ptr.get(),
-                (slice.len() * mem::size_of::<T>()) as isize,
-            ) as *mut u8);
+            let arena_slice = slice::from_raw_parts_mut(mem, slice.len());
             arena_slice.copy_from_slice(slice);
             arena_slice
         }
@@ -465,6 +468,12 @@ impl SyncDroplessArena {
     }
 
     #[inline(always)]
+    pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
+        // Extend the lifetime of the result since it's limited to the lock guard
+        unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) }
+    }
+
+    #[inline(always)]
     pub fn alloc<T>(&self, object: T) -> &mut T {
         // Extend the lifetime of the result since it's limited to the lock guard
         unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }