about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2018-04-04 17:19:16 +0200
committerSimon Sapin <simon.sapin@exyr.org>2018-04-12 22:53:13 +0200
commitc957e99b305ecee113442a7ce0edd6b565200ca9 (patch)
tree02c7f8f7f8f35577d74dfb057625a2a4dae717a7
parentb017742136a5d02b6ba0f2080e97d18a8bfeba4b (diff)
downloadrust-c957e99b305ecee113442a7ce0edd6b565200ca9.tar.gz
rust-c957e99b305ecee113442a7ce0edd6b565200ca9.zip
realloc with a new size only, not a full new layout.
Changing the alignment with realloc is not supported.
-rw-r--r--src/liballoc/alloc.rs22
-rw-r--r--src/liballoc/heap.rs8
-rw-r--r--src/liballoc/raw_vec.rs17
-rw-r--r--src/liballoc_system/lib.rs42
-rw-r--r--src/libcore/alloc.rs87
5 files changed, 74 insertions, 102 deletions
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index a7b5864016c..a6fc8d5004c 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -91,21 +91,17 @@ unsafe impl Alloc for Global {
     unsafe fn realloc(&mut self,
                       ptr: *mut u8,
                       layout: Layout,
-                      new_layout: Layout)
+                      new_size: usize)
                       -> Result<*mut u8, AllocErr>
     {
-        if layout.align() == new_layout.align() {
-            #[cfg(not(stage0))]
-            let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_layout.size());
-            #[cfg(stage0)]
-            let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
-                                     new_layout.size(), new_layout.align(), &mut 0);
-
-            if !ptr.is_null() {
-                Ok(ptr)
-            } else {
-                Err(AllocErr)
-            }
+        #[cfg(not(stage0))]
+        let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_size);
+        #[cfg(stage0)]
+        let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
+                                 new_size, layout.align(), &mut 0);
+
+        if !ptr.is_null() {
+            Ok(ptr)
         } else {
             Err(AllocErr)
         }
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 765fb8458d1..e79383331e1 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -64,7 +64,7 @@ unsafe impl<T> Alloc for T where T: CoreAlloc {
                       ptr: *mut u8,
                       layout: Layout,
                       new_layout: Layout) -> Result<*mut u8, AllocErr> {
-        CoreAlloc::realloc(self, ptr, layout, new_layout)
+        CoreAlloc::realloc(self, ptr, layout, new_layout.size())
     }
 
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
@@ -79,20 +79,20 @@ unsafe impl<T> Alloc for T where T: CoreAlloc {
                              ptr: *mut u8,
                              layout: Layout,
                              new_layout: Layout) -> Result<Excess, AllocErr> {
-        CoreAlloc::realloc_excess(self, ptr, layout, new_layout)
+        CoreAlloc::realloc_excess(self, ptr, layout, new_layout.size())
     }
 
     unsafe fn grow_in_place(&mut self,
                             ptr: *mut u8,
                             layout: Layout,
                             new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        CoreAlloc::grow_in_place(self, ptr, layout, new_layout)
+        CoreAlloc::grow_in_place(self, ptr, layout, new_layout.size())
     }
 
     unsafe fn shrink_in_place(&mut self,
                               ptr: *mut u8,
                               layout: Layout,
                               new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        CoreAlloc::shrink_in_place(self, ptr, layout, new_layout)
+        CoreAlloc::shrink_in_place(self, ptr, layout, new_layout.size())
     }
 }
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 18aaf1de08e..80b816878fb 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -309,11 +309,10 @@ impl<T, A: Alloc> RawVec<T, A> {
                     // `from_size_align_unchecked`.
                     let new_cap = 2 * self.cap;
                     let new_size = new_cap * elem_size;
-                    let new_layout = Layout::from_size_align_unchecked(new_size, cur.align());
                     alloc_guard(new_size).expect("capacity overflow");
                     let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8,
                                                  cur,
-                                                 new_layout);
+                                                 new_size);
                     match ptr_res {
                         Ok(ptr) => (new_cap, Unique::new_unchecked(ptr as *mut T)),
                         Err(_) => self.a.oom(),
@@ -371,8 +370,7 @@ impl<T, A: Alloc> RawVec<T, A> {
             let new_size = new_cap * elem_size;
             alloc_guard(new_size).expect("capacity overflow");
             let ptr = self.ptr() as *mut _;
-            let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
-            match self.a.grow_in_place(ptr, old_layout, new_layout) {
+            match self.a.grow_in_place(ptr, old_layout, new_size) {
                 Ok(_) => {
                     // We can't directly divide `size`.
                     self.cap = new_cap;
@@ -428,8 +426,9 @@ impl<T, A: Alloc> RawVec<T, A> {
 
             let res = match self.current_layout() {
                 Some(layout) => {
+                    debug_assert!(new_layout.align() == layout.align());
                     let old_ptr = self.ptr.as_ptr() as *mut u8;
-                    self.a.realloc(old_ptr, layout, new_layout)
+                    self.a.realloc(old_ptr, layout, new_layout.size())
                 }
                 None => self.a.alloc(new_layout),
             };
@@ -537,8 +536,9 @@ impl<T, A: Alloc> RawVec<T, A> {
 
             let res = match self.current_layout() {
                 Some(layout) => {
+                    debug_assert!(new_layout.align() == layout.align());
                     let old_ptr = self.ptr.as_ptr() as *mut u8;
-                    self.a.realloc(old_ptr, layout, new_layout)
+                    self.a.realloc(old_ptr, layout, new_layout.size())
                 }
                 None => self.a.alloc(new_layout),
             };
@@ -604,7 +604,7 @@ impl<T, A: Alloc> RawVec<T, A> {
             let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
             // FIXME: may crash and burn on over-reserve
             alloc_guard(new_layout.size()).expect("capacity overflow");
-            match self.a.grow_in_place(ptr, old_layout, new_layout) {
+            match self.a.grow_in_place(ptr, old_layout, new_layout.size()) {
                 Ok(_) => {
                     self.cap = new_cap;
                     true
@@ -664,10 +664,9 @@ impl<T, A: Alloc> RawVec<T, A> {
                 let new_size = elem_size * amount;
                 let align = mem::align_of::<T>();
                 let old_layout = Layout::from_size_align_unchecked(old_size, align);
-                let new_layout = Layout::from_size_align_unchecked(new_size, align);
                 match self.a.realloc(self.ptr.as_ptr() as *mut u8,
                                      old_layout,
-                                     new_layout) {
+                                     new_size) {
                     Ok(p) => self.ptr = Unique::new_unchecked(p as *mut T),
                     Err(_) => self.a.oom(),
                 }
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 48a6c1e150a..7b788a5f989 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -69,8 +69,8 @@ unsafe impl Alloc for System {
     unsafe fn realloc(&mut self,
                       ptr: *mut u8,
                       old_layout: Layout,
-                      new_layout: Layout) -> Result<*mut u8, AllocErr> {
-        Alloc::realloc(&mut &*self, ptr, old_layout, new_layout)
+                      new_size: usize) -> Result<*mut u8, AllocErr> {
+        Alloc::realloc(&mut &*self, ptr, old_layout, new_size)
     }
 
     fn oom(&mut self) -> ! {
@@ -91,24 +91,24 @@ unsafe impl Alloc for System {
     unsafe fn realloc_excess(&mut self,
                              ptr: *mut u8,
                              layout: Layout,
-                             new_layout: Layout) -> Result<Excess, AllocErr> {
-        Alloc::realloc_excess(&mut &*self, ptr, layout, new_layout)
+                             new_size: usize) -> Result<Excess, AllocErr> {
+        Alloc::realloc_excess(&mut &*self, ptr, layout, new_size)
     }
 
     #[inline]
     unsafe fn grow_in_place(&mut self,
                             ptr: *mut u8,
                             layout: Layout,
-                            new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        Alloc::grow_in_place(&mut &*self, ptr, layout, new_layout)
+                            new_size: usize) -> Result<(), CannotReallocInPlace> {
+        Alloc::grow_in_place(&mut &*self, ptr, layout, new_size)
     }
 
     #[inline]
     unsafe fn shrink_in_place(&mut self,
                               ptr: *mut u8,
                               layout: Layout,
-                              new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        Alloc::shrink_in_place(&mut &*self, ptr, layout, new_layout)
+                              new_size: usize) -> Result<(), CannotReallocInPlace> {
+        Alloc::shrink_in_place(&mut &*self, ptr, layout, new_size)
     }
 }
 
@@ -166,12 +166,8 @@ macro_rules! alloc_methods_based_on_global_alloc {
         unsafe fn realloc(&mut self,
                           ptr: *mut u8,
                           old_layout: Layout,
-                          new_layout: Layout) -> Result<*mut u8, AllocErr> {
-            if old_layout.align() != new_layout.align() {
-                return Err(AllocErr)
-            }
-
-            let ptr = GlobalAlloc::realloc(*self, ptr as *mut Void, old_layout, new_layout.size());
+                          new_size: usize) -> Result<*mut u8, AllocErr> {
+            let ptr = GlobalAlloc::realloc(*self, ptr as *mut Void, old_layout, new_size);
             if !ptr.is_null() {
                 Ok(ptr as *mut u8)
             } else {
@@ -428,30 +424,26 @@ mod platform {
         unsafe fn grow_in_place(&mut self,
                                 ptr: *mut u8,
                                 layout: Layout,
-                                new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            self.shrink_in_place(ptr, layout, new_layout)
+                                new_size: usize) -> Result<(), CannotReallocInPlace> {
+            self.shrink_in_place(ptr, layout, new_size)
         }
 
         #[inline]
         unsafe fn shrink_in_place(&mut self,
                                   ptr: *mut u8,
-                                  old_layout: Layout,
-                                  new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            if old_layout.align() != new_layout.align() {
-                return Err(CannotReallocInPlace)
-            }
-
-            let new = if new_layout.align() <= MIN_ALIGN {
+                                  layout: Layout,
+                                  new_size: usize) -> Result<(), CannotReallocInPlace> {
+            let new = if layout.align() <= MIN_ALIGN {
                 HeapReAlloc(GetProcessHeap(),
                             HEAP_REALLOC_IN_PLACE_ONLY,
                             ptr as LPVOID,
-                            new_layout.size())
+                            new_size)
             } else {
                 let header = get_header(ptr);
                 HeapReAlloc(GetProcessHeap(),
                             HEAP_REALLOC_IN_PLACE_ONLY,
                             header.0 as LPVOID,
-                            new_layout.size() + new_layout.align())
+                            new_size + layout.align())
             };
             if new.is_null() {
                 Err(CannotReallocInPlace)
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 0acaf54e0d9..757f06e731f 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -633,9 +633,10 @@ pub unsafe trait Alloc {
     // realloc. alloc_excess, realloc_excess
 
     /// Returns a pointer suitable for holding data described by
-    /// `new_layout`, meeting its size and alignment guarantees. To
+    /// a new layout with `layout`’s alginment and a size given
+    /// by `new_size`. To
     /// accomplish this, this may extend or shrink the allocation
-    /// referenced by `ptr` to fit `new_layout`.
+    /// referenced by `ptr` to fit the new layout.
     ///
     /// If this returns `Ok`, then ownership of the memory block
     /// referenced by `ptr` has been transferred to this
@@ -648,12 +649,6 @@ pub unsafe trait Alloc {
     /// block has not been transferred to this allocator, and the
     /// contents of the memory block are unaltered.
     ///
-    /// For best results, `new_layout` should not impose a different
-    /// alignment constraint than `layout`. (In other words,
-    /// `new_layout.align()` should equal `layout.align()`.) However,
-    /// behavior is well-defined (though underspecified) when this
-    /// constraint is violated; further discussion below.
-    ///
     /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
@@ -661,12 +656,13 @@ pub unsafe trait Alloc {
     ///
     /// * `ptr` must be currently allocated via this allocator,
     ///
-    /// * `layout` must *fit* the `ptr` (see above). (The `new_layout`
+    /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
     ///   argument need not fit it.)
     ///
-    /// * `new_layout` must have size greater than zero.
+    /// * `new_size` must be greater than zero.
     ///
-    /// * the alignment of `new_layout` is non-zero.
+    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
+    ///   must not overflow (i.e. the rounded value must be less than `usize::MAX`).
     ///
     /// (Extension subtraits might provide more specific bounds on
     /// behavior, e.g. guarantee a sentinel address or a null pointer
@@ -674,18 +670,11 @@ pub unsafe trait Alloc {
     ///
     /// # Errors
     ///
-    /// Returns `Err` only if `new_layout` does not match the
-    /// alignment of `layout`, or does not meet the allocator's size
+    /// Returns `Err` only if the new layout
+    /// does not meet the allocator's size
     /// and alignment constraints of the allocator, or if reallocation
     /// otherwise fails.
     ///
-    /// (Note the previous sentence did not say "if and only if" -- in
-    /// particular, an implementation of this method *can* return `Ok`
-    /// if `new_layout.align() != old_layout.align()`; or it can
-    /// return `Err` in that scenario, depending on whether this
-    /// allocator can dynamically adjust the alignment constraint for
-    /// the block.)
-    ///
     /// Implementations are encouraged to return `Err` on memory
     /// exhaustion rather than panicking or aborting, but this is not
     /// a strict requirement. (Specifically: it is *legal* to
@@ -698,22 +687,21 @@ pub unsafe trait Alloc {
     unsafe fn realloc(&mut self,
                       ptr: *mut u8,
                       layout: Layout,
-                      new_layout: Layout) -> Result<*mut u8, AllocErr> {
-        let new_size = new_layout.size();
+                      new_size: usize) -> Result<*mut u8, AllocErr> {
         let old_size = layout.size();
-        let aligns_match = layout.align == new_layout.align;
 
-        if new_size >= old_size && aligns_match {
-            if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_layout.clone()) {
+        if new_size >= old_size {
+            if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_size) {
                 return Ok(ptr);
             }
-        } else if new_size < old_size && aligns_match {
-            if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_layout.clone()) {
+        } else if new_size < old_size {
+            if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_size) {
                 return Ok(ptr);
             }
         }
 
         // otherwise, fall back on alloc + copy + dealloc.
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let result = self.alloc(new_layout);
         if let Ok(new_ptr) = result {
             ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));
@@ -789,17 +777,19 @@ pub unsafe trait Alloc {
     unsafe fn realloc_excess(&mut self,
                              ptr: *mut u8,
                              layout: Layout,
-                             new_layout: Layout) -> Result<Excess, AllocErr> {
+                             new_size: usize) -> Result<Excess, AllocErr> {
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let usable_size = self.usable_size(&new_layout);
-        self.realloc(ptr, layout, new_layout)
+        self.realloc(ptr, layout, new_size)
             .map(|p| Excess(p, usable_size.1))
     }
 
-    /// Attempts to extend the allocation referenced by `ptr` to fit `new_layout`.
+    /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
     ///
     /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_layout`, and thus can
-    /// be used to carry data of that layout. (The allocator is allowed to
+    /// memory block referenced by `ptr` now fits `new_size`, and thus can
+    /// be used to carry data of a layout of that size and same alignment as
+    /// `layout`. (The allocator is allowed to
     /// expend effort to accomplish this, such as extending the memory block to
     /// include successor blocks, or virtual memory tricks.)
     ///
@@ -815,11 +805,9 @@ pub unsafe trait Alloc {
     /// * `ptr` must be currently allocated via this allocator,
     ///
     /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_layout` argument need not fit it,
+    ///   `new_size` argument need not fit it,
     ///
-    /// * `new_layout.size()` must not be less than `layout.size()`,
-    ///
-    /// * `new_layout.align()` must equal `layout.align()`.
+    /// * `new_size` must not be less than `layout.size()`,
     ///
     /// # Errors
     ///
@@ -834,24 +822,23 @@ pub unsafe trait Alloc {
     unsafe fn grow_in_place(&mut self,
                             ptr: *mut u8,
                             layout: Layout,
-                            new_layout: Layout) -> Result<(), CannotReallocInPlace> {
+                            new_size: usize) -> Result<(), CannotReallocInPlace> {
         let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_layout.size >= layout.size);
-        debug_assert!(new_layout.align == layout.align);
+        debug_assert!(new_size >= layout.size);
         let (_l, u) = self.usable_size(&layout);
         // _l <= layout.size()                       [guaranteed by usable_size()]
         //       layout.size() <= new_layout.size()  [required by this method]
-        if new_layout.size <= u {
+        if new_size <= u {
             return Ok(());
         } else {
             return Err(CannotReallocInPlace);
         }
     }
 
-    /// Attempts to shrink the allocation referenced by `ptr` to fit `new_layout`.
+    /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
     ///
     /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_layout`, and
+    /// memory block referenced by `ptr` now fits `new_size`, and
     /// thus can only be used to carry data of that smaller
     /// layout. (The allocator is allowed to take advantage of this,
     /// carving off portions of the block for reuse elsewhere.) The
@@ -872,13 +859,11 @@ pub unsafe trait Alloc {
     /// * `ptr` must be currently allocated via this allocator,
     ///
     /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_layout` argument need not fit it,
+    ///   `new_size` argument need not fit it,
     ///
-    /// * `new_layout.size()` must not be greater than `layout.size()`
+    /// * `new_size` must not be greater than `layout.size()`
     ///   (and must be greater than zero),
     ///
-    /// * `new_layout.align()` must equal `layout.align()`.
-    ///
     /// # Errors
     ///
     /// Returns `Err(CannotReallocInPlace)` when the allocator is
@@ -892,14 +877,13 @@ pub unsafe trait Alloc {
     unsafe fn shrink_in_place(&mut self,
                               ptr: *mut u8,
                               layout: Layout,
-                              new_layout: Layout) -> Result<(), CannotReallocInPlace> {
+                              new_size: usize) -> Result<(), CannotReallocInPlace> {
         let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_layout.size <= layout.size);
-        debug_assert!(new_layout.align == layout.align);
+        debug_assert!(new_size <= layout.size);
         let (l, _u) = self.usable_size(&layout);
         //                      layout.size() <= _u  [guaranteed by usable_size()]
         // new_layout.size() <= layout.size()        [required by this method]
-        if l <= new_layout.size {
+        if l <= new_size {
             return Ok(());
         } else {
             return Err(CannotReallocInPlace);
@@ -1061,7 +1045,8 @@ pub unsafe trait Alloc {
     {
         match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
             (Ok(ref k_old), Ok(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
-                self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
+                debug_assert!(k_old.align() == k_new.align());
+                self.realloc(ptr as *mut u8, k_old.clone(), k_new.size())
                     .map(|p| NonNull::new_unchecked(p as *mut T))
             }
             _ => {