about summary refs log tree commit diff
path: root/src/liballoc_system
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-04-16 19:13:52 +0000
committerbors <bors@rust-lang.org>2017-04-16 19:13:52 +0000
commit7627e3d31dd641ae9042675e9032857f58d0c5d1 (patch)
treea9e6a160ae903447feee5c907ac67b1f2281750e /src/liballoc_system
parent9af79f52d0ab43e318bdf3aa73d939c4482cc946 (diff)
parentaad2062073f46f28c6d1269463cc6c19df1e0199 (diff)
downloadrust-7627e3d31dd641ae9042675e9032857f58d0c5d1.tar.gz
rust-7627e3d31dd641ae9042675e9032857f58d0c5d1.zip
Auto merge of #40409 - mbrubeck:calloc, r=sfackler
Specialize Vec::from_elem to use calloc

Fixes #38723.  This specializes the implementation for `u8` only, but it could be extended to other zeroable types if desired.

I haven't tested this extensively, but I did verify that it gives the expected performance boost for large `vec![0; n]` allocations with both alloc_system and jemalloc, on Linux.  (I have not tested or even built the Windows code.)
Diffstat (limited to 'src/liballoc_system')
-rw-r--r--src/liballoc_system/lib.rs34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index de2b75f62b6..6d47c2ff28f 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -45,6 +45,11 @@ pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
 }
 
 #[no_mangle]
+pub extern "C" fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8 {
+    unsafe { imp::allocate_zeroed(size, align) }
+}
+
+#[no_mangle]
 pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
     unsafe { imp::deallocate(ptr, old_size, align) }
 }
@@ -121,6 +126,18 @@ mod imp {
         }
     }
 
+    pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
+        if align <= MIN_ALIGN {
+            libc::calloc(size as libc::size_t, 1) as *mut u8
+        } else {
+            let ptr = aligned_malloc(size, align);
+            if !ptr.is_null() {
+                ptr::write_bytes(ptr, 0, size);
+            }
+            ptr
+        }
+    }
+
     pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
         if align <= MIN_ALIGN {
             libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
@@ -173,6 +190,8 @@ mod imp {
     #[repr(C)]
     struct Header(*mut u8);
 
+
+    const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
     const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
 
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
@@ -185,11 +204,12 @@ mod imp {
         aligned
     }
 
-    pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
+    #[inline]
+    unsafe fn allocate_with_flags(size: usize, align: usize, flags: DWORD) -> *mut u8 {
         if align <= MIN_ALIGN {
-            HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
+            HeapAlloc(GetProcessHeap(), flags, size as SIZE_T) as *mut u8
         } else {
-            let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
+            let ptr = HeapAlloc(GetProcessHeap(), flags, (size + align) as SIZE_T) as *mut u8;
             if ptr.is_null() {
                 return ptr;
             }
@@ -197,6 +217,14 @@ mod imp {
         }
     }
 
+    pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
+        allocate_with_flags(size, align, 0)
+    }
+
+    pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
+        allocate_with_flags(size, align, HEAP_ZERO_MEMORY)
+    }
+
     pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
         if align <= MIN_ALIGN {
             HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8